Wake Lock API 案例研究:BettyCrocker.com 上的购买意愿指标增长了 300%

使用移动设备烹饪时,没有什么比屏幕关闭更糟糕的了 在配方步骤中完成此步骤。 了解烹饪网站 BettyCrocker.com 如何使用 Wake Lock API 来避免这种情况。

近一个世纪,贝蒂·克洛克 (Betty Crocker) 一直是美国现代烹饪教学的参考源 和可信配方开发。 他们的网站 BettyCrocker.com 成立于 1997 年, 目前每月的访问者数量超过 1200 万。 实现 Wake Lock API 后, 指标 购买意愿 与所有用户相比,使用唤醒锁定功能的用户的留存率高出约 300%

废弃的 iOS 和 Android 应用

于 2014 年广为流传, Betty Crocker 最近从 Apple App Store 和 Google Play 商店中下架了他们的应用 系统即会将其优先级降低 长期以来,Betty Crocker 团队更倾向于在移动网站中添加新功能 而不是 iOS/Android 应用 创建 iOS/Android 应用时使用的技术平台已过时, 并且该企业没有足够的资源 为以后更新和维护应用提供支持。 客观地说,Web 应用的流量也更大, 更现代、更易于增强。

不过,iOS/Android 应用的有一项杀手级功能深受用户喜爱:

千禧一代烹饪专业提示:@BettyCrocker 移动应用 不会调暗或锁定。 - @AvaBeilke

80% 的人在厨房里都会使用设备烹饪,但屏幕变暗和锁定是个问题。 @BettyCrocker 是怎么做的? 将应用更新为不调暗用户查看食谱。 - @KatieTweedy

借助 Wake Lock API 将这项杀手级功能带入网络世界

没有什么比用设备烹饪更令人沮丧的事情了 而不必在屏幕关闭时用凌乱的手触碰屏幕,甚至是鼻子。 Betty Crocker 问自己,如何移植其 iOS/Android 应用的杀手级功能 传送到 Web 应用。 就在这个时候 Project FuguWake Lock API

一个人在铺满面粉的厨房桌上按摩面团

Wake Lock API 提供了一种 调暗或锁定屏幕 此功能可以实现到目前为止要求使用 iOS/Android 应用的新体验。 Wake Lock API 减少了对黑客行为和可能非常耗电的解决方法的需求。

请求唤醒锁定

如需请求唤醒锁定,您需要调用 navigator.wakeLock.request() 方法 返回 WakeLockSentinel 对象的方法。您将使用此对象作为 sentinel 值。 浏览器可能会出于各种原因拒绝请求 (例如,由于电池电量过低), 因此最好将调用封装在 try…catch 语句中。

释放唤醒锁定

您还需要一种释放唤醒锁定的方法, 可通过调用 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);

实现

使用新的 Web 应用,应该让用户能够轻松浏览食谱, 甚至无需锁屏就能走开。 为了实现这一目标,该团队首先构建了一个快速前端原型 作为概念验证并收集用户体验意见。

在原型被证明有用后,他们设计了 Vue.js 组件BettyCrockerPillsburyTablespoon)。 尽管只有 Betty Crocker 有 iOS 和 Android 应用, 这三个网站确实具有共享的代码库 因此他们只需实施一次组件,然后就可以在任何地方部署 如以下屏幕截图所示

<ph type="x-smartling-placeholder">
</ph> BettyCrocker.com 唤醒锁定切换开关
BettyCrocker.com 唤醒锁定切换开关。
。 <ph type="x-smartling-placeholder">
</ph> Pillsbury.com 唤醒锁定切换开关
Pillsbury.com 唤醒锁定切换开关。
。 <ph type="x-smartling-placeholder">
</ph> Tablespoon.com 唤醒锁定切换开关
Tablespoon.com 唤醒锁定切换开关。

在根据新网站的现代化框架开发组件时, 过去 30 年中, MVVM 模式的 ViewModel。 该团队在编程时还考虑了互操作性 以启用网站的旧版和新框架上的功能。

为了跟踪可见度和易用性,Betty Crocker 集成了分析跟踪功能 唤醒锁定生命周期中的核心事件。 该团队利用功能管理部署了唤醒锁定组件 部署到单个网站以进行首次正式版发布 然后,在监控使用情况和网页运行状况后,将该功能部署到了其余网站上。 他们会继续根据该组件的使用情况来监控分析数据。

为了给用户提供故障安全保护,该团队设置了强制超时 可在无操作一小时后停用唤醒锁定。 他们决定采用的最终实现方案 。 从长远来看,他们还设想经过改进的食谱页面视图。

唤醒锁定容器

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 组件已全部部署到三个网站上,并且取得了非常好的效果。 在 2019 年 12 月 10 日到 2020 年 1 月 10 日这一时间段内 BettyCrocker.com 报告了以下指标:

  • 在使用与 Wake Lock API 兼容的浏览器的 Betty Crocker 用户中, 其中 3.5% 的用户立即启用了这项功能,这使其成为排在前 5 名的操作。
  • 启用了唤醒锁定的用户的会话时长为原来的 3.1 倍 相较于未这样做的用户
  • 启用了唤醒锁定的用户的跳出率降低了 50% 与未使用唤醒锁定功能的用户相比
  • 唤醒锁定用户的购买意愿指标比所有用户高约 300%。

3.1×

会话时长更长

50% 的用户

跳出率降幅

300%

购买意愿指标更高

总结

Betty Crocker 使用 Wake Lock API 取得了出色的成效。 您可以在任何网站上搜索您最喜爱的食谱,自行测试该功能 (BettyCrockerPillsburyTablespoon) 然后启用烹饪时防止屏幕变暗切换开关。

唤醒锁定的用例不会停止在食谱网站上。 其他示例包括需要让屏幕保持开启状态的登机牌或票务应用 让屏幕持续开启的自助服务终端式应用 或基于网络的演示文稿应用,以防止在演示期间屏幕进入休眠状态。

我们编译了您需要了解的有关 Wake Lock API 的所有信息 。 祝阅读愉快,祝你烹饪愉快!

致谢

一个人正在捏面团,照片由提供者提供 Julian Hochgesang (在 Unsplash 网站上)