前端监控系列——Navigator.sendBeacon上报数据🚀🚀🚀

一、前言

上一篇文章我们介绍了关于前端监控的相关内容,包括前端监控的分类,埋点上报的方式,以及采用图片(GIF)做埋点有哪些好处,想了解的小伙伴可以先看这里! 那么这篇文章的话,我们来认识下前端监控中埋点数据上报的另外一种方式 Navigator.sendBeacon !

二、基本介绍

Navigator.sendBeacon 是目前通用的埋点上报方案,可用于通过 HTTP POST 将少量数据 异步 传输到 Web 服务器。它主要用于将统计数据发送到 Web 服务器,同时避免了用传统技术(如:XMLHttpRequest)发送分析数据的一些问题。

基本语法如下:Navigator.sendBeacon方法接受两个参数,第一个参数是目标服务器的 URL,第二个参数是所要发送的数据(可选),可以是任意类型(字符串、表单对象、二进制对象等)

js 复制代码
navigator.sendBeacon(url);
navigator.sendBeacon(url, data);

当用户代理成功把数据加入传输队列时,sendBeacon() 方法将会返回 true,否则返回 false

相较于img标签,使用 navigator.sendBeacon 会更规范,数据传输上可传输资源类型会更多。sendBeacon 是异步的,不会影响当前页到下一个页面的跳转速度,且不受同域限制。这个方法还是异步发出请求,但是请求与当前页面脱离关联,作为浏览器的任务,因此可以保证会把数据发出去,不拖延卸载流程。

三、痛点分析

这个方法主要用于满足统计和诊断代码的需要,这些代码通常尝试在卸载(unload)文档之前向 web 服务器发送数据。过早的发送数据可能导致错过收集数据的机会。然而,对于开发者来说保证在文档卸载期间发送数据一直是一个困难,因为用户代理通常会忽略在 unload 事件处理器中产生的异步 XMLHttpRequest

为了解决这个问题, 统计和诊断代码通常要在 unload 或者 beforeunload 事件处理器中发起一个同步 XMLHttpRequest 来发送数据。同步的 XMLHttpRequest 迫使用户代理延迟卸载文档,并使得下一个导航出现的更晚,下一个页面对于这种较差的载入表现无能为力。

过去,为了解决这个问题,统计和诊断代码通常要在

  • 发起一个同步 XMLHttpRequest 来发送数据
  • 创建一个 <img> 元素并设置 src,大部分用户代理会延迟卸载(unload)文档以加载图像
  • 创建一个几秒的 no-op 循环

下面的例子展示了一个理论上的统计代码------在卸载事件处理器中尝试通过一个同步的 XMLHttpRequest 向服务器发送数据,导致了页面卸载被延迟。

js 复制代码
window.addEventListener('unload', logData, false);
 
function logData() {
    var client = new XMLHttpRequest();
    client.open("POST", "/log", false); // 第三个参数表明是同步的 xhr
    client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
    client.send(analyticsData);
}

这就是 sendBeacon() 方法存在的意义。使用 sendBeacon() 方法会使用户代理在有机会时异步地向服务器发送数据,同时不会延迟页面的卸载或影响下一导航的载入性能,这意味着:

  • 数据发送是可靠的
  • 数据异步传输
  • 不影响下一导航的载入

四、发送数据的时机

网站通常希望在用户完成页面浏览后向服务器发送分析或诊断数据,最可靠的方法是在 visibilitychange 事件发生时发送数据:

javascript 复制代码
document.addEventListener("visibilitychange", function logData() {
  if (document.visibilityState === "hidden") {
    navigator.sendBeacon("/log", analyticsData);
  }
});

我们应该避免使用 unload 和 beforeunload 事件,过去,许多网站使用 unload 事件以在会话结束时发送统计数据。然而这是不可靠的,在许多情况下(尤其是移动设备)浏览器不会产生 unloadbeforeunloadpagehide 事件。下面列出了一种不触发上述事件的情况:

  1. 用户加载了网页并与其交互
  2. 完成浏览后,用户切换到了其他应用程序,而不是关闭选项卡
  3. 随后,用户通过手机的应用管理器关闭了浏览器应用

此外,unload 事件与现代浏览器实现的往返缓存不兼容

五、常见的埋点行为

1. 点击触发埋点

scss 复制代码
function clickButton(url, data) {
    navigator.sendBeacon(url, data)
}

2. 页面停留上报

路由文件中,初始化一个startTime,当页面离开时通过路由守卫计算停留时间

ini 复制代码
let url = ''// 上报地址
let startTime = Date.now()
let currentTime = ''
router.beforeEach((to, from, next) => { 
     if (to) {
         currentTime = Date.now()
         stayTime = parseInt(currentTime - startTime)
         navigator.sendBeacon(url, {time: stayTime})
         startTime = Date.now()
     }
 })

3. 错误监听埋点

(1)Vue 错误捕获

lua 复制代码
app.config.errorHandler = (err) => { 
    navigator.sendBeacon(url, {error: error.message, text: 'vue运行异常' })
}

(2)JS异常与静态资源加载异常,error 可以监听所有同步、异步的运行时错误,但无法监听语法、接口、资源加载错误

vbnet 复制代码
window.addEventListener('error', (error) => { 
    if (error.message) { 
        navigator.sendBeacon(url, {error: error.message, text: 'js执行异常' })
    } else { 
        navigator.sendBeacon(url, {error: error.filename, text: '资源加载异常' })
    } 
}, true)

(3)unhandledrejection 可以监听到 Promise 中抛出的,未被 .catch 捕获的错误

javascript 复制代码
window.addEventListener('unhandledrejection')

(4)请求错误捕获

javascript 复制代码
axios.interceptors.response.use(
  (response) => {
    if (response.code == 200) {
      return Promise.resolve(response);
    } else {
      return Promise.reject(response);
    }
  },
  (error) => {
    // 返回错误逻辑
    navigator.sendBeacon(url, {error: error, text: '请求错误异常' })
  }
);

3. 内容可见埋点

javascript 复制代码
// 可见性发生变化后的回调 
function callback(data) { 
    navigator.sendBeacon(url, { target: data[0].target, text: '内容可见' }) 
} 
// 交叉观察器配置项 
let options = {}; 
// 生成交叉观察器 
const observer = new IntersectionObserver(callback); 
// 获取目标节点 
let target = document.getElementById("target"); 
// 监听目标元素 
observer.observe(target);
相关推荐
brief of gali4 分钟前
记录一个奇怪的前端布局现象
前端
前端拾光者43 分钟前
利用D3.js实现数据可视化的简单示例
开发语言·javascript·信息可视化
Json_181790144801 小时前
电商拍立淘按图搜索API接口系列,文档说明参考
前端·数据库
风尚云网1 小时前
风尚云网前端学习:一个简易前端新手友好的HTML5页面布局与样式设计
前端·css·学习·html·html5·风尚云网
木子02041 小时前
前端VUE项目启动方式
前端·javascript·vue.js
GISer_Jing1 小时前
React核心功能详解(一)
前端·react.js·前端框架
捂月2 小时前
Spring Boot 深度解析:快速构建高效、现代化的 Web 应用程序
前端·spring boot·后端
深度混淆2 小时前
实用功能,觊觎(Edge)浏览器的内置截(长)图功能
前端·edge
Smartdaili China2 小时前
如何在 Microsoft Edge 中设置代理: 快速而简单的方法
前端·爬虫·安全·microsoft·edge·社交·动态住宅代理
秦老师Q2 小时前
「Chromeg谷歌浏览器/Edge浏览器」篡改猴Tempermongkey插件的安装与使用
前端·chrome·edge