「前端曝光埋点上报」实现方案
前端 实现 方案 曝光 上报 埋点
2023-06-13 09:18:47 时间
现状
为准确分析各前端页面实际对用户的吸引力,需要统计的页面元素的曝光数据。曝光的含义比较模糊,具体的统计方式也比较麻烦,本文分享一个前端曝光埋点上报的实现方案。
方案
为了统计曝光数据,首先要做的是,定义什么是曝光,然后制定上报数据的策略。
根据我们业务的实际情况,我们可以这样设计:
- 曝光定义:dom元素出现在屏幕窗口中,被用户看到,且停留时间超过500ms,才算一次曝光。dom元素退出窗口后重新进入窗口,再停留500ms,记为第二次曝光。
- 数据上报:需要尽量减少上报次数(1)定时器每N秒检查一次,如果有待上报数据就请求接口上报(2)如果待上报数据大于M条,直接上报,不需要等待N秒。
开始操作
整体实现
具体的代码实现如下:
- 使用IntersectionObserver观察是否出现和消失在窗口,用IntersectionObserver polyfill提升兼容性。
- 用vue的指令,实现上报数据的绑定,最后使用的时候,只需要为需要上报的元素,加上v-treport=“上报的数据”。
- 在指令绑定的时候,为dom元素绑定report-data和guid属性,具体值分别为待上报数据和唯一ID。
- 具体观测和上报曝光的逻辑,后面具体讲。
使用方式
绑定指令后的元素:
具体细节
元素X进入窗口
- 元素X进入窗口,记录到sessionStorage的to-observe队列(如果已存在,就不加入队列)(使用sessionStorage,是因为,浏览器关闭了不在需要计算观测结果)
- 结构为 {stime:观测到的时间, id:guid, data:待上报数据,hasObserve:false}
元素X退出窗口
- 从to-observe队列获取X的stime,如果(当前时间-stime)>=500ms而且hasObserve为false,将X元素的数据推入localStorage的to-report的队列(使用localStorage,浏览器关闭了,在下次进来,还可以把to-report未上报的进行上报)。
- 无论何种情况,元素X都要推出to-observe队列。
曝光定时器(每500ms检查一次)
- 如果to-observe队列中存在(当前时间-stime)>=500ms的X,hasObserve置为true,将X元素的数据推入to-report的队列
上报定时器(每1000ms检查一次)
- 如果to-report队列存在记录,上报并从to-report移出。
- 如果推入to-report队列时,队列长度大于M,直接上报。
观测元素的几种情况:
- A:进入窗口,500ms后退出窗口,需要上报
- B:进入窗口,没有退出窗口,超过了500ms,需要上报
- C:进入窗口,不到500ms退出窗口,不需要上报
代码实现
require('intersection-observer');
const MIN_OBSERVE_TIME = 500;
const OBSERVE_REPEAT_TIME = 1000;
const REPORT_REPEAT_TIME = 1000;
// 获取IntersectionObserver的单例
class ReportObserver {
constructor() {
this.instance = null;
this.intersectionObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
handleEnter(entry);
} else {
handleExit(entry);
}
});
});
// 初始化定时器
initInterval();
}
observe(el, reportData) {
el.setAttribute('report-data', JSON.stringify(reportData));
el.setAttribute('guid', guid());
this.intersectionObserver.observe(el);
}
// 获取IntersectionObserver的实例
static getInstance() {
if (!this.instance) {
this.instance = new ReportObserver();
}
return this.instance;
}
}
// 元素X进入窗口,记录到sessionStorage的to-observe队列(如果已存在,就不加入队列),
// 结构为 {stime:观测到的时间, id:元素ID, data:待上报数据,hasObserve:false}。
const handleEnter = function (entry) {
const dom = entry.target;
const data = dom.getAttribute('report-data');
const id = dom.getAttribute('guid');
const stime = new Date().getTime();
const hasObserve = false;
const observeData = { id, data, stime, hasObserve };
if (!findToObserve(id)) {
pushToObserve(observeData);
}
};
// 元素X退出窗口:
// 1、从to-observe队列获取X的stime,如果(当前时间-stime)>=500ms而且hasObserve为false,将X元素的数据推入to-report的队列。
// 2、无论何种情况,元素X都要推出to-observe队列。
const handleExit = function (entry) {
const dom = entry.target;
const id = dom.getAttribute('guid');
const etime = new Date().getTime();
const value = findToObserve(id);
if (value && etime - value.stime >= MIN_OBSERVE_TIME && !value.hasObserve) {
pushToReport(value);
}
deleteFromToObserve(id);
};
// 初始化定时器
const initInterval = function () {
// 曝光定时器
setInterval(() => {
// 如果to-observe队列中存在(当前时间-stime)>=500ms并且hasObserve为false的X,将X的hasObserve置为true,并推入to-report的队列
toObserveList().forEach((value) => {
const etime = new Date().getTime();
if (etime - value.stime >= MIN_OBSERVE_TIME && !value.hasObserve) {
value.hasObserve = true;
pushToObserve(value);
pushToReport(value);
}
});
}, OBSERVE_REPEAT_TIME);
// 上报定时器
setInterval(() => {
// 如果to-report队列存在记录,上报并从to-report移出。
if (toReportList.length) {
postReportData(toReportList);
clearToReport();
}
}, REPORT_REPEAT_TIME);
};
const postReportData = function (dataList) {
// 调用后台接口上报数据
};
export default {
bind(el, binding) {
if (
'IntersectionObserver' in window
&& 'IntersectionObserverEntry' in window
&& 'intersectionRatio' in window.IntersectionObserverEntry.prototype
) {
// 开始监听
ReportObserver.getInstance().observe(el, binding.value);;
}
},
};
参考文献
相关文章
- Vuex与前端表格施展“组合拳”,实现大屏展示应用的交互增强
- 17·灵魂前端工程师养成-JavaScript实现canvas画板
- 微前端02 : 乾坤的微应用加载流程分析(从微应用的注册到loadApp方法内部实现)
- 前端面试题:闭包_前端设计模式面试题
- 百度前端一面常见面试题(附答案)
- 百度前端必会react面试题汇总
- 如何让Android平台像IPC一样实现GB28181前端设备接入
- 前端如何实现整套视频直播技术流程
- 谷粒学院day5 讲师管理模块的前端实现
- 提高工作效率的神器:基于前端表格实现Chrome Excel扩展插件
- vue项目封装组件_前端组件封装
- 路由懒加载的原理及实现_前端路由懒加载
- 2022前端笔试题总结
- nginx前端跨域_nginx实现跨域
- 20道前端高频面试题(附答案)_2023-03-02
- 高级前端react面试题总结
- 高频前端面试题1
- 前端每日一题(10.23题目+10.22答案)
- 分享一行代码实现天气预报,前端页面天气预报
- 《前端技巧复盘》使用纯css实现网站换肤和焦点图切换动画
- 前端脚手架构建实践
- 前端Vue和React项目 Git 管理常用.gitignore配置
- 如何在前端大屏展示中实现真正的自助
- 从 JS 到全生态,云原生时代下的前端成长演进之路 |展望前端工程师的 2023
- 对于“前端状态”相关问题,如何思考比较全面
- Go 框架 Gin 怎么实现允许前端跨域请求?
- vscode前端常用插件推荐,搭建JQuery、Vue等开发环境详解编程语言
- 数据实现MySQL数据的jsp前端展示(jsp显示mysql)
- 台设计使用SQLServer前端设计实现数据可视化(sqlserver编辑前)
- 前端实现的弹性从Redis读取更多(前端读取redis)
- 前端实现直接操作Redis(前端直接连redis)
- 前端弹幕实时更新Redis技术初探(前端实现弹幕redis)