大厂经验:一套 Web 自动曝光埋点技术方案
什么是埋点?
埋点是指在各个终端(如网页、小程序)中收集一些关键访问数据并将数据发送到日志服务器,以供后续的数据分析。
埋点有什么用?
如下笔者在写这篇文章之前对公司内的一些业务做的访谈调研记录:
“采集用户行为并针对性做些投放调整,比如会员权益的展现、影院场次的优先露出、用户想看和看过的互动等”
“做新春大盘活动的时候,某些模块曝光次数不够高,运营会调整相应策略”
“个性化推荐,根据曝光和点击情况推荐用户数据”
“我们这边埋点数据对算法开发、模型训练、效果评估起决定性作用”
“观察用户逛会场深度的分布,做相应决策”
何谓自动曝光?
典型轮播图场景,图片滚动出现后需要打曝光日志:
难点
1、一般而言产品上会要求页面上某个模块一定面积连续一段时间出现在视口才是有效曝光(如30%、300ms)
2、性能,几乎所有的第三方采集平台都会在曝光埋点的说明文档里注明:“请不要配置过多的曝光埋点,这会严重影响你的页面性能”
埋点方式
HTML
方式一:在head头部声明式埋点
方式二:JS注入式埋点
以上两种方式,埋点SDK均会判断cssSelector=".name"的所有元素被曝光时,自动采集这个标签的曝光信息,及当前元素上"data-id"等props参数打包在一起,以logkey=/banner.item.image的形式发出去。如:https://tracker.xxx.com/banner.item.image
技术原理
生命周期
技术细节
初始化
DomReady后做监听埋点配置变化(watchConfig)
watchConfig首次拿到埋点配置
一、监听dom变化(watchDOM)
步骤一、使用MutationObserver或轮询(浏览器最小化、浏览器后台运行、tab未激活均会暂停轮询,直到浏览器窗口再次激活)。MutationObserver监听除['IFRAME', 'BODY', 'OBJECT', 'SCRIPT', 'NOSCRIPT','#text', 'LINK', 'STYLE']之外的所有节点增加监听['class', 'style']属性变化;
步骤二、监听到有dom变化后判断当前元素的track-ae属性是否有值,有则跳过,无则组装参数对象并生成元素唯一HASH,同时设置符合条件的节点状态:“status=init”,再push到_aeElementsHashMap中;
步骤三、分发一个内部事件消息“_AE_DOM_CHANGE”,用于通知watchExposure。
二、监听曝光(watchExposureByIntersectionObserver)
步骤一、监听来自watchDOM分发的内部消息“_AE_DOM_CHANGE”,转至步骤二;
步骤二、使用IntersectionObserver包装埋点配置,拿到回调后将节点带入步骤三;
步骤三、遍历aeElementsHashMap,拿到“status===init && element from IntersectionObserver”后判断被曝光的元素是否符合要求(默认按可视面积30%),符合条件的节点设置“status=exposure_start”并更新aeElementsHashMap;
步骤四、在步骤三的基础上setTimeout 300ms后用getBoundingClientRect拿到节点坐标宽高信息再使用自定义交叉计算方法重新计算一遍交叉面积,如果依然超过30%的面积在视口内,那么将符合条件的节点设置“status=exposure_complete”并更新aeElementsHashMap。分发日志发送命令“AE_EXPOSURE_COMPLETE”,用于通知watchRecord;
步骤五、修改已曝光元素dom锚点:track-ae="${HASH}"。
三、监听曝光(watchExposureByCustomIntersection)
步骤一、监听来自watchDOM分发的内部消息“_AE_DOM_CHANGE”,转至步骤三;
步骤二、监听touchmove、scroll、resize三种事件回调函数做成throttle_handler_exposure,拿到回调进入步骤三;
步骤三、遍历aeElementsHashMap,拿到“status===init”的节点,然后用getBoundingClientRect获取节点坐标宽高计算出交叉面积,符合可视面积超过30%的节点设置“status=exposure_start”并更新aeElementsHashMap;
步骤四、在步骤三的基础上setTimeout 300ms后用getBoundingClientRect拿到节点坐标宽高信息再使用自定义交叉计算方法重新计算一遍交叉面积,如- 果依然超过30%的面积在视口内,那么 将符合条件的节点设置“status=exposure_complete”并更新aeElementsHashMap。分发日志发送命令AE_EXPOSURE_COMPLETE,用于通知watchRecord;
步骤五、修改已曝光元素dom锚点:track-ae="${HASH}"。
四、监听日志发送命令(watchRecord)
步骤一、监听到“_AE_EXPOSURE_COMPLETE”消息后最多10个元素打包在一起发送日志;
步骤二、清理_aeElementsHashMap上下文;
步骤三、给待曝光元素设置dom锚点:track-ae="${index}";
watchConfig非首次拿到埋点配置
1、配置不为空时do_reset,做两件事:
1.1、重置_aeElementsHashMap上下文;
1.2、将符合条件的元素的track-ae属性重置成同类节点索引值,以触发下一轮曝光监听。
2、配置为空值时do_destroy,做三件事:
2.1、销毁_aeElementsHashMap上下文;
2.2、移除所有监听事件;
2.3、清空所有track-ae锚点属性。
效果
性能
笔者通过大量测试和线上优化,拿目前这套架构方案与GA做了一个对比,即对208个元素做了曝光埋点,连续来回滚动,直到所有元素都完成曝光日志上报的性能对比:
额外的收益
有了这个基础,做如下两件事会显得比较轻松了
1、可视化埋点
2、可视化分析
参考文献
————— 招聘广告分界线 —————
某大厂大数据团队招聘前端、Java、C++、数据开发、Android、iOS、安全技术专家,级别不限,欢迎大家私信联系。
原文链接:https://zhuanlan.zhihu.com/p/142762740
版权声明: 本文为 InfoQ 作者【阿亮】的原创文章。
原文链接:【http://xie.infoq.cn/article/ca81dd8f1d0abdb0483a5871c】。文章转载请联系作者。
评论