前端埋点
前端埋点
前言:太良日常的工作,很大一部分是跟进线上用户的问题,所以以下类型的对话就成了频率非常高的存在。

那就引发了一个思考,我怎么在用户发生错误,或者进行某种行为的时候,收集到他的动作与一系列可分析的内容?答案就是前端的埋点。
埋点的目的
获取用户行为以及跟踪产品在用户端的使用情况,并以监控数据为基础,指明产品优化的方向。
前端监控可以分为三类:数据监控、性能监控和异常监控。
(1) 数据监控
数据监控,顾名思义就是监听用户的行为。常见的数据监控包括:
PV/UV:PV(page view),即页面浏览量或点击量。UV:指访问某个站点或点击某条新闻的不同IP地址的人数
用户在每一个页面的停留时间
用户通过什么入口来访问该网页
用户在相应的页面中触发的行为
统计这些数据是有意义的,比如我们知道了用户来源的渠道,可以促进产品的推广,知道用户在每一个页面停留的时间,可以针对停留较长的页面,增加广告推送等等。
(2) 性能监控
性能监控指的是监听前端的性能,主要包括监听网页或者说产品在用户端的体验。常见的性能监控数据包括:
不同用户,不同机型和不同系统下的首屏加载时间、白屏时间
http等请求的响应时间
静态资源整体下载时间
页面渲染时间
页面交互动画完成时间
这些性能监控的结果,可以展示前端性能的好坏,根据性能监测的结果可以进一步的去优化前端性能,比如兼容低版本浏览器的动画效果,加快首屏加载等等。
(3) 异常监控
此外,产品的前端代码在执行过程中也会发生异常,因此需要引入异常监控。及时的上报异常情况,可以避免线上故障的发上。虽然大部分异常可以通过try catch的方式捕获,但是比如内存泄漏以及其他偶现的异常难以捕获。常见的需要监控的异常包括:
Javascript的异常监控
样式丢失的异常监控。
埋点分为什么?

手动埋点
// 手动埋点也叫做代码埋点,在每一处需要的地方,都加一段上报代码逻辑,统计用户的关键行为。
// 实现起来最快,收集到的内容可高度自定义,但影响代码的阅读体验,且散落的代码不方便管理,代码越来越像这样,谁接手谁倒霉,下面我们来看实际代码

可视化埋点
通过可视化交互的手段,代替上述的代码埋点。 将业务代码和埋点代码分离,提供一个可视化交互的页面,输入为业务代码, 通过这个可视化系统,可以在业务代码中自定义的增加埋点事件等等, 最后输出的代码耦合了业务代码和埋点代码。
缺点就是可以埋点的控件有限,不能手动定制。 可视化埋点听起来比较高大上,实际上跟代码埋点还是区别不大。 也就是用一个系统来实现手动插入代码埋点的过程。 比如国外比较早做可视化的是Mixpanel, 国内较早支持可视化埋点的有TalkingData、诸葛 IO,2017年腾讯的MTA也宣布支持可视化埋点;
相比于手动埋点更新困难,埋点成本高的问题,可视化埋点优化了移动运营中数据采集的流程, 能够支持产品运营随时调整埋点,无需再走发版流程,直接把配置结果推入到前端, 数据采集流程更简化,也更方便产品的迭代。可视化埋点中多数基于Xpath的方案, XPath 是一门在 XML 文档中查找信息的语言,XPath 可用来在 XML 文档中对元素和属性进行遍历。
无痕埋点
无痕埋点也叫全埋点,通过控件绑定触发事件,事件被触发的时候系统会有相应的事件让开发者处理这些行为。
实现埋点
最简单的埋点
// 通过window对象的onerror监听,获取所有报错的内容。
window.onerror = function (message, source, lineno, colno, error) {
console.log(message);
console.log(source);
console.log(lineno);
console.log(colno);
console.log(error);
};
console.log(test);
晋级 => 实现一个简单的无痕埋点
借助createElement,通过劫持的形式主动上报,具体看代码
// js
import React from 'react'
export const initTrack = ({ onClickEvent }) => {
const createElement = React.createElement
const handleEditClick = props => {
const click = props.onClick
console.log(props)
props.onClick = e => {
onClickEvent && onClickEvent(props.data)
click && click(e)
}
}
React.createElement = function () {
const args = Array.prototype.slice.call(arguments)
console.log(args)
let zhihong = args[1]
if (zhihong && zhihong.data) {
zhihong = handleEditClick(zhihong)
}
return createElement.apply(null, args)
}
}
// jsx
import React, { useEffect } from 'react'
import { initTrack } from './track'
const Test = () => {
initTrack({
onClickEvent: data => {
// 我在这里 给后端上报咯~~~
console.warn(data)
}
})
return (
<>
<a data={{ test: 2 }}>222</a>
<div
style={{ fontSize: 40 }}
onClick={() => {
console.log('点击')
}}
data={{
a: 1,
b: 2
}}
>
我要点击
</div>
</>
)
}
export default Test
最后更新于
这有帮助吗?