hualctracker

1.0.19 • Public • Published

LinkOffice-Tracker

引言

前端埋点sdk的方案十分成熟,之前用的都是公司内部统一的埋点产品,从前端埋点和数据上报后的可视化查询全链路打通。但是在最近的一个私有化项目中就遇到了问题,因为服务都是在客户自己申请的服务器上的,需要将埋点数据存放到自己的数据库中,同时前端埋点的功能简洁,不需要太多花里胡哨的东西。公司内部的埋点产品不适用,外部一些十分成熟的埋点产品又显得太臃肿,因此着手自己在开源包的基础上封了一个简单的埋点sdk,简单聊聊其中的一些功能和解决方式。

云业务模块appid

模块 模块名称 Appid
门户 portal 10001
公文管理 gongwen 10050
公文管理移动端 gongwen-mobile 10051
业务生成器 ofs 10100
业务生成器移动端 ofs-mobile 10101
信息发布 xinxi 10150
信息发布移动端 xinx-mobile 10151
文档中心 document 10200
文档中心移动端 document-mobile 10201

饮水思源

功能

对于产品来说,埋点上首要关心的是页面的pv、uv,其次是一些重要操作(以点击事件为主)的频率,针对某些曝光量高的页面,可能也会关注页面的热力图效果。满足这些关键功能的基础上,同时把一些通用的用户环境参数(设备参数、时间参数、地区参数)携带上来,发送请求到指定的后端服务接口,这就基本上满足了一个埋点skd的功能。

大概就具备了以下一些功能:

1.页面加载完成自动上报pv、uv 2.支持用户手动上报埋点 3.上报时默认携带时间、设备等通用参数 4.支持用户自定义埋点参数上报 5.支持用户标识设置 6.支持自动开始热力图埋点(页面中的任意点击会自动上报) 7.支持dom元素配置化的点击事件上报 8.支持用户自定义埋点上报接口配置

使用说明

  1. 配置npm的源为:云效

  2. 安装包

    npm install @linkofffice/tracker
  3. 配置环境

    1、创建文件:\src\tracker\index.js

    import Vue from 'vue'
    import Tracker from '@linkoffice/tracker'
    
    Vue.use(Tracker)
    const tracker = new Tracker({
      masterReport: true, // 总开关,控制是否上报,默认开启
      appid: '100001', // 应用标识,用来区分埋点数据中的应用
      uuid: '', // 设备标识,自动生成并存在浏览器中,
      extra: {}, // 用户自定义上传字段对象
      enableTrackerKey: true, // DOM上报
      enableHeatMapTracker: false, // 是否开启热力图自动上报暂不开启
      enableLoadTracker: true, // 是否开启页面加载自动上报,适合多页面应用的pv上报
      enableHistoryTracker: true, // 是否开启页面history变化自动上报,适合单页面应用的history路由
      enableHashTracker: true, // 是否开启页面hash变化自动上报,适合单页面应用的hash路由
      requestUrl: '/tracker' // 埋点请求后端接口
    })
    
    export default tracker

    2、引入main.js文件

    import tracker from './tracker'
    
    new Vue({
      router,
      store,
      tracker, // 注入vue
      render: h => h(App)
    }).$mount('#app')
  4. 设置登录人员信息

    在有身份信息后请第一时间设置登录人的ID

    this.$tracker.setUserId('1001')
  5. js上报

    在代码中直接加入对应的方法

    // 埋点发送方法,3个参数分别是:事件类型,事件标识,上报数据
    this.$tracker.sendTracker('click', 'module1', { a: 1, b: 2, c: 'ccc' })
  6. DOM上报

    需开启enableTrackerKey,直接在DOM 对象上设置属性tracker-key值为对应的eventId

    <Button type="submit" tracker-key="{{eventId}}">确定</Button>

配置参数

参数 说明 类型 默认值
masterReport 上报总开关 Boolean true
appid 应用标识 string
uuid 设备标识,自动生成并存在浏览器中, string uuid
extra 用户自定义上传字段对象 json对象 {}
enableTrackerKey dom点击上报 Boolean false
enableHeatMapTracker 是否开启热力图自动上报 Boolean false
enableLoadTracker 是否开启页面加载自动上报,适合多页面应用的pv上报 Boolean false
enableHistoryTracker 是否开启页面history变化自动上报,适合单页面应用的history路由 Boolean false
enableHashTracker 是否开启页面hash变化自动上报,适合单页面应用的hash路由 Boolean false
requestUrl 埋点请求后端接口 string

可用事件

事件 说明 参数
setUserId 设置登录人ID信息 string
sendTracker 埋点发送方法 事件类型,事件标识,上报数据

上报参数说明

字段 简写 含义
appid api 应用标识
uuid uid 设备id
branchid bid 分支ID
eventType et 事件类型
eventId ei 事件ID
userId uei 用户id
browser br 浏览器类型
browserVersion bv 浏览器版本
engine eng 浏览器引擎
language lang 语言
device dv 客户端
os os 设备类型
osVersion osv 设备版本号
eventTime eti 埋点上报时间
title tit 页面标题
url ul 页面地址
domPath dp 事件触发的dom
offsetX ox 事件触发的dom的x坐标
offsetY oy 事件触发的dom的y坐标
extra 用户自定义字段对象

更新说明

  1. 修改代码

  2. 编译代码

    npm run build
  3. 推送私有化npm 说明

    npm publish
    

代码说明

pv统计

pv的统计根据业务方需求有两种方式,第1种是完全由业务方自己来控制,在页面加载或变化的时候调用通用埋点方法来上报。第2种是通过初始化配置开启自动pv统计,由sdk来完成这一部分的埋点上报。第1种方式非常好理解,就不具体展开来,下面具体说一些sdk自动埋点统计的实现原理:

对于多页面应用,每次进一个页面就是一次pv访问,所以配置了 addEventListener = true 之后,sdk内部会对浏览器的load事件进行监听,当页面load后进行埋点上报,所以本质上是对浏览器load事件的监听和处理。

对于单页面应用来说,只有第一次加载页面才会触发load事件,后续路由的变化都不会触发。因此除了监听load事件外,还需要根据路由的变化监听对应的事件,单页面应用有两种路由模式:hash模式和history模式,两者的处理方式有所差异:

  • hash模式,单页面应用的hash路由实现原理是通过改变url的hash值来实现无页面刷新的,hash的变化会触发浏览器的hashchange事件,因此埋点sdk中只需要对hashchange事件进行监听,就可以在事件触发时进行埋点上报。
  • history模式,单页面应用的history路由实现的原理是通过操纵浏览器原生的history对象,history对象中记录着浏览器会话的历史记录,并提供了一些方法对会话栈进行管理。如:
history.go(): 
history.forward():
history.back():
history.pushState():
history.replaceState():

和hash模式不同的是,上述的history.go、history.forward 和 history.back 3个方法会触发浏览器的popstate事件,但是history.pushState 和 history.replaceState 这2个方法不会触发浏览器的popstate事件。然而主流的前端框架如react、vue中的单页面应用history模式路由的底层实现是依赖 history.pushState 和 history.replaceState 的。因此并没有原生的事件能够被用来监听触发埋点。为了解决这个问题,可以通过改写history的这两个事件来实现新事件触发:

const createHistoryEvent = function(type) {
    var origin = history[type];
    return function() {
        var res = origin.apply(this, arguments);
        var e = new Event(type);
        e.arguments = arguments;
        window.dispatchEvent(e);
        return res;
    };
};

history['pushState'] = createHistoryEvent('pushState');
history['replaceState'] = createHistoryEvent('replaceState');

改写完之后,只要在埋点sdk中对pushState和replaceState事件进行监听,就能实现对history模式下路由变化的埋点上报。

uv统计

埋点对pv的支持是必不可少的,sdk会提供了一个设置用户uid的方法setUserId暴露给业务使用,当业务平台获取到登录用户的信息后,调用该方法,则会在后续的埋点请求中都带上uid,最后在埋点分析的时候以该字段进行uv的统计。但是这样的uv统计是不准确的,因为忽略了用户未登录的情况,统计出来的uv值是小于实际的,因此需要在用户未登录的情况下也给一个区分标识。这种标识常见的有以下几种方式:

  • 用户ip地址
  • 用户第一次访问时,在cookie或localStorage中存储一个随机生成的uuid
  • 浏览器指纹追踪技术,通过获取浏览器具有辨识度的信息,进行一些计算得出一个值,那么这个值就是浏览器指纹,辨识度的信息可以是UA、时区、地理位置或者是你使用的语言等等

这几种方式各自存在着自己的一些弊端,ip地址准确度不够,比如同一个局域网内的共享一个ip、代理、动态ip等原因都会造成数据统计都错误。cookie和localStorage都缺陷是用户可以主动去清除。而浏览器指纹追踪技术的应用目前并不是很成熟。

综合考虑后,sdk中采用了localStorage技术,当用户第一次访问时,会自动生成一个随机的uuid存储下来,后续的埋点上报中都会携带这个uuid,进行用户信息都标识。同时如果业务平台调用了setUserId方法,则会把用户id存储到uid字段中。最后统计uv都时候,根据实际情况参考uid或者uuid字段,准确的uv数据,应该是介于uid和uuid之间的一个数值。

热力图上报

热力图埋点的意思是:监听页面中任意位置的用户点击事件,记录下点击的元素和位置,最后根据点击次数的多少,得到页面中的点击分布热力图。这一块的实现原理比较简单,只需要在埋点sdk中开启对所有元素对点击事件对监听即可,比较关键的一点是要计算出鼠标的点击x、y位置坐标,同时也可以把当前点击的元素名称或者class也一起上报,以便做更精细化的数据分析。

dom点击上报

dom点击上报就是通过在dom元素上添加指定属性来达到自动上报埋点数据的功能。具体来说就是在页面的dom元素,配置一个 tracker-key = 'xxx' 的属性,表示需要进行该元素的点击上报,适用于上报通用的埋点数据(没有自定义的埋点数据),但是又不需要热力图上报的程度。这种配置方式是为了节省了要主动调用上报方法的步骤,但是如果埋点中有自定义的数据字段,还是应该在代码中去调用sdk的埋点上报方法。实现的方式也很简单,通过对body上点击事件进行全局监听,当触发事件时,判断当前event的getAttribute('tracker-key')值是否存在,如果存在则说明需要上报埋点事件,调用埋点上报方法即可

上报埋点方式

埋点上报的方式最常见的是通过img标签的形式,img标签发送埋点使用方便,且不受浏览器跨域影响,但是存在的一个问题就是url的长度会收到浏览器的限制,超过了长度限制,就会被自动截断,不同浏览器的大小限制不同,为了兼容长度限制最严格的IE浏览器,字符长度不能超过2083。 为了解决img上报的字符长度限制问题,可以使用浏览器自带的beacon请求来上报埋点,使用方式为:

navigator.sendBeacon(url, data);

这种方式的埋点上报使用的是post方法,因此数据长度不受限制,同时可将数据异步发送至服务端,且能够保证在页面卸载完成前发送请求,即埋点的上报不受页面意外卸载的影响,解决了ajax页面卸载会终止请求的问题。但是缺点也有两个:

1.存在浏览器的兼容性,主流的大部分浏览器都能支持,ie不支持。 2.需要服务端配置跨域

因此可以将这两种方式结合起来,封装成统一的方法来进行埋点的上报。优先使用img标签,当字符长度超过2083时,改用beacon请求,若浏览器不支持beacon请求,最好换成原生的ajax请求进行兜底。(不过如果不考虑ie浏览器的情况下,img上报的方式其实已经够用,是最适合的方式)

const reportTracker = function (url, data) {
    const reportData = stringify(data);
    let urlLength = (url + (url.indexOf('?') < 0 ? '?' : '&') + reportData).length;
    if (urlLength < 2083) {
      imgReport(url, data);
    } else if (navigator.sendBeacon){
      sendBeacon(url, data);
    } else {
      xmlHttpRequest(url, data);
    }
}

Package Sidebar

Install

npm i hualctracker

Weekly Downloads

1

Version

1.0.19

License

MIT

Unpacked Size

167 kB

Total Files

7

Last publish

Collaborators

  • hualc