捕获用户在该页面停留的时长,我是这样做的(前端监测)
前言
为什么要做这个监测用户停留的呢?原因很简单,如果我们要分析这个页面对我们的产品有没有价格,那么用户浏览的时长是一个很关键的点,如果每个用户平均每天在这个页面停留两个小时以上,那么我们会觉得这个页面的价值很高;如果一个页面一个月也没几个用户去浏览,那我们就会有疑问,这个页面对我们的产品还有价值吗?我们的产品后续还要保留它的?这些需求都是可以让我们考虑是否要去获取用户停留时长这个功能的。
针对哪些应用?
多页面应用
单页面应用
如何去获取用户停留的时长?
在监测功能的时候,我们首要考虑的就是,我们的监测代码不能影响我们现在的业务代码,和以后的业务代码。
多页面应用
在多页面应用,要获取用户的停留时间还是挺简单的,看看下面几个Api????
onload (页面加载完后)
onbeforeunload (页面卸载前,也就是点击叉的时候)
onpageshow (页面显示的时候)
onpagehide (页面隐藏的时候)
经过自己的一点小测试,发现无论在关闭的时候(也就是点击叉),还是隐藏的时候(也就是点击左右箭头)都会触发 onpagehide
;也无论是在首次加载,还是刷新的时候,都会触发onpageshow
,但是刷新的时候会先触发onpagehide
,在触发onpageshow
。其他两个API也是类似,最后,个人选择了用onpageshow
和onpagehide
这个两个API获取用户停留的时长,你也可以用其他两个API做。只要在onpageshow
初始时间值,在onpagehide
的时间求出差值,然后上传到后台就行。
let stopTimewindow.onpageshow = ()=>{stopTime = new Date().getTime()
}window.onpagehide = ()=>{stopTime = new Date().getTime() - stopTimelet record = localStorage.getItem('data')let data = record && JSON.parse(record) || []localStorage.setItem('data',JSON.stringify([...data,{user:new Date().getTime(),path:window.location.href,stopTime}]))
}
完成代码就那么点,这里我只是测试,就把模拟的用户id,真实的路径,真实的停留时长存储了在localStorage,在项目中可以传到后台,然后通过分析,再可视化展示出来。
上面效果图(录得GIF就那AV画质,没钱开VIP,将就看吧,有点AV感觉也好,哈哈),第一次点击的是叉
,点击叉那也可以理解为离开了页面,第二次a链接跳转
,第三次刷新
,刷新也可以理解为一次离开吧,一共存了三条数据,有兴趣自己试试更好理解。
单页面应用
单页面应用可能,会复杂一点,但是也复杂到哪里去。
单页面应用的路由跳出,但是基于 H5的History API(browserHistory)
和 Hash(hashHistory)
实现的。
browserHistory
单页面的browserHistory路由
是基于H5的History API实现的,我们只要监听popstate
就可以知道,点击前进后退按钮改变的url变化,表url发生变化,我们就能统计用户在该页面待了多长时间,代码如下????
let timeStrwindow.addEventListener('onload',(e)=>{timeStr = new Date().getTime()
})window.addEventListener('popstate',()=>{let t = new Date().getTime() - timeStrtimeStr = new Date().getTime()console.log('待了时长:'+ t)
})
但是,pushState和replaceState(也就是,点击router-view,$router.push,$router.replace,window.history.pushState,window.history.replaceState不会触发,可以自行试试)
不会触发popstate
,那我们就统计不了用户待在该页面的时长的了;可是解决方法还是有的,只需要重写pushState和replaceState
,然后监听两个自定义事件就行,看下面代码????
// 对原函数做一个拓展
let rewriteHis = function(type){let origin = window.history[type] // 先将原函数存放起来return function(){ // 当window.history[type]函数被执行时,这个函数就会被执行let rs = origin.apply(this, arguments) // 执行原函数let e = new Event(type.toLocaleLowerCase()) // 定义一个自定义事假e.arguments = arguments // 把默认参数,绑定到自定义事件上,new Event返回的结果,自身上市没有arguments的window.dispatchEvent(e) // 触发自定义事件,把载荷传给自定义事件return rs}
}window.history.pushState = rewriteHis('pushState') // 覆盖原来的pushState方法window.history.replaceState = rewriteHis('replaceState') // 覆盖原来的replaceState方法// 监听自定义事件, pushstate事件是在rewriteHis时注册的,不是原生事件
// 当点击router-link 或者 window.history.pushState 或者 this.$router.push 时都会被该事件监听到
window.addEventListener('pushstate',()=>{})// 监听自定义事件, replacestate事件是在rewriteHis时注册的,不是原生事件
// 当点击window.history.replaceState 或者 this.$router.replace 时都会被该事件监听到
window.addEventListener('replacestate',()=>{})
rewriteHis函数
,这个函数主要是对原函数做了一个拓展,上面代码的注释应该说了很清楚了。
browserHistory路由变化监听完整代码????
let timeStrlet rewriteHis = function(type){let origin = window.history[type]return function(){let rs = origin.apply(this, arguments)let e = new Event(type.toLocaleLowerCase())e.arguments = argumentswindow.dispatchEvent(e)return rs}
}window.history.pushState = rewriteHis('pushState')window.history.replaceState = rewriteHis('replaceState')window.addEventListener('onload',(e)=>{timeStr = new Date().getTime()
})window.addEventListener('popstate',()=>{let t = new Date().getTime() - timeStrtimeStr = new Date().getTime()console.log('待了时长popstate:'+ t)
})window.addEventListener('pushstate',()=>{let t = new Date().getTime() - timeStrtimeStr = new Date().getTime()console.log('待了时长pushstate:'+ t)
})window.addEventListener('replacestate',()=>{let t = new Date().getTime() - timeStrtimeStr = new Date().getTime()console.log('待了时长replacestate:'+ t)
})
这里的演示就不做任何存储了,喜欢的话,自己做一下????
hashHistory
hashHistory
就简单得不行了,直接监听hashchange
就行
window.addEventListener('hashchange',()=>{let t = new Date().getTime() - timeStrtimeStr = new Date().getTime()console.log('待了时长:'+ t)
})
到这里为止,单页面应用,多页面应用怎么去获取用户待在该页面的时长就说完了。也不是很理解,挺简单的。
后续
你以为这就完事了吧,还有一个奇怪的问题。
const router = new VueRouter({mode:'hash',routes:[...]
})
我在测试hash路由
切换的时候,看会不会触发window.addEventListener('hashchange',()=>{})
,奇怪的事情发生了,它没有触发,却触发了自定义window.addEventListener('replacestate',()=>{}和window.addEventListener('pushstate',()=>{})等History API
,究竟是为什么?我明明把它设置为hash路由了,为什么还会触发History API?带着这个疑问,我忍不住的去看了vue-router的源码,最后,解开了自己的疑问,看下面:
在vue-router的hash路由实现文件????
有这么一段代码,在 supportsPushState
为false
时,才会走else
逻辑,else
的逻辑才会触发window.addEventListener('hashchange',()=>{})
,那它为什么不走?supportsPushState
又是什么?pushState,replaceState
又是怎么实现的?为什么它会触发自定义事件?
supportsPushState
来看看supportsPushState是什么????
上面是supportsPushState的逻辑,看到这逻辑,是不是瞬间就明白了为什么不走else
逻辑的hash语句了。当满足这些条件才会走else语句(ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) && ua.indexOf('Mobile Safari') !== -1 && ua.indexOf('Chrome') === -1 && ua.indexOf('Windows Phone') === -1
,否则其他都是走基于History API实现的Hash-router
,我测了几个浏览器(谷歌,UC,火狐,IE最新版那个,搜狗)都是走基于History API实现的Hash-router
,有兴趣的子集测一下。
pushState , replaceState
再来看看这两个api的实现????
原来它们都是调用了 History API
实现,这就解开了为什么它会触发自定义事件的原因了。
看源码指引????
如果你不相信,我比比的话,可以自行看看源码。
最后
以上是个人,获取用户在多页面,单页面停留的时长,如果有更好的方法,欢迎交流。????保命)
❤️爱心三连击1.看到这里了就点个在看支持下吧,你的「点赞,在看」是我创作的动力。
2.关注公众号程序员成长指北,回复「1」加入高级前端交流群!「在这里有好多 前端 开发者,会讨论 前端 Node 知识,互相学习」!
3.也可添加微信【ikoala520】,一起成长。“在看转发”是最大的支持
捕获用户在该页面停留的时长,我是这样做的(前端监测)相关推荐
- 捕获用户在该页面停留的时长(前端监测)
捕获用户在该页面停留的时长,我是这样做的(前端监测) 前言 为什么要做这个监测用户停留的呢?原因很简单,如果我们要分析这个页面对我们的产品有没有价格,那么用户浏览的时长是一个很关键的点,如果每个用户平 ...
- 前端如何捕获用户在该页面停留的时长?
前言 为什么要做这个监测用户停留的呢?原因很简单,如果我们要分析这个页面对我们的产品有没有价格,那么用户浏览的时长是一个很关键的点,如果每个用户平均每天在这个页面停留两个小时以上,那么我们会觉得这个页 ...
- 监听用户在页面停留的时长 / 监听多个页面时长
1.监听用户在页面停留的时长 2.如果要监听多个页面的时间,并且返回上一页累加上次浏览的时间功能 //记录阅读任务阅读列表recordTaskList() {this.quit_time = 0;le ...
- react利用useEffect记录用户在当前页面停留时长
项目场景: 小程序项目中需要记录用户在当前页面停留的时长,下意识想到在useState中记录一个时间戳,在useEffect中的return中获取一个时间戳,减去state中记录的时间戳,用得到的值取 ...
- 怎样统计用户在当前页面停留的时间
页面停留时间(Time on Page)简称 Tp,是网站分析中很常见的一个指标,用于反映用户在某些页面上停留时间的长短,传统的Tp统计方法会存在一定的统计盲区,比如无法监控单页应用,没有考虑用户切换 ...
- App性能:启动耗时和页面加载时长
如何监控 iOS 的启动耗时 Github use wwdc 2016 all Video 抖音品质建设 - iOS启动优化<原理篇> 抖音品质建设 - iOS启动优化<实战篇> ...
- 时长一年半的前端练习生2022年终总结
2022感觉过得真快,还有一周就结束了,趁着周末有时间来总结一下2022做了什么.最近小
- 如何精确统计用户在页面的停留时长?
作者:今日头条技术 链接:https://techblog.toutiao.com/2018/06/05/ru-he-jing-que-tong-ji-ye-mian-ting-liu-shi-cha ...
- 如何精确统计页面停留时长
关注公众号 前端开发博客,回复"加群" 加入我们一起学习,天天进步 作者:今日头条技术 链接:https://techblog.toutiao.com/2018/06/05/ru- ...
最新文章
- 快速入门cocos2d-x jsbinding
- datavideo切换台说明书_巴掌大三轴稳定器,稳过微云台,试试飞宇VLOGPocket2
- (4)ZYNQ AXI4总线协议介绍
- c 语言程序上机考试系统,计算机二级C语言上机考试操作步骤及流程
- 多闪实名举报河南法院;ofo 内部发反腐文件;库克访华点赞故宫 App | 极客头条...
- 论文笔记之:Deep Reinforcement Learning with Double Q-learning
- Tensorflow中的RNN个人备忘
- Android Problem- android.content.res.Resources$NotFoundException: String resource ID #0xa
- 数据结构和算法(C语言版)期末速成基础不挂科补考
- Spring框架的详细学习
- 英伟达服务器系统显卡驱动,NVIDIA显卡驱动
- selenium调用javascript代码的方法
- 拥抱云原生,聊聊高度解耦的密码管理解法
- 嵌入式C语言学习笔记附图
- 收费的Chemdraw跟不上时代潮流
- 圆柱模板价格计算器V1.0版本
- 一个静态网站需要服务器吗,静态网站需要服务器吗
- [004]爬虫系列 | 中文编码问题
- Arduino ESP32自平衡小车制作实现(不需编码器)
- 理解逻辑回归中的后验概率和损失函数
热门文章
- 既然来到了这个世界,何必还是那么认真
- @Pointcut 的常用方式:execution,within,this,target,args,@within,@target,@args,@annotation等介绍
- 初学者的外汇交易平台
- Docker数据持久化
- java httpclient 使用_java之HttpClient简单使用
- MIME到底是什么?那些重要?
- 涡旋光束(二)--矢量涡旋光束的介绍
- 《飞鸽传书下载》发送和接收信息
- oracle odp.net 11g,Oracle 11g客户端是否需要ODP.NET?
- gis是一门集计算机科学,gis是什么_GIS技术对生活生产有什么作用