首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【实战】1886- 教你怎么前端实现埋点上报

【实战】1886- 教你怎么前端实现埋点上报

作者头像
pingan8787
发布于 2023-12-06 09:13:02
发布于 2023-12-06 09:13:02
83300
代码可运行
举报
文章被收录于专栏:前端自习课前端自习课
运行总次数:0
代码可运行

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

埋点方式

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

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

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

基于ajax的埋点上报

介绍

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

代码实现

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
js复制代码function buryingPointAjax(data) {
  return new Promise((resolve, reject) => {
    // 创建ajax请求
    const xhr = new XMLHttpRequest();
    // 定义请求接口
    xhr.open("post", '/buryingPoint', true);
    // 发送数据
    xhr.send(data);
  });
}

使用时,直接调用即可

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
js复制代码let info = {}
buryingPointAjax(info) // 这样就成功上报了info的对象

缺点

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

基于img的埋点上报

上面可以看到如果使用ajax的话,会存在跨域的问题。而且数据上报前端主要是负责将数据传递到后端,并不过分强调前后端交互。因此我们可以通过一些支持跨域的标签去实现数据上报功能。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
script,link,img就是我们上报的数据的最好对象

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

script及link的缺陷

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

验证缺陷

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
js复制代码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标签,未挂载中页面上,并不会发起请求

image.png

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
js
复制代码document.body.appendChild(a)

这时发起了请求

image.png

结论

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

基于img做埋点上报

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

验证img优势

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
js复制代码var img=new Image();
img.src="https://lf3-cdn-tos.bytescm.com/obj/static/xitu_juejin_web/img/MaskGroup.13dfc4f1.png";

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

image.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 将少量数据 异步 传输到 Web 服务器。

作用

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

补充

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

例子

以掘金为例:

image.png

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

image.png

优势

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

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

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

注意

该方法在支付宝中可能会被拦截,如果发现支付宝数据上报异常,可以尝试排查这块。

总结

前端埋点上报常使用ajax,img,navigator.sendBeacon。不推荐使用ajax。如果考虑兼容性的话,img是不二之选。目前最合适的方案是navigator.sendBeacon,不仅是异步的,而且不受同域限制,而且作为浏览器的任务,因此可以保证会把数据发出去,不影响页面卸载。

常见埋点行为

点击触发埋点

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
js复制代码function clickButton(url, data) {
    navigator.sendBeacon(url, data)
}

页面停留时间上报埋点

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
js复制代码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错误捕获

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
js复制代码app.config.errorHandler = (err) => { 
    navigator.sendBeacon(url, {error: error.message, text: 'vue运行异常' })
}

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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)

请求错误捕获

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
js复制代码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: '请求错误异常' })
  }
);

内容可见埋点

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
js复制代码// 可见性发生变化后的回调 
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);

后续

开发的时候可以封装这三种上报方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
js复制代码// sendBeacon 上报
export async function sendBeacon( {url = '', params }: reportParams) {
    if (navigator?.sendBeacon && url) {
      const isSuccess = await navigator?.sendBeacon(url, JSON.stringify(params));
      if (isSuccess) return true;
    }
    return false;
}

// img 上报
export function sendImg({ img = '', params }: reportParams) {
    return new Promise<boolean>((resolve, reject) => {
        const imageData  = objectToQueryString(params)
        const img_o = new Image();
        img_o.onload = () => resolve(true);
        img_o.onerror = () => reject(false);
        img_o.src = `${img}?${imageData}`;
    })
}

// ajax 上报
export function sendAjax({ req = '', params }: reportParams) {
    return new Promise<boolean>((resolve, reject) => {
        if (req) {
            postAction(req, params)
                .then(() => resolve(true))
                .catch(() => reject(false));
        } else {
            reject(false);
        }
    });
}

使用的时候再导出一个真实上报函数,有由用户决定使用什么上报组合

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
js复制代码// 基础上报函数
export async function reportEvent(params: reportParams, reportType:string[] = [IMG, BEACON, AJAX]) {
    let finalType = false
    for (const key in reportType) {
        if (!finalType) {
            try {
                await EVENT_REPORT_FUNCTION_MAP[key](params).then(()=>{
                    finalType = true
                })
            } catch (error) {
                console.error(error)
            }
        }
    }
    return finalType
}

作者:闭目入神 链接:‍https://juejin.cn/post/7224132741997281338‍

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-12-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端自习课 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
前端埋点数据收集及上报方案
埋点,它的学名是事件追踪(Event Tracking),主要是针对特定用户行为或业务过程进行捕获、处理和发送的相关技术及实施过程。埋点是数据领域的一个专业术语,也是互联网领域的一个俗称。
落落落洛克
2021/10/12
7.1K0
前端埋点上报的几种方式
在现代Web应用程序中,埋点上报是一种重要的数据收集和分析手段。本文将介绍前端埋点上报的几种常见方式,并详细阐述如何在项目中运用这些方式进行数据上报,以帮助开发者更好地进行数据收集和分析。
can4hou6joeng4
2023/11/16
1.9K0
前端埋点方案
日常前端开发中,无论是性能监控,还是用户埋点,都会接触到埋点方案,以下为整理的几种方案:
剁椒鱼鳞
2023/06/05
1.8K0
前端埋点方案
腾讯二面:现在要你实现一个埋点监控SDK,你会怎么设计?
这是小伙伴上周被问到的一个综合性设计题,如果是没有用过埋点监控系统,或者没有深入了解,基本就凉凉。
用户9899350
2022/07/29
2.4K1
腾讯二面:现在要你实现一个埋点监控SDK,你会怎么设计?
一文搞懂得物前端监控
得物的服务端监控是比较全面和有效的,除了上报原始日志数据,还通过数据分析制定线上告警机制,调用链路分析,而针对前端项目这一块,还是不够全面的。对前端线上问题感应不及时,靠人肉发现,没有告警机制等问题,所以就有个前端监控这个项目。前端监控也确实很有必要,我们需要对线上的页面有个全面的把控,而至于怎么做监控,做数据上报,以及数据分析,如何针对监控数据分析出有用的核心链路的告警等也能有个全面的认识。本文主要是介绍得物针对监控做了哪些事情以及对前端底层监控手段做个总结。
得物技术
2023/12/13
8380
一文搞懂得物前端监控
数据埋点好帮手,这个Beacon API ,建议每位前端开发者了解下
Beacon API是HTML5提供的新型浏览器API,可以在不影响当前页面加载和性能的情况下,在浏览器后台异步发送数据。借助Beacon API,开发人员可以在页面卸载或关闭时向服务器发送数据,从而实现一些监控和日志记录功能。
前端达人
2023/08/31
8380
数据埋点好帮手,这个Beacon API ,建议每位前端开发者了解下
项目实战-埋点系统初探
最近杂七杂八的事情比较多,难得抽出时间来弥补一下之前的系列,欠大家的埋点系列现在开始走起来
Cookieboty
2020/10/23
2.3K0
项目实战-埋点系统初探
去大厂,你就应该了解前端监控和埋点!
踏足行业几年了,始终游离于中小型项目,由于项目用户较少,所以前端监控方面非常生疏,最近开始接收大流量项目,却对埋点,监控一无所知,深感惭愧,于是苦学几日,心得如下:
用户7413032
2020/06/11
3.9K0
去大厂,你就应该了解前端监控和埋点!
JavaScript 设计模式 —— 代理模式
Emm...最近绩效评估季,绩效总结、360 评估,要写的东西比较多嚯,耽搁了一段时间
前端LeBron
2022/11/21
5350
JavaScript 设计模式 —— 代理模式
让前端监控数据采集更高效
随着业务的快速发展,我们对生产环境下的问题感知能力越来越关注。作为距离用户最近的一层,前端的表现是否可靠、稳定、好用,很大程度上决定着用户对整个产品的体验和感受。因此,对于前端的监控不容忽视。
桃翁
2019/05/31
1.5K0
GA源代码里的小技巧之Beacon请求
GA监控脚本一般都放在开发者的网页上。域名往往和Google不一样,这样发送请求到Google服务器的时候会涉及到跨域。普通的Ajax请求是做不到的,通常称这种请求为beacon或是ping。业内常用的一个方案是发送一个图片请求(GET方式),将请求参数放在图片请求的地址后面。例如:
mmzhou
2018/08/01
1.4K0
自己动手打造前端性能监控系统
我们从三个各方面,前端上报,数据收集和入库,数据展示来介绍了如何打造一个测速系统。
QQ音乐前端团队
2018/08/28
3.8K8
自己动手打造前端性能监控系统
聊一聊H5营销页面的性能优化
我来自机票BU,目前负责机票营销的业务开发,众所周知营销业务的普遍特点是:访问量很大。每次营销活动,对于不同角色的同学,关注的点也不一样。
前端森林
2022/12/10
1.1K0
聊一聊H5营销页面的性能优化
【JS】1680- 重学 JavaScript API - Beacon API
Beacon API 是 HTML5 提供的一种新的浏览器 API,可以用于在浏览器后台异步地发送数据,而不影响当前页面的加载和性能。通过 Beacon API,开发者可以在「页面卸载或关闭时」,「将数据发送给服务器」,从而实现一些监控和日志等功能。
pingan8787
2023/09/01
4500
【JS】1680- 重学 JavaScript API - Beacon API
浅析前端监控技术
但是会发现根本没有收到消息,因为我们发的是异步的请求,请请求发出去之前当前页面的上下文环境已经被销毁了,因此什么也发不出去。
码之有理
2023/04/14
1K0
前端异常埋点系统初探
https://juejin.cn/post/6965022635470110733
@超人
2021/07/05
1.2K0
前端异常埋点系统初探
web前端监控的三个方面探讨
以 init 为程序的入口,代码中所有同步执行出现的错误都会被捕获,这种方式也可以很好的避免程序刚跑起来就挂。
smy
2018/08/01
1.2K0
web前端监控的三个方面探讨
前端错误捕获方案总结
本文主要摘抄自:https://juejin.cn/post/7172072612430872584#heading-10,主要用来记录和学习,也推荐大家看看原博主的文章。
蓓蕾心晴
2022/12/30
1.8K0
前端错误捕获方案总结
实现一套前端应用监控系统
我们通过浏览器的 performance API 获取性能数据, 其中要用到以下数据
木子星兮
2020/07/16
7860
前端监控 SDK 的一些技术要点原理分析
本文要讲的就是其中的第一个环节——数据采集与上报。下图是本文要讲述内容的大纲,大家可以先大致了解一下:
谭光志
2022/03/24
2.5K0
前端监控 SDK 的一些技术要点原理分析
相关推荐
前端埋点数据收集及上报方案
更多 >
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验