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

分享如何实现前端埋点工程

这篇文章主要是分享一下在实际项目中如何做好前端埋点。前端埋点相关的知识点,在面试中也会经常被遇到。这篇将会从技术方案设计到最终实现给出简易版代码。

什么是埋点?为什么项目中需要埋点?

埋点主要是用来收集用户行为的数据,在项目开发中,我们会在前端代码中插入代码或者脚本的方式实现埋点功能。

埋点的作用主要是为了在应用中特定流程收集一些信息及关键业务数据,用来追踪应用使用的状况,以便后续进一步优化产品提供运营数据的支撑。例如某一功能的访问数、访客数、停留时间时长等

实现埋点的方案

  1. 手动埋点:也就是代码埋点,需要上报的时候写js代码调用接口上报。
    弊端:在业务中混入了大量的埋点,对业务代码有破坏性,甚至会因为埋点报错导致页面崩溃。

  2. 声明式埋点:在dom匀速上写入点位,然后自动上报。目前主流的技术方案。它的思路是将埋点代码和具体的交互业务逻辑解耦,开发者只需关心需要埋点的空间,并且为这些控件声明需要埋点的数据即可,降低埋点成本。

  3. 可视化埋点:通过工具界面需要采集的元素和事件、可不用手写代码。目前开源的有mixpanel

声明式埋点实现逻辑

首先就是在应用启动后的初始化埋点,初始化之后,便是埋点系统的三大核心监听事件了。
1️⃣是监听页面dom的变化,dom新增或销毁时,上报给服务器;2️⃣是监听页面的点击事件,当我们定义的d位的dom被点击时,上报服务器3️⃣监听页面关闭,当页面关闭时,找出所有埋点dom,上报服务器。
截屏2026-02-03 16.26.09

代码实现

接下来开始编写我们的代码,在写代码之前,我们应该先要了解一下点位的概念

点位:
点位是我们上报给接口的东西,我们通过这个点位就能知道它代码的是什么。

下图中的示例中,我使用data-tp的自定义属性来设置埋点dom,用data-tp-data来传递埋点上报时的数据

截屏2026-02-03 17.51.07

接下来进入到js的编写,一般情况下,我们可以单独封装js,这样避免和业务逻辑的混淆。

import server from './server'
// 前端 埋点上报
const reportServer = (doms:any,dataTp='') => {server.post('/user/tp/report',{domMap:doms,dataTp:dataTp})
}const domMap:any= {}
const hasRepeat= (tp:string) => {return domMap[tp]?.log || false
}const reportAll = () => {document.querySelectorAll('data-tp').forEach((item) => {const dataTP = item?.getAttribute?.('data-tp')const dataVal = item?.getAttribute?.('data-tp-data') || ''reportServer(dataTP,dataVal)})
}// 监听dom节点变化
const initObserver = () => {const observer = new MutationObserver((mutation) => {console.log(mutation,'mutation');mutation.forEach((item) => {// 当页面销毁时,也可以选择在页面节点新增时,需要将removedNodes改为addedNodesif (item.type == 'childList' && item.removedNodes?.length > 0) {item.removedNodes.forEach((ritem:any) => {if (ritem?.getAttribute?.('data-tp')) {const dataTP = ritem?.getAttribute('data-tp')const dataVal = ritem?.getAttribute('data-tp-data')if (hasRepeat(dataTP)) return reportServer(dataTP,dataVal)domMap[dataTP] = {log:true,data:dataVal}}})}})})observer.observe(document.body,{subtree:true,childList:true,})
}
// 监听所有的点击事件
const initClickObserver = () => {window.addEventListener('click',(e) => {const target = e.target as Elementconst dataTP = target?.getAttribute?.('data-tp')const dataVal = target?.getAttribute?.('data-tp-data') || ''reportServer(dataTP,dataVal)})
}
// 监听浏览器页签关闭/切换时
const initPageChangeObserver = () => {window.addEventListener('visibilityChange',() => {reportAll()})
}const initTrackPort = () => {initObserver()initClickObserver()initPageChangeObserver()
}initTrackPort()

上述的便是在项目中可实现的埋点简易版代码,实际的代码还需要根据业务需求调整

http://www.jsqmd.com/news/338654/

相关文章:

  • 2026金三银四必看:AI Agent全栈学习路线,三个月从小白到Offer收割机!
  • 2026届毕业生就业新方向,从零开始学大模型开发,实战项目+名师指导,立即收藏!
  • 设计师必藏!1招秒杀相似图,告别手动翻文件夹的痛
  • 技巧总结
  • 春晚AI机器人揭秘:大模型技术已成熟,普通人如何抓住新风口?
  • 模型数据标注规范全解析:从国标到企标的标准化实践指南
  • 墨韵新生:一位书法爱好者的鸿蒙原生应用开发手记——从手机拍字帖到PC临摹的42天破界之旅
  • 大数据领域数据产品的体育行业应用
  • 收藏必看!大模型时代来临:计算机缺口500万,应届生如何拿50W+年薪
  • C++与Docker集成开发
  • 在Windows上启用Selenium + Chrome Profile建立自动登录爬虫
  • Spring Boot 定时任务详解(从入门到实战)
  • 提示工程架构师必备:领域驱动设计(DDD)落地实战指南,从理论到代码全流程!
  • 2026澳洲奶粉品牌推荐:CareBirth臻护新苼聚焦A2奶源与科学分阶,澳洲袋鼠标认证 - 深度智识库
  • 5个实用的诊断性分析工具推荐:大数据工程师必备
  • C++ Primer Notes
  • 基于区块链的传感器数据存证与溯源系统
  • MIT-6-036-机器学习入门笔记-全-
  • C++中的享元模式实战
  • supermemo体验前的准备 - LI,Yi
  • 多核并行计算优化
  • 最小表示法
  • 代码动态生成技术
  • C++20概念(Concepts)入门指南
  • 2026年有袋鼠标的澳洲奶粉品牌精选:科学分阶营养,宝宝吸收更好、性价比更高 - 深度智识库
  • C++中的备忘录模式
  • 分布式锁服务实现
  • leetcode 896. Monotonic Array 单调数列-耗时100
  • Victim01_042220
  • leetcode 897. Increasing Order Search Tree 递增顺序搜索树-耗时100