衡量实际网页指标的最佳做法

如何使用您当前的分析工具衡量网页指标。

能够衡量和报告网页的实际效果对于诊断和改进效果至关重要。如果没有实地数据,您就无法确定自己对网站所做的更改是否真的取得了预期成效。

许多热门的实时用户监控 (RUM) 分析服务提供商已经在其工具中支持核心网页指标(以及许多其他 Web Vitals)。如果您目前使用的是其中一种 RUM 分析工具,则可以很好地评估您网站上的网页在多大程度上符合建议的核心网页指标阈值,并防止日后出现回归问题。

虽然我们建议您使用支持 Core Web Vitals 指标的分析工具,但如果您目前使用的分析工具不支持这些指标,您不一定需要改用其他工具。几乎所有分析工具都提供了定义和衡量自定义指标事件的方法,这意味着您可能可以使用当前的分析服务提供商衡量 Core Web Vitals 指标,并将其添加到现有的分析报告和信息中心。

本指南介绍了使用第三方或内部分析工具衡量 Core Web Vitals 指标(或任何自定义指标)的最佳实践。它还可为希望为其服务添加 Core Web Vitals 支持的分析服务提供商提供指导。

使用自定义指标或事件

如上所述,大多数分析工具都支持衡量自定义数据。如果您的分析工具支持此功能,您应该能够使用此机制衡量每个 Core Web Vitals 指标。

在分析工具中衡量自定义指标或事件通常是一个三步流程:

  1. 在工具的管理界面中定义或注册自定义指标(如果需要)。(注意:并非所有分析服务提供商都要求您提前定义自定义指标。)
  2. 在前端 JavaScript 代码中计算指标的值。
  3. 将指标值发送到您的分析后端,确保名称或 ID 与第 1 步中定义的名称或 ID 一致(如果需要,请再次执行此操作)。

对于第 1 步和第 3 步,您可以参阅分析工具的文档,了解相关说明。对于第 2 步,您可以使用 web-vitals JavaScript 库计算每个核心网页指标的值。

以下代码示例展示了如何轻松地在代码中跟踪这些指标并将其发送到分析服务。

import {onCLS, onINP, onLCP} from 'web-vitals';

function sendToAnalytics({name, value, id}) {
  const body = JSON.stringify({name, value, id});
  // Use `navigator.sendBeacon()` if available, falling back to `fetch()`.
  (navigator.sendBeacon && navigator.sendBeacon('/analytics', body)) ||
      fetch('/analytics', {body, method: 'POST', keepalive: true});
}

onCLS(sendToAnalytics);
onINP(sendToAnalytics);
onLCP(sendToAnalytics);

避免使用平均值

我们很容易通过计算平均值来对效果指标的一系列值进行求和。平均值乍一看似乎很方便,因为它们是对大量数据的简洁总结,但您不应依赖平均值来解读网页性能。

平均值存在问题,因为它们并不能代表任何单个用户的会话。分布范围的任一端点的离群值都可能会以误导性的方式使平均值偏离。

例如,一小部分用户可能使用的是极其缓慢的网络或接近最大值范围的设备,但其用户会话数不足以对平均值产生影响,因此不会导致系统认为存在问题。

请尽可能使用百分位数,而不是平均值。针对给定效果指标的整个分布范围的百分位数可以更好地描述您的网站的所有用户体验。这样,您就可以专注于实际体验的子集,从而获得比单个值更深入的数据洞见。

确保您可以举报分发

计算每个核心网页指标的值并使用自定义指标或事件将其发送到您的分析服务后,下一步是构建一个报告或信息中心,以显示收集到的值。

为确保您达到推荐的核心网页指标阈值,您的报告需要显示每个指标的第 75 百分位的值。

如果您的分析工具未提供内置的百分位数报告,您或许仍可以通过生成一个按升序排列每个指标值的报告来手动获取此类数据。生成此报告后,该报告中所有值的完整排序列表中位于 75% 位置的结果将是该指标的第 75 个百分位数,无论您如何细分数据(按设备类型、连接类型、国家/地区等)都是如此。

如果您的分析工具默认不提供指标级报告粒度,那么如果您的分析工具支持自定义维度,您或许可以实现相同的结果。如果您为自己跟踪的每个指标实例设置唯一的自定义维度值,并在报告配置中添加该自定义维度,则应该能够生成按各个指标实例细分的报告。由于每个实例都具有唯一的维度值,因此不会进行分组。

网页指标报告就是使用 Google Analytics 的这种方法的一个示例。该报告的代码是开源的,因此开发者可以将其用作本部分中介绍的技术示例。

网页指标报告的屏幕截图

在适当的时间发送数据

有些性能指标可以在网页加载完毕后计算,而另一些指标(例如 CLS)则会考虑网页的整个生命周期,并且只有在网页开始卸载后才会最终确定。

不过,这可能会有问题,因为 beforeunloadunload 事件不可靠(尤其是在移动设备上),不建议使用它们(因为它们可能会导致网页不符合使用往返缓存的条件)。

对于跟踪网页整个生命周期的指标,最好在每次网页的公开范围状态更改为 hidden 时,在 visibilitychange 事件期间发送该指标的当前值。这是因为,网页的公开范围状态更改为 hidden 后,无法保证该网页上的任何脚本都能够再次运行。在移动操作系统上尤其如此,因为浏览器应用本身可能会关闭,而不会触发任何页面回调。

请注意,移动操作系统通常会在切换标签页、切换应用或关闭浏览器应用本身时触发 visibilitychange 事件。它们还会在关闭标签页或导航到新页面时触发 visibilitychange 事件。这使得 visibilitychange 事件比 unloadbeforeunload 事件可靠得多。

长期监控性能

更新分析实现以跟踪和报告 Core Web Vitals 指标后,下一步是跟踪网站更改对其性能在一段时间内的具体影响。

为更改添加版本号

一种简单(但最终不可靠)的更改跟踪方法是将更改部署到生产环境,然后假定在部署日期之后收到的所有指标对应于新网站,而在部署日期之前收到的所有指标对应于旧网站。不过,多种因素(包括 HTTP、Service Worker 或 CDN 层中的缓存)都可能会导致此方法无法正常运行。

更好的方法是为每个部署的更改创建一个唯一的版本,然后在分析工具中跟踪该版本。大多数分析工具都支持设置版本。如果您的版本不支持,您可以创建自定义维度,并将该维度设置为已部署的版本。

运行实验

您可以更进一步,同时跟踪多个版本(或实验)。

如果您的分析工具允许您定义实验组,请使用该功能。或者,您也可以使用自定义维度,确保每个指标值都可以与报告中的特定实验组相关联。

在 Google Analytics 中启用实验功能后,您可以面向部分用户发布实验性更改,并将该更改的效果与对照组用户的效果进行比较。当您确信某项更改确实可以提升效果后,就可以面向所有用户发布该更改。

确保衡量不会影响效果

在真实用户群中衡量性能时,所运行的任何性能衡量代码都不能对网页的性能产生负面影响,这一点至关重要。如果存在,那么您尝试就效果对业务的影响得出的任何结论都将不可靠,因为您永远无法知道是分析代码本身的存在造成了最大的负面影响,还是其他因素造成了最大的负面影响。

在生产网站上部署 RUM 分析代码时,请始终遵循以下原则:

延迟执行分析环节

Google Analytics 代码应始终以异步、非阻塞的方式加载,并且通常应最后加载。如果您以阻塞方式加载分析代码,可能会对 LCP 产生负面影响。

用于衡量核心 Web Vitals 指标的所有 API 均专为支持异步和延迟脚本加载(通过 buffered 标志)而设计,因此您无需急于提前加载脚本。

如果您要衡量在网页加载时间轴的后续时间段内无法计算的指标,则应将需要尽早运行的代码内嵌到文档的 <head> 中(以便其不是呈现阻塞请求),并推迟其余代码。不要仅仅因为某个指标需要,就提前加载所有分析数据。

不要创建长任务

分析代码通常会在响应用户输入时运行,但如果您的分析代码正在进行大量 DOM 测量或使用其他耗用大量处理器资源的 API,则分析代码本身可能会导致输入响应缓慢。此外,如果包含分析代码的 JavaScript 文件很大,执行该文件可能会阻塞主线程,并对网页的互动到下次绘制时间 (INP) 产生负面影响。

使用非阻塞 API

sendBeacon()requestIdleCallback() 等 API 专为以不会阻塞用户关键任务的方式运行非关键任务而设计。

这些 API 非常适合在 RUM 分析库中使用。

通常,所有分析信标都应使用 sendBeacon() API(如果可用)发送,所有被动分析衡量代码都应在空闲期间运行。

不要跟踪超出需要的内容

浏览器会公开大量性能数据,但数据可用并不一定意味着您应该记录这些数据并将其发送到分析服务器。

例如,Resource Timing API 可为网页上加载的每个资源提供详细的时间数据。不过,这些数据不太可能全部对提升资源加载性能有必要或有用。

简而言之,请勿仅仅因为数据存在而跟踪数据,请先确保数据将被使用,然后再消耗跟踪数据的资源。