前端埋点简单实现方式

1.为什么使用前端埋点?

主要是为了收集产品数据,它的目的是上报相关行为数据,相关人员以数据为依据来分析产品在用户端的使用情况,根据分析出来的结果辅助产品优化、迭代、以及新需求的开发。

2.目前项目埋点方面存在的痛点?

1.逻辑复用问题:特别是曝光相关的点需要在业务代码里面做额外的处理,所以逻辑复用很困难,对现有代码的侵入也很严重;

2.埋点在多个项目中分散存在,维护会比较麻烦。

3.前端埋点方案

目前主要有 3 种方案:

1.手动代码埋点:用户触发某个动作后手动上报数据
优点:是最准确的,可以满足很多定制化的需求。
缺点:埋点逻辑与业务代码耦合到一起,不利于代码维护和复用。

2.可视化埋点:通过可视化工具配置采集节点,指定自己想要监测的元素和属性。核心是查找 dom 然后绑定事件,业界比较有名的是 Mixpanel、GrowingIO、神策
优点:可以做到按需配置,又不会像全埋点那样产生大量的无用数据。
缺点:比较难加载一些运行时参数;页面结构发生变化的时候,可能就需要进行部分重新配置。

3.无埋点:也叫“全埋点”,前端自动采集全部事件并上报埋点数据,在后端数据计算时过滤出有用数据
优点:收集用户的所有端上行为,很全面。
缺点:无效的数据很多、上报数据量大。

4.埋点方式
按照获取数据的方式一般分为三类:
页面埋点:统计用户进入或离开页面的各种维度信息,如页面浏览次数(PV)、浏览页面人数(UV)、页面停留时间、浏览器信息等。
点击埋点:统计用户在应用内的每一次点击事件,如报价列表的浏览次数、再次询价的次数等。
曝光埋点:统计具体区域是否被用户浏览到,如活动的引流入口的显示、投放广告的显示等

5.埋点方案
目前我们项目中埋点需求主要有,点击埋点(dom点击)、页面埋点(主要是pv)。再根据我们目前选用的vue技术栈,所以考虑了以下两种实现方式:组件方式或者指令方式
点击埋点开始的是想提供一个组件,包裹需要进行点击埋点的 dom 元素,也有可能是组件,然后给子元素绑定点击事件,当用户触发事件时进行埋点相关处理。
但是这样就必须绑定点击事件到 dom 上,但是又不想在文档结构中引入额外的 dom 元素,因为这会增加 dom 结构层级,层级会变得更复杂。
所以最终采用了自定义指令的方式。

  1. 项目埋点实现

使用策略模式分别处理埋点需求:

/**
 * @description: 埋点方式:点击埋点、页面PV
 * @param {key} 埋点key值
 * @return {el} 点击埋点被绑定的元素
 */
const handler = {
  click (key, el) {
    el.addEventListener('click', () => {
      appPointBatchInsert(key)
    })
  },
  pv (key) {
    appPointBatchInsert(key)
  }
}

自定义埋点指令

const Point = {}

Point.install = Vue => {
  Vue.directive('point', {
    inserted (el, binding) {
      const data = binding.value
      if (data) {
        const { key, type } = data
        handler[type](key, el)
      } else {
        throw new Error('请补充正确的埋点参数')
      }
    }
  }, false)
}

export default Point

使用示例

import point from '@/utils/directive/point.js'
Vue.use(point)
<!-- 点击埋点 -->
<el-button v-point="{key: 'additionalInquiryClickKey', type: 'click'}">追加</el-button>
<!-- 页面pv埋点: section为页面根元素 -->
<section class="additional-inquiry" v-point="{key: 'additionalInquiryKey', type: 'pv'}">

7、之后拓展方向
曝光埋点(可能产品需求方向??) 思路:当指令第一绑定在元素上时监听目标元素,当指令从元素上解绑时停止监听目标元素。

const options = {
    root: null, //默认浏览器视窗
    threshold: 1 //元素完全出现在浏览器视窗内才执行callback函数。
}
const callback =(entries, observer) => {
  entries.forEach(entry => {})
}
const observer = new IntersectionObserver(callback, options)
const addListenner = (ele, binding) => {
 observer.observe(ele)
}
const removeListener = (ele) => {
  observer.unobserve(ele)
}
//自定义曝光指令
Vue.directive('point', {
  bind: addListenner,
  unbind: removeListener
})

注意,我们需要创建一个list将已经上报过的埋点信息记录下来,防止重复曝光。

let pointList = []; //记录已经上报过的埋点信息
const addListenner = (ele, binding) => {
 if(pointList.indexOf(binding.value) !== -1) return

 observer.observe(ele)
}

我们将要上报的信息绑定在目标元素的 'point-data' 属性中,当目标元素出现在视窗内时,并停留 5 秒以上(或者规定记录秒数时)时,上报埋点信息。

let timer = {} //增加定时器对象
const callback = entries => {
  entries.forEach(entry => {
    let pointData = null
    try {
      pointData = JSON.parse(entry.target.getAttribute('point-data'))
    } catch (e) {
      pointData = null
      console.error('埋点数据格式异常', e)
    }
    //没有埋点数据取消上报
    if (!pointData) {
      observer.unobserve(entry.target)
      return
    }

    if (entry.isIntersecting) {
      timer[pointData.id] = setTimeout(function() {
        //上报埋点信息
        sendUtm(pointData).then(res => {
          if (res.success) {
            //上报成功后取消监听
            observer.unobserve(entry.target)
            visuallyList.push(pointData.id)
            timer[pointData.id] = null
          }
        })
      }, 5000)
  } else {
    if (timer[pointData.id]) {
      clearTimeout(timer[pointData.id])
      timer[pointData.id] = null
    }
  }
  })
}

在代码中可以直接使用指令实现曝光埋点了:

<div v-point="pointData.id" :point-data="JSON.stringify(pointData)"></div>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351