กรณีศึกษา Wake Lock API: ตัวชี้วัดความตั้งใจในการซื้อเพิ่มขึ้น 300% บน BettyCrocker.com

ไม่มีอะไรแย่ไปกว่าการทําอาหารด้วยอุปกรณ์เคลื่อนที่แล้วหน้าจอดับไปกลางคัน ดูวิธีที่เว็บไซต์สอนทำอาหารอย่าง BettyCrocker.com ใช้ Wake Lock API เพื่อป้องกันไม่ให้เกิดเหตุการณ์นี้

Betty Crocker เป็นแหล่งที่มาของวิธีการทำอาหารสมัยใหม่และการพัฒนาสูตรอาหารที่เชื่อถือได้ในอเมริกามาเกือบศตวรรษ เว็บไซต์ BettyCrocker.com เปิดตัวในปี 1997 ปัจจุบันมีผู้เข้าชมมากกว่า 12 ล้านคนต่อเดือน หลังจากติดตั้งใช้งาน Wake Lock API แล้ว ตัวบ่งชี้ความตั้งใจซื้อของผู้ใช้ Wake Lock เพิ่มขึ้นประมาณ 300% เมื่อเทียบกับผู้ใช้ทั้งหมด

แอป iOS และ Android ที่หยุดให้บริการแล้ว

Betty Crocker เปิดตัวแอปอย่างยิ่งใหญ่ในปี 2014 แต่เพิ่งนำแอปออกจาก Apple App Store และ Google Play Store หลังจากที่แอปถูกลดลำดับความสำคัญ ทีม Betty Crocker ต้องการเพิ่มฟีเจอร์ใหม่ๆ ลงในเว็บไซต์เวอร์ชันอุปกรณ์เคลื่อนที่แทนแอป iOS/Android มาเป็นเวลานาน แพลตฟอร์มทางเทคนิคที่ใช้สร้างแอป iOS/Android ล้าสมัยแล้ว และธุรกิจไม่มีทรัพยากรที่จะรองรับการอัปเดตและการดูแลรักษาแอปในอนาคต นอกจากนี้ เว็บแอปยังมีการเข้าชมมากกว่าอย่างเห็นได้ชัด ทันสมัยกว่า และปรับปรุงได้ง่ายกว่า

อย่างไรก็ตาม แอป iOS/Android มีฟีเจอร์เด็ดอย่างหนึ่งที่ผู้ใช้ชื่นชอบ

เคล็ดลับสำหรับมือโปรเรื่องทำอาหารมิลเลนเนียล: แอป @BettyCrocker บนอุปกรณ์เคลื่อนที่ จะไม่หรี่แสงหรือล็อกเมื่อติดตามสูตรอาหาร —@AvaBeilke

ผู้คน 80% ประกอบอาหารด้วยอุปกรณ์ในห้องครัว แต่หน้าจอหรี่ลงและล็อกเป็นปัญหา @BettyCrocker ทำอะไร อัปเดตแอปให้ไม่หรี่แสงเมื่อผู้ใช้อยู่ในสูตรอาหาร —@KatieTweedy

การนำฟีเจอร์ที่ยอดเยี่ยมมาสู่เว็บด้วย Wake Lock API

เมื่อทำอาหารด้วยอุปกรณ์ ไม่มีอะไรน่าหงุดหงิดไปกว่าการต้องสัมผัสหน้าจอด้วยมือที่เลอะเทอะหรือแม้แต่จมูกเมื่อหน้าจอปิดอยู่ Betty Crocker ถามตัวเองว่าจะพอร์ตฟีเจอร์เด็ดๆ ของแอป iOS/Android ไปยังเว็บแอปได้อย่างไร ตอนนั้นเองที่พวกเขาได้รู้จัก Project Fugu และ Wake Lock API

บุคคลกำลังนวดแป้งบนโต๊ะในครัวที่เต็มไปด้วยแป้ง

Wake Lock API มีวิธีป้องกันไม่ให้อุปกรณ์หรี่แสงหรือล็อกหน้าจอ ความสามารถนี้ช่วยให้คุณได้รับประสบการณ์การใช้งานใหม่ๆ ซึ่งก่อนหน้านี้ต้องใช้แอป iOS/Android Wake Lock API ช่วยลดความจำเป็นในการแก้ปัญหาแบบแฮ็กๆ และอาจสิ้นเปลืองพลังงาน

การขอ Wake Lock

หากต้องการขอการล็อกการปลุก คุณต้องเรียกใช้เมธอด 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);

การติดตั้งใช้งาน

เว็บแอปใหม่นี้จะช่วยให้ผู้ใช้ไปยังส่วนต่างๆ ของสูตรอาหาร ดำเนินการตามขั้นตอนต่างๆ และออกจากหน้าจอได้โดยไม่ต้องล็อกหน้าจอ ทีมจึงสร้างโปรโตไทป์ฟรอนต์เอนด์อย่างรวดเร็วเป็นขั้นแรกเพื่อพิสูจน์แนวคิดและรวบรวมข้อมูล UX

หลังจากพบว่าต้นแบบมีประโยชน์แล้ว บริษัทได้ออกแบบคอมโพเนนต์ Vue.js ที่แชร์กับแบรนด์ทั้งหมดได้ (BettyCrocker, Pillsbury และ Tablespoon) แม้ว่าจะมีเพียง Betty Crocker เท่านั้นที่มีแอป iOS และ Android แต่ทั้ง 3 เว็บไซต์มีฐานโค้ดที่ใช้ร่วมกัน จึงติดตั้งใช้งานคอมโพเนนต์เพียงครั้งเดียวและนำไปใช้งานได้ทุกที่ ดังที่แสดงในภาพหน้าจอด้านล่าง

ปุ่มเปิด/ปิด Wake Lock ของ BettyCrocker.com
ปุ่มเปิด/ปิดการล็อกเมื่ออยู่ในโหมดสลีปของ BettyCrocker.com
ปุ่มเปิด/ปิด Wake Lock ของ Pillsbury.com
ปุ่มเปิด/ปิดการล็อกเมื่ออยู่ในโหมดสลีปของ Pillsbury.com
ปุ่มเปิด/ปิด Wake Lock ของ Tablespoon.com
ปุ่มเปิด/ปิดการทำงานขณะล็อกของ Tablespoon.com

เมื่อพัฒนาคอมโพเนนต์ตามเฟรมเวิร์กที่ปรับให้ทันสมัยของเว็บไซต์ใหม่ เราให้ความสำคัญกับ ViewModel เลเยอร์ของรูปแบบ MVVM เป็นอย่างมาก ทีมยังได้เขียนโปรแกรมโดยคำนึงถึงความเข้ากันได้เพื่อเปิดใช้ฟังก์ชันการทำงานในเฟรมเวิร์กเดิมและเฟรมเวิร์กใหม่ของเว็บไซต์

Betty Crocker ผสานรวมการติดตามข้อมูลวิเคราะห์สำหรับกิจกรรมหลักในวงจร Wake Lock ไว้เพื่อติดตามการมองเห็นโฆษณาและความสามารถในการใช้งาน ทีมใช้การจัดการฟีเจอร์เพื่อติดตั้งใช้งานคอมโพเนนต์การปลุกระบบในเว็บไซต์เดียวสำหรับการเปิดตัวเวอร์ชันที่ใช้งานจริงครั้งแรก จากนั้นจึงติดตั้งใช้งานฟีเจอร์ในเว็บไซต์ที่เหลือหลังจากตรวจสอบการใช้งานและประสิทธิภาพของหน้าเว็บ โดยจะยังคงตรวจสอบข้อมูลวิเคราะห์ตามการใช้งานคอมโพเนนต์นี้ต่อไป

ทีมได้สร้างการหมดเวลาที่บังคับเพื่อปิดใช้การปลุกหลังจากไม่มีการใช้งานเป็นเวลา 1 ชั่วโมง เพื่อเป็นการป้องกันข้อผิดพลาดที่อาจเกิดขึ้นกับผู้ใช้ การใช้งานขั้นสุดท้ายที่พวกเขาเลือกใช้ในระยะสั้นคือสวิตช์เปิด/ปิดในหน้าสูตรอาหารทุกหน้าในเว็บไซต์ ในระยะยาว ทีมมีวิสัยทัศน์ที่จะปรับปรุงการดูหน้าสูตรอาหาร

คอนเทนเนอร์ Wake Lock

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');
      }
    },
  },
};

คอมโพเนนต์ Wake Lock

<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 ใช้งานได้ในเว็บไซต์ทั้ง 3 แห่งแล้วและให้ผลลัพธ์ที่ยอดเยี่ยม ในช่วงวันที่ 10 ธันวาคม 2019 ถึง 10 มกราคม 2020 BettyCrocker.com รายงานเมตริกต่อไปนี้

  • จากผู้ใช้ Betty Crocker ทั้งหมดที่มีเบราว์เซอร์ที่เข้ากันได้กับ Wake Lock API มีผู้ใช้ 3.5% ที่เปิดใช้ฟีเจอร์นี้ทันที ซึ่งทำให้การดำเนินการนี้เป็นหนึ่งใน 5 อันดับแรก
  • ระยะเวลาเซสชันสำหรับผู้ใช้ที่เปิดใช้ Wake Lock ไว้นั้นนานกว่าของผู้ใช้ที่ไม่ได้เปิดใช้ 3.1 เท่า
  • อัตราตีกลับของผู้ใช้ที่เปิดใช้การปลุกอุปกรณ์ลดลง 50% เมื่อเทียบกับผู้ที่ไม่ได้ใช้ฟีเจอร์การปลุกอุปกรณ์
  • ตัวบ่งชี้ความตั้งใจในการซื้อสูงขึ้นประมาณ 300% สำหรับผู้ใช้ Wake Lock เมื่อเทียบกับผู้ใช้ทั้งหมด

3.1×

ระยะเวลาเซสชันนานขึ้น

50%

อัตราตีกลับลดลง

300%

ตัวบ่งชี้ความตั้งใจซื้อที่สูงขึ้น

สรุป

Betty Crocker พบผลลัพธ์ที่ยอดเยี่ยมเมื่อใช้ Wake Lock API คุณสามารถทดสอบฟีเจอร์นี้ด้วยตนเองโดยค้นหาสูตรอาหารที่คุณชื่นชอบในเว็บไซต์ของแบรนด์เหล่านี้ (BettyCrocker, Pillsbury หรือ Tablespoon) และเปิดใช้ปุ่มสลับป้องกันไม่ให้หน้าจอดับขณะที่คุณทำอาหาร

กรณีการใช้งานสำหรับล็อกการปลุกไม่ได้มีแค่เว็บไซต์สูตรอาหาร ตัวอย่างอื่นๆ ได้แก่ แอปตั๋วเครื่องบินหรือตั๋วที่ต้องเปิดหน้าจอไว้จนกว่าจะสแกนบาร์โค้ด แอปแบบคีออสก์ที่เปิดหน้าจอไว้อย่างต่อเนื่อง หรือแอปนำเสนอบนเว็บที่ป้องกันไม่ให้หน้าจอเข้าสู่โหมดสลีประหว่างการนำเสนอ

เราได้รวบรวมข้อมูลทั้งหมดที่คุณต้องทราบเกี่ยวกับ Wake Lock API ไว้ในบทความที่ครอบคลุมในเว็บไซต์นี้ ขอให้มีความสุขกับการอ่านและการทำอาหาร

ขอขอบคุณ

รูปภาพคนนวดแป้งได้รับความอนุเคราะห์จาก Julian Hochgesang ใน Unsplash