一个几乎无感知的前端埋点模块

项目github仓库:https://github.com/darkXmo/bury
项目npm仓库:@xmon/bury
项目gitee仓库:Xmo/bury
如果你的项目埋点会严重影响到业务代码,是时候考虑使用 @xmon/bury 了
除了必要的添加 eventId,即为项目添加 ID 标识的行为以外,@xmon/bury 不会影响到你的业务代码,你只需要添加一下配置就够了!
页面行为埋点,通过事件监听来进行行为监测,目前可以监控事件包括

  1. 点击事件(Click)
  2. 页面加载(Load & Unload)
  3. 特定行为(Action)
  4. Axios 请求(Api)
  5. 路由跳转(Router)
安装
# yarn yarn add @xmon/bury# npm npm install @xmon/bury# pnpm pnpm install @xmon/bury

Examples 监听一般事件(开启监听点击、页面加载,特定行为)
// main.js import { init } from "@xmon/bury"; import config from "./config.js"; const bury = init(config);

配置 你需要在 config 中指定你要监听的路由,路由对应事件(进入和离开)的 eventId
同时你需要指定埋点的基础参数,他们通常是环境,埋点版本以及系统版本,这些参数都是可选的。
// config.js import { initUrlMap } from "@xmon/bury"; // 用initUrlMap配置你想要监听的1页面路径和2加载页面,3离开页面的事件ID initUrlMap([ { path: "/user/:id", leave: "eventIdLeavePage", // Leave EventId enter: "eventIdEnterPage", // Enter EventId }, ]); // 这里填写埋点事件返回值中的额外字段,通常你需要添加以下几个配置信息 const config = { environment: process.env.NODE_ENV, dataPointVersion: "v0.0.1", version: "1.0.0", }; export default config;

监听 Router
如果你使用的是 Vue 单页面应用,则还需要监听 Vue-Router 跳转,因此你还需要传入 router 实例作为第 2 个参数
import router from "@/router"; // 把router实例注册到bury中 const bury = init(config, router);

监听 Api
如果你需要监听 Axios Api ,则需要封装 Axios 实例。
import axios from "axios"; import { trackApi } from "@xmon/bury"; const axiosInstance = axios.create({ ... }); // 提醒 @xmon/bury 监听 axios示例 发出请求的行为 trackApi(axiosInstance);

配置 和页面监听类似,你也需要指定你要监听的 api 路径以及对应的 eventId
import { initUrlMap, initApiMap } from "@xmon/bury"; initUrlMap([ ... ]); // 利用 initApiMap 来配置需要监听的url initApiMap([ { url: "/v3/search/anime", eventId: "eventIdApi", }, ]); const config = { ... }; export default config;

值得注意的是,无论是监听页面加载还是监听 api,都会忽略 query 参数。
监听点击事件
一个几乎无感知的前端埋点模块
文章图片

对于需要监听点击事件的元素,添加 data-bupoint 属性,并注入 eventId 即可。
监听特定行为
import { track } from "@xmon/bury"; // 对于特定的行为,你需要将行为包装成函数,并配置好eventId,然后再使用track来监听这个函数行为 const increase = track(() => { console.log("I am tracked"); }, "eventId"); // track的返回值是你传入的函数,原封不动。 // increase = () => { console.log('I am tracked') }

对于行为,你应当使用 track 进行封装,第一个参数是要封装的函数,第二个参数是 eventId
track 会在封装后返回被封装的函数。
埋点行为发生在特定行为执行之前。
触发埋点事件回调 触发监听行为会同时触发埋点行为,通过 onBury 我们可以获取到埋点行为的回调。
初始化(init)之后才能访问到 instancetracktrackApionBury 等方法,否则会抛出未定义错误
import { onBury } from "@xmon/bury"; // 做好配置之后,你可以使用 onBury 来监听事件 // 一旦 你配置过的url加载或关闭了 OR 你监听的api请求发送了 OR 你监听的事件被调用了 OR 你观察的Dom被点击了 => 就会触发在 onBury 中注册的回调函数 onBury((value) => { // 下文中 BuryConfig 中会说明 payload 中包含哪些值 const buryInfo = value.payload; // 下面是我的埋点回调示例行为,你应当用你的行为代替示例 const queries = Object.entries(buryInfo) .map(([key, value]) => { return key + "=" + encodeURI(value); }) .join("&"); let img = new Image(1, 1); // 请将url改成你的后端埋点系统的API img.src = https://www.it610.com/article/`http://exmapleApi.com/bury?` + queries; // 3000ms超时处理 setTimeout(() => { if (img && (!img.complete || !img.naturalWidth)) { img.srchttps://www.it610.com/article/= ""; } }, 3000); });

每当被监听的事件发生的时候,都会注册在 onBury 事件中的回调函数。
在这个例子中,它将会取出回调参数中的 payload ,并将它封装并发出 imgGet 请求。
由于 onBeforeUnload 方法在页面即将关闭时执行,此时无法使用 Axios 来发起异步请求。但 imgXMLHttpRequest 同步请求仍然可以执行。
API init
export const init = (config: BuryConfig, router?: VueRouter) => Bury; // 预配置中的一些配置并没有默认值,可以通过 config 手动添加预设 // 标记为 !!! 的参数是 payload 中预定义的。 // 你也可以自定义参数 export interface BuryConfig { eventId?: string; // 必要,事件ID timestamp?: string; // !!! ua?: string; // !!! browser?: "MSIE" | "Firefox" | "Safari" | "Chrome" | "Opera"; // !!! referrer?: string; // !!! width?: string; // !!! height?: string; // !!! ip?: string; // !!! cityName?: string; // !!! isPhone?: "phone" | "pc"; // !!! userId?: string; apiUrl?: string; pageUrl?: string; pageStayTime?: string; project?: string; environment?: string; dataPointVersion?: string; version?: string; channelCode?: string; sourceCode?: string; topCause?: string; phone?: string; enterTime?: string; extraInfo?: string; [K: string]: string; }

BuryConfig 中通过 "@fingerprintjs/fingerprintjs" 模块 以及 "http://pv.sohu.com/cityjson?ie=utf-8" Api 接口获取了一些预设值,它们分别是
  1. timestamp - 时间戳 - new Date().getTime()
  2. ua - 客户端信息(navigator.userAgent),详情请查看 https://developer.mozilla.org...
  3. browser - 浏览器类型
  4. referrer - 引用来源 - http://www.ruanyifeng.com/blo...
  5. width - 窗口宽度
  6. height - 窗口高度
  7. ip - 客户端 ip 地址
  8. cityName - 客户端省市名 - 如 “江苏省南京市”
  9. isPhone - 是否是移动端,如果是,则值为 phone
  10. userId - 客户端设备的唯一标识符 详情请查阅 https://github.com/fingerprin...
一个通常的方案是传入 projectversiondataPointVersionenvironment
const bury = init(config, router);

  • config 预定义参数
  • router 可选参数,如果要监听 VueRouter 跳转的话
Bury.spy 开启监听模式(生产模式下请不要打开),可以在 devtools 的控制台中查看每次触发埋点事件的返回值
bury.spy();

initUrlMap 初始化监听的 url 的页面路径及其 eventId 的数组。
所有的 eventId 都会被包含在回调函数参数中的 payload 中
interface UrlMap: { path: string; // 页面url地址,同VueRouter中的path的定义方式 enter?: string; // 进入该页面的 EventId leave?: string; // 离开该页面的 EventId }[]

  • url 页面的 url 地址,定义遵循 https://github.com/pillarjs/p... ,通常可以和 VueRouter 中的 path 参数对照着填。
  • enter 进入该埋点页面的 eventId
  • leave 离开该埋点页面的 eventId
关于 path https://github.com/pillarjs/p...
initApiMap
interface ApiMap: { url: string; // 接口的url地址 method?: Method; // Method ,例如 `GET` `POST` ,如果不定义,则监听该url下的所有 Method eventId: string; // 接口被触发时的 EventId }[] = [];

  • url 接口的 url 地址
  • method 可选参数 Method ,例如 GET POST ,如果未定义,则监听该 url 下的所有 Method
  • eventId 该埋点接口的 eventId
track 对事件进行埋点监听
function track any>(fn: T, eventId: string): T;

  • fn 被埋点的方法
  • eventId 该埋点方法的 eventId
为传入的方法埋点,并返回埋完点的方法。
trackApi 对 Axios 进行埋点监听
function trackApi(axiosInstance: AxiosInstance): void;

onBury 当被埋点的时间触发时的回调函数
function onBury(callback: (value: BuryCallBack) => void): void;

  • callback 回调函数
BuryCallBack
interface BuryCallBack { type: "Action" | "Click" | "Leave" | "Enter" | "Api"; payload: BuryConfig; extra?: | Payload.ActionPayload | Payload.ApiPayload | Payload.ClickPayload | Payload.LoadPayload | Payload.RoutePayload; }

  • type 类型 分别是埋点事件、点击、离开页面、载入页面和接口
  • payload 负载,除了预定义的配置以外
    • Enter
      • pageUrl 进入的页面 url
    • Leave
      • PageStayTime 在当前页面停留的时间
      • pageUrl 离开的页面 url
    • Api
      • apiUrl 接口的 url
  • extra 监听事件的负载,详情请查看 https://github.com/darkXmo/mo...
help 如何在 Nuxt2 项目中使用
plugins 在 plugins 文件夹中创建文件 bury.jsbury.ts ;
// bury.js import { init, initUrlMap } from '@xmon/bury'; const bury = init({ version: 'projectVersion', dataPointVersion: 'v1', project: 'projectName' }); initUrlMap([{ path: "/", enter: "EnterEventPoint", leave: "LeaveEventPoint" }, ...])bury.spy(); bury.onBury((value) => { // do something with value })

【一个几乎无感知的前端埋点模块】nuxt.config.jsnuxt.config.ts 中添加插件配置
{ plugins: [ ... { src: "@/plugins/bury.ts", mode: 'client' }, ... ], }

    推荐阅读