统计用户停留网站时长

6,069 阅读4分钟

最近接到一个需求,需要统计用户从进入网页到全部网页都在浏览器关闭这个过程的时间。

首先确定一下需求:

  1. 用户一进来,记录用户进入页面的开始时间;
  2. 用户在新的标签页打开页面,如果其他标签页已经打开了页面,这时候的开始时间还是算第一次进入的页面的时间;
  3. 用户关闭该网页的全部标签页时,需要记录关闭的结束时间,调用接口传数据给后台;

首先,进入页面的时候,浏览器会调用onload事件,浏览器关闭时,浏览器会调用beforeunload事件,可以从这两个事件入手。

但是这里有几个问题,那就是浏览器刷新的时候,也会调用beforeunload,还有就是如何知道用户在其它标签页也打开了网页呢?

有什么可以记录浏览器是否刷新呢?这时候我想到了sessionStorage

sessionStorage,用于临时保存同一窗口(或标签页)的数据,在关闭窗口或标签页之后将会删除这些数据。也就是说数据存储在sessionStorage中,在当前标签页会一直存在。

首先在初次进入页面时在onload事件中往sessionStorage存入一个标识

window.addEventListener("load",function(){
    if(sessionStorage.getItem("flag")){
        return;
    }
    sessionStorage.setItem("flag", true);
})

上面说的还有一个问题,就是如何统计用户打开了多个标签页呢?

在本地缓存中,localStorage中的数据是整个网站都可以共享的,也就是具有相同域名、ip的网站,localStorage里的数据在不同标签页中也是相同的。

这时候可以往localStorage里存一个计数器,当用户进入页面时,计数器加1,当用户离开页面时计数器减1。当计数器为0时,标志页面全部关闭,此时可以记录页面关闭的结束时间。同时访问网站的开始时间也存到localStorage

window.addEventListener("load",function(){
    let nowTime = getNowTime()
    let openPageCount = localStorage.getItem("openPageCount")
    openPageCount += 1
    localStorage.setItem("openPageCount",openPageCount)
    //其实说明是页面是刷新后加载的,不应该统计开始时间
    if(sessionStorage.getItem("flag")){
        return;
    }
    localStorage.setItem("startTime",nowTime)
    sessionStorage.setItem("flag", true);
})

window.addEventListener("beforeunload",function(){
    let nowTime = getNowTime()
    let openPageCount = localStorage.getItem("openPageCount")
    openPageCount -= 1
    localStorage.setItem("endTime",nowTime)
    localStorage.setItem("openPageCount",openPageCount)
    if(openPageCount == 0){
        //说明页面全部关闭,这时候可以传数据给后台
    }
})

function getNowTime(){
    let nowTime = new Date().getTime()
    return nowTime
}

这里还有个问题,就是用户意外关掉电脑或者突然断电了,这时候是不会执行beforeunload是不会执行,此时这个数据是不正确,是应该抛弃的。

要解决这个问题,可以往localStorage里存一个刷新时间,每30秒更新这个刷新时间,用户加载网站时,读取这个刷新时间,如果当前时间和这个刷新时间相差大于1分钟,说明数据有断层,此时应该抛弃这一条记录数据。

window.addEventListener("load",function(){
    let nowTime = getNowTime()
    let openPageCount = localStorage.getItem("openPageCount")
    openPageCount = openPageCount ? parseInt(openPageCount) : 0
    openPageCount += 1
    localStorage.setItem("openPageCount",openPageCount)
    refreshTime()
    let isRightTime =  compareRefreshTime()
    //其实说明是页面是刷新后加载的,不需要统计开始时间
    if(sessionStorage.getItem("flag") && isRightTime){
        return;
    }
    localStorage.setItem("startTime",nowTime)
    localStorage.setItem("refreshTime",nowTime)
    sessionStorage.setItem("flag", true);
})

window.addEventListener("beforeunload",function(){
    let nowTime = getNowTime()
    let openPageCount = localStorage.getItem("openPageCount")
    openPageCount -= 1
    localStorage.setItem("endTime",nowTime)
    localStorage.setItem("openPageCount",openPageCount)
    if(openPageCount == 0){
        //说明页面全部关闭,这时候可以传数据给后台
    }
})

function getNowTime(){
    let nowTime = new Date().getTime()
    return nowTime
}

function compareRefreshTime(){
   let nowTime = getNowTime()
   let refreshTime = localStorage.getItem("refreshTime")
   return nowTime - refreshTime < 60 * 1000
}

function refreshTime(){
    setTimeout(refreshTime ,30 * 1000)
    let nowTime = getNowTime()
    localStorage.setItem("refreshTime",nowTime)
}

以上就是统计用户停留网站时长思路的全部代码。

应用场景可以是统计手机App使用时长、统计用户打开网站后多久会关闭,这都是属于大数据的范畴。

由此可以拓展到用户使用每个页面的浏览时长,统计每个页面浏览时长可以更好的统计哪些页面是用户经常浏览,从而更好的优化这些页面,而浏览量比较少的或者没有浏览量的页面应该重新设计或者花更少时间去维护。而在前端方面存储这些数据的实现思路总体是差不多的。

当然上面的方法也有一定的缺点,比如数据可能会丢失、每个打开的页面都要启动一个定时器等等。

如果需要数据更精准些,我们可以使用websocket或者启动一个定时器定时向后台传数据等等,这样会也有一点的缺点,比如增大服务器压力,影响性能。