如何在百度做网站推广,怎么做网页推广,新手学做网站txt,企业所得税公式计算例子前端实现埋点
如何去了解用户呢#xff1f;最直接有效的方式就是了解用户的行为#xff0c;了解用户在网站中做了什么#xff0c;呆了多久。而如何去实现这一操作#xff0c;这就涉及到我们前端的埋点了。
埋点方式
什么是埋点#xff1f;
所谓埋点是数据采集领域最直接有效的方式就是了解用户的行为了解用户在网站中做了什么呆了多久。而如何去实现这一操作这就涉及到我们前端的埋点了。
埋点方式
什么是埋点
所谓埋点是数据采集领域尤其是用户行为数据采集领域的术语指的是针对特定用户行为或事件进行捕获、处理和发送的相关技术及其实施过程。比如用户某个icon点击次数、观看某个视频的时长等等。从数据产品经理视角聊聊埋点的意义 | 人人都是产品经理 (woshipm.com)
基于此我们可以知道埋点是实际上是对特定事件或者行为的数据监控和上报常见的埋点上报方式有ajaximgnavigator.sendBeacon下面介绍下这三种埋点上报方式
介绍
因为埋点实际上是对关键节点的数据进行上报是和服务端交互的一个过程所以我们可以和后端约定一个接口通过ajax去进行数据上报。 代码实现
我们可以封装一个方法代码如下
function buryingPointAjax(data) {return new Promise((resolve, reject) {// 创建ajax请求const xhr new XMLHttpRequest();// 定义请求接口xhr.open(post, /buryingPoint, true);// 发送数据xhr.send(data);});
}使用时直接调用即可
let info {}
buryingPointAjax(info) // 这样就成功上报了info的对象缺点
一般而言埋点域名并不是当前域名因此请求会存在跨域风险且如果ajax配置不正确可能会被浏览器拦截。因此使用ajax这类请求并不是万全之策。 基于img的埋点上报
上面可以看到如果使用ajax的话会存在跨域的问题。而且数据上报前端主要是负责将数据传递到后端并不过分强调前后端交互。因此我们可以通过一些支持跨域的标签去实现数据上报功能。
scriptlinkimg就是我们上报的数据的最好对象
先说结论这里推荐使用img标签去实现。
script及link的缺陷
因为埋点涉及到请求因此我们需要保证script和link标签的src可以正常请求。如果需要请求script和link我们需要将标签挂载到页面上。
验证缺陷
不妨验证下我们在管理台中加入以下代码
let a document.createElement(script)
a.src https://lf-headquarters-speed.yhgfb-cn-static.com/obj/rc-client-security/web/stable/1.0.0.28/bdms.js创建一个script标签未挂载中页面上并不会发起请求 书接上文当我们将这个标签挂载中页面上时
document.body.appendChild(a);这时发起了请求 结论
当我们使用script和link进行埋点上报时需要挂载到页面上而反复操作dom会造成页面性能受影响而且载入js/css资源还会阻塞页面渲染影响用户体验因此对于需要频繁上报的埋点而言script和link并不合适。
基于img做埋点上报
通常使用img标签去做埋点上报img标签加载并不需要挂载到页面上基于js去new image()设置其src之后就可以直接请求图片。
验证img优势
控制台去创建一个image标签如下
const img new Image();
img.src https://lf3-cdn-tos.bytescm.com/obj/static/xitu_juejin_web/img/MaskGroup.13dfc4f1.png;可以看到即便未被挂载到页面上依旧发起了请求。 结论
因此当我们做埋点上报时使用img是一个不错的选择。
img兼容性好无需挂载到页面上反复操作domimg的加载不会阻塞html的解析但img加载后并不渲染它需要等待Render Tree生成完后才和Render Tree一起渲染出来
注通常埋点上报会使用gif图合法的 GIF 只需要 43 个字节 基于Navigator.sendBeacon的埋点上报
Navigator.sendBeacon是目前通用的埋点上报方案Navigator.sendBeacon方法接受两个参数第一个参数是目标服务器的 URL第二个参数是所要发送的数据可选可以是任意类型字符串、表单对象、二进制对象等等。
介绍
navigator.sendBeacon() 方法可用于通过 HTTP POST 将少量数据 异步 传输到 Web 服务器。
作用
它主要用于将统计数据发送到 Web 服务器同时避免了用传统技术如XMLHttpRequest发送分析数据的一些问题。
补充
sendBeacon 如果成功进入浏览器的发送队列后会返回true如果受到队列总数、数据大小的限制后会返回false。返回ture后只是表示进入了发送队列浏览器会尽力保证发送成功但是否成功了不会再有任何返回值。
例子
以掘金为例 这里发了一个post请求将小量的数据发到服务端用于统计数据 优势
相较于img标签使用navigator.sendBeacon会更规范数据传输上可传输资源类型会更多。
对于ajax在页面卸载时上报ajax有可能没上报完页面就卸载了导致请求中断因此ajax处理这种情况时必须作为同步操作。
sendBeacon是异步的不会影响当前页到下一个页面的跳转速度且不受同域限制。这个方法还是异步发出请求但是请求与当前页面脱离关联作为浏览器的任务因此可以保证会把数据发出去不拖延卸载流程。注意
该方法在支付宝中可能会被拦截如果发现支付宝数据上报异常可以尝试排查这块。
总结
前端埋点上报常使用ajaximgnavigator.sendBeacon。不推荐使用ajax。如果考虑兼容性的话img是不二之选。目前最合适的方案是navigator.sendBeacon不仅是异步的而且不受同域限制而且作为浏览器的任务因此可以保证会把数据发出去不影响页面卸载。
常见埋点行为 点击触发埋点 绑定点击事件当点击目标元素时触发埋点上报。 function clickButton(url, data) {navigator.sendBeacon(url, data)
}页面停留时间上报埋点 路由文件中初始化一个startTime当页面离开时通过路由守卫计算停留时间。 let url // 上报地址
let startTime Date.now()
let currentTime
router.beforeEach((to, from, next) { if (to) {currentTime Date.now()stayTime parseInt(currentTime - startTime)navigator.sendBeacon(url, {time: stayTime})startTime Date.now()}})错误监听埋点 通过监听函数去接收错误信息。 vue错误捕获 app.config.errorHandler (err) { navigator.sendBeacon(url, {error: error.message, text: vue运行异常 })
}JS异常与静态资源加载异常 window.addEventListener(error, (error) { if (error.message) { navigator.sendBeacon(url, {error: error.message, text: js执行异常 })} else { navigator.sendBeacon(url, {error: error.filename, text: 资源加载异常 })}
}, true)请求错误捕获 axios.interceptors.response.use((response) {if (response.code 200) {return Promise.resolve(response);} else {return Promise.reject(response);}},(error) {// 返回错误逻辑navigator.sendBeacon(url, {error: error, text: 请求错误异常 })}
);内容可见埋点 通过交叉观察器去监听当前元素是否出现在页面 // 可见性发生变化后的回调
function callback(data) { navigator.sendBeacon(url, { target: data[0].target, text: 内容可见 })
}
// 交叉观察器配置项
let options {};
// 生成交叉观察器
const observer new IntersectionObserver(callback);
// 获取目标节点
let target document.getElementById(target);
// 监听目标元素
observer.observe(target);后续
开发的时候可以封装这三种上报方法
// sendBeacon 上报
export async function sendBeacon( {url , params }: reportParams) {if (navigator?.sendBeacon url) {const isSuccess await navigator?.sendBeacon(url, JSON.stringify(params));if (isSuccess) return true;}return false;
}// img 上报
export function sendImg({ img , params }: reportParams) {return new Promiseboolean((resolve, reject) {const imageData objectToQueryString(params)const img_o new Image();img_o.onload () resolve(true);img_o.onerror () reject(false);img_o.src ${img}?${imageData};})
}// ajax 上报
export function sendAjax({ req , params }: reportParams) {return new Promiseboolean((resolve, reject) {if (req) {postAction(req, params).then(() resolve(true)).catch(() reject(false));} else {reject(false);}});
}使用的时候再导出一个真实上报函数由用户决定使用什么上报组合。
// 基础上报函数
export async function reportEvent(params: reportParams, reportType:string[] [IMG, BEACON, AJAX]) {let finalType falsefor (const key in reportType) {if (!finalType) {try {await EVENT_REPORT_FUNCTION_MAP[key](params).then((){finalType true})} catch (error) {console.error(error)}}}return finalType
}