使用 Web Beacon API 记录活动

已发表: 2022-03-10
快速总结 ↬ Beacon API 是一种轻量级且高效的方式,可将信息从网页记录回服务器。 了解如何使用它以及它与传统 Ajax 技术的不同之处。

Beacon API 是一种基于 JavaScript 的 Web API,用于将少量数据从浏览器发送到 Web 服务器,而无需等待响应。 在本文中,我们将看看它有什么用处,它与XMLHTTPRequest ('Ajax') 等熟悉的技术有何不同,以及如何开始使用它。

如果您已经知道为什么要使用 Beacon,请随时直接跳到入门部分。

信标 API 有什么用?

Beacon API 用于在不等待响应的情况下向服务器发送少量数据。 最后一部分很关键,也是 Beacon 如此有用的关键——我们的代码甚至无法看到响应,即使服务器发送了响应。 信标专门用于发送数据然后忘记它。 我们不期望得到回应,也没有得到回应。

把它想象成度假时寄回家的明信片。 你在上面放了少量的数据(有点“希望你在这里”和“天气真好”),把它放在邮箱里,你不期望得到回应。 没有人寄回明信片说“是的,我真希望我真的在那里,非常感谢!”

对于现代网站和应用程序,有许多用例非常巧妙地属于这种发送后忘记的模式。

跳跃后更多! 继续往下看↓

跟踪统计和分析数据

大多数人想到的第一个用例是分析。 像谷歌分析这样的大型解决方案可能会很好地概述页面访问等内容,但如果我们想要更多定制的东西怎么办? 我们可以编写一些 JavaScript 来跟踪页面中发生的事情(可能是用户如何与组件交互,他们滚动到多远,或者在他们遵循 CTA 之前已经显示了哪些文章)但是我们需要发送该数据当用户离开页面时发送给服务器。 Beacon 非常适合这一点,因为我们只是记录数据而不需要响应。

我们没有理由不能涵盖 Google Analytics 经常处理的那种日常任务,报告用户本身以及他们的设备和浏览器的功能。 如果用户有登录会话,您甚至可以将这些统计信息与已知个人联系起来。 无论您收集什么数据,您都可以使用 Beacon 将其发送回服务器。

调试和记录

此行为的另一个有用应用程序是记录来自您的 JavaScript 代码的信息。 想象一下,您的页面上有一个复杂的交互式组件,它完美地适用于您的所有测试,但偶尔会在生产中失败。 您知道它失败了,但是您看不到错误以开始调试它。 如果您可以检测到代码本身的故障,则可以收集诊断信息并使用 Beacon 将其全部发回以进行日志记录。

事实上,任何日志记录任务都可以使用 Beacon 有效地执行,例如在游戏中创建保存点、收集有关功能使用的信息或记录多变量测试的结果。 如果这是您希望服务器知道的浏览器中发生的事情,那么 Beacon 很可能是一个竞争者。

我们不能这样做吗?

我知道你在想什么。 这些都不是新的,是吗? 十多年来,我们一直能够使用XMLHTTPRequest从浏览器与服务器进行通信。 最近,我们还有 Fetch API,它使用更现代的基于 Promise 的接口做很多相同的事情。 鉴于此,我们为什么需要 Beacon API?

这里的关键是,因为我们没有得到响应,浏览器可以将请求排队并发送,而不会阻塞任何其他代码的执行。 就浏览器而言,我们的代码是否仍在运行,或者脚本执行到哪里都没有关系,因为没有什么可以返回,它可以只是后台发送 HTTP 请求,直到方便发送。

这可能意味着等到 CPU 负载降低,或者网络空闲,或者如果可以的话,甚至直接发送它。 重要的是浏览器将信标排队并立即返回控制权。 信标发送时它不会阻止任何事情。

要理解为什么这很重要,我们需要看看这些请求是如何以及何时从我们的代码发出的。 以我们的分析日志记录脚本为例。 我们的代码可能会计时用户在页面上花费的时间,因此在可能的最后时刻将数据发送回服务器变得至关重要。 当用户离开页面时,我们希望停止计时并将数据发送回主页。

通常,您会使用unloadbeforeunload事件来执行日志记录。 当用户执行诸如跟随页面上的链接导航离开之类的操作时会触发这些。 这里的问题是在unload事件之一上运行的代码可能会阻塞执行并延迟页面的卸载。 如果页面的卸载延迟,那么加载下一页也会延迟,因此体验感觉非常缓慢。

请记住 HTTP 请求的速度有多慢。 如果您正在考虑性能,通常您尝试减少的主要因素之一是额外的 HTTP 请求,因为进入网络并获得响应可能非常慢。 您要做的最后一件事就是在链接的激活和下一页请求的开始之间放慢速度。

Beacon 通过在不阻塞的情况下对请求进行排队,立即将控制权返回给您的脚本来解决这个问题。 然后浏览器负责在后台发送该请求而不会阻塞。 这让一切变得更快,让用户更快乐,让我们都保住工作。

入门

所以我们了解了 Beacon 是什么,以及我们为什么会使用它,所以让我们开始编写一些代码。 基础再简单不过了:

 let result = navigator.sendBeacon(url, data);

结果是布尔值, true浏览器接受并排队请求,则返回false ,如果这样做有问题,则返回 false。

使用navigator.sendBeacon()

navigator.sendBeacon有两个参数。 第一个是发出请求的 URL。 该请求作为 HTTP POST 执行,发送第二个参数中提供的任何数据。

数据参数可以是多种格式之一,如果这些格式都直接取自 Fetch API。 这可以是BlobBufferSourceFormDataURLSearchParams — 基本上是使用 Fetch 发出请求时使用的任何主体类型。

我喜欢将FormData用于基本键值数据,因为它简单且易于回读。

 // URL to send the data to let url = '/api/my-endpoint'; // Create a new FormData and add a key/value pair let data = new FormData(); data.append('hello', 'world'); let result = navigator.sendBeacon(url, data); if (result) { console.log('Successfully queued!'); } else { console.log('Failure.'); }

浏览器支持

浏览器对 Beacon 的支持非常好,唯一值得注意的例外是 Internet Explorer(在 Edge 中工作)和 Opera Mini。 对于大多数用途来说,这应该没问题,但在尝试使用navigator.sendBeacon之前值得测试支持。

这很容易做到:

 if (navigator.sendBeacon) { // Beacon code } else { // No Beacon. Maybe fall back to XHR? }

如果 Beacon 不可用并且您的请求很重要,您可以回退到 XHR 等阻塞方法。 根据您的受众和目的,您可能同样选择不打扰。

示例:在页面上记录时间

为了在实践中看到这一点,让我们创建一个基本系统来计算用户在页面上停留的时间。 当页面加载时,我们会记录时间,当用户离开页面时,我们会将开始时间和当前时间发送到服务器。

由于我们只关心花费的时间(而不是一天中的实际时间),我们可以使用performance.now()来获取页面加载时的基本时间戳:

 let startTime = performance.now();

如果我们将日志记录封装到一个函数中,我们可以在页面卸载时调用它。

 let logVisit = function() { // Test that we have support if (!navigator.sendBeacon) return true; // URL to send the data to, eg let url = '/api/log-visit'; // Data to send let data = new FormData(); data.append('start', startTime); data.append('end', performance.now()); data.append('url', document.URL); // Let's go! navigator.sendBeacon(url, data); };

最后,我们需要在用户离开页面时调用这个函数。 我的第一反应是使用unload事件,但 Mac 上的 Safari 似乎用安全警告阻止了请求,所以beforeunload在这里对我们来说工作得很好。

 window.addEventListener('beforeunload', logVisit);

当页面卸载(或在卸载之前)我们的logVisit()函数将被调用,并且如果浏览器支持 Beacon API,我们的信标将被发送。

(请注意,如果没有 Beacon 支持,我们返回true并假装一切正常。返回false将取消事件并停止页面卸载。那将是不幸的。)

跟踪时的注意事项

由于 Beacon 的许多潜在用途都围绕着活动跟踪,我认为在记录和跟踪可能与用户相关的活动时,我们作为开发人员所承担的社会和法律责任就更不用说了。

GDPR

我们可能会认为最近的欧洲 GDPR 法律与电子邮件有关,但当然,该立法与存储任何类型的个人数据有关。 如果您知道您的用户是谁并且可以识别他们的会话,那么您应该检查您正在记录的活动以及它与您声明的政策的关系。

通常,我们不需要像开发人员告诉我们应该跟踪的那样多的数据。 最好故意存储会识别用户的信息,然后减少出错的可能性。

DNT:不跟踪

除了法律要求外,大多数浏览器都有一个设置,使用户能够表达不被跟踪的愿望。 Do Not Track 会发送一个 HTTP 标头,其中包含如下所示的请求:

 DNT: 1

如果您正在记录可以跟踪特定用户的数据并且用户发送了一个肯定的DNT标头,那么最好遵循用户的意愿并将该数据匿名或根本不跟踪它。

例如,在 PHP 中,您可以非常轻松地测试此标头,如下所示:

 if (!empty($_SERVER['HTTP_DNT'])) { // User does not wish to be tracked ... }

综上所述

Beacon API 是一种将数据从页面发送回服务器的非常有用的方法,尤其是在日志上下文中。 浏览器支持非常广泛,它使您能够无缝地记录数据,而不会对用户的浏览体验和您网站的性能产生负面影响。 请求的非阻塞性质意味着性能比 XHR 和 Fetch 等替代方案快得多。

如果您想了解有关 Beacon API 的更多信息,以下站点值得一看。

  • “W3C 信标规范”,W3C 候选推荐
  • “MDN 信标文档”,MDN 网络文档,Mozilla
  • “浏览器支持信息”,caniuse.com