埋点具有很重要的意义,可以获取用户在使用 app 时的各种行为或数据指标。这篇文章主要用来记录我们的项目中对于埋点的一些预研,包括页面点击埋点、页面路由埋点、应用启动时的性能数据埋点三个方面。
点击埋点
思路
顾名思义,就是在用户点击每一个类似按钮这样的可点击元素时,进行记录,然后发送给后端。如果在传统的如 jquery 下做的话,可能需要在每个点击事件里都加上一段统一的逻辑,这样显得很麻烦。 好在我们使用的Angular
,可以写一个自定义的指令,指令会监控宿主元素上的点击事件,然后进行埋点记录。对的,思路就是这么简单。
指令
这个指令的代码如下:
1 | @Directive( { |
这里的trackorClick
是一个专门用于埋点的服务中的一个方法,关键代码如下:
服务
1 | private userInfo: any; // 登录用户信息的对象 |
这里的track2Server
实际上使用了( new Image() ).src = xxx
信标的方式来向后端发送记录,就不贴具体代码了。
使用方法
有了这个指令后,就可以很简单的在模板文件中使用了,只用传递一个描述信息给指令就行,示范如下:
1 | <div>单纯指令: <button type="button" id="test-trackor1" crmTrackor="crmTrackortest1">测试1</button></div> |
页面路由埋点
思路
我们的项目中使用了ionic
框架,其有两个生命钩子ionViewDidEnter
和ionViewDidLeave
,前者在用户进入了当前页面后触发,后者在离开了当前页面后触发。我们只需在这两个钩子中插入埋点代码即可。关键在于我们的项目是多人合作开发的,如何让其他人花费最少的时间呢? 我们面临两个现状:
- 有很多页面其实并没有实现这两个钩子
- 即使实现了这个钩子,把埋点代码硬编码到其中总让人觉得不爽,侵入性太强
于是想到了 ts 中的装饰器,具体语法请直接参考官网。它可以修改某个类或者方法的元数据,有点类似 java 中的注解。 如果我们利用一个装饰器自动在这两个钩子中插入我们的埋点代码,那岂不是用起来很爽,就像 spring 中的切面编程一样。
类装饰器
先来试试类装饰器:
1 | /** |
使用方法
1 | @CrmTrackor.ViewTrackor |
这里只拦截了ionViewDidEnter
,但是测试发现方法是被替换掉了,但最终这个方法根本就没有执行,囧,暂时还没有找到原因,待日后再研究。
方法装饰器
再来试试方法装饰器吧
1 | /** |
其中,TraceType
是一个自定义枚举,用来表示是进入还是退出页面:
1 | /** |
getTrace
方法用于获取待记录的页面标识,这个标识有点麻烦,还是看代码吧:
1 | private static getTrace( comp: any, constructor: Function ) { |
大致思路是获取views
路由栈和已记录的pageTraces
栈,然后针对各种情况测试这两个栈的变化情况,最后总结出规律。pageTraces
栈会在CrmTrackor.logTrace
方法中进行记录:
1 | public static pageTraces: Trace[] = []; |
Trace
是一个自定义的类,记录页面浏览的关键数据:
1 | class Trace { |
使用方法
前提条件:因为getTrace
中使用了NavController
,故需要页面中注入NavController
,并将实例名固定为navCtrl
。 示范:constructor(public navCtrl: NavController){}
在每个页面中:
1 | @CrmTrackor.ViewDidEnterTrackor |
效果
初始化时进入列表页面:
列表进入详情:
详情返回列表:
记录到后端
最后,在页面卸载前将路由记录发送到后端:
1 | public ngOnInit() { |
相关代码
启动性能埋点
主要利用了performance.timing API
,一些相关的资料:
这里直接贴出代码:
1 |
|
然后在页面加载之后将这些数据发送到后端:
1 | export class MyApp implements OnInit{ |