前端数据埋点
前提
应用变得更受欢迎,了解用户的行为就更迫切,埋点的事就更重要了。前后端都会进行埋点,也有各自适合的场景,例如 api 回调里的埋点显然更适合后端,相比前端,这样更快也更精准。而前端的原住业务代码也很关注侵入的埋点代码,会希望它们能矜持一些,不至于扎堆妨碍业务。把一份埋点文档转译成埋点代码,这份代码最好就能像文档一样方便定位、添加、修改、删除、查看,并且和业务代码保持距离。
怎么做呢
这里用各个元素DOM
的id
来区分各个埋点数据,即用 DOM id 来进行埋点,这里介绍这种埋点方案。
根据前端埋点文档看,有三类埋点类型:
- 点击事件埋点;
- 页面进入离开式的绑定埋点;
- 元素曝光的统计时长埋点。
之所以选择DOM id
,是因为id
和埋点性质相似,上面三类埋点也都是埋在DOM
上:
- 每个埋点是不同的,
DOM id
也都是唯一的; - 点击事件点击的是具体某个
DOM
; - 页面绑定埋点将利用组件,组件是
DOM
; - 被曝光的元素依然是
DOM
; DOM id
在DOM 树
上,离JS
业务代码最远;- 关联
DOM
更符合声明式编码。
后面的内容会围绕第一种“点击事件埋点”做介绍。
在业务程序里埋一次点
所以怎么做呢?下面是业务里的(一次)埋点部分代码(Vue):
// ... 省略
<Icon
id="icon"
@click="iconClickHandler($event, 0, 'firstTitle', 1632028563744)"
/>
// ... 省略
import { sendEventTagByIdClick } from './tracker.js'
function iconClickHandler(e, i, title, time) {
sendEventTagByIdClick({ id: e.currentTarget.id, iconIdx: i, iconTitle: title, iconTime: time }) // 埋点
// ... 业务程序
}
// ... 省略
上面是在用户点击 Icon 的时候触发一次埋点,这段埋点代码只是一次埋点流程的一部分,也是这部分和业务最亲密,所以抓住让读写代码费力的发源地,分开它们。
代码里id
值icon
被传入到埋点函数sendEventTagByIdClick
,这个id
将被用来辨识埋点数据(“用 DOM id 来进行埋点”),并且该函数的其它入参只传入了最基础的数据(原始埋点数据),例如i
、title
和时间戳time
,不过我想埋点的服务端是不会想收到一份时间戳的,所以格式化时间戳成可读时间的工作会留给整个埋点流程里的其它环节,只是这儿只想解耦埋点和业务。
我的实现
像下面这样创建 3 个文件,这 3 个文件拆分流程,分离业务和埋点:
...
--libs
|--tracker.js // 埋点业务
|--tracker-config.js // 这儿是个埋点数据表,埋点数据都列在这,自文档化
|--tracker-tools.js // 处理埋点数据的工具箱
...
接下来通过这仨文件来走过一次埋点的一生。
tracker.js
tracker.js
向用户(业务程序开发者)提供接口函数,用户在业务层成功调用函数就完成 1 次埋点。
这个函数会接收入参,入参是原始埋点数据,然后传递生成最终埋点数据,最后将数据发送给服务端。下面是主要代码(js):
import {
genTrackingFinalData } from './tracker-config.js'
export async function sendEventTagByIdClick(data) {
const eventTrackingData = await genTrackingFinalData(data)
if (eventTrackingData != null)