מקרה לדוגמה של Wake Lock API: עלייה של 300% באינדיקטורים של כוונת רכישה באתר BettyCrocker.com

אין דבר יותר גרוע כשמבשלים עם מכשיר נייד מאשר שהמסך נכבה באמצע שלב מתכון. כך אתר הבישול BettyCrocker.com השתמש ב-Wake Lock API כדי למנוע את זה.

במשך כמעט מאה שנים, בטי קרוקר הייתה המקור באמריקה ללימודי בישול מודרני ולפיתוח מתכונים מהימן. האתר BettyCrocker.com, שהושק ב-1997, מקבל כיום יותר מ-12 מיליון מבקרים בחודש. אחרי שהחברה הטמיעה את Wake Lock API, האינדיקטורים של כוונת הרכישה שלהם היו גבוהים ב-300% בערך בקרב משתמשים שפתחו את ה-Wake Lock בהשוואה לכל המשתמשים.

האפליקציות ל-iOS ול-Android שהוצאו משימוש

לאחר שהאפליקציות הושקו ב-2014, בטי קרוקר (Betty Crocker) הוציאו לאחרונה את האפליקציות שלהם מ-Apple App Store ומחנות Google Play, אחרי שהעדיפות שלהן נדחתה. במשך זמן רב, הצוות של Betty Crocker העדיף להוסיף תכונות חדשות לאתר לנייד במקום לאפליקציות ל-iOS או ל-Android. הפלטפורמה הטכנית שבה נוצרו האפליקציות ל-iOS או ל-Android הייתה מיושנת, ולעסק לא היו משאבים לתמיכה בעדכון ובתחזוקה של האפליקציות בהמשך. באופן אובייקטיבי, אפליקציית האינטרנט הייתה גדולה יותר מבחינת תנועה, מודרנית יותר וקלה יותר לשיפור.

עם זאת, האפליקציות ל-iOS או ל-Android כללו פיצ'ר קיצוני שהמשתמשים שלהן אהבו:

טיפ למתקדמים בנושא בישול@AvaBeilke

80% מהאנשים מבשלים עם מכשיר במטבח, אבל עמעום המסך ונעילת המסך הן בעיה. מה עשה @BettyCrocker? האפליקציה עודכנה כך שלא תעמעם כשמשתמשים במתכון. —@KatieTweedy

העלאת פיצ'ר הרומן לאינטרנט באמצעות ממשק ה-API של Wake Lock

כשמבשלים עם מכשיר, אין דבר מתסכל יותר מלגעת במסך עם ידיים מלוכלכות או אפילו כשהמסך נכבה. בטי קרוקר שאלה את עצמה איך להעביר את התכונה הקטלנית של אפליקציות ל-iOS ו-Android לאפליקציית האינטרנט. זה כשהם למדו על Project Fugu ועל Wake Lock API.

אדם ללוש בצק על שולחן מטבח מכוסה בקמח

השימוש בממשק ה-API של נעילת מצב השינה מאפשר למנוע מהמכשיר לעמעם או לנעול את המסך. היכולת הזו מאפשרת חוויות חדשות שדרשו עד עכשיו אפליקציות ל-iOS או ל-Android. ממשק ה-Wake Lock API מצמצם את הצורך בפתרונות עקיפים שעשויים להיות צורך אנרגיה רבה.

בקשה לנעילת מצב שינה

כדי לבקש נעילת מצב שינה, עליכם לקרוא ל-method navigator.wakeLock.request() שמחזירה אובייקט WakeLockSentinel. תשתמשו באובייקט הזה כערך סנטינל. הדפדפן יכול לדחות את הבקשה מסיבות שונות (לדוגמה, כי הסוללה חלשה מדי), ולכן מומלץ להגדיר את השיחה בהצהרה של try…catch.

שחרור של נעילת מצב שינה

נדרשת גם דרך לשחרר נעילה ממצב שינה, שמושגת על ידי קריאה לשיטה release() של האובייקט WakeLockSentinel. אם רוצים לשחרר את הנעילה של מצב השינה באופן אוטומטי אחרי פרק זמן מסוים, אפשר להשתמש ב-window.setTimeout() כדי להפעיל את release(), כמו בדוגמה למטה.

// The wake lock sentinel.
let wakeLock = null;

// Function that attempts to request a wake lock.
const requestWakeLock = async () => {
  try {
    wakeLock = await navigator.wakeLock.request('screen');
    wakeLock.addEventListener('release', () => {
      console.log('Wake Lock was released');
    });
    console.log('Wake Lock is active');
  } catch (err) {
    console.error(`${err.name}, ${err.message}`);
  }
};

// Request a wake lock…
await requestWakeLock();
// …and release it again after 5s.
window.setTimeout(() => {
  wakeLock.release();
  wakeLock = null;
}, 5000);

ההטמעה

אפליקציית האינטרנט החדשה צריכה לאפשר למשתמשים לנווט בקלות במתכון, לבצע פעולות ואפילו לצאת מהבית בלי נעילת המסך. כדי להשיג את המטרה הזו, הצוות יצר תחילה אב-טיפוס מהיר של ממשק-קצה כהוכחת היתכנות ואיסוף קלט של חוויית המשתמש.

אחרי שאבי הטיפוס הוכח כיעיל, היא תכננה רכיב Vue.js שאפשר לשתף בין כל המותגים של החברה (BettyCrocker, Pillsbridge ו-Tablespoon). למרות שרק לבטי קרוקר היו אפליקציות ל-iOS ול-Android, לשלושת האתרים יש בסיס קוד משותף, כך שהם יכלו להטמיע את הרכיב פעם אחת ולפרוס אותו בכל מקום, כפי שמוצג בצילומי המסך שבהמשך.

מתג לנעילת מצב השינה של BettyCrocker.com
מתג נעילת מצב שינה של BettyCrocker.com.
מתג לנעילת מצב השינה של Pillsbridge.com
מתג הנעילה של מצב שינה ב-Pillsborn.com
.
מתג לנעילת מצב השינה של Tablespoon.com
מתג לביטול מצב שינה של Tablespoon.com.

כשפיתחנו את הרכיב על סמך המסגרת המודרנית של האתר, התמקדנו בעיקר בשכבת ViewModel של תבנית ה-MVVM. הצוות גם תכנת מתוך מחשבה על יכולת פעולה הדדית, כדי לאפשר פונקציונליות במסגרות מדור קודם ובמסגרות חדשות של האתר.

כדי לעקוב אחרי הניראות ונוחות השימוש, בטי קרוקר שילבה את מעקב הנתונים של אירועי ליבה במחזור החיים של נעילת מצב השינה. הצוות השתמש בניהול תכונות כדי לפרוס את הרכיב של נעילת מצב השינה באתר יחיד לצורך השקה ראשונית של האפליקציה, ולאחר מכן פרס את התכונה בשאר האתרים אחרי מעקב אחרי השימוש ותקינות הדפים. הם ממשיכים לעקוב אחר ניתוח הנתונים על סמך השימוש ברכיב הזה.

כשכבת הגנה מפני כשל למשתמשים, הצוות יצר זמן קצוב מאולץ של זמן קצוב לתפוגה כדי להשבית את נעילת מצב השינה אחרי שעה אחת של חוסר פעילות. היישום הסופי שעליו הם בחרו היה בטווח הקצר מתג בכל דפי המתכונים באתרים שלהם. בטווח הארוך, הם חוזים תצוגה משופרת בדף מתכונים.

מאגר מצב השינה

var wakeLockControl = () => {
  return import(/* webpackChunkName: 'wakeLock' */ './wakeLock');
};

export default {
  components: {
    wakeLockControl: wakeLockControl,
  },
  data() {
    return {
      config: {},
      wakeLockComponent: '',
    };
  },
  methods: {
    init: function(config) {
      this.config = config || {};
      if ('wakeLock' in navigator && 'request' in navigator.wakeLock) {
        this.wakeLockComponent = 'wakeLockControl';
      } else {
        console.log('Browser not supported');
      }
    },
  },
};

רכיב של חסימת מצב שינה

<template>
  <div class="wakeLock">
    <div class="textAbove"></div>
    <label class="switch" :aria-label="settingsInternal.textAbove">
      <input type="checkbox" @change="onChange()" v-model="isChecked">
      <span class="slider round"></span>
    </label>
  </div>
</template>

<script type="text/javascript">
  import debounce from 'lodash.debounce';

  const scrollDebounceMs = 1000;

  export default {
    props: {
      settings: { type: Object },
    },
    data() {
      return {
        settingsInternal: this.settings || {},
        isChecked: false,
        wakeLock: null,
        timerId: 0,
      };
    },
    created() {
      this.$_raiseAnalyticsEvent('Wake Lock Toggle Available');
    },
    methods: {
      onChange: function() {
        if (this.isChecked) {
          this.$_requestWakeLock();
        } else {
          this.$_releaseWakeLock();
        }
      },
      $_requestWakeLock: async function() {
        try {
          this.wakeLock = await navigator.wakeLock.request('screen');
          //Start new timer
          this.$_handleAbortTimer();
          //Only add event listeners after wake lock is successfully enabled
          document.addEventListener(
            'visibilitychange',
            this.$_handleVisibilityChange,
          );
          window.addEventListener(
            'scroll',
            debounce(this.$_handleAbortTimer, scrollDebounceMs),
          );
          this.$_raiseAnalyticsEvent('Wake Lock Toggle Enabled');
        } catch (e) {
          this.isChecked = false;
        }
      },
      $_releaseWakeLock: function() {
        try {
          this.wakeLock.release();
          this.wakeLock = null;
          //Clear timer
          this.$_handleAbortTimer();
          //Clean up event listeners
          document.removeEventListener(
            'visibilitychange',
            this.$_handleVisibilityChange,
          );
          window.removeEventListener(
            'scroll',
            debounce(this.$_handleAbortTimer, scrollDebounceMs),
          );
        } catch (e) {
          console.log(`Wake Lock Release Error: ${e.name}, ${e.message}`);
        }
      },
      $_handleAbortTimer: function() {
        //If there is an existing timer then clear it and set to zero
        if (this.timerId !== 0) {
          clearTimeout(this.timerId);
          this.timerId = 0;
        }
        //Start new timer; Will be triggered from toggle enabled or scroll event
        if (this.isChecked) {
          this.timerId = setTimeout(
            this.$_releaseWakeLock,
            this.settingsInternal.timeoutDurationMs,
          );
        }
      },
      $_handleVisibilityChange: function() {
        //Handle navigating away from page/tab
        if (this.isChecked) {
          this.$_releaseWakeLock();
          this.isChecked = false;
        }
      },
      $_raiseAnalyticsEvent: function(eventType) {
        let eventParams = {
          EventType: eventType,
          Position: window.location.pathname || '',
        };
        Analytics.raiseEvent(eventParams);
      },
    },
  };
</script>

תוצאות

רכיב Vue.js נפרס בכל שלושת האתרים והניב תוצאות מעולות. במהלך התקופה מ-10 בדצמבר 2019 עד 10 בינואר 2020, BettyCrocker.com דיווח על המדדים הבאים:

  • מתוך כל המשתמשים ב-Betty Crocker שיש להם דפדפן שתואם ל-Wake Lock API, 3.5% מהם הפעילו את התכונה באופן מיידי, מה שהופך אותה ל-5 הפעולות המובילות.
  • משך הסשן של משתמשים שהפעילו את התכונה 'נעילת מצב שינה' היה ארוך פי 3.1 ממשך הסשן של משתמשים שלא הפעילו.
  • שיעור העזיבה של משתמשים שהפעילו את התכונה 'נעילת מצב שינה' היה נמוך ב-50% מזה של משתמשים שלא השתמשו בתכונה 'נעילת מצב שינה'.
  • המדדים של כוונת רכישה היו גבוהים ב-300% בערך בקרב משתמשים שפתחו את הדפוס של מצב שינה בהשוואה לכל המשתמשים.

3.1×

משך סשן ארוך יותר

50%

שיעור יציאה נמוך יותר

300%

אינדיקטורים גבוהים יותר של כוונת רכישה

מסקנות

Betty Crocker ראתה תוצאות מדהימות תוך שימוש ב-Wake Lock API. כדי לבדוק את הפיצ'ר בעצמכם, אפשר לחפש את המתכון המועדף עליכם בכל אחד מהאתרים של המסעדה (BettyCrocker, Pillsborn או Tablespoon) ולהפעיל את המתג מניעת מצב כהה במסך בזמן הבישול.

התרחישים לדוגמה של חסימות מצב שינה לא מופסקות באתרי מתכונים. דוגמאות נוספות: אפליקציות של כרטיסי עלייה למטוס או כרטיסים לכרטיסים שצריכים להישאר במסך עד שסורקים את הברקוד, אפליקציות בסגנון קיוסק שפועלות כל הזמן או אפליקציות מבוססות-אינטרנט להצגת מצגות שמונעות מהמסך לעבור למצב שינה במהלך מצגת.

אספנו את כל מה שצריך לדעת על Wake Lock API במאמר מקיף שנמצא באתר הזה. קריאה נעימה, ובישול שמח!

אישורים

התמונה של ליעת בצק באדיבות Julian Hochgesang ב-UnFlood.