被裁
三月上海疫情爆发,宝哥所处公司的业绩也是不断下滑,所以决定裁掉一部分人员。宝哥就这么的光荣“毕业”了,由于疫情原因,无法进行面试,所以利用在家的这段时间,来好好的准备下面试吧,并将相关的内容输出出来,供大家参考和讨论,一起学习,一起进步。
这是我一个大佬同事面小红书面试官一面问的问题,其中第一项就是前端埋点设计,可见埋点也日渐成为了必须掌握的技能之一了。 我们这节就来浅谈一下埋点(前端技术层面)。
埋点的概念
埋点的定义:是数据采集领域(尤其是用户行为数据采集领域)的术语。指的是针对``特定用户行为或事件进行捕获、处理和发送的相关技术以及实施过程```。比如用户某个icon点击次数、观看某个视频的时长等。
埋点的技术实质:是先监听软件应用运行过程中的事件,当需要关注的事件发生时进行判断和捕获。
举个一个最简流程的例子(如上图),模拟用户购买华为手机:用户的目的是为了购买华为手机,但是并不是一步就能到达结算页面的,你需要1.打开淘宝App->2.搜索华为手机->3.进行选择华为手机的规格型号等->4.最后一步才是结算购买手机。在购买华为手机前一定会有这三步流程且不可避免,我们前端开发者可以在这1、2、3步流程进行埋点监控,比如在第3步中每当用户在选择型号大小颜色,我们都对这个点击事件进行监控,后期客户犹豫再三并没有下单,我们就可以利用这些数据进行分析,用此来优化我们的产品。
埋点的核心作用就是1.监控用户数据->2.然后分析用户数据->3.最后再优化我们的产品,这也是一个闭环的过程。
埋点的分类
一般情况下,主要有3类埋点:展现埋点+曝光埋点+交互埋点。
- 展现埋点
定义展现其实是一个服务端的触发。服务端被触发后,用户侧将会展示什么内容,展现埋点需要记录的是页面展现的内容,即服务端下发的内容是什么(这些东西一定是当前页面主要内容,不包含一些交互信息)。
- 曝光埋点
哪些下发的内容被用户实际看到了。和展现埋点类似,由于屏幕有限,但内容可以无限。哪些内容被用户侧世纪看到(曝光),需要记录的是单个“内容”被看到。一系列被下发的内容,可以触发多次埋点曝光。
- 交互埋点
交互埋点表明的是功能/内容被用户“点击“了。从埋点时机来说,这个是展现&曝光的下游。记录对于我们提供的”服务“的”消费“情况。比如,一个页面,用户可以点击,那么我们需要记录相应的交互动作埋点;比如,一个视频可以点赞,我们也可以记录交互埋点;比如,一个视频可以播放暂停,我们也可以记录消费埋点。
埋点SDK设计
当然设计sdk是我们这篇文章的重点。
我们可以从数据监控+性能监控+异常监控三个点去设计。
- 数据监控
首先设计一个class类来编写我们的SDK,所谓sdk就是一个工具类库而已,只是底层帮我们封装了一些事件方便我们使用。
product 需要埋点的产品,一般对接第三方是使用第三方提供的token。
使用img标签发送请求有2个原因:1、防止跨域 2、兼容性较好。
pv代表用户页面浏览量。
//prodcut为当前产品性为了通用性考虑
//url是传递给服务端的url
interface SdkProp {
product: string;
url:string;
}
interface MySDKProp {
currentProduct: string;
}
class MySDK {
currentProduct: string;
url:string;
constructor(props: SdkProp) {
//指明产品名称
this.currentProduct = props.product;
this.url = props.url;
}
//数据浏览器访问量
pv() {
this.event('pv','');
}
//发送数据
private send(url, params: any = {}) {
params.product = this.currentProduct;
const paramsArr = [];
for (let key in params) {
const val = params[key];
paramsArr.push(`${key}-${val}`);
}
const newVal=`${url}?${paramsArr.join("&")}`;
const img=document.createElement('img');
img.src=newVal;
}
//内部事件
event(key,value) {
this.send(this.url,{key,value})
}
}
- 性能监控
实际上就是使用了performence这个api。
class MySDK {
constructor(props){
+ this.initPerformance();
}
//初始化性能统计
+ initPerformance(){
+ const url='yyy';
+ this.send(url,performance.timing);
+ }
}
- 异常监控
监听error、unhandledrejection事件
initError(){
//监听js的错误
window.addEventListener('error',event=>{
const { error,lineno,colno}=event;
this.error(error,{lineno,colno})
})
//捕获Promise没有catch的数据
window.addEventListener('unhandledrejection',event=>{
const { reason }=event;
this.error(new Error(event.reason),{type:'unhandledrejection'})
})
}
error(error,info={}){
const { message,stack }=error;
this.send(this.url,{message,stack,...info})
}
埋点SDK使用
const sdk=new MySDK({
product:'testxxx',
url:'http://www.youshu.com'
});
//页面监听
sdk.error();
//自定义事件监听
sdk.event();
//监听性能
window.addEventListener('DOMContentLoaded',()=>{
//为了避免没有数据,可以在文档加载全部完成以后再进行实例化
const sdk=new MySDK({
product:'testxxx',
url:'http://www.youshu.com'
});
});
//自定义捕获错误
try{
let S=null;
S.a;
}catch(e){
sdk.error()
}
面试简答
面试官:如何设计一个前端统计埋点SDK?
简单:前端埋点大致可分为数据监控、性能监控、错误监控。其中数据监控包括监控pv以及自定义事件的监控。性能监控可以使用浏览器给我们提供的performance api。而错误监控我们可以监听window对象的error事件以及监听promise没有catch情况的unhandlerejected api。其中需要注意的是我们必须使用img等来进行请求,因为img标签不会跨域且兼容性较好。最后,react/vue内部提供了一些api如ComponentDidCatch(react)/errorCaptured(vue)等api方便我们调用自定义事件进行发送。