4

统计用户停留时间前端方案

 3 years ago
source link: https://zhuanlan.zhihu.com/p/121730508
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

统计用户停留时间前端方案

前端工程师 铲屎官 秃头码妹

负责 toC 端的小伙伴可能更多的会遇到产品需要统计用户轨迹的场景,统计用户停留时间是最常见的统计指标。相比 Google Analytics 统计和百度统计,自定义统计更加可定制化不过随之而来的是风险大,以及开发人员的统计精确度问题。 不过鉴于各种限制(比如 Ga 翻墙)所以还是有些需要自己统计的场景。

  • GA 统计已经帮我们完善了大部分基础统计,比如用户是否失焦页面、进入页面开始时间、停留页面时间等。所以只需要自定义添加剩余的业务埋点。

触发开始结束时间

  • (进入页面)首次加载、页面跳转、刷新、浏览器前进后推
  • (离开页面)关闭窗口、页面跳转、刷新、浏览器前进后推

这里提供三种方案。针对不同精确度以及使用场景。

方案一 navigator.sendBeacon()

使用 navigator.sendBeacon(url, data)在用户卸载页面时上报数据,这个方案最直观和高效,也是 GA 统计用户停留时间的实现方案。 采用 FetchApi 来发起异步请求不阻塞页面卸载, 第二个参数可以是使用 Fetch 创建请求时使用的任何请求体类型( Blob,BufferSource,FormData 或者 URLSearchParams)。

  • 浏览器对 Beacon 的支持很好,不过 IE 依旧不支持。
  • 相比 XHR 请求,可以在不阻塞页面卸载的情况下正常上报数据。

示例代码:

import { collectDomain } from "config"; 
 
export const reportData = () => { 
  let startTime = performance.now(); // 进入页面的时间点 
 
  let logVisit = async function() { 
 if (!navigator.sendBeacon) return false; 
 
 const endeTime = performance.now(); // 页面卸载的时间点 
 
    let data = new FormData(); 
 const reportDataList = { 
      event_id, 
      event_name, 
      event_attr, 
        ... 
      stayTime: endeTime - startTime // 用户停留时间 
    }; 
 Object.keys(reportDataList).map(item => { 
      data.append(item, reportDataList[item]); 
    }); 
 
    navigator.sendBeacon("/api/collectData", data); // 异步上报的方式 
  }; 
 window.addEventListener("beforeunload", logVisit); 
};

方案二 进入下一页面时上报

既然方案一接近完美为什么有方案 B ? 因为公司的数据中心部门只采集 json 数据格式的数据,当然优先协商解决,否则可参考方案二。

在卸载页面 A 时存储要上报数据(reportDataA) 到本地存储,进入页面 B 的时候再上报页面 A 的数据(reportDataA)。

  • 本地存储的方式可以是(eventBus、indexDB、localstorage、cookie

示例代码:

import { 
  set as setCookie, 
  get as getCookie, 
  remove as removeCookie 
} from "js-cookie"; 
 
import { dataCollectReport } from "./../services/app"; 
 
const reportDataAxios = async data => { 
  await dataCollectReport(data); 
}; 
 
export const reportData = () => { 
  let startTime = performance.now(); 
 
 // 卸载页面时存储埋点数据到本地缓存, 但未上报 
  let beforeunloadReportData = async () => { 
 const endeTime = performance.now(); 
 const event_id = getCookie("reportDataEventId"); 
 
 if (!event_id) return false; 
 const storageReportData = { 
      event_id, 
      ... 
      stayTime: endeTime - startTime, 
    }; 
    setCookie('storageReportData', reportDataList); 
 
  }; 
 window.addEventListener("beforeunload", beforeunloadReportData); 
};

方案三 精确度 100%,但页面性能降低的降级方案

场景: 直播平台统计学员在页面停留时间需要统计考勤,需要精确度达到 100%。

轮询当前页面最新时间戳,存储要上报数据(reportDataA) 到本地存储,进入页面 B 的时候再上报页面 A 的数据(reportDataA)。

这种方案虽然精确度最高,但是同时最消耗页面性能,酌情使用。

其他埋点要考虑的细节

超链接统计埋点

Image Beacon 方案: 使用 1x1 的透明 gif 图片发送埋点。

使用图片埋点有几个好处:

  1. 执行过程不会引起页面阻塞
  2. GIF 的最低合法体积最小(最小的 BMP 文件需要 74 个字节,PNG 需要 67 个字节,而合法的 GIF,只需要 43 个字节。
  3. 能够完成整个 http 请求加响应。
  1. 只可以是 GET 请求方式

示例代码:

const thisPage = location.href; 
const referringPage = document.referrer || ""; 
const beacon = new Image(); 
beacon.src = 
 "http://www.example.com/logger/beacon.gif?page=" + 
  encodeURI(thisPage) + 
 "&ref=" + 
  encodeURI(referringPage);



// 业务代码
<a href="超链接跳转前要上报数据"> 
  // 这里引入刚创建的img 
</a>

单页面应用跳转页面

  • 首先要了解 React Router 跳转的实现原理
  • 单页面路由的切换主要有两种方式
  • hashchange 变化,监听带"#"链接变化。
  • html5 的 HistoryApi,监听 window.history 的变化。

来看下代码:

// 第一阶段:我们对原生方法进行包装,调用前执行 dispatchEvent 了一个同样的事件 
function aop(type) { 
 var source = window.history[type]; 
 return function() { 
 var event = new Event(type); 
    event.arguments = arguments; 
 window.dispatchEvent(event); 
 var rewrite = source.apply(this, arguments); 
 return rewrite; 
  }; 
} 
 
// 第二阶段:将 pushState 和 replaceState 进行基于 AOP 思想的代码注入 
window.history.pushState = aop("pushState"); 
window.history.replaceState = aop("replaceState"); // 更改路由,不会留下历史记录 
 
// 第三阶段:捕获pushState 和 replaceState 
window.addEventListener( 
 "pushState", 
 function() { 
 // 上报【进入页面】事件 
  }, 
 true 
); 
window.addEventListener( 
 "replaceState", 
 function() { 
 // 上报【进入页面】事件 
  }, 
 true 
);

友情链接跳转

image beacon 方案参考文献
w3c navigator.sendBeacon()
单页面应用数据采集


Recommend

  • 92
    • 新浪科技 tech.sina.com.cn 6 years ago
    • Cache

    Facebook的大麻烦:用户平均停留时间大幅缩水

    来源:华尔街见闻&nbsp;作者:曹弋在被欧盟施压反垄断调查,前高管曝光恶意算法文化后,麻烦缠身的facebook又面临重大问题:平均用户停留时间下降24%。据fastcompany报道,12月份的新数字表明问题似乎越来越严重。最新数据显示

  • 39

    有问题,上知乎。知乎是中文互联网知名知识分享平台,以「知识连接一切」为愿景,致力于构建一个人人都可以便捷接入的知识分享网络,让人们便捷地与世界分享知识、经验和见解,发现更大的世界。

  • 46

    过了个国庆,比上班还要累还要紧张。今天是国庆后的第一个小周末,真是倍儿感轻松,终于有时间把我的最新研究成果公布了。 大家知道,做前端都绕不开跟css打交道。往大了说要布局,往小了说要改颜色,字体大小,

  • 53
    • 掘金 juejin.im 5 years ago
    • Cache

    前端埋点统计方案思考

    埋点即监控用户在应用表现层的行为,于产品迭代而言至关重要。埋点数据分析是产品需求的 来源,检验功能是否达预期的 佐证。前端较服务端更接近用户,本小白将在此对前端埋点统计方案述说一二。 采集埋点数据可做如下分析(以百度统计为例): 将 用户属性、用户行...

  • 3

    使用 Redis 统计在线用户人数¶ 在构建应用的时候, 我们经常需要对用户的一举一动进行记录, 而其中一个比较重要的操作, 就是对在线的用户进行记录。 ...

  • 8
    • segmentfault.com 2 years ago
    • Cache

    使用 Nginx 构建前端日志统计服务

    使用 Nginx 构建前端日志统计服务之前的几篇文章都是关于之前提到的低代码平台的。这个大的项目以 low code 为核心,囊括了编辑器前端、编辑器后端、C 端...

  • 5

    CNZZ自5月10日起停止免费用户的网站统计使用 - 游魂博客-分享技术,资源共享 首页 / CNZZ自5月10日起停止免费用户的网站统计使用 ...

  • 3
    • dreampiggy.com 2 years ago
    • Cache

    Xcode LLDB耗时监控统计方案

    Xcode LLDB耗时监控统计方案 2022-09-07...

  • 6

    停留时间限制措施生效?仅有低于20%无证移民再次申请庇护所1月前纽约市长亚当斯(Eric Adams)对移民采取的严厉措施似乎正在奏效——新的市政府数据显示,在收到30或60天的搬离通知后,只有20%的寻求庇护者返回...

  • 1

    自定义开发odoo14的统计在线用户人数 在 Odoo 14 中统计在线人数通常涉及到定制开发或者使用特定的模块。 ...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK