前端埋点SDK 3 - 重写pushState, replaceState事件

847 阅读1分钟

几个概念:

  • PV: 页面访问量,即PageView, 用户每次对网站的访问均被记录

    主要监听history和hash:

    • history API: go back forward pushState, replaceState(history 无法通过popstate监听pushState, replaceState, 所以只能重写其函数)
    • hash 使用hashchange监听
  • UV(独立访客): 即Unique Vistor, 访问网站的一台电脑客户端未一个访客

用户唯一标识, 在登录之后天天接口返回的id进行设置。也可以使用canvas指纹追踪技术

  • navigator.sendBeacon 和 XMLHttpRequest的区别是:

    • 前者即使页面关闭了也会完成请求,而XMLHttpRequest不一定 ??
  • DOM事件监听

    给需要监听的元素添加一个属性,用来区分是否需要监听target-key

    • const e = new Event(type) 创建自定义事件

    • window.dispatchEvent(e) 派发事件

    • addEventListener 监听事件

    • removeEventListener 删除事件

相关代码

// utils/pv.ts
export const createHistoryEvent = <T extends keyof History>(type: T) => {
    const origin = history[type]

    return function(this: any) {
        const res = origin.apply(this, arguments)

        const e = new Event(type)

        window.dispatchEvent(e)

        return res
    }
}
//index.ts
import { DefaultOptions, TrackerConfig, Options } from '../types/index';
import { createHistoryEvent } from '../utils/pv';

export default class Tracker {
    public data: Options;
    
    constructor(options: Options) {
        this.data = Object.assign(this.initDefaults(), options)
        this.installTracker()
    }

    private initDefaults(): DefaultOptions {
        // 重写pushState, replaceState事件
        window.history['pushState'] = createHistoryEvent('pushState')
        window.history['replaceState'] = createHistoryEvent('replaceState')
        return {
            sdkVersion: TrackerConfig.version,
            historyTracker: false,
            hashTracher: false,
            domTracker: false,
            jsError: false
        } as DefaultOptions
    }

    private captureEvents<T>(mouseEventList: string[], targetKey: string, data?: T) {
        mouseEventList.forEach(event => {
            window.addEventListener(event, () => {
                console.log('listening..', event)
            })
        })
    }

    private installTracker() {
        if (this.data.historyTracker) {
            this.captureEvents(['pushState', 'replaceState', 'popstate'], 'history-pv')
        }
    }
}

验证修改

  1. 执行pnpm run build
  2. 根目录下创建index.html目录,引入dist/index.js
  3. 使用浏览器打开index.html, 在控制台输入history.pushState('params', 'title', '/a')观察控制台输出(执行了captureEvents中的监听),点击浏览器返回,观察输出

扩展阅读