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

使用行動裝置烹飪時,最糟的是,在食譜步驟中途關閉螢幕。瞭解烹飪網站 BettyCrocker.com 如何運用 Wake Lock API 避免這種情形。

近一個世紀,Betty Crocker 一直是美國的現代烹飪教學和食譜發展來源。自 1997 年推出以來,他們網站 BettyCrocker.com 目前每個月可獲得超過 1, 200 萬名訪客。他們導入 Wake Lock API 後,與所有使用者相比,Wake Lock 使用者的購買意圖指標高出約 300%

已淘汰的 iOS 和 Android 應用程式

Betty Crocker 在 2014 年發布超讚粉絲群後,最近才將這類應用程式從 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,您需要呼叫傳回 WakeLockSentinel 物件的 navigator.wakeLock.request() 方法。您將使用這個物件做為音符值。瀏覽器可能會基於各種原因拒絕要求 (例如因為電量過低),因此建議您將呼叫納入 try…catch 陳述式中。

釋出 Wake Lock

您也必須藉由呼叫 WakeLockSentinel 物件的 release() 方法,釋出 Wake Lock。如果您想在一段時間後自動釋放 Wake Lock,可以使用 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 Wake Lock 切換鈕。
Pillsbury.com Wake Lock 切換鈕
Pillsbury.com Wake Lock 切換鈕。
Tablespoon.com Wake Lock 切換鈕
Tablespoon.com Wake Lock 切換鈕。

根據新網站的現代化架構開發元件時,會著重在 MVVM 模式的 ViewModel。該團隊也在設計上考量互通性,以啟用網站的舊版和新架構功能。

為了追蹤可視度和可用性,Betty Crocker 針對 Wake Lock 生命週期中的核心事件整合了分析追蹤功能。該團隊利用功能管理功能,將 Wake Lock 元件部署至單一站點,進行初次推出作業,然後在監控使用情形和網頁健康狀態後,將該功能部署至其他網站。他們會繼續按照元件的使用情形監控數據分析資料。

為了安全起見,該團隊建立了強制逾時功能,以在閒置一小時後停用 Wake Lock。他們最後設定的實作方法,是將網站所有食譜頁面的短期切換鈕設為切換開關。 長期來看,他們預想到食譜頁面的瀏覽體驗截然不同。

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 回報了下列指標:

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

3.1×

工作階段持續時間較長

50%

跳出率較低

300%

購買意願指標增幅

結論

採用 Wake Lock API 後,Betty Crocker 看到了絕佳的成果。如要自行測試功能,您可以在網站的任何網站 (BettyCrockerPillsburyTablespoon) 搜尋喜愛的食譜,然後啟用「避免烹飪時螢幕變暗」切換鈕。

在食譜網站上,Wake Lock 的用途不會停止。其他例子包括登機證或票券應用程式 (在掃描條碼前需要讓螢幕保持開啟)、資訊站式應用程式 (會讓螢幕持續開啟螢幕),或網頁式簡報應用程式 (會在簡報期間避免螢幕休眠)。

我們將有關 Wake Lock API 的須知事項彙整在這個網站的詳盡文章中。祝閱讀愉快,烹飪愉快!

特別銘謝

人脈鍛鍊麵粉」相片由 Unsplash 提供的 Julian Hochgesang 提供。