前端埋点全解及埋点SDK实现方式

2024-03-27 18:28

本文主要是介绍前端埋点全解及埋点SDK实现方式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、什么是埋点

        所谓“埋点”,是数据采集领域(尤其是用户行为数据采集领域)的术语,指的是针对特定用户行为或事件进行捕获、处理和发送的相关技术及其实施过程。比如用户某个icon点击次数、观看某个视频的时长等等。
        埋点的技术实质,是先监听软件应用运行过程中的事件,当需要关注的事件发生时进行判断和捕获。埋点需要在特定的时机来收集数据,然后上报给服务端进行分析

二、为什么需要埋点

        数据生产-》数据采集-》数据处理-》数据分析挖掘-》数据驱动/用户反馈-》产品优化/迭代
上述是整个数据从产生到最终作用于产品优化上的过程。埋点是整个流程的开始点,终端提供商在收集到埋点数据之后,通过大数据处理、数据统计、数据分析、数据挖掘等加工处理,可以得到衡量产品状态的一些基本指标,比如活跃、留存、新增等大盘数据,从而洞察产品的状态,随着数据挖掘等技术的兴起,埋点采集到的数据在以下方面的作用也越来越凸显。

三、如何去埋点

一般情况下,主要有3类埋点:展现埋点 + 曝光埋点 + 交互埋点。
1、展现埋点
定义展现其实是一个服务端的触发。服务端被触发后,用户侧将会展现什么内容,展现埋点需要记录的是页面展现的内容信息,即服务端下发的内容是什么(这些东西一定是当前页面主要内容,不包含一些交互信息)。
2、曝光埋点
哪些下发的内容被用户实际看到了。和展现埋点类似,由于屏幕有限,但内容可以无限。哪些内容被用户侧实际看到(曝光),需要记录的是单个“内容”被看到。一系列被下发的内容,可以触发多次曝光埋点。
3、交互埋点
交互埋点表明的是功能/内容被用户“点击”了。从埋点时机来说,这个是展现 & 曝光的下游。记录对于我们提供的“服务”的“消费”情况。比如,一个页面,用户可以点击,那么我们需要记录相应的交互动作埋点;比如,一个视频可以点赞,我们也可以记录交互埋点;比如,一个视频可以播放暂停,我们也可以记录消费埋点。总体来说,就是,我们要记录 被看到的可交互功能/信息的“消费”数据。

四、埋点记录

关于埋点记录需要明确记录两个信息:点位信息、点位映射。
点位信息:明确每个业务事件下的具体的参数信息,包含公共参数、业务参数。
点位映射:每个埋点对应的业务含义。

五、前端监控

        一般来讲一个成熟的产品,运营与产品团队需要关注用户在产品内的行为记录,通过用户的行为记录来优化产品,研发与测试团队则需要关注产品的性能以及异常,确保产品的性能体验以及安全迭代。

前端监控一般也分为三大类:

5.1 数据监控(监控用户行为)


●PV/UV: PV(page view):即页面浏览量或点击量;UV:指访问某个站点或点击某条新闻的不同 IP 地址的人数
●用户在每一个页面的停留时间
●用户通过什么入口来访问该网页
●用户在相应的页面中触发的行为,等...
统计这些数据是有意义的,比如我们知道了用户来源的渠道,可以促进产品的推广,知道用户在每一个页面停留的时间,可以针对停留较长的页面,增加广告推送等等。

5.2 性能监控(监控页面性能)


●不同用户,不同机型和不同系统下的首屏加载时间
●白屏时间
●http 等请求的响应时间
●静态资源整体下载时间
●页面渲染时间
●页面交互动画完成时间,等...
这些性能监控的结果,可以展示前端性能的好坏,根据性能监测的结果可以进一步的去优化前端性能,尽可能的提高用户体验。

5.3 异常监控(监控产品、系统异常)

及时的上报异常情况,可以避免线上故障的发上。虽然大部分异常可以通过 try catch 的方式捕获,但是比如内存泄漏以及其他偶现的异常难以捕获。常见的需要监控的异常包括:
●Javascript 的异常监控
●样式丢失的异常监控

六、埋点上报

实现前端监控,第一步肯定是将我们要监控的事项(数据)给收集起来,再提交给后台进行入库,最后再给数据分析组进行数据分析,最后处理好的数据再同步给运营或者是产品。数据收集的丰富性和准确性会直接影响到我们做前端监控的质量,因为我们会以此为基础,为产品的未来发展指引方向。
现在常见的埋点上报方法有三种:手动埋点、可视化埋点、无埋点


6.1 手动埋点


手动埋点,也叫代码埋点,即纯手动写代码,调用埋点 SDK 的函数,在需要埋点的业务逻辑功能位置调用接口,上报埋点数据,像**[友盟][百度统计]**等第三方数据统计服务商大都采用这种方案。手动埋点让使用者可以方便地设置自定义属性、自定义事件;所以当你需要深入下钻,并精细化自定义分析时,比较适合使用手动埋点。
手动埋点的缺陷就是,项目工程量大,需要埋点的位置太多,而且需要产品开发运营之间相互反复沟通,容易出现手动差错,如果错误,重新埋点的成本也很高。


6.2 可视化埋点


通过可视化交互的手段,代替上述的代码埋点。将业务代码和埋点代码分离,提供一个可视化交互的页面,输入为业务代码,通过这个可视化系统,可以在业务代码中自定义的增加埋点事件等等,最后输出的代码耦合了业务代码和埋点代码。
可视化埋点的缺陷就是可以埋点的控件有限,不能手动定制。


6.3 无埋点


无埋点则是前端自动采集全部事件,上报埋点数据,由后端来过滤和计算出有用的数据。优点是前端只要一次加载埋点脚本,缺点是流量和采集的数据过于庞大,服务器性能压力山大。
佳佳
HTML
COBUB
PHP
无码埋点

七、SDK实现

数据收集以及数据上报的方式都有了,那么就可以开始实现SDK了,这里先以单文件(非工程化)进行实现

7.1 非工程化

// JS 完整代码部分
(function (e) {function wrap(event) {const fun = history[event];return function () {const res = fun.apply(this, arguments);const e = new Event(event);window.dispatchEvent(e);return res;};}class TrackingDemo {constructor(options = {}) {// 重写 pushState、replaceStatewindow.history.pushState = wrap("pushState");window.history.replaceState = wrap("replaceState");// 上报地址this.reportUrl = options.reportUrl || "";this.sdkVersion = "1.0.0";this._eventList = ["click", "dblclick", "mouseout", "mouseover"];this._dulation = {startTime: 0,value: 0,};this._initJSError();// 初始化事件数据收集this._initEventHandler();// 初始化PV统计this._initPV();this._initPageDulation();}setUserId(uid) {this.uid = uid;}_initEventHandler() {this._eventList.forEach((event) => {window.addEventListener(event, (e) => {const target = e.target;const reportKey = target.getAttribute("report-key");if (reportKey) {this._report("event", {tagName: e.target.nodeName,tagText: e.target.innerText,event,});}});});}_initPV() {window.addEventListener("pushState", (e) => {this._report("pv", {type: "pushState",referrer: document.referrer,});});window.addEventListener("replaceState", (e) => {this._report("pv", {type: "replaceState",referrer: document.referrer,});});window.addEventListener("hashchange", () => {this._report("pv", {type: "hashchange",referrer: document.referrer,});});}_initPageDulation() {let self = this;function initDulation() {const time = new Date().getTime();self._dulation.value = time - self._dulation.startTime;self._report("dulation", {...self._dulation,});self._dulation.startTime = time;self._dulation.value = 0;}// 首次进入页面window.addEventListener("load", () => {// 记录时间const time = new Date().getTime();this._dulation.startTime = time;});// 单页应用页面跳转(触发 replaceState)window.addEventListener("replaceState", () => {initDulation();});// 单页应用页面跳转(触发 pushState)window.addEventListener("pushState", () => {initDulation();});// 非单页应用跳转触发 popstatewindow.addEventListener("popstate", () => {initDulation();});// 页面没有任何跳转, 直接关闭页面的情况window.addEventListener("beforeunload", () => {initDulation();});}_initJSError() {window.addEventListener("error", (e) => {this._report("error", {message: e.message,});});window.addEventListener("unhandledrejection", (e) => {this._report("error", {message: e.reason,});});}// 用户可主动上报reportTracker(data) {this._report("custom", data);}_getPageInfo() {const { width, height } = window.screen;const { userAgent } = navigator;return {uid: this.uid,title: document.title,url: window.location.href,time: new Date().getTime(),ua: userAgent,screen: `${width}x${height}`,};}_report(type, data) {const reportData = {...this._getPageInfo(),type,data,sdk: this.sdkVersion,};if (navigator.sendBeacon) {navigator.sendBeacon(this.reportUrl, JSON.stringify(reportData));} else {const imgReq = new Image();imgReq.src = `${this.reportUrl}?params=${JSON.stringify(reportData)}&t=${new Date().getTime()}`;}}}e.TrackingDemo = TrackingDemo;
})(window);
// HTML 代码部分
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button report-key="button">按钮</button>
</body>
<script src="./tackerDemo.js"></script>
<script>const trackingDemo = new TrackingDemo()
</script>
</html>

实现方式就是将此文中 数据收集 部分的代码整合成一个类。

7.2 工程化

如果项目是模块化开发的话,就需要打包工具进行打包,以便支持esm、cjs和umd三种方式,同时工程化还便于维护。

这里使用rollup进行打包,以及使用typescript进行类型约束。

GitHub - GaLiDunGuide/TrackerDemo

7.3 发布NPM包

"files": ["dist"],  // 发布 npm 时需要上传的目录
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"browser": "dist/index.js",

八、为什么都用GIF来做埋点?

向服务器端上报数据,可以通过请求接口,请求普通文件,或者请求图片资源的方式进行。只要能上报数据,无论是请求GIF文件还是请求js文件或者是调用页面接口,服务器端其实并不关心具体的上报方式。那为什么所有系统都统一使用了请求GIF图片的方式上报数据呢?
●防止跨域
一般而言,打点域名都不是当前域名,所以所有的接口请求都会构成跨域。而跨域请求很容易出现由于配置不当被浏览器拦截并报错,这是不能接受的。但图片的src属性并不会跨域,并且同样可以发起请求。(排除接口上报)
●防止阻塞页面加载,影响用户体验
通常,创建资源节点后只有将对象注入到浏览器DOM树后,浏览器才会实际发送资源请求。反复操作DOM不仅会引发性能问题,而且载入js/css资源还会阻塞页面渲染,影响用户体验。
但是图片请求例外。构造图片打点不仅不用插入DOM,只要在js中new出Image对象就能发起请求,而且还没有阻塞问题,在没有js的浏览器环境中也能通过img标签正常打点,这是其他类型的资源请求所做不到的。(排除文件方式)
●相比PNG/JPG,GIF的体积最小
最小的BMP文件需要74个字节,PNG需要67个字节,而合法的GIF,只需要43个字节。
同样的响应,GIF可以比BMP节约41%的流量,比PNG节约35%的流量。
并且大多采用的是1*1像素的透明GIF来上报
1x1像素是最小的合法图片。而且,因为是通过图片打点,所以图片最好是透明的,这样一来不会影响页面本身展示效果,二者表示图片透明只要使用一个二进制位标记图片是透明色即可,不用存储色彩空间数据,可以节约体积。

这篇关于前端埋点全解及埋点SDK实现方式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/852994

相关文章

gradle第三方Jar包依赖统一管理方式

《gradle第三方Jar包依赖统一管理方式》:本文主要介绍gradle第三方Jar包依赖统一管理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录背景实现1.顶层模块build.gradle添加依赖管理插件2.顶层模块build.gradle添加所有管理依赖包

使用Python实现IP地址和端口状态检测与监控

《使用Python实现IP地址和端口状态检测与监控》在网络运维和服务器管理中,IP地址和端口的可用性监控是保障业务连续性的基础需求,本文将带你用Python从零打造一个高可用IP监控系统,感兴趣的小伙... 目录概述:为什么需要IP监控系统使用步骤说明1. 环境准备2. 系统部署3. 核心功能配置系统效果展

Python实现微信自动锁定工具

《Python实现微信自动锁定工具》在数字化办公时代,微信已成为职场沟通的重要工具,但临时离开时忘记锁屏可能导致敏感信息泄露,下面我们就来看看如何使用Python打造一个微信自动锁定工具吧... 目录引言:当微信隐私遇到自动化守护效果展示核心功能全景图技术亮点深度解析1. 无操作检测引擎2. 微信路径智能获

Python中pywin32 常用窗口操作的实现

《Python中pywin32常用窗口操作的实现》本文主要介绍了Python中pywin32常用窗口操作的实现,pywin32主要的作用是供Python开发者快速调用WindowsAPI的一个... 目录获取窗口句柄获取最前端窗口句柄获取指定坐标处的窗口根据窗口的完整标题匹配获取句柄根据窗口的类别匹配获取句

Linux之systemV共享内存方式

《Linux之systemV共享内存方式》:本文主要介绍Linux之systemV共享内存方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、工作原理二、系统调用接口1、申请共享内存(一)key的获取(二)共享内存的申请2、将共享内存段连接到进程地址空间3、将

Maven中引入 springboot 相关依赖的方式(最新推荐)

《Maven中引入springboot相关依赖的方式(最新推荐)》:本文主要介绍Maven中引入springboot相关依赖的方式(最新推荐),本文给大家介绍的非常详细,对大家的学习或工作具有... 目录Maven中引入 springboot 相关依赖的方式1. 不使用版本管理(不推荐)2、使用版本管理(推

在 Spring Boot 中实现异常处理最佳实践

《在SpringBoot中实现异常处理最佳实践》本文介绍如何在SpringBoot中实现异常处理,涵盖核心概念、实现方法、与先前查询的集成、性能分析、常见问题和最佳实践,感兴趣的朋友一起看看吧... 目录一、Spring Boot 异常处理的背景与核心概念1.1 为什么需要异常处理?1.2 Spring B

Python位移操作和位运算的实现示例

《Python位移操作和位运算的实现示例》本文主要介绍了Python位移操作和位运算的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 位移操作1.1 左移操作 (<<)1.2 右移操作 (>>)注意事项:2. 位运算2.1

如何在 Spring Boot 中实现 FreeMarker 模板

《如何在SpringBoot中实现FreeMarker模板》FreeMarker是一种功能强大、轻量级的模板引擎,用于在Java应用中生成动态文本输出(如HTML、XML、邮件内容等),本文... 目录什么是 FreeMarker 模板?在 Spring Boot 中实现 FreeMarker 模板1. 环

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义