前言
在业务需求中,常常会统计页面的 UV, PV。并且会对用户的行为进行上报,包括但不限于:访问次数、浏览时长、浏览百分比。 如何在合适的时机发送埋点是重中之重,那么我们在 用户退出界面时 该如何上报,使用什么方法上报,上报要注意什么问题呢?
页面退出事件
常见的退出页面事件有 pagehide、beforeunload、unload,当用户离开、刷新页面将会执行。各个方法在 PC/Android/IOS 上表现不同
window.addEventListener('beforeunload', eventCallback) // 页面退出前
window.addEventListener('pagehide', eventCallback) // 页面退出前
window.addEventListener('unload', eventCallback) // 页面退出后
执行顺序为 beforeunload / pagehide -> unload
beforeunload、unload、pagehide 在 Android 上均可以使用。pagehide 在 IOS 上可以使用。
页面退出上报埋点
在页面创建时就可以对退出页面相关的事件进行监听,在结束时触发相关的 event 函数,此时可以发送相关的请求进行上报。
function eventCallback(e) {
// 上报埋点
}
浏览器不一定保留离开时发送的 HTTP 请求
但是问题来了,当我们离开页面发送请求时,会发现网络请求不一定会发出去,或者还没发完就被取消。原来当浏览器中的某个页面发生终止时,不能保证进程中的HTTP请求会成功(请参阅有关“终止”和页面生命周期的其他状态的更多信息)。这些请求的可靠性可能取决于--网络连接、应用程序性能,外部服务本身的配置。
Navigator.sendBeacon() / Fetch
此时就需要用到浏览器自带的 API Navigator.sendBeacon 或 JS 原生的 fetch api。
navigator.sendBeacon('/log', JSON.stringify({ some: "data" }))
Navigator.sendBeacon() - MDN 而 Navigator.sendBeacon 不支持自定义请求头,它将会自动识别传入的数据自己设置请求头,这多少有点不方便。例如我们需要 application/json 的请求头就需要将数据转换为 Blob 对象再进行发送。
const blob = new Blob(
[JSON.stringify({ some: "data" })],
{ type: 'application/json; charset=UTF-8' }
)
navigator.sendBeacon('/log', blob)
使用 Navigator.sendBeacon 后就可以将退出后的埋点发送出去。而方法 fetch 则更好使用。
fetch('/log', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ some: 'data' }),
keepalive: true
});
如果将 keepalive 属性设为 true,那么即使发送请求的页面已经退出,请求也将发送出去。
那么我们应该选择哪个使用呢?
fetch():keepalive
- 请求传递自定义标头。
- 向
GET服务发出请求。 - 正在支持较旧的浏览器(如 IE)并且已经
fetch加载了一个 polyfill。
sendBeacon()
- 不需要太多自定义的简单服务请求。
- 更简洁、更优雅的 API。
- 确保请求不会与应用程序中发送的其他高优先级请求竞争。