关于页面退出上报埋点这件事

1,011 阅读2分钟

前言

在业务需求中,常常会统计页面的 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。
  • 确保请求不会与应用程序中发送的其他高优先级请求竞争。