埋点设计与管理
埋点的作用
开始之前我们先看一下我们为什么要收集埋点数据,埋点都可以做什么,埋点主要用于记录用户行为,几乎是应用必不可少的功能.埋点的作用包括但不限于
分析用户转化以及存留
例如下载的用户数量,注册的用户数量,一段时间之后的存留用户数量;
分析用户偏好
例如通过用户行为的分析,可以对用户的偏好做一定的概括,便于投其所好针对特性的用户推送特定的服务,甚至开发不同的用户体验;
收集市场反馈
例如针对新功能的用户行为进行统计,就可以分析出功能的市场反馈,为是否保留功能或者改良方向提供依据;
保障用户数据安全
例如用户的地理位置数据在短时间内突然发生了异常变更,这一秒在南京,下一秒突然就在东京登陆了,那就说明账号发生了异常,需要对账号身份进行验证,以确保用户数据的安全.
定位异常
例如特定的数据(比如注册)在某一段时间内数据突然无缘由发生持续性异常,说明该功能可能存在异常,需要及时做排查.
其他作用
例如当某一个较早机型占比降低到某一个阀值时,就可以在下一个版本中去掉对该设备的支持.
埋点数仓设计
数据进入数仓之前我们就需要设计好数仓表,埋点的表的数据有几个特点,所以我们在设计的时候需要考虑到
- 数据量非常大,可能是所有数据集成渠道里面,流量最大的了
- 数据不存在更新,这是埋点表的数据特点
面对这两个特点,我们需要做一些设计,当然还有一些其他设计方面的点需要注意一下,首先因为量大,而且我们往往关注的是昨天的数据,所以我们的表肯定是分区表,其次因为我们使用的特点,例如关注的是页面浏览或者是按钮点击,所以我们在时间分区的基础上按照事件进行分区。这样我们可以在数据查询的时候过滤掉大量的数据从而提高查询的性能。
其次就是埋点表的作为数据报表的数据来源的时候,可能会大概率遇到计算延迟,或者是一些其他问题,所以在宽表的设计或者是报表展示中,请尽量地将集成进行后延,从而更好的保证稳定性和可用性。关于这一点,请参考数仓建模—宽表的设计
这里是我们公司小程序端的埋点表
下面是web 端的埋点表
埋点的类型
埋点:在期望的点位,埋设一个记录的标记。这个点位,一般多是指用户与产品进行一次次交互的接触点,从而可以在用户和产品交互的时候,将用户的数据进行上报。
通过收集这些标记点的数据,可以帮助产品运营及开发同学了解功能的整体使用、运行情况,并通过数据基础上做出下一步调整或优化的方向。遇事不拍脑袋,而是用数据说话,这是数据埋点最大的价值。
在AB测试的场景下,数据埋点为实验组的效果提供数据支持,其本质也是数据决策的基础。
根据目前常见的数据埋点形式,可以将数据埋点分为全埋点、代码埋点(自定义埋点),当然我们也可以按照产品的类型划分为,APP埋点、web 埋点、小程序埋点
全埋点
全埋点的逻辑,是指数据采集sdk无区别的对待所有事件的,将所有事件(页面的加载成功事件、控件的浏览和点击事件)全部获取后先存下来,到使用的时候,再根据具体的页面路径和控件名称,去捞取相应的数据。
可视化埋点
基于此,可视化埋点是指,在全埋点部署成功、已经可以获得全量数据的基础上,以可视化的方式,然后进行数据选择。
这种方案的弊端之一是耗流量和存储空间,全埋点采集的数据一般会根据情况设定一个销毁时限,比如7天。即:全采集过来的数据,如果7天之内没有被使用,则会删除。而一旦对圈选数据做了圈选定义之后,则被定义的页面数据、控件数据,则会一直采集,且不会删除。
全埋点,其优势和特点是功能上线时,不需要开发做额外的埋点定义工作,用的时候再根据需求去获取对应的数据,因此也叫无埋点。
全埋点的缺点:
- 耗用户流量、占存储空间;
- 一旦版本迭代,对页面的路径做修改,或者控件位置、文案有修改,原来的圈选数据可能就会出错,需要重新圈选,之前利用圈选指标设定的分析模型都要替换;
- 圈选指标无法区分细部参数,比如:商品详情页,无法通过圈选数据来区分是哪一个商品或哪一个类目;
- 对web的页面数据处理一直不好,尤其是涉及到APP的内嵌H5页时,非常痛苦。
因此,全埋点适用于业务多变、经常调整,且分析诉求比较轻量的场景。对于通用的功能,形态相对比较固定,且对数据分析颗粒度、下钻深度、聚合程度要求比较高,那就需要用到代码埋点
代码埋点
代码埋点也叫自定义埋点,从字面上即可理解:是针对想要的点位单独定义,并可以通过变量丰富埋点的信息,以支持上下游分析。
代码埋点分为前端埋点和后端埋点。
前端埋点,包括但不限于APP客户端、H5、微信小程序、PC网页,是指对具体的功能场景(如加载成功、浏览、点击等)进行明确的定义,由前端触发,采集上来的数据相比于全埋点,更准确、稳定,且通过变量字段,能够实现更细颗粒度数据的拆分、聚合和下钻。
后端埋点,指触发了服务端接口调用(如:接口回调成功触发)的事件埋点,如最典型的注册成功事件、付费成功事件。后端埋点对数据的准确度要求更高,同时也可以通过变量字段的扩展支持数据拆分、聚合和下钻。需要强调的是,后端事件一般采集的是已登录状态下的用户行为,如果想使用后端埋点事件作为流程分析的其中一环(如漏斗分析),则可能出现未登录的用户会漏掉的情况。
综合以上,几种埋点类型的比较
埋点上报方式
对于一个埋点方案来说,数据上报有两个点需要着重考虑:
- 对跨域做特殊处理。
- 页面销毁后,如何还能够将未上传的埋点数据成功上报
参考 https://juejin.cn/post/6844904153739706375
图片请求
有下面几点优势:
- 没有跨域问题,一般这种上报数据,代码要写通用的,img 天然支持跨域;(排除 ajax)
- 不会阻塞页面加载,影响用户的体验,只要 new Image 对象就好了, 通过它的onerror和onload事件来检测发送状态;(排 除 JS/CSS 文件资源方式上报)
- 在所有图片中,简单、安全、相比PNG/JPG体积最小;(比较 PNG/JPG)(tip:最小的BMP文件需要74个字节,PNG需要67个字节,而合法的GIF,只需要43个字
这种使用方式也存在缺陷。首先对于src 中的URL内容是有大小限制的,太大的数据量不适用。详细看这里。其次,在页面卸载的时候,若存在数据未发送的情况,会先将对应的数据发送完,再执行页面卸载。这种情况下,会在体验上给使用者带来不方便。
GET 请求
GET把参数包含在URL中,也就是说我们的上报的数据是在一个url 参数中或者是几个参数中,例如 ?data=XXXX
这里的data 就是我们上报的数据
GET 请求 最大的特点就是简单,但是同时也带来了很多其他的问题,首先是安全问题因为GET 请求参数被暴露在IURL 中,GET请求只能进行url编码,而POST支持多种编码方式,其次GET请求在URL中传送的参数是有长度限制的,也就是如果你上报的数据内容比较多,可能会被截断。
POST 请求
POST 请求 相比GET 请求首先就是更加安全,其次是支持多种编码,而且所能发送的数据量也更大,看起来是个不错的选择,但是还是不如图片请求好
埋点管理设计
整个埋点的事件我们可以使用4W1H 进行表示
下面是APP 端的一个例子
事件模型
我们使用“事件模型( Event 模型)”来描述用户的各种行为,事件模型包括事件( Event )和用户( User )两个核心实体。整个埋点的属性,我们可以分为两大类,第一类是事件属性,第二类是用户属性。
为什么这两个实体结合在一起就可以清晰地描述清楚用户行为?实际上,我们在描述用户行为时,往往只需要描述清楚几个要点,即可将整个行为描述清楚,要点包括:是谁、什么时间、什么地点、以什么方式、干了什么。而事件( Event )和用户( User )这两个实体结合在一起就可以达到这一目的。下面分别介绍一下这两个实体。
一个完整的事件( Event ),包含如下的几个关键因素:
Who:即参与这个事件的用户是谁。
When:即这个事件发生的实际时间。
Where:即事件发生的地点。
How:即用户从事这个事件的方式。这个概念就比较广了,包括用户使用的设备、使用的浏览器、使用的 App 版本、操作系统版本、进入的渠道、跳转过来时的 referer 等。
What:以字段的方式记录用户所做的事件的具体内容。不同的事件需要记录的信息不同,下面给出一些典型的例子:
对于一个“购买”类型的事件,则可能需要记录的字段有:商品名称、商品类型、购买数量、购买金额、 付款方式等;
对于一个“搜索”类型的事件,则可能需要记录的字段有:搜索关键词、搜索类型等;
对于一个“点击”类型的事件,则可能需要记录的字段有:点击 URL、点击 title、点击位置等;
对于一个“用户注册”类型的事件,则可能需要记录的字段有:注册渠道、注册邀请码等;
对于一个“用户投诉”类型的事件,则可能需要记录的字段有:投诉内容、投诉对象、投诉渠道、投诉方式等;
对于一个“申请退货”类型的事件,则可能需要记录的字段有:退货金额、退货原因、退货方式等。
描述事件的任意一个字段,都是一个事件属性。应该采集哪些事件,以及每个事件采集哪些事件属性,完全取决于产品形态以及分析需求。
事件的设计
下面分别是 H5、APP 、小程序 端埋点的一个设计
基本规范
我们在设计的时候要注意一些基本的规范,例如我们属性的命名,这样才能可以更好的维护
预置属性
设计原则
整个埋点的设计我们应该遵循一下几个原则,从而可以更好的维护和管理整个埋点系统
通用基础事件
埋点时间能通用则不单独埋点,不是说单独埋点越多越好,我们应该尽可能的从上层设计比较通用的事件,这样方便复用。
重要事件
重要事件单独处理,统一上报,保证采集的可用性
业务主流程
对于主要的业务流程,我们可以设计独立的事件,从而方便更好的分析
自定义事件
其实所有的事件都是自定义事件,但是我们为什么还是要区分自定义事件呢?
这是因为我们在一开始定义可很多通用的事件,所以我们的自定义事件是相对我们的通用事件而言的,但是我们怎么去定义一个自定义事件吗,其实还要考虑到通用的属性,因为这样我们可以复用通用事件的一些属性的定义,而不是完全重新设计一套东西。
举例来说,一个电商产品可能包含如下事件:用户注册、浏览商品、添加购物车、支付订单等,这里我们就那用户注册事件来说吧,其实它应该是一个点击事件,但是和点击事件不一样的是,我们需要添加一些新的属性,所以我们可以在点击事件的基础上去添加属性,有点类似编程语言的继承,但是有的时候我们也可以去组合多个事件的属性,其实这个是不常见的。
数据从生产到应用的流程
业务流程
确定场景或目标
确定一个场景,或者一个目标。比如,我们发现很多用户访问了注册页面,但是最终完成注册的很少。那么我们的目标就是提高注册转化率,了解为什么用户没有完成注册,是哪一个步骤挡住用户了。
数据采集规划
思考哪些数据我们需要了解,以帮助我们实现这个目标。比如对于之前的目标,我们需要拆解从进入注册页面到完成注册的每一个步骤的数据,每一次输入的数据,同时,还有完成或者未完成这些步骤的人的特征数据。
埋点采集数据
我们需要确定谁来负责收集数据,一般是工程师,有些企业有专门的数据工
程师,负责埋点采集数据。
数据评估和数据分析
给出优化方案
发现问题后,怎么给出解决方案。比如,是否需要在设计上改进,或者是否是工程上的 bug。
实施优化方案
谁负责实现解决方案,需要确定方案的实施责任人。
评估解决方案的效果
进行下一轮数据采集和分析,回到第一步继续迭代。
知易行难。这整个流程里,第 2 步到第 4 步是关键。目前传统的服务商
比如 Google Analytics、百度统计、友盟所采用的方式称作 Capture 模
式。通过在客户端埋下确定的点,采集相关数据到云端,最终在云端做呈
现。
开发流程
首先是基于一定的需求出发,然后产品/业务/分析师 对需求进行评审,主要就是需求同步,信息对齐,接下来就是埋点的开发与测试,埋点上线之后,数据同学开始进行数据需求开发在此过程中对埋点进行验收,最后对数据需求进行交付
这个过程,需要专门投入专人去做这个事情,企业需要定制顶层的业务规范,上面的流程中有一个环节是没有的,那就是埋点的下线。
数据产品和数据分析师不仅要考虑到业务需求和数据分析的工作,还要站在业务线数据体系和数据应用负责人的角度,对埋点实施、管理、迭代、文档、交付、支持进行掌控和维护
埋点管理系统设计
其实很多公司针对埋点会维护单独的一个系统,这个系统主要维护了公司的全部埋点,其实你可以将其理解为和jira 类似的一套系统。下面我们看系统的核心
埋点列表
埋点注册
埋点详情
主要提供关于埋点的基本信息和统计信息
属性管理
在埋点元数据中维护产品/业务层面的通用属性,由数据团队统一维护,所有可见的属性,都可以在注册/编辑埋点是添加属性时搜索到。自定义属性相对于通用属性,是某个事件下特有的属性,由业务方根据埋点方案维护
表设计/展示设计
字段名称 | 备注 |
埋点ID | 表的自增ID 即可 |
埋点域 | 是APP 埋点还是web 埋点还是都是 |
埋点中文名称 | |
埋点英文名称 | |
埋点位置 | 这个位置我们要求使用图片进行展示+文字说明 这里的图片展示很重要,因为这样很形象 |
埋点开发负责人 | 谁负责开发,很多时候会涉及到APP 和 Web 同时开发 |
埋点业务负责人 | 谁提的需求 |
埋点数据负责人 | 谁负责该埋点对应数据需求的处理,完成最终埋点的验收 |
埋点业务含义 | 为什么埋点,关于埋点的具体数据计算逻辑是什么 |
埋点所属事件 | 埋点所属的事件,一般情况下我们都可以将一个埋点归到我们已经定义的埋点事件中去 如果是没有合适的埋点事件,需要先定义事件,再定义该埋点 |
埋点通用属性 | 一旦归类到某个埋点事件下面,我们要求上报该事件的全部属性 |
自定义属性 | 该埋点的自定义属性 |
埋点代码git的PR | 是一个url,方便追踪埋点代码 |
埋点的Jira | 埋点需求的jira 跟踪 |
埋点的状态 | 上线、测试、开发、下线、不可见等状态 这里下线,指的是如果埋点的功能不要了或者其他的一些原因,我们需要对埋点进行及时下线 |
埋点的创建时间 | |
埋点的上线时间 | |
埋点的更新时间 |
主要的就是上面这些,我们需要做的就是将这些进行前端展示和前端录入。
数据解析在哪里做
首先我们还是先看一下一个架构图,从而理解一下数据流转,下面就是数据流转的一个大致方向
最后面的maxcompute 是我们的计算引擎,你可以将其当作是hive/spark ,具体是啥不重要,我们的数据通过前端(APP/web)前端上报,但是我们需要一个后端服务用来接收数据,然后后端获取到数据之后进入消息队列,最后我们再通过数据同步工具/数据消工具 把数据同步到大数据平台,从而开始数据计算和建模。
这里有一个问题就是我们上报上来的数据可能是加密的,或者是我们的消息队列是支持schema的(kafka 不支持),这种情况下我们的数据要不要解析呢?直接说结论吧,最好不要解析,将解析的工作放在计算引擎中做,原因很多,下面陈述两点:
- 后端服务在这里扮演的角色其实和消息队列差不多,如果这个过程有逻辑越多,耦合就越高,可扩展性就差,例如前端上报的数据格式变了,或者是有其他的一些升级,这个时候后端也要做对应的操作,然后重新发布。
- 后端服务如果在这里有大量的逻辑的话,对性能也不好,因为埋点的数据量很大,如果这里出现瓶颈的话,就会出现服务不稳定,从而导致数据丢失
其实我看到有的人可能将IP 解析放在这里做,其实这也是不合理的,因为做IP 解析之前你需要先做数据解密、JSON 解析,然后数据推送到消息队列之前还要做数据加密,可以看出这里的加解密想当于白做了。
但是凡事也有例外,你也可以在后端这里做一些数据过滤,这样可以减少后面数据处理的压力,毕竟相比CPU ,网络才是最慢的。
数据丢失如何处理
这里我们主要关注前端—>后端—> 消息队列的这个环节的消息丢失,我们认为消息只要成功投递就不会发生消息丢失,关于这一点很多消息队列都可以保证,我们不做过多讨论,可以参考: https://blog.csdn.net/king14bhhb/article/details/114624437
所以我们的消息丢失主要在后端这一块,当然这里丢失的原因,我们可以分为两类
- 后端服务不稳定,前端请求得不到影响,数据丢失,我们可以认为是前端数据丢失
- 消息队列服务不稳定,后端消息不能成功投递,导致消息丢失,我们可以认为是后端数据丢失
可以看出来,这里后端是关键,所以我们采取的措施是日志补偿的方式,也就是对于投递失败的消息,我们可以将其追加到特定的日志文件,然后再将抽取到大数据计算平台,这里有一个问题就是最好监控,如果有大量的消息投递失败,我们一定要及时修复,防止日志文件过大。
对于后端服务的不稳定导致前端数据投递失败,我们需要做的就是做好监控和高可用,以及自动扩容,因为很多时候是因为流量急剧增加导致后端服务压力太大,从而导致不稳定。
总结
- 埋点是数据平台很重要的一部分,如果只有业务数据没有埋点数据,那么用户在我们平台上的一切行为对我们来说都是黑盒,所以我们想要做到精细化运营埋点是必须的。
- 由于埋点的数据从产生到使用链路很长,而且很复杂,这就需要我们做好设计和管理工作。