React 埋点(案例分享)

前段时间在开发过程中有一个埋点需求,一开始还不知道什么是埋点,在一番了解过后有所见解,故在此分享!(本次分享主要以React项目为背景,事实上主要还是思想,基本没有使用过多的框架提供的API。)

首先来解释何为埋点:

  • 埋点(Burying Point,BP)就是将用户在网站中的某些交互行为进行上报,从而收集对某些功能、页面的访问情况进行收集,进一步为产品优化、数据分析提供支持。
  • 举个例子:项目中新上线了一个页面,该页面为用户提供了某些信息的展示,由于是新页面,我们想知道这个页面在一段时间内用户的访问量以及具体使用了哪些功能进行数据收集,以针对性的优化页面。此时就需要这个新页面以及某些交互功能进行埋点了。

埋点的流程实际上十分简单:用户交互行为-->携带数据发送请求

那么我们需要明确以下几点:

  • 如何监听用户交互行为?
  • 如何收集数据?
  • 何种方式发送请求?

如何监听用户交互行为?

实际上很简单,埋点可以分为两类

  1. 对某个功能的埋点
  2. 一类是对页面访问的埋点,即PV(Page View)埋点

对某个功能的埋点

用户对想要使用某个功能,一定离不开触发某个事件。以onClick事件为例,我们可以在项目的入口处添加事件监听器来监听整个项目的onClick事件;

js 复制代码
  useEffect(() => {
    //监听点击事件,触发埋点请求
    document.addEventListener('click', report);
    return () => {
      document.removeEventListener('click', report);
    };
  }, []);

其中report函数为获取埋点信息并进行上报,会在后面提到。

对某个页面访问的埋点

对于PV埋点来说,实现方式会更加简单,我们只需要在路由发生变化时进行数据上报即可; 以React为例,我们可以利用React Router,当路由地址发生变化时,通过对路由地址过滤,有针对性地上报数据。 PV埋点不同于点击埋点,下一节收集数据仅针对点击埋点,实际PV埋点到此处就已经介绍完了,我们需要做的只是在路由切换时对不同路由进行过滤以及发送请求即可。

如何收集数据

在这里我们使用的方案是通过HTML标签的自定义数据属性data-*携带数据,并通过从事件源递归向上寻找该标签进而发送请求。

在项目的入口处,我们监听了click事件并触发了report()函数,这个函数的功能就是:

  1. 递归寻找带有data-bp的标签
  2. 发送请求,上报数据(见下一节)

递归寻找带有data-bp的标签:

js 复制代码
  //从事件源递归向父级元素寻找 data-bp 属性
  const collectBpInfo = (dom) => {
    if (!dom || dom.getAttribute('id') === 'root') {
      return '';
    }
    //判断data-bp是否为空
    if (!isBlank(dom.getAttribute('data-bp'))) {
      return dom.getAttribute('data-bp');
    }
    return collectBpInfo(dom.parentElement);
  };
  
  const report = (e) => {
    const bpInfo = collectBpInfo(e.target);
    if (isBlank(bpInfo)) {
      return;
    }
    //发送请求,上报数据
    ...
  };

至此,我们就监听到了项目中的所有点击事件,并且收集了数据 只差最后一步发送请求了。

何种方式发送请求

通常发送请求我们首选就是axios,但实际上浏览器为我们提供了一个更适用于埋点场景的API:

-->Navigator.sendBeacon(url,data)

详见MDN

这种方式的好处在于,不会由于用户的某些操作而中断了请求的发送(页面卸载...),并且这是一个异步的post请求,浏览器会在合适的时机将其发送给服务器。

总结

至此,我们就实现了一个基本的埋点需求,当我们想要在某些点击事件的功能上触发埋点,只需要像这样: <button data-bp="info" ...>...</button> 即可。

这种方式虽然在后续增删埋点时十分方便,但是也带来一定问题:

  • 递归向上搜索可能会由于项目结构过于复杂,递归调用栈过多而导致栈溢出
  • 所有点击事件都会触发这个report()函数

但是这些性能消耗在中小项目中带来的影响并不大。 如果为了更好的解决这个问题,我们只有在需要触发埋点的地方主动发送请求,这就有点麻烦了,可以使用自定义Hook来简化,但也简化不了多少,可以看看这篇(React 实现自动上报 pv/click 的埋点 hooks)。

总之对于埋点问题,方案很多,但是没有一个适用于所有情况的方案(没有"银弹"),对于小项目中还是很推荐以上这种方案的,一劳永逸嘛!

相关推荐
bysking36 分钟前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓1 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_4111 小时前
无网络安装ionic和运行
前端·npm
理想不理想v1 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云1 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
微信:137971205871 小时前
web端手机录音
前端
齐 飞1 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
神仙别闹2 小时前
基于tensorflow和flask的本地图片库web图片搜索引擎
前端·flask·tensorflow
aPurpleBerry2 小时前
JS常用数组方法 reduce filter find forEach
javascript
GIS程序媛—椰子2 小时前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js