🔥面试官:如何设计一个埋点SDK

5,634 阅读5分钟

被裁

三月上海疫情爆发,宝哥所处公司的业绩也是不断下滑,所以决定裁掉一部分人员。宝哥就这么的光荣“毕业”了,由于疫情原因,无法进行面试,所以利用在家的这段时间,来好好的准备下面试吧,并将相关的内容输出出来,供大家参考和讨论,一起学习,一起进步。

1648618282605.jpg

这是我一个大佬同事面小红书面试官一面问的问题,其中第一项就是前端埋点设计,可见埋点也日渐成为了必须掌握的技能之一了。 我们这节就来浅谈一下埋点(前端技术层面)。

埋点的概念

埋点的定义:是数据采集领域(尤其是用户行为数据采集领域)的术语。指的是针对``特定用户行为或事件进行捕获、处理和发送的相关技术以及实施过程```。比如用户某个icon点击次数、观看某个视频的时长等。

埋点的技术实质:是先监听软件应用运行过程中的事件,当需要关注的事件发生时进行判断和捕获。

1648619598679.jpg

举个一个最简流程的例子(如上图),模拟用户购买华为手机:用户的目的是为了购买华为手机,但是并不是一步就能到达结算页面的,你需要1.打开淘宝App->2.搜索华为手机->3.进行选择华为手机的规格型号等->4.最后一步才是结算购买手机。在购买华为手机前一定会有这三步流程且不可避免,我们前端开发者可以在这1、2、3步流程进行埋点监控,比如在第3步中每当用户在选择型号大小颜色,我们都对这个点击事件进行监控,后期客户犹豫再三并没有下单,我们就可以利用这些数据进行分析,用此来优化我们的产品。

埋点的核心作用就是1.监控用户数据->2.然后分析用户数据->3.最后再优化我们的产品,这也是一个闭环的过程。

1648620405361.jpg

埋点的分类

一般情况下,主要有3类埋点:展现埋点+曝光埋点+交互埋点

  1. 展现埋点

定义展现其实是一个服务端的触发。服务端被触发后,用户侧将会展示什么内容,展现埋点需要记录的是页面展现的内容,即服务端下发的内容是什么(这些东西一定是当前页面主要内容,不包含一些交互信息)。

  1. 曝光埋点

哪些下发的内容被用户实际看到了。和展现埋点类似,由于屏幕有限,但内容可以无限。哪些内容被用户侧世纪看到(曝光),需要记录的是单个“内容”被看到。一系列被下发的内容,可以触发多次埋点曝光。

  1. 交互埋点

交互埋点表明的是功能/内容被用户“点击“了。从埋点时机来说,这个是展现&曝光的下游。记录对于我们提供的”服务“的”消费“情况。比如,一个页面,用户可以点击,那么我们需要记录相应的交互动作埋点;比如,一个视频可以点赞,我们也可以记录交互埋点;比如,一个视频可以播放暂停,我们也可以记录消费埋点。

埋点SDK设计

当然设计sdk是我们这篇文章的重点。

我们可以从数据监控+性能监控+异常监控三个点去设计。

  1. 数据监控

首先设计一个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})
    }
}
  1. 性能监控

实际上就是使用了performence这个api。

class MySDK {
    constructor(props){
+       this.initPerformance();
    }
    //初始化性能统计
+   initPerformance(){
+       const url='yyy';
+       this.send(url,performance.timing);
+   }
}
  1. 异常监控

监听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方便我们调用自定义事件进行发送。