使用 visibilitychange 事件配合时间戳可准确统计用户真正观看页面的时长:仅在 document.visibilitystate === 'visible' 时计时,状态变 hidden 时累加时长并上报,卸载前用 beforeunload 补报,兼顾兼容性与准确性。

直接用 visibilitychange 事件配合时间戳,就能准确统计用户“真正看到页面”的时长,避开切到其他标签页、锁屏、最小化等无效停留时间。
监听页面可见性变化
Page Visibility API 提供 document.visibilityState(当前状态)和 visibilitychange 事件(状态切换时触发)。关键状态有:
- visible:页面在前台且可见(包括被部分遮挡但未完全隐藏)
- hidden:页面不在前台(切换标签页、最小化、锁屏、系统休眠等)
- prerender(已废弃或极少使用,可忽略)
记录有效停留的起止时间
只在 visibilityState === 'visible' 时才计入有效时长。建议这样操作:
- 页面加载完成时,记录初始时间(
startTime),但先不开始计时 - 首次触发
visibilitychange且状态变为'visible'时,标记为“真正开始使用”,记录activeStart = Date.now() - 状态变为
'hidden'时,计算本次可见时长:Date.now() - activeStart,累加到总时长中 - 再次变回
'visible',重新设置activeStart,继续累计
注意:不要依赖 pagehide 或 beforeunload,它们可能不触发(如安卓后台杀进程),而 visibilitychange 更可靠。
处理页面卸载前的最终上报
用户关闭标签页或跳转前,可能还有一次 'visible' 到 'hidden' 的切换;但若直接关闭,也可能没机会触发。稳妥做法是:
- 在
visibilitychange中每次状态变为'hidden'就立即上报当前累计时长(可节流,避免高频) - 同时监听
beforeunload,做最后一次补报(仅当尚未上报过该次 hidden 状态) - 服务端应支持合并同一会话的多次上报,取最大值或累加,避免重复计费或统计偏差
补充细节与兼容性提醒
实际使用需注意:
- 旧版浏览器需加前缀:
webkitvisibilitychange、msvisibilitychange,现代浏览器已原生支持 - iOS Safari 在后台播放音频/视频时可能保持
visible,但用户实际未看页面——如有精准场景,可结合document.hasFocus()辅助判断 - 单页应用(SPA)中,路由切换不会触发 visibilitychange,所以无需额外处理;但要确保每个“逻辑页面”都独立统计或继承会话 ID
- 不要把 visibilitychange 当作用户行为埋点替代品(如点击、滚动),它只反映可见性,不反映是否在交互
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










