乐趣区

关于前端:通过自定义Vue指令实现前端曝光埋点

这是第 94 篇不掺水的原创,想获取更多原创好文,请搜寻公众号关注咱们吧~ 本文首发于政采云前端博客:通过自定义 Vue 指令实现前端曝光埋点

前言

互联网倒退至今,数据的重要性曾经显而易见,尤其是在电商公司,数据的统计分析尤为重要,通过数据分析能够晋升用户的购买体验,不便经营和产品调整销售策略等等。埋点就是网站剖析的一种罕用的数据采集办法。

埋点依照获取数据的形式个别能够分为以下 3 种:

  • 页面埋点:统计用户进入或来到页面的各种维度信息,如页面浏览次数(PV)、浏览页面人数(UV)、页面停留时间、浏览器信息等。
  • 点击埋点:统计用户在利用内的每一次点击事件,如新闻的浏览次数、文件下载的次数、举荐商品的命中次数等。
  • 曝光埋点:统计具体区域是否被用户浏览到,如流动的引流入口的显示、投放广告的显示等。

政采云前端团队(ZooTeam)通过 浑仪零碎 实现数据采集及数据可视化,剖析量化的能力,想理解浑仪零碎或者还不理解埋点的同学能够先浏览前端工程实际之数据埋点剖析零碎。

浑仪零碎的数据采集是基于 代码侵入式埋点计划 实现的,提供了主动发送和手动调用埋点信息上报接口发送两种形式实现埋点数据上报。其中 页面埋点 点击埋点 是应用主动上报的形式实现,在 DOM 节点挂载非凡属性,通过 埋点采集 JSSDK 监听挂载了相应属性对应的事件,在事件触发时进行埋点数据上报。曝光 埋点 因为波及到 无效曝光逻辑的判断,主动上报不能满足相应的需要,所以咱们采纳手动调用接口方式进行埋点数据上报。

无效曝光

先举个例子:

上图是某电商首页底部的举荐区域,为了掂量用户对举荐后果的感兴趣水平,须要计算举荐区域的点击率(点击次数 / 曝光次数)。为了保障点击率的准确性,咱们必须确保用户真正的浏览到了这些商品,因为用户浏览商品的不确定性会产生雷同商品的频繁曝光,咱们还要防止反复的曝光行为。所以咱们须要制订一套逻辑来规定何时进行曝光埋点的数据上报。比方:

  1. 商品卡片必须齐全的呈现在浏览器可视化区域内。
  2. 商品必须在可视化区域内停留 5s 以上。
  3. 用户进入页面到来到页面雷同的商品只进行一次曝光。

满足以上规定的曝光就是一次 无效曝光。理解了无效曝光后,咱们来看看曝光埋点实现最重要的一环,如何判断元素呈现在页面的可视化区域内。

判断元素呈现在页面的可视化区域内

咱们首先想到商品曝光相似于图片懒加载的模式,通过监听 scroll 事件,调用 Element.getBoundingClientRect()办法以获取相干元素的边界信息,而后判断元素是否呈现在页面的可视化区域内。因为 scroll 事件频发触发,计算量很大,所以很容易造成性能问题,尽管咱们能够采纳防抖节流等形式去解决。

目前有一个新的 IntersectionObserver API,提供了一种异步检测指标元素与先人元素或 viewport(可视窗口)相交状况变动的办法。能够主动 ” 察看 ” 元素是否可见。

IntersectionObserver 根本用法

let options = {root: document.querySelector('#scrollArea'),
    rootMargin: '0px',
    threshold: 1.0
}
let callback =(entries, observer) => {entries.forEach(entry => {});
};
let observer = new IntersectionObserver(callback, options);

IntersectionObserver 是浏览器原生提供的构造函数,承受两个参数:callback 是可见性变动时的回调函数,option 是配置对象(该参数可选),返回一个 observer 实例。
咱们能够看到,创立一个 IntersectionObserver 对象,承受两个参数:callback 可见性变动时的回调函数,该回调函数将会在 指标(target)元素和根(root)元素的交加大小超过 阈值(threshold)规定的大小时候被执行。

options 是配置对象,它有以下字段:

  • root:指定根 (root) 元素,用于查看指标的可见性。必须是指标元素的父级元素。如果未指定或者为 null,则默认为浏览器视窗。
  • rootMargin:根 (root) 元素的外边距。相似于 CSS 中的 margin 属性。默认值为 0。
  • threshold:target 元素和 root 元素相交水平达到该值的时候 callback 函数将会被执行,能够是繁多的 Number 也能够是 Number 数组,当为数组时每达到该值都会执行 callback 函数。

咱们通过实例的办法能够指定察看哪个 DOM 节点。实例的办法有:

  • IntersectionObserver.observe():使 IntersectionObserver 开始监听一个指标元素。
  • IntersectionObserver.disconnect():使 IntersectionObserver 对象进行监听工作。
  • IntersectionObserver.takeRecords():返回所有察看指标的 IntersectionObserverEntry 对象数组。
  • IntersectionObserver.unobserve():使 IntersectionObserver 进行监听特定指标元素。

IntersectionObserverEntry 对象提供指标元素的信息,一共有七个属性:

  • IntersectionObserverEntry.target:须要察看的指标元素,是一个 DOM 节点对象。
  • IntersectionObserverEntry.boundingClientRect:返回蕴含指标元素的边界信息。边界的计算形式与 Element.getBoundingClientRect() 雷同。
  • IntersectionObserverEntry.intersectionRect:用来形容根和指标元素的相交区域的信息.
  • IntersectionObserverEntry.intersectionRatio:返回 intersectionRectboundingClientRect 的比例值,0 为齐全不可见,1 为齐全可见。
  • IntersectionObserverEntry.isIntersecting:返回一个布尔值, 如果根与指标元素相交(即从不可视状态变为可视状态),则返回 true。如果返回 false, 变换是从可视状态到不可视状态。
  • IntersectionObserverEntry.rootBounds:根元素的区域的信息。
  • IntersectionObserverEntry.time:可见性状态产生扭转工夫的工夫戳,单位为毫秒。

指标元素的可见性变动时,就会调用观察器的回调函数 callbackcallback 函数的参数 entries 是一个数组,每个成员都是一个 IntersectionObserverEntry 对象,observer 是被调用的 IntersectionObserver 实例。callback 函数个别会被调用两次,一次是指标元素进入可视化区域,另一次是来到可视化区域。配置 options.threshold 会影响 callback 函数的调用次数。

咱们再来看看 Intersection Observer API 的浏览器兼容状况

咱们看到是存在兼容性问题的,好在曾经有了兼容的 polyfill。以后浏览器不反对 Intersection Observer API 时,应用 Element.getBoundingClientRect()去实现 Intersection Observer API。

具体实现

理解了 Intersection Observer 的根本用法了当前,上面咱们来实现前端的曝光埋点。因为业务是基于 Vue 实现的,所以咱们通过自定义 Vue 指令实现前端的曝光埋点。

首先咱们自定义一个 visually 指令,当指令第一次绑定在元素上时应用 IntersectionObserver 监听指标元素,当指令从元素上解绑时进行监听指标元素。

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('visually', {
  bind: addListenner,
  unbind: removeListener,
});

咱们须要一个 List 将曾经上报过的埋点信息记录下来,避免反复曝光。

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

咱们将要上报的信息绑定在指标元素的 ‘visually-data’ 属性中,当指标元素呈现在视窗内时,并停留 5 秒以上时,咱们上报埋点信息。

let timer = {}; // 减少定时器对象
const callback = entries => {
  entries.forEach(entry => {
    let visuallyData = null;
    try {visuallyData = JSON.parse(entry.target.getAttribute('visually-data'));
    } catch (e) {
      visuallyData = null;
      console.error('埋点数据格式异样', e);
    }
    // 没有埋点数据勾销上报
    if (!visuallyData) {observer.unobserve(entry.target);
      return;
    }
    
    if (entry.isIntersecting) {timer[visuallyData.id] = setTimeout(function() {
        // 上报埋点信息
        sendUtm(visuallyData).then(res => {if (res.success) {
            // 上报胜利后勾销监听
            observer.unobserve(entry.target);
            visuallyList.push(visuallyData.id);
            timer[visuallyData.id] = null;
          }
        });
      }, 5000);
  } else {if (timer[visuallyData.id]) {clearTimeout(timer[visuallyData.id]);
      timer[visuallyData.id] = null;
    }
  }
  });
};

最初咱们引入 polyfill 实现 IE 的兼容,封装一个全局指令。

require('intersection-observer');
export default Vue => {
    ...
  // 自定义曝光指令
  Vue.directive('visually', {
    bind: addListenner,
    unbind: removeListener,
  });
};

咱们通过 Vue.use() 引入组件后,就能够在业务代码中间接通过指令实现曝光埋点。曝光数据 visuallyData 中必须要有一个惟一 ID。

<div v-visually="visuallyData.id" :visually-data="JSON.stringify(visuallyData)" class="browse"></div>

总结

埋点是数据分析的根底,埋点数据统计的准确性对后续的数据分析十分重要,所以咱们在统计曝光埋点的时候肯定要基于实用场景优先制订曝光埋点的规定。本文只是针对前端曝光埋点的实现计划,如有问题处,请大佬们多多交换。

招贤纳士

政采云前端团队(ZooTeam),一个年老富裕激情和创造力的前端团队,隶属于政采云产品研发部,Base 在风景如画的杭州。团队现有 40 余个前端小伙伴,平均年龄 27 岁,近 3 成是全栈工程师,妥妥的青年风暴团。成员形成既有来自于阿里、网易的“老”兵,也有浙大、中科大、杭电等校的应届新人。团队在日常的业务对接之外,还在物料体系、工程平台、搭建平台、性能体验、云端利用、数据分析及可视化等方向进行技术摸索和实战,推动并落地了一系列的外部技术产品,继续摸索前端技术体系的新边界。

如果你想扭转始终被事折腾,心愿开始能折腾事;如果你想扭转始终被告诫须要多些想法,却无从破局;如果你想扭转你有能力去做成那个后果,却不须要你;如果你想扭转你想做成的事须要一个团队去撑持,但没你带人的地位;如果你想扭转既定的节奏,将会是“5 年工作工夫 3 年工作教训”;如果你想扭转原本悟性不错,但总是有那一层窗户纸的含糊… 如果你置信置信的力量,置信平凡人能成就不凡事,置信能遇到更好的本人。如果你心愿参加到随着业务腾飞的过程,亲手推动一个有着深刻的业务了解、欠缺的技术体系、技术发明价值、影响力外溢的前端团队的成长历程,我感觉咱们该聊聊。任何工夫,等着你写点什么,发给 ZooTeam@cai-inc.com

退出移动版