当前位置: 首页 > news >正文

前端埋点方式

前言:
想要了解用户在系统中所做的操作,从而得出用户在本系统中最常用的模块、在系统中停留的时间。对于了解用户的行为、分析用户的需求有很大的帮助,想实现这种需求可以通过前端埋点的方式。
埋点方式:
1.什么是埋点?
“埋点”是一种在应用程序或网站中插入代码的方式,用于收集用户行为或特定事件(点击事件、浏览时间、搜索事件等)的信息。它是用于分析和监控用户行为、应用性能和其他指标的一种方法。
2.埋点的目的
为了收集关键的数据和指标,以便帮助了解用户的行为、改进用户的体验、·优化应用性能、支持业务决策
3.埋点收集的数据类型
(1)用户行为类型:例如:页面浏览量、点击事件、表单提交、购买行为等
(2)应用性能数据:例如:页面加载时间、API调用延迟、错误日志等
(3)设备和环境数据:例如:用户设备类型、操作系统、浏览器版本等
(4)用户属性数据:例如:用户ID、地理位置、用户角色等
4.常见的埋点方式
(1)手动埋点:开发人员在代码中显示的插入埋点代码,通常使用Javascript或其他编程语言实现。(比较常用的方法)
(2)自动埋点:使用自动化工具或框架,自动收集 某些标准事件或用户行为数据
(3)可视化埋点:使用可视化工具,在页面上直接选择元素或交互,并配置要捕获的事件
5.常用埋点方法实例
(1)基于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请求并不是万全之策

(2)基于img的埋点上报
数据上报前端主要是负责将数据传递到后端,并不过分强调前后端交互,因此可以通过一些支持跨域的标签去实现数据上报功能。script、link、img就是我们上报的数据最好对象,推荐使用img标签去实现。如果需要请求script和link,我们需要将标签挂载到页面上,会反复操作dom造成页面性能受影响,而且载入js/css资源还会阻塞页面渲染,影响用户体验,所以选择使用script和link进行埋点的话要慎重考虑。而img标签并不需要挂载到页面上,基于js去new image(),设置src后就可以直接请求图片。

代码如下:

// 控制台创建一个image标签
var img = new image()
img.src="https://lf3-cdn-tos.bytescm.com/obj/static/xitu_juejin_web/img/MaskGroup.13dfc4f1.png"

可以看到即使未被挂载到页面上依旧发起了请求
在这里插入图片描述

// 创建script标签
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)

这个时候就可以看到发起请求了
在这里插入图片描述
(3)基于Navigator.sendBeacon的埋点上报
Navigator.sendBeacon是目前通用的埋点上报方案。Navigator.sendBeacon方法接受两个参数,第一个参数是目标服务器的URL,第二个参数是所要发送的数据(可选),可以是任意类型(字符串、表单对象、二进制对象等等)。
navigator.sendBeacon()方法可用于通过HTTP POST将少量数据异步传输到Web服务器。它主要用于将统计数据发送到Web服务器,同时避免了用传统技术(XMLHttpRequest)发送分析数据的一些问题。

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

例子:
在这里插入图片描述
发送了一个post请求,将小量的数据发送到服务端,用于统计数据
在这里插入图片描述
相较于img标签,使用navigator.sendBeacon会更规范,数据传输上可传输资源类型会更多。
对于ajax在页面卸载时上报,ajax有可能没上报完,页面就卸载了导致请求中断,因此ajax处理这种情况时必须作为同步操作。
sendBeacon是异步的,不会影响当前页到下一个页面的跳转速度,且不受同域限制。这个方法还是异步发出请求,但是请求和当前页面脱离关联,作为浏览器的任务,因此可以保证会把数据发出去,不拖延卸载流程。

结论
1.img兼容性好
2.无需挂载到页面上,反复操作DOM
3.img的加载不会阻塞html的解析,但img加载后并不渲染,它需要等待Render Tree生成完之后才和Render Tree一起渲染出来
4.通常埋点上报会使用gif图,合法的GIF只需要43字节
5.不推荐ajax
6.考虑兼容性的话,img是不二之选
7.最适合的方案是Navigator.sendBeacon

6.常见的埋点行为

点击触发埋点

// 绑定点击事假,当点击目标元素时,触发埋点上报
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: '资源加载异常'})}
})// 请求错误捕获
axios.interceptors.response.use((response) => {if(response.code === 200) {return Pormise.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)

其他更详细埋点内容可参考:https://mp.weixin.qq.com/s/lQos8C9y_6-ZT886k3aR9g

相关文章:

  • C++中浅复制及其存在的问题
  • Python 代码格式化工具YAPF 0.17.0问世
  • C++类和对象(七)const成员 及其初始化列表
  • Pytorch图像模型转ONNX后出现色偏问题
  • Visual Studio 2010 软件安装教程(附下载链接)——计算机二级专用编程软件
  • 虽然许多人表示对Windows 11的透明任务栏不满,但有时效果还是挺好的
  • uni-app小程序使用vant
  • 虚拟机VirtualBox添加磁盘
  • React——简便获取经纬度信息
  • 家庭私人影院 - Windows搭建Emby媒体库服务器并远程访问 「无公网IP」
  • 不必安装,快速设计数据库表结构
  • 【gpt redis】原理篇
  • 蓝桥杯官网填空题(含2天数)
  • Java程序设计2023-第三次上机练习
  • pytorch复现_conv2d
  • Apache Pulsar 2.1 重磅发布
  • CentOS 7 防火墙操作
  • CSS居中完全指南——构建CSS居中决策树
  • JavaScript对象详解
  • leetcode46 Permutation 排列组合
  • Linux中的硬链接与软链接
  • Spring核心 Bean的高级装配
  • 大数据与云计算学习:数据分析(二)
  • 京东美团研发面经
  • 使用docker-compose进行多节点部署
  • 微信小程序:实现悬浮返回和分享按钮
  • 用Canvas画一棵二叉树
  • gunicorn工作原理
  • HanLP分词命名实体提取详解
  • 整理一些计算机基础知识!
  • ​低代码平台的核心价值与优势
  • ​一些不规范的GTID使用场景
  • #微信小程序(布局、渲染层基础知识)
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • $refs 、$nextTic、动态组件、name的使用
  • (3)llvm ir转换过程
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练
  • (一)基于IDEA的JAVA基础12
  • (转)LINQ之路
  • (轉)JSON.stringify 语法实例讲解
  • *p++,*(p++),*++p,(*p)++区别?
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .NET Compact Framework 多线程环境下的UI异步刷新
  • .NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式
  • .net refrector
  • .NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中(Constrained Execution Regions)
  • .NET开发人员必知的八个网站
  • /使用匿名内部类来复写Handler当中的handlerMessage()方法
  • @configuration注解_2w字长文给你讲透了配置类为什么要添加 @Configuration注解
  • @synthesize和@dynamic分别有什么作用?
  • [ 常用工具篇 ] AntSword 蚁剑安装及使用详解
  • [100天算法】-不同路径 III(day 73)