首页 > 其他分享 >分享3种常用的前端埋点方式

分享3种常用的前端埋点方式

时间:2024-02-01 17:23:57浏览次数:26  
标签:img 前端 sendBeacon 上报 埋点 分享 navigator 页面

在一个企业中,我们要如何去了解用户呢?
最直接有效的方式就是了解用户的行为,了解用户在网站中做了什么,呆了多久。
而如何去实现这一操作,这就涉及到我们前端的埋点了。

埋点方式

在聊如何进行埋点前,我们先介绍下什么是埋点?

所谓'埋点'是数据采集领域(尤其是用户行为数据采集领域)的术语,指的是针对特定用户行为或事件进行捕获、处理和发送的相关技术及其实施过程。. 比如用户某个icon点击次数、观看某个视频的时长等等。

我们可以知道埋点是实际上是对特定事件或者行为的数据监控和上报,常见的埋点上报方式有ajax,img,navigator.sendBeacon下面介绍下这三种埋点上报方式

 

基于ajax的埋点上报

 

介绍

因为埋点实际上是对关键节点的数据进行上报是和服务端交互的一个过程,所以我们可以和后端约定一个接口通过ajax去进行数据上报。

代码实现

我们可以封装一个方法,代码如下:

function buryingPointAjax(data) {
  return new Promise((resolve, reject) => {
    // 创建ajax请求
    const xhr = new XMLHttpRequest();
    // 定义请求接口
    xhr.open("post", '/buryingPoint', true);
    // 发送数据
    xhr.send(data);
  });
}

使用时,直接调用即可

let info = {}
buryingPointAjax(info) // 这样就成功上报了info的对象

缺点

一般而言,埋点域名并不是当前域名,因此请求会存在跨域风险,且如果ajax配置不正确可能会浏览器拦截。因此使用ajax这类请求并不是万全之策。

基于img的埋点上报

上面可以看到如果使用ajax的话,会存在跨域的问题。而且数据上报前端主要是负责将数据传递到后端,并不过分强调前后端交互。

因此我们可以通过一些支持跨域的标签去实现数据上报功能。

script,link,img就是我们上报的数据的最好对象

先说结论,这里推荐使用img标签去实现。

script及link的缺陷

因为埋点涉及到请求,因此我们需要保证script和link标签的src可以正常请求
如果需要请求script和link,我们需要将标签挂载到页面上。

验证缺陷

不妨验证下,我们在管理台中加入以下代码:

let a = document.createElement('script')
a.src = 'https://lf-headquarters-speed.yhgfb-cn-static.com/obj/rc-client-security/web/stable/1.0.0.28/bdms.js'

创建一个script标签,未挂载中页面上,并不会发起请求

书接上文,当我们将这个标签挂载中页面上时:

document.body.appendChild(a)

这时发起了请求

结论

当我们使用script和link进行埋点上报时,需要挂载到页面上,而反复操作dom会造成页面性能受影响,而且载入js/css资源还会阻塞页面渲染,影响用户体验,因此对于需要频繁上报的埋点而言,script和link并不合适。

基于img做埋点上报

通常使用img标签去做埋点上报,img标签加载并不需要挂载到页面上,基于js去new image(),设置其src之后就可以直接请求图片。

验证img优势

控制台去创建一个image标签,如下:

var img=new Image();
img.src="https://lf3-cdn-tos.bytescm.com/obj/static/xitu_juejin_web/img/MaskGroup.13dfc4f1.png";

可以看到即便未被挂载到页面上依旧发起了请求。

结论

因此当我们做埋点上报时,使用img是一个不错的选择。

  1. img兼容性好
  2. 无需挂载到页面上,反复操作dom
  3. img的加载不会阻塞html的解析,但img加载后并不渲染,它需要等待Render Tree生成完后才和Render Tree一起渲染出来

注:通常埋点上报会使用gif图,合法的 GIF 只需要 43 个字节

基于Navigator.sendBeacon的埋点上报

Navigator.sendBeacon是目前通用的埋点上报方案,Navigator.sendBeacon方法接受两个参数,第一个参数是目标服务器的 URL,第二个参数是所要发送的数据(可选),可以是任意类型(字符串、表单对象、二进制对象等等)。

介绍

navigator.sendBeacon() 方法可用于通过 HTTP POST[1] 将少量数据 异步[2] 传输到 Web 服务器。

作用

它主要用于将统计数据发送到 Web 服务器,同时避免了用传统技术(如:XMLHttpRequest[3])发送分析数据的一些问题。

补充

sendBeacon 如果成功进入浏览器的发送队列后,会返回true;如果受到队列总数、数据大小的限制后,会返回false。返回ture后,只是表示进入了发送队列,浏览器会尽力保证发送成功,但是否成功了,不会再有任何返回值。

例子

以掘金为例:

这里发了一个post请求,将小量的数据发到服务端,用于统计数据

优势

相较于img标签,使用navigator.sendBeacon会更规范,数据传输上可传输资源类型会更多。

对于ajax在页面卸载时上报,ajax有可能没上报完,页面就卸载了导致请求中断,因此ajax处理这种情况时必须作为同步操作.

sendBeacon是异步的,不会影响当前页到下一个页面的跳转速度,且不受同域限制。这个方法还是异步发出请求,但是请求与当前页面脱离关联,作为浏览器的任务,因此可以保证会把数据发出去,不拖延卸载流程。

总结

前端埋点上报常使用ajax,img,navigator.sendBeacon。

不推荐使用ajax。

如果考虑兼容性的话,img是不二之选。

目前最合适的方案是navigator.sendBeacon,不仅是异步的,而且不受同域限制,而且作为浏览器的任务,因此可以保证会把数据发出去,不影响页面卸载。

常见埋点行为

点击触发埋点

绑定点击事件,当点击目标元素时,触发埋点上报。

function clickButton(url, data) {
    navigator.sendBeacon(url, data)
}

页面停留时间上报埋点

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

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()
     }
 })

错误监听埋点

通过监听函数去接收错误信息。

vue错误捕获

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

JS异常与静态资源加载异常

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

请求错误捕获

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: '请求错误异常' })
  }
);

内容可见埋点

通过交叉观察器去监听当前元素是否出现在页面

// 可见性发生变化后的回调 
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);

标签:img,前端,sendBeacon,上报,埋点,分享,navigator,页面
From: https://www.cnblogs.com/houxianzhou/p/18001681

相关文章

  • 【分享贴】节前想要提前休假的项目经理,一定会做这几件事!
    还记得年初的时候我分享过一篇文章,主要是由于年前我没有提前做好规划,导致年后开工出现了以下这些问题:1) 部分项目成员年后突然离职,项目任务无人承接(资源管理问题);2) 紧急待完成项目任务的责任人,年后临时延长休假,项目任务无法按时完成(资源管理问题);3) 团队成员临时承担了其他更......
  • 【分享贴】节前想要提前休假的项目经理,一定会做这几件事!
    还记得年初的时候我分享过一篇文章,主要是由于年前我没有提前做好规划,导致年后开工出现了以下这些问题:1) 部分项目成员年后突然离职,项目任务无人承接(资源管理问题);2) 紧急待完成项目任务的责任人,年后临时延长休假,项目任务无法按时完成(资源管理问题);3) 团队成员临时承担了其他更重要......
  • 前端必学-40个精选案例实战-案例5-首页单屏案例实战
    经典背景图文列表案例分析与思路图文背景如何设定<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport......
  • AI生成前端组件的价值思考
    想法来源这个想法来源于我自己的需求,我自己首先就是最精准的目标用户,在这个AI时代,我希望AI可以帮我尽量多地干活。结合自己的日常独立开发情况,发现花在调前端组件样式上的时间很多,因此思考能不能让AI把这部分活接过去,或者能提高一些效率也行。适合用户外行或刚入门的前端开发......
  • 【专题】2023年新消费趋势行业报告汇总PDF合集分享(附原数据表)
    原文链接:https://tecdat.cn/?p=35100原文出处:拓端数据部落公众号2022年,全球面临疫情和经济放缓的挑战,给消费市场带来了不确定性。消费者的消费理念和生活方式也发生了变化,更加注重产品的实用性和简单性。居民收入增长放缓,消费支出减少。然而,随着疫情逐渐得到控制,中国消费市场正......
  • 【专题】2023年中国工业互联网平台行业研究报告PDF合集分享(附原数据表)
    原文链接:https://tecdat.cn/?p=33647原文出处:拓端数据部落公众号这份报告合集是基于中国工业产业升级和智能制造的大背景而展开的。报告合集分析了工业互联网平台市场的发展阶段、平台玩家的产品和服务的底层逻辑以及变化趋势,并探讨了补贴减少、数据归属权之争、标准化与盈利模......
  • 微信H5分享不能展示卡片问题
    来源与微信开放社区微信H5已成功接入,微信api以及配置项验证正常,通过手机微信里面链接打开页面进行分享,分享出去的还是链接,需要从以下场景进入才可以正常分享卡片从二维码进入分享卡片进入公众号图文消息进入公众号菜单进入公众号原文链接进入通过收藏链接,再打开分享也......
  • 虹科分享 | Redis与MySQL协同升级企业缓存
    传统的MySQL数据库在处理大规模应用时已经到了瓶颈,RedisEnterprise怎样助力突破这一瓶颈?RedisEnterprise与MYSQL共同用作企业级缓存或副本数据库,会产生什么样的火花?二者联合的解决方案,如何加速应用程序,提升效率,实现可拓展性?使用RedisEnterprise与MYSQL共同用作企业级缓存或副......
  • 保安员怎么搜题答案?3个受欢迎的搜题分享了
    大学生必备的搜题工具,专业课本习题、电子版教材、考研资料、英语四六级等考试题目也能一并搜索,每道题目都有详细的讲解,每个都堪称大学神器。1.灵兔搜题这是个微信公众号大学生免费搜题王者软件,题目超级全,可以拍照,语音,文字搜题。重点还是免费无广告的!下方附上一些测试的试题及答案1......
  • 解决前端JSZip读取压缩包内文件中文名称乱码问题
    1importJSZipfrom"jszip";23functionjszipFile(file){4if(!/\.zip$/i.test(file.name)){5reject(`文件"${file.name}"不是zip文件`);6return;7}89constfileReader=newFileReader();1011//转换文件为Arra......