埋点方案实现

// 埋点信息分析

1. 埋点标识

  • eventId:事件唯一标识,如:【立即购买】标识为'click/detail/buy'
  • eventType:click点击事件、event访问事件

2. 埋点上报数据有哪些?

js 复制代码
report(eventId, options)

interface options {
    [key:string]: any    // 自定义的事件信息
    eventType            // 埋点类型
    userId               // 用户ID(登录才有,未登录为空)
    userAgent            // 浏览器信息,内核信息,设备品牌/版本
    netType              // 网络信息,4G WIFI 5G
    deviceId             // 当前设备唯一ID
    timestamp            // 埋点时间,非上报时间
    loacation            // 页面地址
    refer                // 访问来源,如:百度/抖音/微信导流
}

3. 如何上报信息?

延时上报,在浏览器空闲时间上报信息,可以使用web worker / requestIdelCallback 等技术实现。

实现步骤:

ts 复制代码
// 埋点
interface Params {
  [key: string]: unknown
  // eventType: string           // 埋点类型
  // userId: string              // 用户ID(登录才有,未登录为空)
  // userAgent: string           // 浏览器信息,内核信息,设备品牌/版本
  // netType: string             // 网络信息,4G WIFI 5G
  // deviceId: string            // 当前设备唯一ID
  // timestamp: number           // 埋点时间,非上报时间
  // loacation: string           // 页面地址
  // refer: string               // 访问来源,如:百度/抖音/微信导流
}
let image: HTMLImageElement | null
interface Storage {
  eventId: string
  data: string
}

const queryString = (data: Params): string => {
  return data + 'queryString' // 生成唯一ID
}

const uuid = () => {
  return 'uuid' // 生成唯一ID
}

class BaseTrack {
  constructor() {
    if (window.addEventListener) {
      // 页面卸载前/进入页面时,执行任务池
      window.addEventListener('load', this.todoTrackPool, false)
      window.addEventListener('beforeunload', this.todoTrackPool, false)
    }
  }
  private ServerUrl = '//上报埋点的地址API'

  // 记录埋点信息
  track(eventId: string, params: Params | string, fromPool: boolean = false) {
    if (!fromPool && typeof params !== 'string') {  // 需要处理的埋点(直接调用)
      const qs = queryString({
        ...params,
        timestamp: Date.now(),
        url: location.href,
        userId: '', // 用户ID
        deviceId: TrackStorage.getDeviceId()
      })
      const uniqueEventId = `${uuid()}_${eventId}}` // 埋点ID 增加唯一性,因为任务池可能有多个一样的event id
      TrackStorage.pushStorage(uniqueEventId, qs)
      this.report(uniqueEventId, qs)
    } else if (typeof params === 'string') {  // 任务池内未完成/上报失败的任务(非直接调用)
      this.report(eventId, params)
    }
  }
  // 上报埋点信息
  report(uniqueEventId: string, qs: string, times: number = 3) {
    const spend = () => {
      image = null;
      if (times > 0) {
        this.report(uniqueEventId, qs, times - 1)
      }
    }
    return new Promise(() => {
      try {
        const eventId = uniqueEventId.split('_')[1]
        image = new Image()
        image.onload = () => { // 上报成功
          TrackStorage.removeStorage(uniqueEventId)
        }
        image.onerror = () => {  // 上报失败,再次上报
          spend()
        }
        image.src = this.ServerUrl + qs + `&eventId=${eventId}`
      } catch (error) {
        spend()
        console.error(error);
      }
    }).catch((error) => {
      console.error(error);
    })
  }
  todoTrackPool() {
    const Events: Storage[] = TrackStorage.getStorage() || []
    Events.forEach((e: Storage) => {
      this.track(e.eventId, e.data, false)
    })
  }
}

class TrackStorage {
  private static readonly TRACK_KEY = 'track'
  public static pushStorage(eventId: string, data: string) {
    const Events: Storage[] = this.getStorage()
    localStorage.setItem(this.TRACK_KEY, JSON.stringify(Events.concat({ eventId, data })))
  }
  public static removeStorage(eventId: string) {
    const Events: Storage[] = this.getStorage()
    localStorage.setItem(this.TRACK_KEY, JSON.stringify(Events.filter(e => e.eventId !== eventId)))
  }
  public static getStorage(): Storage[] {
    const storage = localStorage.getItem(this.TRACK_KEY)
    return storage ? JSON.parse(storage) : []
  }
  public static getDeviceId() { // 生成唯一的设备ID
    try {
      const key = 'device_id'
      let device_id = localStorage.getItem(key)
      if (!device_id) {
        device_id = uuid()
        localStorage.setItem(key, device_id)
      }
      return device_id
    } catch (error) {
      console.log(error);
      return ''
    }
  }
}

const track = new BaseTrack()
track.track('click/buy', { nimei: '' })
相关推荐
console.log('npc')29 分钟前
Git 冲突与 AI 协助指南
前端·人工智能·git·大模型
爱学堂IT分享2 小时前
Cesium可视化系统实战课程-Cesium教程学习
前端
糖墨夕2 小时前
理解大语言模型:Agent 的“大脑”
前端·agent
Rain的Java大神之路2 小时前
JavaWeb开发如何解决跨域问题
java·前端·后端·nginx·web安全·面试·运维开发
cpolar技术支持3 小时前
浏览器也能跑本地 AI:用 Transformers.js + WebGPU 做一个最小推理 Demo,cpolar 给同事远程体验
前端·ai·cpolar·webgpu·transformers.js
计算机魔术师4 小时前
OpenAI 发布 GPT-6 Astra:多项基准刷新纪录, cybersecurity 能力达 Critical 阈值
前端
xy34534 小时前
Axure9.0中继器遮罩实现方法
前端·ui·html·axure·原型·产品设计
风骏时光牛马4 小时前
智能任务自动化协同AI工作流
前端
IT_陈寒4 小时前
Python的多线程居然是个假把式?搞清GIL让我少熬三天夜
前端·人工智能·后端
宿6744 小时前
vue3-config
前端·javascript·vue.js