衡量离线使用情况

如何跟踪网站的离线使用情况,以说明为何您的网站需要更好的离线体验。

史蒂芬·吉索
Stephan Giesau
马丁·希尔勒
Martin Schierle

本文介绍了如何跟踪网站的离线使用情况,从而说明您的网站为何需要更好的离线模式。还介绍了在实现离线使用情况分析时应避免的陷阱和问题。

有关在线和离线浏览器事件的问题

跟踪离线使用情况的显而易见的解决方案是为 onlineoffline 事件(许多浏览器支持)创建事件监听器,然后将 Google Analytics(分析)跟踪逻辑放置在这些监听器中。遗憾的是,这种方法存在一些问题和限制:

  • 一般来说,跟踪每个网络连接状态事件可能会过于复杂,并且在以隐私保护为中心的世界中,应尽可能少地收集数据。此外,在网络丢失的一瞬间,用户就可能触发 onlineoffline 事件,而用户可能不曾注意到或注意到此类事件。
  • 对离线活动的分析跟踪永远不会到达分析服务器,因为用户实际上处于离线状态。
  • 在用户恢复联网后,在本地跟踪用户离线时的时间戳并将离线活动发送到分析服务器则取决于用户是否重新访问您的网站。如果用户由于缺少离线模式而离开您的网站,并且从未再次访问,您将无法跟踪这种情况。跟踪线下流失率是构建相关案例的关键数据,有助于说明您的网站为什么需要更好的离线模式。
  • online 事件不太可靠,因为它只知道网络访问,而不知道互联网访问。因此,用户可能仍然处于离线状态,并且发送跟踪 ping 可能仍会失败。
  • 即使用户在离线时仍停留在当前页面,系统也不会跟踪其他任何分析事件(例如滚动事件、点击等),这可能是更相关、更有用的信息。
  • 总体而言,离线模式本身也没有太大意义。作为网站开发者,了解无法加载哪些类型的资源可能更为重要。这在 SPA 中尤为重要:因为网络连接中断可能不会导致浏览器进入离线错误页面(用户能够理解),但更有可能随机显示网页的动态部分失败,但无任何提示。

您仍然可以使用此解决方案对离线使用有基本的了解,但需要仔细考虑许多缺点和限制。

更好的方法:Service Worker

事实证明,启用离线模式的解决方案是跟踪离线使用情况的更好解决方案。其基本思路是,只要用户处于离线状态,系统就会将分析 ping 存储到 IndexedDB 中,并在用户再次联网时重新发送这些 ping。对于 Google Analytics(分析),该功能已通过 Workbox 模块开箱即用,但请注意,如果命中发送时间超过延迟 4 小时,则可能无法得到处理。最简单的形式是,您可以使用下面两行代码在基于 Workbox 的 Service Worker 中激活它:

import * as googleAnalytics from 'workbox-google-analytics';

googleAnalytics.initialize();

这会在离线状态下跟踪所有现有事件和网页浏览 ping,但是您不会知道它们是在离线状态下发生的(因为它们会按原样重放)。为此,您可以使用 Workbox 处理跟踪请求,方法是使用自定义维度(以下代码示例中的 cd1)向分析 ping 添加 offline 标志:

import * as googleAnalytics from 'workbox-google-analytics';

googleAnalytics.initialize({
  parameterOverrides: {
    cd1: 'offline',
  },
});

如果用户在互联网连接恢复之前因离线而离开页面,该怎么办?虽然这通常会使 Service Worker 进入休眠状态(因为在连接恢复时它无法发送数据),但 Workbox Google Analytics(分析)模块会使用 Background Sync API,该 API 会在连接恢复时发送分析数据,即使用户关闭标签页或浏览器也是如此。

但目前仍存在一个缺点:虽然这使得现有的跟踪变得能够离线使用,但在实现基本离线模式之前,您很可能不会看到大量相关数据。如果连接中断,用户仍会快速离开您的网站。但现在,您至少可以衡量和量化这一指标,方法是比较应用了离线维度的用户与常规用户的平均会话时长和用户互动时长。

SPA 和延迟加载

如果用户访问作为多页网站构建的网页离线并尝试导航,系统会显示浏览器的默认离线页面,以帮助用户了解正在发生的情况。但是,作为单页应用构建的页面的工作原理有所不同。用户停留在同一页面上,新内容则通过 AJAX 动态加载,无需任何浏览器导航。用户在离线时不会看到浏览器错误页面。相反,网页的动态部分会呈现错误、进入未定义的状态或不再是动态的。

由于延迟加载,在多页网站中也可能会出现类似的效果。例如,初始加载可能发生在网上,但用户在滚动之前就离线了。非首屏的所有延迟加载内容都将静默失败并缺失。

由于这类情况会让用户非常反感,因此有必要对此类情况进行跟踪。Service Worker 是捕获网络错误并最终使用分析来跟踪这些错误的绝佳选择。使用 Workbox,可以配置全局捕获处理程序,以通过发送消息事件来通知网页请求失败:

import { setCatchHandler } from 'workbox-routing';

setCatchHandler(({ event }) => {
  // https://developer.mozilla.org/docs/Web/API/Client/postMessage
  event.waitUntil(async function () {
    // Exit early if we don't have access to the client.
    // Eg, if it's cross-origin.
    if (!event.clientId) return;

    // Get the client.
    const client = await clients.get(event.clientId);
    // Exit early if we don't get the client.
    // Eg, if it closed.
    if (!client) return;

    // Send a message to the client.
    client.postMessage({
      action: "network_fail",
      url: event.request.url,
      destination: event.request.destination
    });

    return Response.error();

  }());
});

另一种方法是仅捕获特定路由上的错误,而不是监听所有失败的请求。例如,如果我们只想报告通向 /products/* 的路由发生的错误,可以在 setCatchHandler 中添加一项检查,以使用正则表达式过滤 URI。一个更简洁的解决方案是使用自定义处理程序实现 registerRoute。这会将业务逻辑封装到单独的路由中,从而在更复杂的 Service Worker 中具有更好的可维护性:

import { registerRoute } from 'workbox-routing';
import { NetworkOnly } from 'workbox-strategies';

const networkOnly = new NetworkOnly();
registerRoute(
  new RegExp('https:\/\/example\.com\/products\/.+'),
  async (params) => {
    try {
      // Attempt a network request.
      return await networkOnly.handle(params);
    } catch (error) {
      // If it fails, report the error.
      const event = params.event;
      if (!event.clientId) return;
      const client = await clients.get(event.clientId);
      if (!client) return;

      client.postMessage({
        action: "network_fail",
        url: event.request.url,
        destination: "products"
      });

      return Response.error();
    }
  }
);

最后,网页需要监听 message 事件并发出分析 ping。 同样,请确保缓冲在 Service Worker 中离线发送的分析请求。如前所述,初始化 workbox-google-analytics 插件以获取内置 Google Analytics(分析)支持。

以下示例使用的是 Google Analytics(分析),但同样适用于其他分析服务供应商。

if ("serviceWorker" in navigator) {
  // ... SW registration here

  // track offline error events
  navigator.serviceWorker.addEventListener("message", event => {
    if (gtag && event.data && event.data.action === "network_fail") {
      gtag("event", "network_fail", {
        event_category: event.data.destination,
        // event_label: event.data.url,
        // value: event.data.value
      });
    }
  });
}

这将在 Google Analytics(分析)中跟踪失败的资源加载,您可以使用报告对其进行分析。获得的数据分析通常可用于改进 Service Worker 缓存和错误处理,使网页在不稳定的网络条件下更加可靠和可靠。

后续步骤

本文介绍了跟踪离线使用情况的不同方法及其优缺点。 虽然这有助于量化有多少用户下线并因此而遇到问题,但这仅仅是一个开始。只要您的网站未提供精心构建的离线模式,您显然不会在数据分析中看到太多离线使用情况。

我们建议实施完整的跟踪,然后在通过迭代过程中关注跟踪数据来扩展离线功能。先从简单的离线错误页面着手(使用 Workbox 其实很简单),而且应将其视为与自定义 404 页面类似的用户体验最佳实践。然后采用更高级的离线回退方式,最终使用真正的离线内容。请务必妥当地向用户进行广告宣传并向用户说明这一点,您的使用量也会随之增加。毕竟,每个人都会时不时地处于离线状态。

请参阅如何报告指标并打造性能文化跨职能修正网站速度,了解如何说服跨职能利益相关方在您的网站上加大投入。虽然这些帖子侧重于性能,但它们应该可以帮助您获得有关如何与利益相关方互动的一般思路。

主打照片:JC GellidonUnsplash 用户。