前提

最近项目有需求,需要对一个小程序以及官网项目就行数据埋点上报,但是又不让使用第三方的SDK,要自己封装,哎,难搞,没办法,就各种抠脑壳查资料,在这做个笔记,总结一下

什么是数据埋点,有什么用

个人理解就是对网站,项目进行业务数据,用户行为数据及其他实际需要的数据进行采集上报,是了解用户行为,分析用户行为,提高用户体验的一种方式,通过这些采集来的数据就可以进行分析,知道用户来源,访问量,点击量,停留时长等数据,将用户使用产品的行为进行可视化,对产品进行优化调整,

常见的解决方案有三种,代码埋点、可视化埋点、和无埋点(全埋点)三种。这三种大体上字面意思也能懂,具体介绍我在这就偷懒不写了,自行百度吧

实现方式

我在项目中 主要采用的是全埋点和代码埋点相结合的方式,因为要采集一部分业务数据,全埋点满足不了,只能结合代码埋点来进行了

全埋点实现过程

全埋点主要是采集一些基本信息,比如浏览器版本号,页面路径,屏幕信息,停留时长,点击事件等数据。而且重要的一点是监测代码不能影响我们现在的业务代码,和以后的业务代码。要解耦。否则难以维护

基础信息采集

首先封装一个对象,包括基础数据,基础配置,数据上报方法,初始化基本信息采集方法,数据上报的方法有很多种,此处是借助访问图片资源的方法来,可以避免跨域,防止阻塞主流程,当然也可以直接使用ajax上报,只要上报的时候如果接口报错异常什么的不要影响到主业务流程即可,下面代码示例中,只是简单的demo,如需其他数据,就自行添加即可

var collect = {params: {},  // 传递或上报的参数data: {serverUrl: "", //上报接口EVENT_PREFIX: "longan-", //全局事件过滤节点前缀},// 设置基本参数配置setData: function (data) {this.data = Object.assign({}, this.data, data);},// 初始化init: function () {//Document对象数据if (document) {this.params.domain = document.domain || ""; //获取域名this.params.url = document.URL || ""; //当前Url地址this.params.title = document.title || "";this.params.referrer = document.referrer || ""; //上一跳路径}//Window对象数据if (window && window.screen) {this.params.sh = window.screen.height || 0; //获取显示屏信息this.params.sw = window.screen.width || 0;this.params.cd = window.screen.colorDepth || 0;this.params.origin = window.location.origin;this.params.pathname = window.location.pathname;}//navigator对象数据if (navigator) {this.params.lang = navigator.language || ""; //获取所用语言种类}},// 上报数据sendRequest: (config) => {config.route = window.location.origin + window.location.pathname;config.createTime = (new Date().getTime() / 1000).toFixed(0);// 直接上报const image = new Image();image.src = data.serverUrl + "?" + parseParams(params);},
};
监听全局的点击事件

大部分埋点都会有对点击事件的采集,这块采集逻辑不能写入业务代码中,避免污染业务逻辑代码,后期难以维护,一般是需要监听特定的功能区按钮,banner等的点击事件,不需要对全局所有节点的点击做采集,所以要做好过滤,通过data-***=’—'的方式传递参数,定义加上事件前缀的id,进行过滤

// 监听全局事件埋点,此处还是属于collect这个对象的一个方法listenTriggerEvent: function (config) {const EVENT_PREFIX = this.data.EVENT_PREFIX;//全局事件过滤节点前缀document.addEventListener("click", (e) => {var dataset = e.target.dataset// 如果目标节点存在事件前缀 则继续if (e.target.id && e.target.id.startsWith(EVENT_PREFIX)) {// ...... 自己搞一些事情.......下面是个示例//const eventName = e.target.id.split(EVENT_PREFIX)[1];//const eventContent = e.target.innerHTML || "";//const payload = Object.assign(config,dataset,{//   type: "event-click",//    client: navigator.userAgent,//  content: eventContent,//    name: eventName,// })//console.log(payload);//上传埋点信息fn// sendRequest(payload);}});},

采集页面停留时长

此处分两种情况单页面应用和多页面应用

  • 多页面应用 (传统的原生写法。没有用spa框架开发的)
    在多页面应用中获取停留时长挺简单的,就是在进入页面或页面显示的时候记录下时间,然后离开页面的时候记录下时间,可以前端算好时间差,也可以直接传给后台由后台计算时间差。主要用到下面几个api

    • onload (页面加载完后)

    • onbeforeunload (页面卸载前,也就是点击叉的时候)

    • onpageshow (页面显示的时候)

    • onpagehide (页面隐藏的时候)
      以上随意取一组就可以了。下面是代码示例,getCurrentTime()是个取当前时间戳的方法,看你们项目需求,自定义返回时间就可以了

listenHistory: function (params) {window.onload = function () {params.createTime = getCurrentTime();params.type = '进入页面'console.log('onload',params);};window.onbeforeunload = function () {params.leaveTime = getCurrentTime();params.type = '离开页面'params.stayLength= params.leaveTime - params.createTimelocalStorage.setItem('onbeforeunload',JSON.stringify(params))};},
  1. 单页面应用

单页面应用复杂些,此处以Vue举例,Vue的路由模式有两种,一种是History,另一种是Hash模式

  • History模式是基于H5的History API实现的,我们只要监听popstate就可以知道,点击前进后退按钮改变的url变化,监听到url发生变化,我们就能统计用户在该页面待了多长时间

window.addEventListener('onload',(e)=>{params.createTime = getCurrentTime()
})window.addEventListener('popstate',()=>{params.leaveTime = getCurrentTime()params.stayLength= params.leaveTime - params.createTimeconsole.log('待了时长:'+ t)
})

但是监听popstate会存在漏洞,看下图

所以还需要重写pushState和replaceState,然后监听两个自定义事件就行,

let resetHistoryFun= function(type){// 将原先的方法复制出来let origin = window.history[type]// 当window.history[type]函数被执行时,这个return出来的函数就会被执行return function(){// 执行原先的方法let rs = origin.apply(this, arguments)// 然后自定义事件let e = new Event(type.toLocaleLowerCase())// 将原先函数的参数绑定到自定义的事件上去,原先的是没有的e.arguments = arguments// 然后用window.dispatchEvent()主动触发window.dispatchEvent(e)return e}
}
--------------------------------
// 更新 20210528
// 最近新了解到哟个新的api 用于自定义事件,但是这个可以传递参数
let e = new CustomEvent(事件名, 参数)
---------------------------------------------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',()=>{})下面是统计时长的具体一点的方法
window.addEventListener('load',(event)=>{timeStr = new Date().getTime()
})window.addEventListener('popstate',(event)=>{let t = new Date().getTime() - timeStrtimeStr = new Date().getTime()console.log('待了时长popstate:'+ t)
})window.addEventListener('pushstate',(event)=>{let t = new Date().getTime() - timeStrtimeStr = new Date().getTime()console.log('待了时长pushstate:'+ t)
})window.addEventListener('replacestate',(event)=>{let t = new Date().getTime() - timeStrtimeStr = new Date().getTime()console.log('待了时长replacestate:'+ t)
})
  • hash模式的话是直接监听hashchange事件就可以了
window.addEventListener('hashchange',()=>{let t = new Date().getTime() - timeStrtimeStr = new Date().getTime()console.log('待了时长:'+ t)
})

但是你会发现 ,咦,我的路由模式是hash模式 怎么不触发hashchange事件呢,主要原因在vue-router源码中有体现,大部分的浏览器中,hash模式的实现还是基于History API实现的Hash-router。具体原因就看源码,或者看这里,这个文章中后续说的很详细

以上就是大概自己封装埋点方法的内容了,可以把上述功能代码用闭包给包裹起来,保存私有变量,避免污染全局,只暴漏出来一些方法,或可以把这个js文件使用rollup打包成各种版本的sdk文件,与业务代码完全分离,供多个项目使用。如果有更好的实现方式,欢迎交流。

关于前端代码埋点数据上报的实现相关推荐

  1. 【前端监控系统】埋点数据上报的3种方式

    前言 首先,我们先对前端监控做一些简单的描述: 前端监控的目的? 提升用户体验 更快的发现发现异常.定位异常.解决异常 了解业务数据,指导产品升级--数据驱动的思想 它指的是通过一定的手段来获取用户行 ...

  2. 京东科技埋点数据治理和平台建设实践

    本文核心内容聚焦为什么要埋点治理.埋点治理的方法论和实践.奇点一站式埋点管理平台的建设和创新功能.读者可以从全局角度深入了解埋点.埋点治理的整体思路和实践方法,落地的埋点工具和创新功能都有较高的实用参 ...

  3. 前端埋点数据收集及上报方案

    本文作者:随风丶逆风 本文链接:https://juejin.cn/post/6938075086737899534 什么是埋点 埋点,它的学名是事件追踪(Event Tracking),主要是针对特 ...

  4. 前端埋点数据收集及上报方案实战

    什么是埋点 埋点,它的学名是事件追踪(Event Tracking),主要是针对特定用户行为或业务过程进行捕获.处理和发送的相关技术及实施过程.埋点是数据领域的一个专业术语,也是互联网领域的一个俗称. ...

  5. 基于指令和混合的前端通用埋点方案

    https://zhuanlan.zhihu.com/p/27659302 摘要 本文介绍了一种通用的前端埋点方案的设计和实现,具有适配项目广泛,易于使用,与业务逻辑解耦等优点,已经在外卖商业平台进行 ...

  6. 埋点tracker:前端数据埋点-方案设计思路梳理

    一.理解埋点 所谓埋点就是在应用中特定的流程收集一些信息,用来跟踪应用使用的状况,后续用来进一步优化产品或是提供运营的数据支撑,包括访问数(Visits),访客数(Visitor),停留时长(Time ...

  7. 美团点评前端无痕埋点实践

    构建一个数据平台,大体上包括数据采集.数据上报.数据存储.数据计算以及数据可视化展示等几个重要的环节.其中,数据采集与上报是整个流程中重要的一环,只有确保前端数据生产的全面.准确.及时,最终产生的数据 ...

  8. 前端代码异常日志收集与监控

    在复杂的网络环境和浏览器环境下,自测.QA测试以及 Code Review 都是不够的,如果对页面稳定性和准确性要求较高,就必须有一套完善的代码异常监控体系,本文从前端代码异常监控的方法和问题着手,尽 ...

  9. 代码埋点、可视化埋点、无埋点几种数据埋点方案的分析报告

    目录 数据采集的核心问题 一.埋点是什么 二.为什么要埋点 三.埋点有哪些方式 四.各埋点方式优劣对比 五.其他 在这篇文章里面,我们会对数据采集的一些基本概念进行阐述,然后,会针对目前市面上新增的一 ...

最新文章

  1. vb中5种打开文件夹浏览框的方法总结(转)
  2. 天秀,17 岁高中生独立开发全球疫情追踪网站后火了!
  3. JAVA里tokens意思_Java TokenMetadata.sortedTokens方法代码示例
  4. 《 短文本数据理解》——2.5小结
  5. 「 每日一练,快乐水题 」258. 各位相加
  6. kafka一键启动集群
  7. 实现自己的.NET Core配置Provider之Yaml
  8. MySQL笔记-免密码登录小技巧(运行参数填写skip-grant-tables)
  9. WinAPI: PolylineTo - 绘制一组连续线段(更新当前位置)
  10. Windows Shellcode学习笔记——Shellcode的提取与测试
  11. MaxCompute 2.0 生态开放之路及最新发展
  12. Linux安装ParaView
  13. 一些用JAVA实现的小题目
  14. 经典图书介绍:广义相对论--1972讲稿
  15. 关于示波器探头的输入容抗问题解决
  16. NS3系列—3———NS3中文:4 概念描述
  17. ubuntu18.04安装中中文输入法
  18. “Project1.exe”(Win32): 已加载“C:\Windows\syswow64\ntdll.dll”。无法查找或打开 PDB 文件。 “Project1.exe”(Win32): 已加载
  19. Java poi api插入文字水印到docx文件
  20. Win10 提示WerFault.exe 应用程序错误解决方法(非常规方法)

热门文章

  1. QT QGraphicsItem 消除重影 移动重影
  2. 抖音视频如何发到快手?短视频如何一键发布?
  3. [AHK]通达信联动到同花顺下单
  4. 什么是生化分析中的反应曲线?
  5. [HTML5]简单网页本地音乐播放器
  6. vlog拍摄与剪辑入门之路
  7. 从0开始构建一个k8s集群
  8. SPSS MODELER笔记1----数据基本处理和整体方法概念
  9. 2020.10.18--PS--长角动画、挡眼、闪光效果
  10. 电商资讯 | 黑鲨大幅裁员,2022年游戏手机销量大跳水,降幅近40%