当前位置: 首页 > news >正文

数据埋点指南

一、埋点基本概念

1、什么是埋点

埋点是一种用于跟踪用户在网站或应用中行为的数据采集技术,通过记录点击浏览等操作,帮助团队进行:

  • 用户行为分析:记录用户在产品中的具体操作,比如点击、浏览、停留时间、跳转路径等,帮助产品团队了解用户是如何使用产品的,从而发现用户行为模式、偏好和痛点

  • 指导产品优化与迭代问题:通过埋点数据,可以评估产品功能的使用情况,比如哪些功能被频繁使用、哪些功能被忽略甚至导致用户流失,从而指导产品功能的优化与迭代方向

  • 转化率与漏斗分析问题:埋点可以帮助构建用户行为漏斗(如注册、登录、浏览商品、加入购物车、下单等),分析各环节的转化率,找出流失点,优化用户体验,提高转化效率

    • 漏斗分析:将用户完成一个目标的过程拆解为多个关键步骤(也称为“转化节点”),然后统计每个步骤的用户数量,以及从上一个步骤到下一个步骤的转化率

    • 例如:“访问首页 → 浏览商品 → 加入购物车 → 提交订单 → 支付成功”,通过对比各步骤的用户数量,可以直观地看到在哪一步用户流失最多,从而定位问题。

    • 针对流失严重的环节,可以深入分析原因(如页面设计、交互流程、加载速度等),进行优化改进。

  • A/B 实验:在进行产品功能或页面设计 A/B 测试时,埋点可以收集不同版本的用户行为数据,帮助评估哪个版本效果更好,从而做出数据驱动的决策

    • A/B 实验:也称为拆分测试或对照实验,是一种通过对比不同版本(A 和 B)的页面、功能或策略,其核心是通过数据埋点收集用户与不同版本的交互数据,从而量化分析哪个版本效果更优
  • 异常监控与问题排查问题:埋点数据可以用于监控产品运行状态,比如页面加载失败、功能异常点击等,帮助快速发现和定位问题,提高产品稳定性

2、埋点类型

基于我们要监控的内容,可以分为:数据监控、性能监控、异常监控等三个部分,常包括以下几类能力:

  • 性能监控(如页面加载时间、白屏时间、资源加载)

  • 错误监控(JS 报错、Promise 异常、资源加载失败)

  • 行为追踪(如点击、跳转、输入等埋点数据)

  • 用户环境(设备型号、浏览器类型、网络状况)

  • 可用性/崩溃率(页面是否正常加载、崩溃次数)

2.1、数据监控

数据监控主要指对用户行为、业务数据等进行埋点监控,采集并上报关键信息。目的是:通过收集用户在系统中的行为数据,帮助产品经理、运营人员更好地分析用户行为,优化产品决策。

例如:

  • 用户操作数据:点击某个按钮、页面的浏览路径、搜索的关键词、用户停留时间等。

  • 电商平台:监控用户的商品浏览记录、加入购物车、购买行为、支付情况等数据。

  • 社交平台:记录用户点赞、评论、分享、发布动态等操作。

优点缺点
数据量大,覆盖面广,有利于全面掌握用户的操作行为数据量大时,可能增加数据处理和存储的成本
为业务决策提供有力的数据支持,帮助进行 AB 实验、用户行为分析等埋点较多时,可能影响页面性能
需考虑数据的可信问题,且埋点的开发维护成本会偏高

2.2、性能监控

性能监控关注的是系统性能的表现,重点监控页面:

  • 核心 Web Vitals 指标:FCP、LCP、FID、CLS、TTI(页面可交互时间,用于衡量页面从开始加载到完全可交互所花费的时间)

  • 页面加载耗时:DOMContentLoaded、load、白屏、首屏等

  • 资源加载性能:ResourceTiming、long task

补充:ResourceTiming

资源计时(ResourceTiming)是浏览器提供的一种性能监测 API,用于详细记录网页中各类资源(如脚本、样式表、图片等)从请求到加载完成的整个过程时间数据。例如重定向开始和结束时间、获取(fetch)开始、DNS 查询开始和结束时间、响应开始和结束时间等

const entries = performance.getEntriesByType('resource')
console.log(entries[0]) // 检查目标资源的详情
// 结果:
PerformanceResourceTiming: {connectEnd: 19.100000023841858connectStart: 19.100000023841858decodedBodySize: 324864deliveryType: 'cache'domainLookupEnd: 19.100000023841858domainLookupStart: 19.100000023841858duration: 0encodedBodySize: 324864entryType: 'resource'fetchStart: 19.100000023841858finalResponseHeadersStart: 0firstInterimResponseStart: 0initiatorType: 'link'name: 'https://developer.mozilla.org/static/media/Inter.var.c2fe3cb2b7c746f7966a.woff2'nextHopProtocol: 'h2'redirectEnd: 0redirectStart: 0renderBlockingStatus: 'non-blocking'requestStart: 19.100000023841858responseEnd: 19.100000023841858responseStart: 19.100000023841858responseStatus: 200secureConnectionStart: 19.100000023841858serverTiming: []startTime: 19.100000023841858transferSize: 0workerStart: 0
}

补充:long task

long task(长任务)是指浏览器主线程上执行时间超过 50 毫秒(ms)的连续任务。由于浏览器的主线程负责处理 JavaScript、渲染、用户交互等关键任务,长时间占用主线程会导致页面卡顿、交互延迟,影响用户体验。

检测方法:使用 PerformanceObserver (推荐)

const observer = new PerformanceObserver((list) => {for (const entry of list.getEntries()) {console.log("Long Task detected:", entry);// entry.duration 可获取任务耗时(ms)}
});
observer.observe({ type: "longtask", buffered: true });// 输出:
{name: "self", // 表示任务来源(如脚本、渲染等)duration: 68, // 任务耗时(ms)startTime: 1200, // 任务开始时间(相对于页面加载)attribution: [{ containerType: "window", containerName: "" } // 任务来源容器]
}

目的是:帮助开发者了解项目的性能数据,为性能优化做导向。

例如:监控页面从开始加载到完全展示各阶段的时间,如 FP、FCP、LCP、JS 初始化、主接口加载等

🤔 性能数据数据如何采集?

  • FP(白屏时间)
// 方案1 performance
const whiteScreenTime =performance.timing.responseStart - performance.timing.navigationStart
console.log('白屏时间:', whiteScreenTime, 'ms')// 方案2 PerformanceObserver
const observer = new PerformanceObserver((list) => {const entries = list.getEntries()for (const entry of entries) {if (entry.entryType === 'paint' && entry.name === 'first-paint') {console.log('白屏时间(FP):', entry.startTime, 'ms')observer.disconnect()}}
})observer.observe({ entryTypes: ['paint'] })
  • FCP
// 方法1: 直接获取
const fcpTime = performance.getEntriesByName('first-contentful-paint')[0]?.startTime// 方法2: 使用PerformanceObserver (推荐)
const observer = new PerformanceObserver((list) => {const entries = list.getEntriesByType('paint')for (const entry of entries) {if (entry.name === 'first-contentful-paint') {console.log('FCP时间:', entry.startTime, '毫秒')// 可以在这里上报数据到分析系统observer.disconnect() // 停止观察}}
})
// 开始观察paint类型的性能条目
observer.observe({ type: 'paint', buffered: true })
  • DOMContentLoaded
// 在页面完全加载后获取性能数据
window.addEventListener('load', function () {const timing = performance.timingconst domContentLoadedTime =timing.domContentLoadedEventEnd - timing.navigationStartconsole.log('DOMContentLoaded耗时:', domContentLoadedTime + 'ms')
})

2.3、异常监控

异常监控主要用于捕获系统中的异常情况,包括:

  • JavaScript 错误: error 事件
window.onerror
window.addEventListener('error')
  • 接口请求失败: try…catch 捕获

  • 未处理的 Promise 错误: unhandledrejection 事件

// 当 Promise 被 reject 且没有 reject 处理器的时候,会触发 unhandledrejection 事件
window.addEventListener('unhandledrejection')
  • 资源加载失败: script/img/css

目的是:通过及时捕获并上报异常信息,帮助开发者迅速定位问题、解决问题

优点缺点
实时捕获异常,帮助开发者迅速发现并修复问题,提高用户体验捕获到的异常信息可能过多,数据筛选和处理的难度较高
能够自动化捕获大量错误信息,减少手动调试的压力

3、上报方式

在了解了埋点的监控类型后,我们再看看埋点的上报都有哪些方式

3.1、手动上报

手动上报是指我们基于业务需求,在代码中显式地添加埋点逻辑。 每当需要记录用户行为或系统事件时,手动调用上报函数,将数据发送至服务器,这种方式的 可控性强,开发者可以精确地控制埋点位置和上报时机

例如:

  • 点击事件:在用户点击某个按钮时,开发者会在按钮的点击事件中调用埋点上报函数
button.addEventListener('click', () => {trackClick('click_button', {userId: '12345',pageLevelId: '121014209',domId: 'login-btn',clickId: 200003,pageParam: {scene: talkerType}})
})
  • 页面展示:在页面加载完成时,埋点记录页面的展示情况
window.addEventListener('load', () => {trackView('page_view', {pageLevelId: '121014244',pageParam: {templateid: tplId}})
})

上报服务器:

采用 beacon API(推荐)或 fetch/xhr 上报数据

  • beacon API:beacon 用于发送异步和非阻塞请求到服务器。这类请求不需要响应。浏览器会保证在页面卸载前,将信标请求初始化并运行完成。主要的使用场景是将分析数据发送给服务器。
// 前端
window.addEventListener('unload',() => {// 上报异常navigator.sendBeacon('http://127.0.0.1:3000/log', '1')},false
)// 后端正常书写post请求即可

优缺点:

  • 优点:

    • 灵活度高,开发者可以精确控制上报时机、数据内容
    • 适合复杂业务场景或需要精确控制的埋点需求
  • 缺点:

    • 需要手动编写大量代码,增加了开发和维护成本

3.2、可视化上报

可视化上报是通过图形界面或后台工具来配置埋点,无需开发人员手动编写代码。在业务人员或测试人员通过可视化工具对页面上的元素(如按钮、链接等)进行选择和配置后,系统自动生成埋点逻辑并上报数据。这种方式降低了技术门槛,使非开发人员也能够参与埋点配置

优缺点

  • 优点:

    • 减少了开发者的工作量,业务人员可以快速配置埋点
    • 埋点配置灵活,可以根据需要随时调整,无需发布新的代码
  • 缺点:

    • 灵活性不如手动上报,复杂的业务逻辑可能无法通过可视化工具实现
    • 依赖第三方工具,可能带来兼容性或平台限制的问题

3.3、自动上报(无埋点)

自动上报(无埋点)是指系统通过框架或插件自动捕获用户行为或系统事件,无需手动埋点

优缺点

  • 优点:

    • 减少了开发和运维成本,开发人员无需为每个事件手动编写埋点逻辑
  • 缺点:

    • 灵活性较低,自动捕获的行为数据可能无法满足某些特定业务需求,且不容易精确控制上报的内容和时机

二、埋点数据消费

1、PV 和 UV

PV(Page View):页面访问量

UV(Unique Visitor):独立访客数

二者区别:

  • PV:用户每次打开或刷新一个页面,都会记录一次 PV。同一用户多次访问同一页面会累计 PV(例如刷新页面、跳转后返回)。

  • UV:统计一定时间内访问网站的唯一用户数量(通常通过 Cookie、设备 ID 或 IP+用户代理识别)。同一用户多次访问只计为 1 个 UV(无论访问多少页面或刷新多少次)。

2、事件行为分析

事件行为分析通过埋点捕捉用户的操作习惯和行为路径,是我们最常用的分析模式

例如:分析 click_button 事件中按钮名称为某个具体值的 PV(PV 为 500,表示 submit 按钮被点击了 500 次)

3、路径转换分析

路径转换分析用于跟踪用户从进入系统到完成某个目标(如购买、注册、下单)的转化过程,可以查看用户经过的关键步骤,发现在哪一步可能有大量用户流失

4、异常值与极端行为分析

有时我们需要分析极端的用户行为(如长时间不操作或过于频繁操作)。通过分析这些异常行为,研发可以定位到系统中的潜在问题或优化点

例如:某个用户反复多次点击某个按钮,这可能是系统卡顿或用户困惑导致的行为

三、埋点实战

1、如何使用

这里拿公司的 vue3 项目埋点举例

在 index.html 中引入了埋点 sdk,并且添加 meta 以便后续参数获取

<!-- 默认配置 -->
<metaname="platform-id"content="1"
/>
<metaname="biz-type"content="006"
/>
<metaname="app-id"content="2"
/><scriptsrc="//st.haiziwang.com/static/tracker/4.0.0/tracker.js"crossorigin="anonymous"
></script>

公司埋点统计主要分为两种:页面级别、事件级别、错误请求埋点

内部的 sdk:页面级别、事件级别

第三方的监控埋点 sentry:请求错误埋点

2、采集哪些数据

2.1、事件上报

编写了一个 trackClick 方法,将采集的数据通过 sdk 注入的 window.track._launch 方法将参数进行上报

在 sdk 中会将用户信息和设备信息获取后,参数合并上传

/* 上报事件/页面埋点 */
export const trackClick = (options) => {const {bizType,pageLevelId,clickId,positionId,logType = '20000'} = optionslet { pageParam, positionParam } = optionspageParam = pageParam ? JSON.stringify(pageParam) : undefinedpositionParam = positionParam ? JSON.stringify(positionParam) : undefinedtry {const params = {bizType, // 业务类型pageLevelId, // 页面 IDclickId, // 事件编码logType, // 上报类型: '10000'页面、'20000'事件pageParam, // 页面参数positionId, // 坑位编码positionParam // 坑位内容参数}console.log(params)window.track && window.track._launch(params)} catch (e) {console.error(e)}
}

例如:“搜索”按钮的点击上报

const onSearch = () => {trackClick({pageLevelId: '121014210',clickId: 200004,positionParam: {keyword: keyword.value},pageParam: {tabname: activeContentTab.value === 1 ? '原创视频' : '跟创视频',scounts:activeContentTab.value === 1? sampleNums.value.original: sampleNums.value.follow}})initState()
}

2.2、页面上报

/* 上报页面埋点 */
export const trackView = (options: TrackParmsType) => {const { bizType, pageLevelId, positionId, pageParam, positionParam } = optionsconst params = {bizType,pageLevelId,logType: '10000',pageParam,positionId,positionParam}trackClick(params)
}

公司的采集一般会在页面初始化后,或者跟着点击事件一起上传

// 初始化后采集
onMounted(() => {trackView({pageLevelId: '121014208',pageParam: {scene: talkerType}
})// 跟事件一起上传
const handleClick = () => {trackView({pageLevelId: '121014234',pageParam: {scene: talkerType}})trackClick({pageLevelId: '121014208',clickId: 200002,pageParam: {scene: talkerType}})
}

从公司的情况来看,不管是页面的还是事件的,都是根据需要进行采集,不是固定的

2.3、错误请求埋点

公司对请求错误信息采用的是第三方库 sentry ,这个库也支持很多其他语言的监听统计( https://docs.sentry.io/ )。

基本使用

这里需要安装两个库: @sentry/tracing @sentry/vue

  1. 编写 plugin/sentry.ts
import { App } from 'vue'
// https://docs.sentry.io/platforms/javascript/guides/vue/#vue-3
import * as Sentry from '@sentry/vue'export default (app: App) => {const isDEV = import.meta.env.DEVif (!isDEV) {Sentry.init({app,dsn: DSN, // DSN 是上报的地址,在 .sentryclirc 中配置environment: 'production',release: ''})}
}
  1. .sentryclirc
[defaults]
url=http://example.com/[auth]
token=xxxxxxx[update]
disable_check=true
  1. main.ts
import sentry from './plugins/sentry'
const app = createApp(App)
app.use(sentry)

公司主要是在请求响应拦截中对请求进行收集的。

export function http(options: AxiosRequestConfig,extraConfig?: AxiosExtraConfig
) {const service = axios.create({ withCredentials: true })service.interceptors.response.use((response: AxiosResponse) => {if (response && response.config && response.config.url) {reportUrl(response)}// ...return Promise.resolve(res.data)},(error: AxiosError) => {if (error.isAxiosError) {reportUrl(error.response, true)}return Promise.reject(error)})return service(options)
}

核心埋点方法:reportUrl

export const reportUrl = (response: AxiosResponse | undefined,isError = false
) => {const res: any = response && response.data// 对错误请求进行埋点统计if (hasErrCode || isError) {// https://docs.sentry.io/platforms/javascript/guides/vue/enriching-events/scopes/#local-scopesimport('@sentry/vue').then((Sentry) => {Sentry.withScope((scope) => {scope.setLevel(isError ? 'error' : 'warning')if (errMsg) {Sentry.captureMessage(errMsg)}})})}
}

3、可能出现的问题

  • 数据混乱:比如 page_name 参数,如果用成别的页面的命名,就导致数据错报了

    • 解决办法:

      • 标准化参数命名与取值
      • 固定为预定义值,禁止随意填写
      • 自动化校验机制,在埋点 SDK 中内置参数校验逻辑,对非法参数抛出错误或警告(开发阶段即可暴露问题)
  • 事件参数复杂,难以维护:比如每个团队都可能往公共事件里面加入参数定义,导致公共事件的参数越来越冗长,对公共事件的更新会变的异常艰难

    • 解决办法:

      • 分层设计事件体系:核心事件(必须)+ 扩展事件(可选)
{"event_name": "button_click", // 必须"user_id": "123", // 必须"ext_params": { // ext_params扩展,可选"team_a": { "promotion_id": "x1y2" },"team_b": { "experiment_group": "control" }}
}

参考文章:

https://juejin.cn/post/7415911686929268788

https://juejin.cn/post/7480160283312390144

四、埋点 SDK 设计

要设计一个埋点系统,我们需要思考的内容有:

  1. 需要统计哪些数据

  2. 如何触发埋点(点击埋点,曝光埋点…)

  3. 埋点 sdk 上传策略

  4. 未上报成功的埋点数据如何处理

下面来一一解决问题:

1、统计的数据(埋点类型)

可以参考【一、埋点基本概念 2、埋点类型】

  • 标准字段:设备 ID、用户 ID、时间戳、APP 版本、操作系统、网络类型等

  • 业务数据:

biz-type:业务类型
page-id:页面ID,也可以是路由路径,便于页面寻找
platform-id:平台
os:系统
log-type:上报事件类型
page-param:页面参数
user-id
time:时间
...

当一些必填参数缺失,可以提供一些警告

2、埋点触发

要如何触发埋点机制也是需要考虑的,例如通过点击事件触发,或者当元素出现在页面的时候触发

  • 事件触发:当点击事件时,调用上报函数进行手动上报

  • 元素出现时触发:可以通过 MutationObserver 来判断元素是否出现在视口,同时也可以结合 DOM 埋点来实现自动埋点

拿 DOM 埋点举例:可以通过给元素绑定自定义属性 data-track-block 来对该元素进行点击事件绑定(这种方法简化了代码量)

<div data-track-block="clickid"><div data-track-position="positionid|positionparam|cpm"></div>
</div>
  • 监听 JS 异常、网络请求失败等来上传错误

3、埋点数据上传策略

  • 实时上报:关键事件(如支付成功)立即发送。

  • 批量上报:非关键事件合并后定时上报(减少网络请求)。

  • 本地缓存:弱网环境下暂存本地,网络恢复后重试。

  • 智能压缩:对重复事件去重或聚合(如滚动事件采样)。

4、优化

  • 跨平台兼容性

  • 性能优化

    • 异步上报:避免阻塞主线程(如 Web 使用 requestIdleCallback ,移动端用后台线程)
  • 数据可靠性

    • 重试机制:设置上报失败次数

    • 数据校验:上报前校验必填字段和数据格式(如 JSON Schema)

    • 未上传成功的埋点请求:可以缓存存入 cookie 中,等到页面又一次访问加载的时候,对其进行重新上报

    • 使用浏览器指纹限制设备

  • 安全性

    • 数据加密

    • 采用 HTTPS 传输

五、🆚 面试官可能会问

1、什么是前端埋点?它的优缺点是什么?

回答要点:
定义:埋点是一种用于跟踪用户在网站或应用中行为的数据采集技术。
优点:能够获取详细的用户行为数据,支持业务决策。
缺点:手动埋点成本高,自动埋点可能引入噪声数据。

2、如何实现自动埋点?

回答要点:
1. 利用 `document.addEventListener` 监听用户事件(如点击、滚动)。
2. 重写浏览器 API(如 `fetch`、`XMLHttpRequest`)捕获网络请求。
3. `MutationObserver` 监听元素是否出现在视口,用于流量曝光场景

代码示例:

// 监听事件
document.addEventListener('click', (event) => {const target = event.target;if (target.tagName === 'BUTTON') {sendEvent('button_click', { buttonId: target.id });}
});
// 网络请求重写
const originalFetch = window.fetch;
window.fetch = function (...args) {sendEvent('api_request', { url: args[0] });return originalFetch.apply(this, args);
};

3、前端性能监控的关键指标有哪些?

回答要点:
1. FP、FCP、LCP、TTI、DOMContentLoaded、load
2. 使用 `Performance API` 获取这些指标

4、如何捕获前端运行时错误?

回答要点:(代码参考上面)
1. 使用 `window.onerror` 捕获全局错误。
2. 使用 `unhandledrejection` 捕获未处理的 `Promise` 错误。

5、前端监控与后端监控的区别是什么?

回答要点:
1. 前端监控主要关注用户体验(如性能、错误、用户行为),后端监控主要关注服务器状态(如 CPU、内存、数据库性能)。
2. 前端监控需要结合埋点技术,而后端监控通常依赖日志和系统指标。

6、如何设计一个埋点系统?

具体参考【四、埋点 SDK 设计】

回答要点:
1. 埋点类型- 数据监控- 设备- os- 时间戳- userId- 页面路径- 业务数据- ...- 性能监控- FCP、FP等性能数据- 异常监控
2. 埋点触发和上报策略- 实时上报:关键事件(如支付成功)立即发送。- 批量上报:非关键事件合并后定时上报(减少网络请求)。- 本地缓存:弱网环境下暂存本地,网络恢复后重试。- 智能压缩:对重复事件去重或聚合(如滚动事件采样)。
3. 优化- 跨平台兼容性- 性能优化- 异步上报:避免阻塞主线程(如Web使用  requestIdleCallback ,移动端用后台线程)- 数据可靠性- 重试机制:设置上报失败次数- 数据校验:上报前校验必填字段和数据格式(如JSON Schema)- 未上传成功的埋点请求:可以缓存存入cookie中,等到页面又一次访问加载的时候,对其进行重新上报- 使用浏览器指纹限制设备- 安全性- 数据加密- 采用HTTPS传输

参考文章: https://juejin.cn/post/7474872585412640778

http://www.dtcms.com/a/450586.html

相关文章:

  • 2025-10-06 Python不基础 11——if 判断
  • AI智能体升级实战:从规则匹配到Function Call,准确率提升86%的技术选型之路
  • 威联通nas 做网站湖州市南浔区建设局网站
  • C47-数组指针
  • 品牌网站建设咨询新产品上市推广策划方案
  • 男和男做的视频网站网站被攻击如何处理
  • 石家庄seo关键词网站推广优化怎样
  • 卓越建站快车南充建设企业网站
  • MySQL删除数据后表空间处理
  • 在线学习建设网站宁波易通建设网站
  • 济南网站制作企业设计网站的步骤有哪些
  • LeetCode:96.只出现一次的数字
  • 我国空间站建造西安做网站推广
  • 算法竞赛补题1
  • 网站优化设计公司百度小程序平台
  • 衡水网站制作费用潜山做网站
  • 光全息|OAM-旋转双维度复用全息
  • 发布网站iis上报404错误网站建设的行业分析
  • 专业购物网站建设网站备案 互联网信息
  • 光通信|OAM-偏振并行(解)复用器
  • 企业级大模型部署
  • FreeRTOS与信号量(四)
  • 欧洲网站服务器织梦网站更改网站的导航
  • 怎么搭建mysql数据库网站网站做多语言
  • 网站开发带后台南通网站建设心得
  • 福田做棋牌网站建设多少钱如何开发微信小程序商店
  • 运营网站是多少沧州开发网站多少钱
  • 泰州模板建站哪家好海外网站有哪些
  • 自主建设网站的意义软件园做网站
  • Linux内核进程管理子系统有什么第六十三回 —— 进程主结构详解(59)