数据埋点方案、监控方案
代码埋点
代码埋点是最灵活,同时也是最耗时的一种方式。
一般大厂内部会封装自己的一套埋点上报的npm包, 提供给各业务线使用。
一般我们需要上报什么信息呢?
- 埋点的标识信息, 比如eventId, eventType
 - 业务自定义的信息, 比如教育行业, 点击一个按钮, 我们要上报用户点击的是哪个年级
 - 通用的设备信息, 比如用户的userId, useragent, deviceId, timestamp, locationUrl等等
 
一般怎么上报?
- 实时上报, 业务方调用发送埋点的api后, 立即发出上报请求
 - 延时上报, sdk内部收集业务方要上报的信息, 在浏览器空闲时间或者页面卸载前统一上报,上报失败会做补偿措施。
 
实现
无埋点
概念
无埋点并不是真正的字面意思,其真实含义其实是,不需要研发去手动埋点。
一般会有一个 sdk 封装好各种逻辑, 然后业务方直接引用即可。
sdk中做的事情一般是监听所有页面事件, 上报所有点击事件以及对应的事件所在的元素,然后通过后台去分析这些数据。
业界有GrowingIO, 神策, 诸葛IO, Heap, Mixpanel等等商业产品
实现
监听window元素
window.addEventListener("click", function(event){let e = window.event || event;let target = e.srcElement || e.target;}, false);
获取元素唯一标识 xPath ```javascript function getXPath(element) { // 如果元素有id属性,直接返回//*[@id=”xPath”] if (element.id) {
return '//*[@id=\"' + element.id + '\"]';
} // 向上查找到body,结束查找, 返回结果 if (element == document.body) {
return '/html/' + element.tagName.toLowerCase();
} let currentIndex = 1, // 默认第一个元素的索引为1
siblings = element.parentNode.childNodes;
for (let sibling of siblings) {if (sibling == element) {// 确定了当前元素在兄弟节点中的索引后, 向上查找return getXPath(element.parentNode) + '/' + element.tagName.toLowerCase() + '[' + (currentIndex) +']';} else if (sibling.nodeType == 1 && sibling.tagName == element.tagName) {// 继续寻找当前元素在兄弟节点中的索引currentIndex++;}}
};
<a name="456da6de"></a>## 获取元素的位置```javascriptfunction getOffset(event) {const rect = getBoundingClientRect(event.target);if (rect.width == 0 || rect.height == 0) {return;}let doc = document.documentElement || document.body.parentNode;const scrollX = doc.scrollLeft;const scrollY = doc.scrollTop;const pageX = event.pageX || event.clientX + scrollX;const pageY = event.pageY || event.clientY + scrollY;const data = {offsetX: ((pageX - rect.left - scrollX) / rect.width).toFixed(4),offsetY: ((pageY - rect.top - scrollY) / rect.height).toFixed(4),};return data;}
上报
window.addEventListener("click", function(event){const e = window.event || event;const target = e.srcElement || e.target;const xPath = getXPath(target);const offsetData = getOffset(event);report({ xPath, ...offsetData});}, false);
