Wake Lock API 個案研究:BettyCrocker.com 上的購買意願指標提升了 300%

使用行動裝置做菜時,沒有什麼事比在食譜步驟中途關閉螢幕是最壞的事。瞭解烹飪網站 BettyCrocker.com 如何使用 Wake Lock API 避免發生這種情況。

近一個世紀以來,Betty Crocker 一直是美國現代烹飪教學和可靠食譜開發的來源。該公司在 1997 年推出的網站 BettyCrocker.com,目前每月吸引超過 1, 200 萬名訪客造訪。實作 Wake Lock API 後,與所有使用者相比,喚醒鎖定使用者的購買意圖指標提升了約 300%

於 2014 年推出超級粉絲群,Betty Crocker 最近將應用程式降低排名,因此最近將應用程式從 Apple App Store 和 Google Play 商店下架。長期以來,Betty Crocker 團隊都偏好在行動網站中加入新功能,而不是在 iOS/Android 應用程式中加入。用來建立 iOS/Android 應用程式的技術平台已過時,企業沒有資源支援更新及維護日後的應用程式。從流量角度來看,網頁應用程式也更有優勢,因為它更現代化,也更容易強化。

不過 iOS/Android 應用程式提供一項使用者喜愛的終止功能

千禧世代烹飪專家提示:@BettyCrocker 行動應用程式在你按照食譜操作時,不會調低亮度或鎖定。—@AvaBeilke

80% 的使用者會在廚房中使用裝置烹飪,但螢幕調暗和鎖定功能仍有問題。@BettyCrocker 執行了什麼動作? 在使用者閱讀食譜時,將應用程式更新為「不要」調暗。—@KatieTweedy

使用 Wake Lock API 為網路帶來強大功能

使用裝置烹飪時,最令人沮喪的莫過於在螢幕關閉時,必須用髒手或鼻子觸碰螢幕。Betty Crocker 想知道如何將 iOS/Android 應用程式的重點功能移植到網路應用程式。這時,她瞭解了 Project FuguWake Lock API

有人在廚房的桌上揉麵團,桌上有麵粉

Wake Lock API 提供一種方法,可防止裝置調低亮度或鎖定螢幕。這項功能可提供新體驗,但目前便需使用 iOS/Android 應用程式。 Wake Lock API 可減少重獲駭客攻擊的機會,也不用擔心可能會用到電動問題。

要求 Wake Lock

如要要求 Wake Lock,您必須呼叫 navigator.wakeLock.request() 方法,以傳回 WakeLockSentinel 物件。您會將這個物件用做哨值值。瀏覽器可能會基於各種原因 (例如電池電量過低) 拒絕要求,因此建議您在 try…catch 陳述式中包裝呼叫。

釋放 Wake Lock

您還需要一種釋放喚醒鎖定的方法,方法是呼叫 WakeLockSentinel 物件的 release() 方法。如果您想在一段時間過後自動釋放喚醒鎖定,可以使用 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 元件,可供所有品牌 (BettyCrockerPillsburyTablespoon) 共用。雖然只有 Betty Crocker 有 iOS 和 Android 應用程式,但這三個網站確實有共用的程式碼集,因此可以實作一次元件,然後在所有地方部署,如以下螢幕截圖所示。

BettyCrocker.com Wake Lock 切換鈕
BettyCrocker.com 喚醒鎖定切換鈕。
Pillsbury.com Wake Lock 切換鈕
Pillsbury.com 喚醒鎖定切換鈕。
Tablespoon.com Wake Lock 切換鈕
Tablespoon.com Wake Lock 切換鈕。

在根據新網站的現代化架構開發元件時,我們特別著重於 MVVM 模式的 ViewModel。這個團隊也規劃了互通性,為網站的舊版和新架構啟用功能。

為了追蹤可視度和可用性,Betty Crocker 整合了喚醒鎖定生命週期中核心事件的數據分析追蹤功能。團隊利用功能管理功能,將喚醒鎖定元件部署到單一網站,以便進行初始正式版推出作業,然後在監控使用情形和網頁健康狀況後,將該功能部署到其他網站。並根據這個元件的使用情形,持續監控數據分析資料。

為確保使用者安全,團隊建立了強制逾時機制,在閒置一小時後停用喚醒鎖定機制。他們最終決定在短期內,在網站上的所有食譜頁面中加入切換鈕。長期來看,他們希望能看到修改食譜的頁面檢視。

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 元件已部署在全部三個網站上,並帶來出色的結果。 在 2019 年 12 月 10 日至 2020 年 1 月 10 日期間,BettyCrocker.com 回報了以下指標:

  • 在 Betty Crocker 使用者中,有 3.5% 使用者使用與 Wake Lock API 相容的瀏覽器,並立即啟用這項功能,因此這項功能成為前 5 大操作。
  • 啟用喚醒鎖定功能的使用者的工作階段時間比未啟用的使用者長 3.1 倍。
  • 相較於未使用 Wake Lock 功能的使用者,啟用 Wake Lock 的跳出率降低了 50%。
  • 與所有使用者相比,喚醒鎖定使用者的購買意願指標高出約 300%。

3.1 倍

工作階段持續時間更長

50%

跳出率降低

300%

購買意願升幅指標

結論

Betty Crocker 使用 Wake Lock API 獲得了出色的成果。你可以在任何網站 (BettyCrockerPillsburyTablespoon) 搜尋喜愛的食譜,然後啟用「烹飪時避免螢幕變暗」切換鈕,自行測試這項功能。

食譜網站不會停止 Wake Lock 的用途。其他例子包括登機證或票證應用程式,需要在掃描條碼前保持螢幕開啟;自助式應用程式,需要持續保持螢幕開啟;或以網頁為主的簡報應用程式,需要在簡報期間防止螢幕進入休眠狀態。

我們彙整了 Wake Lock API 的所有必知文章,歡迎參閱這個網站提供的完整文章。祝你閱讀愉快,烹飪愉快!

特別銘謝

人物揉麵相片Julian Hochgesang 提供,取自 Unsplash