大厂经验(一):一套 Web 自动曝光埋点技术方案

2023-11-11

阿里云数据中台官网 https://dp.alibaba.com/index


(作者:qingliang_hu)

关联阅读:大厂经验(二):多端可视化埋点解决方案

前言

首先在介绍这套方案前,咱们还是简单地普及一下“埋点”这个名词。

埋点是指在各个终端(如网页、小程序)中收集一些关键访问数据并将数据发送到日志服务器,以供后续的数据分析。

如下笔者在写这篇文章之前对公司内的一些业务做的访谈调研记录,可以发现埋点在实际业务中大概会有这些作用:

  • “采集并针对性做些投放调整,比如会员权益的展现、影院场次的优先露出、用户想看和看过的互动等”
  • “做新春大盘活动的时候,某些模块曝光次数不够高,运营会调整相应策略”
  • “个性化推荐,根据曝光和点击情况推荐用户数据”
  • “我们这边埋点数据对算法开发、模型训练、效果评估起决定性作用”
  • “观察用户逛会场深度的分布,做相应决策”

在简单介绍今天的主角——埋点的定义后,接下来,我们一起来研究一下自动曝光这件事情。

什么是自动曝光?

自动曝光是指按照埋点规范在页面上进行一个简单的声明式埋点,第三方采集SDK会根据埋点信息自动的采集元素曝光信息的一种方式。

如下图,页面滑动过程中A、B、C、D模块出现在视口内采集SDK会自动上报埋点日志:
image.png

典型轮播图场景,图片滚动出现后需要打曝光日志:
image.png

自动曝光的实现难点?

1、一般而言产品上会要求页面上某个模块一定面积连续一段时间出现在视口才是有效曝光(如30%、300ms)

2、性能,几乎所有的第三方采集平台都会在曝光埋点的说明文档里注明:“请不要配置过多的曝光埋点,这会严重影响你的页面性能”

两个埋点方式
HTML如下:

 

 

<title>轮播图自动曝光埋点demo</title>
<style type="text/css">
ul {
  padding: 0;
}
.clear{
  clear:both;
  zoom: 1;
}
*, :after, :before {
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
}
.clearfix:after {
  clear: both;
}
.clearfix:after,
.clearfix:before {
  display: table;
  content: "";
}
.promo-bd {
  margin: 0 auto;
  overflow: hidden;
  width: 520px;
}
.promo-bd .items-container {
  list-style: none;
  overflow: hidden;
  width: 2280px;
  left: 0px;
  opacity: 1;
  height: 280px;
}
.promo-bd .items-container .item {
  display: list-item;
  float: left;
  overflow: hidden;
  display: block; 
  visibility: visible;
  height: 100%;
}
.promo-bd .items-container .item a {
  display: inline-block;
  height: 100%;
}
.sld-ft-nav {
  text-align: center;
}
.sld-ft-nav li {
  display: inline-block;
  margin-left: 8px;
  border-radius: 10px;
  width: 20px;
  height: 20px;
  line-height: 20px;
  background-color: #ccc;
  color: #fff;
  font-size: 12px;
  cursor: pointer;
}
.sld-ft-nav li:first-child {
  margin-left: 0px;
}
.sld-ft-nav li.selector {
  background-color: #ff7300;
}


 

<div class="container">
  <div class="promo-bd">
    <div class="items-container clear">
      <div class="item" data-id="111">
        <a href="#">
          <img src="https://img.alicdn.com/tfs/TB1fEOLCrr1gK0jSZFDXXb9yVXa-520-280.jpg">
        </a>
      </div>
      <div class="item" data-id="112">
        <a href="#">
          <img src="//img.alicdn.com/tfs/TB1BrwUFuL2gK0jSZPhXXahvXXa-520-280.jpg_q90_.webp">
        </a>
      </div>
      <div class="item" data-id="113">
        <a href="#">
          <img border="0" src="//aecpm.alicdn.com/simba/img/TB183NQapLM8KJjSZFBSutJHVXa.jpg">
        </a>
      </div>
      <div class="item" data-id="114">
        <a href="#">
          <img border="0" src="//aecpm.alicdn.com/simba/img/TB1JNHwKFXXXXafXVXXSutbFXXX.jpg">
        </a>
      </div>
    </div>
    <ul class="promo-nav sld-ft-nav">
      <li class="dot selector" onclick="handlerClick(0)">1</li>
      <li class="dot" onclick="handlerClick(1)">2</li>
      <li class="dot" onclick="handlerClick(2)">3</li>
      <li class="dot" onclick="handlerClick(3)">4</li>
    </ul>
  </div>
</div>
<script type="text/javascript">
  let handlerLoop;
  let width = 520;
  function transform (num) {
    document.querySelector('.items-container').setAttribute('style', `
      transition-duration: 0.3s;
      transform: translate3d(-${width * num}px, 0px, 0px);
      backface-visibility: hidden;
      left: 0px;
      opacity: 1;
    `);
    document.querySelectorAll('li.dot').forEach(function(ele, i){
      ele.setAttribute('class', 'dot');
      if (i === num) {
        ele.setAttribute('class', 'dot selector');
      }
    });
  }
  function loop (n) {
    let num = n;
    handlerLoop = setInterval(function(){
      if (num === 3) {
        num = 0;
      } else {
        num++;  
      }
      transform(num);
    }, 1500);
  }
  loop(0);
  function handlerClick (index) {
    clearInterval(handlerLoop);
    transform(index);
    loop(index);
  }
</script>

 

方式1:在head头部声明式埋点

 

......
<meta name="auto-exp-track" 
      content='[{"logkey":"/banner.item.image","cssSelector":".item","props":["data-id"]}]' />

 

 

......

 

方式2:JS注入式埋点

 

......
  <script>
  var q = (window.tracksdk_queue.push || (window.tracksdk_queue.push = []));
  q.push({
    action: 'trackSdk.setMetaInfo',
    arguments: ['auto-exp-track',[{
      "logkey":"/banner.item.image",
      "cssSelector":".item",
      "props":["data-id"]
    }]]
  })
</sctipt>

 

 

......

 

以上两种方式,埋点SDK均会判断cssSelector=".name"的所有元素被曝光时,自动采集这个标签的曝光信息,及当前元素上"data-id"等props参数打包在一起,以logkey=/banner.item.image的形式发出去。

如:https://tracker.xxx.com/banner.item.image

技术原理

生命周期
image.png

技术细节
1、初始化:DomReady后做监听埋点配置变化(watchConfig)
2、watchConfig首次拿到埋点配置

①监听dom变化(watchDOM)

  • 步骤一、使用MutationObserver或轮询(浏览器最小化、浏览器后台运行、tab未激活均会暂停轮询,直到浏览器窗口再次激活)。MutationObserver监听除['IFRAME', 'BODY', 'OBJECT', 'SCRIPT', 'NOSCRIPT','#text', 'LINK', 'STYLE']之外的所有节点增加监听['class', 'style']属性变化;
  • 步骤二、监听到有dom变化后判断当前元素的track-ae属性是否有值,有则跳过,无则组装参数对象并生成元素唯一HASH,同时设置符合条件的节点状态:“status=init”,再push到_aeElementsHashMap中;
  • 步骤三、分发一个内部事件消息“_AE_DOM_CHANGE”,用于通知watchExposure。

②监听曝光(watchExposureByIntersectionObserver)

  • 步骤一、监听来自watchDOM分发的内部消息“_AE_DOM_CHANGE”,转至步骤二;
  • 步骤二、使用IntersectionObserver包装埋点配置,拿到回调后将节点带入步骤三;
  • 步骤三、遍历aeElementsHashMap,拿到“status===init && element from IntersectionObserver”后判断被曝光的元素是否符合要求(默认按可视面积30%),符合条件的节点设置“status=exposure_start”并更新aeElementsHashMap;
  • 步骤四、在步骤三的基础上setTimeout 300ms后用getBoundingClientRect拿到节点坐标宽高信息再使用自定义交叉计算方法重新计算一遍交叉面积,如果依然超过30%的面积在视口内,那么将符合条件的节点设置“status=exposure_complete”并更新aeElementsHashMap。分发日志发送命令“AE_EXPOSURE_COMPLETE”,用于通知watchRecord;
  • 步骤五、修改已曝光元素dom锚点:track-ae="${HASH}"。

③监听曝光(watchExposureByCustomIntersection)

  • 步骤一、监听来自watchDOM分发的内部消息“_AE_DOM_CHANGE”,转至步骤三;
  • 步骤二、监听touchmove、scroll、resize三种事件回调函数做成throttle_handler_exposure,拿到回调进入步骤三;
  • 步骤三、遍历aeElementsHashMap,拿到“status===init”的节点,然后用getBoundingClientRect获取节点坐标宽高计算出交叉面积,符合可视面积超过30%的节点设置“status=exposure_start”并更新aeElementsHashMap;
  • 步骤四、在步骤三的基础上setTimeout 300ms后用getBoundingClientRect拿到节点坐标宽高信息再使用自定义交叉计算方法重新计算一遍交叉面积,如- 果依然超过30%的面积在视口内,那么 将符合条件的节点设置“status=exposure_complete”并更新aeElementsHashMap。分发日志发送命令AE_EXPOSURE_COMPLETE,用于通知watchRecord;
  • 步骤五、修改已曝光元素dom锚点:track-ae="${HASH}"。

④监听日志发送命令(watchRecord)

  • 步骤一、监听到“_AE_EXPOSURE_COMPLETE”消息后最多10个元素打包在一起发送日志;
  • 步骤二、清理_aeElementsHashMap上下文;
  • 步骤三、给待曝光元素设置dom锚点:track-ae="${index}";

⑤watchConfig非首次拿到埋点配置
1、配置不为空时do_reset,做两件事:1.1、重置_aeElementsHashMap上下文;1.2、将符合条件的元素的track-ae属性重置成同类节点索引值,以触发下一轮曝光监听。

2、配置为空值时do_destroy,做三件事:2.1、销毁_aeElementsHashMap上下文;2.2、移除所有监听事件;2.3、清空所有track-ae锚点属性。

效果

 

性能

笔者通过大量测试和线上优化,拿目前这套架构方案与GA做了一个对比,即对208个元素做了曝光埋点,连续来回滚动,直到所有元素都完成曝光日志上报的性能对比:
image.png

额外收益

有了这个基础,做如下两件事会显得比较轻松了
1、可视化埋点
2、可视化分析

原文链接>>
参考文献:
IntersectionObserver
IntersectionObserverPolyfill

 

数据中台是企业数智化的新基建,阿里巴巴认为数据中台是集方法论、工具、组织于一体的,“快”、“准”、“全”、“统”、“通”的智能大数据体系。目前正通过阿里云数据中台解决方案对外输出,包括零售金融互联网政务等领域,其中核心产品有:

官方站点:
数据中台官网 https://dp.alibaba.com

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

大厂经验(一):一套 Web 自动曝光埋点技术方案 的相关文章

  • nacos源码启动找不到istio包

    现象 源码版本2 1 0 启动时 编译不通过 报错 找不到 istio mcp v1alpha1 MetadataOuterClass Metadata istio networking v1alpha3 ServiceEntryOuter
  • 算法:链表

    单链表 单链表是一种链式存取的数据结构 链表中的数据是以结点来表示的 每个结点存储两个数据 一是该结点本身的值 二是其指向的下一结点的下标 用e i 表示节点i的值 用ne i 表示结点i指向的下一结点的坐标 head表示头结点的下标 id
  • 网关系统架构

    目录 一 API网关业务域 1 业务域 2 统一接入 3 安全防护 4 流量管控 5 协议转换 6 其他业务 1 接口文档管理 2 调试工具和示例 3 SDK自动生成能力 4 API增强 二 API网关核心指标 1 模型 2 安全性 3 高
  • C语言编写的简单计算器程序

    这两天在看一个C语言写的计算器程序 做了不少的功夫 跟着作者一步步的进行完善 了解了许多细节性的东西 在此自己做个总结 加深自己对程序的印象 也算是梳理 在该计算器程序 能进行加减乘除 sin cos exp等操作 同时能进行数值保存功能
  • 2021浙江工商计算机机试1

    1不在数列中的数字 给出一个长度为n的数列 包含1到n的数字 输出1到n中不在数列中的数字 include
  • Android studio64新建APP项目时,报错 junit:junit:4.12

    大家都是要求注释掉 但不想这样 看了很多博客 快绝望的时候 用这个办法成功了 文件 E android app 工程文件目录 下面的 build gradle 文件 在这个文件中加入最后划线3行 保存即可 然后再retry apply pl
  • VS安装配置OpenCV(C++)

    目录 第一章 Opencv安装及其环境变量配置 1 1下载并安装OpenCV 1 2 OpenCV环境变量配置 第二章 Visual Studio 2019 编译器下载安装 第三章 OpenCV开发环境配置 C 3 1创建项目 3 2 添加
  • 全国信息技术标准化技术委员会汉字内码扩展规范(GBK)

    全国信息技术标准化技术委员会 汉字内码扩展规范 GBK Chinese Internal Code Specification 1 0 版 按编码顺序排列 81 丂 丄 丅 丆 丏 丒 丗 丟 丠 両 丣 並 丩 丮 丯 丱 丳 丵 丷 丼
  • 记一次使用EasyExcel出现Convert excel format exception.You can try specifying the ‘excelType‘ yourself

    EasyExcel 3 0 出现 com alibaba excel exception ExcelCommonException Convert excel format exception You can try specifying
  • Vue常用知识点汇总

    1 Vue常见的指令有哪些 有什么用 1 v text 会替换掉元素里的内容 2 v html 可以渲染html界面 3 v clock 防止界面闪烁 4 v bind 界面元素属性值的绑定 简写为 5 v on 事件绑定 简写为 6 v
  • K8s 管理工具 kubectl 详解

    文章目录 一 陈述式管理 1 陈述式资源管理方法 2 k8s 相关信息查看 2 1 查看版本信息 2 2 查看资源对象简写 2 3 查看集群信息 2 4 配置kubectl自动补全 2 5 查看日志 2 6 基本信息查看 2 6 1 查看m
  • SPRING是如何解决循环依赖的?为什么无法解决多例和构造器的循环依赖

    标签 java spring 文章目录 1 什么是循环依赖 2 解决循环依赖思路 3 二级缓存能否解决循环依赖 三级缓存存在的意义 4 多例和构造器为什么无法解决循环依赖 5 如何进行扩展 6 spring在创建bean的时候 在哪里创建的
  • 【C++数据结构】程序性能分析

    程序性能分析 2 1 什么是程序性能 程序性能 所谓程序性能 performance of a program 是指运行这个程序所需要的内存和时间的多少 性能分析 在性能分析 performance analysis 时 采用分析方法 性能
  • 在gitee网页中创建分支后,在vscode中更新分支

    在vscode中更新gitee上创建的分支 在网页创建分支之后 vscode中git pull origin更新在gitee创建的分支 更新之后这里有origin test分支 选中之后 通过git bracn就可以看到线上的分支了
  • 深度理解yolov3损失函数

    深度理解yolov3损失函数 在yolov3中 loss分为三个部分 一个是xywh部分带来的误差 也就是bbox带来的loss 一个是置信度带来的误差 也就是obj带来的loss 最后一个是类别带来的误差 也就是class带来的loss
  • 支付订单同步回调

    public function pay params input 接收数据 判断订单号支付方式不为空 validate this gt validate params order sn gt require pay code 支付方式 gt
  • 30秒内便能学会的30个超实用Python代码片段

    许多人在数据科学 机器学习 web开发 脚本编写和自动化等领域中都会使用Python 它是一种十分流行的语言 Python流行的部分原因在于简单易学 本文将简要介绍30个简短的 且能在30秒内掌握的代码片段 1 唯一性 以下方法可以检查给定
  • MFC多线程同步

    MFC提供了多种同步对象 下面我们只介绍最常用的四种 1 临界区 CCriticalSection 2 事件 CEvent 3 互斥量 CMutex 4 信号量 CSemaphore 一 临界区 使用CCriticalSection类 是一
  • vue路由拦截

    1 在main js中写入下面这些代码 路由拦截 router beforeEach to from next gt if to meta requireAuth 判断该路由是否需要登录权限 if sessionStorage getIte
  • git 下载和安装

    1 什么是git git 是一个分布式的版本控制工具 git 官网 git 官网 2 为什么使用git 保留之前所有版本 以便后续的修改和回滚 方便多人协同开发 3 安装git 3 1 在Linux 上安装 以 Fedora 为例 如果你在

随机推荐

  • Nginx Ubuntu下编译和安装

    1 登录nginx官网http nginx org en download html 下载nginx最新版本 解压nginx 得到目录nginx 1 17 8 tar zxvf nginx 1 17 8 tar gz 2 下载http fl
  • YouCompleteMe unavailable : requires Vim 7.4.143

    版本问题 ubuntu 14 05 安装完YouCompleteMe后不生效 提示 YouCompleteMe unavailable requires Vim 7 4 143经过检索与查询 ubuntu自带的vim为7 4 50 需要安装
  • js延时函数

    js延时函数总结 在js中 延迟执行函数有两种 setTimeout和setInterval 用法如下 setTimeout test 5000 5秒后执行testFunction 函数 只执行一次 setInterval test 500
  • Ubuntu小技巧9--使用Samba服务实现Windows和Linux文件访问

    Ubuntu小技巧8 Ubuntu小技巧9 使用Samba服务实现Windows和Linux文件访问 很多时候做开发的时候需要在Linux上编译运行 但是又想用Windows的优秀工具 不停的将文件拷贝到Windows和Linux是极其浪费
  • 高德地图api之编码(Geocoder)

    高德地图目前仅支持中国范围内的的地理编码和反地理编码 当我们在做搜索功能的时候 由于用户不可以记住地点的经纬度 所以只可能输入地名 所以地理编码就显得额外重要 这里我们查看一下AMap api中的地理编码 地理编码 地理编码 顾名思义就是根
  • Linux系列:编写 jar包 启动脚本

    包含指定环境 启动的脚本 指定springBoot的 application properties 创建 start sh 文件 文件内容如下 1 直接启动 bin sh 该脚本为Linux下启动java程序的 1第一个参数为方法名star
  • 设计模式-装饰模式(Decorator)

    装饰模式又叫包装模式 通过一种对客户端透明的方式来扩展对象的功能 是继承关系的一个替换方案 角色和职责 1 抽象组件 Component Car 为统一接口 也是装饰类和被装饰类的统一接口 2 具体组件 concrete Component
  • DGL中minibatch训练子图Prefetch到GPU中加速

    2022 04 update 最近DGL官方提供了prefetch的功能 可以直接使用官方实现了 https github com dmlc dgl pull 3665 导读 这两天在研究怎么加速DGL上GNN的训练 使用line prof
  • 关于内核autoconf.h

    1 老版内核autoconf h的生成 在make menuconfig时生成 config然后再make zImage时就会由 config生成autoconf h 都是脚本做的 2 关于新版的内核 在比较老的版本比如http lxr l
  • 分享160多种ChatGPT 高频中文prompt 提示词指令合集——秒变AI训练师

    ChatGPT 中文 Prompt 提示词 常用 高频集合 在本篇文档中 我将展示超过 160 种 prompt 提示词 你可以挑选自己感兴趣的提示词进行尝试 国内免费ChatGPT聊天地址 https chat bytearch com
  • react学习—ref Hook

    ref Hook 一 ref Hook 1 useRef 2 其它使用 一 ref Hook 1 useRef useRef函数 一个参数 默认值 返回一个固定的对象 current 值 import React createRef use
  • 如何寻找数组中的最大值和最小值

    以下五种解法可以寻找到数组中的最大值和最小值 1 问题分解法 把本题看做两个独立的问题 而非一个问题 所以 每次分别找出最小值和最大值即可 此时 一共需要遍历两次数组 比较次数为2N次 N表示数组的长度 2 取单元素法 维持两个变量min和
  • 为什么ping不通某网站,但是却可以访问该网站?

    本文转载自 http blog csdn net u013078669 article details 48437559 今天在访问一个网站的时候 我想看看它的ip是多少 就在windows 命令行下去ping了下该网站 ip地址是解析出来
  • Hive sql语法详解

    1 DDL 操作 DDL 建表 删除表 修改表结构 创建 删除视图 创建数据库 显示命令 建表 CREATE EXTERNAL TABLE IF NOT EXISTS table name col name data type COMMEN
  • Sublime Text3 js语法错误提示

    1 插件安装输入 SublimeLinter 2 插件安装输入 sublimeLinter jshint 3 确保安装了nodeJs 4 命令行进入npm目录 输入 npm install g jshint 5 重启Sublime ctrl
  • STM32超声波模块 HAL库 输入捕获

    STM32 HAL库 CubeMX 输入捕获 超声波模块 前言 软件及硬件准备 硬件连接 CubeMX配置 定时器配置 串口配置 keil软件编写 代码讲解 注意事项 前言 本教程使用的是STM32F103C6T6 利用定时器输入捕获双边沿
  • 【1day】H5S视频平台未授权漏洞学习

    注 该文章来自作者日常学习笔记 请勿利用文章内的相关技术从事非法测试 如因此产生的一切不良后果与作者无关 目录 一 漏洞描述 二 资产测绘 三 漏洞复现 四 漏洞修复 一 漏洞描述 H5S视频平台是一个基于Web技术的视频播放和流媒体管理平
  • STM32F4 USB Speaker代码分析

    主机 WIN10 64位 设备 STM32F411 PCM5102 STM32CubeMX版本 V6 0 1 JAVA JDK 11 写这篇文章主要是给自己备忘 因对USB协议规范没有系统的了解 可能有些地方理解不是很正确 配置CubeMX
  • cygwin和mingw的比较

    Unix下编译通过的C代码 在win32下编译是不能通过的 当然Unix 和win32的API都是符合标准C 也就是说 大多数函数调用在unix和win32下是相同的 但是 unix有自己一些独特的API 如fork spawn signa
  • 大厂经验(一):一套 Web 自动曝光埋点技术方案

    阿里云数据中台官网 https dp alibaba com index 作者 qingliang hu 关联阅读 大厂经验 二 多端可视化埋点解决方案 前言 首先在介绍这套方案前 咱们还是简单地普及一下 埋点 这个名词 埋点是指在各个终端