likes
comments
collection
share

埋点项目实录之三:页面停留时间

作者站长头像
站长
· 阅读数 17

页面停留时间

Time on Page简称Tp,用于反映用户在某些页面上停留时间的长短。

分析停留

页面的生命周期抽象为三个动作: 进入活跃状态切换离开

动作触发行为
进入首次加载、页面跳转、刷新、浏览器前进后退
活跃状态切换页面失去焦点/获得焦点、切换窗口最小化、切换浏览器tab、电脑睡眠和唤醒
离开关闭窗口、页面跳转、刷新、浏览器前进后退

监听页面

常规页面的首次加载、页面关闭、刷新、等操作都可以通过window.onloadwindow.onbeforeunload事件来监听。

页面进入和离开浏览器的前进和后退可以通过pageshowpagehide处理。

监听页面活跃状态切换可以使用Page Visibility API和window上声明onblur/onfocus事件来处理。

这里建议使用Page Visibility API来处理,具体原因见埋点项目实录之二:数据上报

单页面应用

内部的跳转可以转化为两个问题:

  1. 监听路由变化
  2. 判断变化的URL是否为不同页面

主流的单页面应用大部分都是基于browserHistory(history api)或者hashHistory来做路由处理,通过监听路由变化来判断页面是否有可能切换

注意是有可能切换,因为URL发生变化不代表页面一定切换,具体的路由配置是由业务决定的。

browserHistory

路由变化的本质都会调用history.pushState()history.replaceState(),但是popState事件只会在浏览器前进后退的时候触发(调用history.back()或者history.forward()),当调用history.pushState()或者history.replaceState()的时候并不触发,因此需要重写history.pushStatehistory.replaceState方法。

let wr = function(type){
  let origin = window.history[type];
  return function(){
      let value = origin.apply(this, arguments);
      let e = new Event(type.toLowerCase());
      e.arguments = arguments;
      window.dispatchEvent(e);
      return value;
  }
}
window.history.pushState = wr('pushState');
window.history.replaceState = wr('replaceState');

hashHistory

hashHistory的实现是基于hash的变化,hash的变化可以通过hashchange来监听。

vue-router源码

function pushHash (path) {
  if (supportsPushState) {
    pushState(getUrl(path))
  } else {
    window.location.hash = path
  }
}

function replaceHash (path) {
  if (supportsPushState) {
    replaceState(getUrl(path))
  } else {
    window.location.replace(getUrl(path))
  }
}


export const supportsPushState = inBrowser && (function () {
  const ua = window.navigator.userAgent

  if (
    (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
  ) {
    return false
  }

  return window.history && 'pushState' in window.history
})()

export function pushState (url?: string, replace?: boolean) {
  saveScrollPosition()
  // try...catch the pushState call to get around Safari
  // DOM Exception 18 where it limits to 100 pushState calls
  const history = window.history
  try {
    if (replace) {
      history.replaceState({ key: _key }, '', url)
    } else {
      _key = genKey()
      history.pushState({ key: _key }, '', url)
    }
  } catch (e) {
    window.location[replace ? 'replace' : 'assign'](url)
  }
}

export function replaceState (url?: string) {
  pushState(url, true)
}

观察vue-router源码可知,使用hash路由时,只有在supportsPushStatefalse的情况下,才会真的使用window.location进行hash切换,否则还是使用的browserHistory路由进行切换。

以上全部内容,如有疑问,欢迎指正。

埋点项目实录之三:页面停留时间