再谈埋点
埋点是数据的来源,埋点数据是分析的原材料,无论从哪方面来看,确保埋点的准确性合理性都至关重要。
一、埋点采集框架
这里直接推荐神策开源的sdk,数据模型就是event模型,简单来说就是who、when、where、how、what模型,用来描述event发生时的具体场景和内容。
WHO:即参与这个事件的用户是谁。用户进入一个功能页面,我们要知道进来的用户是谁,并且同一个用户以不同身 份状态在不同的端操作时,都能是识别出来就是同一个人,一套合适且完备的ID-mapping解决方案,对于提高用户行为 分析的准确性、完整性有非常大的影响,对用户数量的统计、以及漏斗、留存、路径等期望用户行为流相关的分析尤其明显。 同一用户的识别出现断层,会导致以上分析数据不准确或不可用。因此,我们在进行任何数据接入之前,都应当先确定如 何来标识用户。以APP的页面浏览为例,在互联网时代,用户都以设备为载体,因此可通过设备旧来记录;具体业务场 景下,用户自身也带着业务属性,可通过user_id、 login_id等类似的业务身份标识来记录,确保单个用户在多设备之间 的行为可以打通。总之,关于who,大家要想清楚要如何准确地标识客户,一个项目的旧机制要在项目开始时特别慎重地进行确认,之后技术人员需要遵循这个规范来埋点,否则后期修改旧机制、清洗旧错误都是一个非常麻烦的事情。
WHEN:即这个事件发生的时间,神策分析通过自动采集的时间戳属性来记录。
WHAT:WHAT描述了一个事件具体是什么,这里就是神策事件设计模型的一个独特的地方。在这里场景下,按照神策的事件设计规范,事件是‘’APP页面浏览”,而不是“首页的浏览”,通过增加『页面名称』这个属性来区分究竟浏览的是 哪个具体的页面,大家可以思考下,为什么是这种设计思路呢?实际上,一般一个产品会有N多个不同的页面,如果将每个页面都单独定义为一个事件,那么后台的事件将会有几百上千个,业务人员在使用时会非常的麻烦,筛选事件的成本也会非常大。神策分析在做埋点需求设计时,针对所有类似的触发机制和场景的事件,都会做聚合处理,因此企业的事件量 通常会维持在30-50个左右,配以神策的归类机制,极大方便企业进行事件管理,给业务人员带来极强的易用性。
HOW:即用户从事这个事件的方式,HOW关联的是与事件强相关的属性内容。这是企业在事件梳理过程中非常容易出纰漏的地方。比如在APP页面浏览或者APP的点击事件上,经常会出现找不到按钮,或者无法定位页面的情况,原因就是研发的规范性较差,比如对页面标题的定义不规范等。神策针对页面标题做了自定义和规范,主要包括两方面:一是所有页面本身都有名字,并且与APP的页面是同一个名字,如此保证业务同学定位该页面时很容易找到;一是针对lOS与安卓经常出现两个同样的页面命名不一样的情况,神策分析会做维度字典的规整,如此,其可用性能够满足绝大多数的应用 场景。 .
WHERE: IP、国家、省、市区等用户的操作属性,神策分析都是会在基础信息采集上做加工衍生,可以做到自动采集。 端口、应用版本、操作系统、操作系统版本、设备制造商、设备型号、屏幕高度、屏幕宽度这些前端维度与属性,神策分 析的采集也是默认获取的。对于后端自定义采集来说,则需要根据分析需求进行判断和梳理,确认是否需要通过接口透传等方式获取到对应这些前端属性,否则将会影响后续的多维分析。
神策开源的埋点SDK http://opensource.sensorsdata.cn/
二、埋点采集的数据源
通常而言,包括三项数据源,分别是:
前端操作和业务数据是我们最常使用的埋点数据,分析时所使用的大部分数据也是这两个来源的数据,我们会比较容易忽略后端日志来源的数据,有些前后端交互的行为,比如点赞这个动作,既有前端采集的动作,又有后端的数据库记录,但是后端数据库记录的时候往往是从业务的角度决定记录什么字段,但是在分析的角度,可能就没有我们需要分析的维度了,所以,此时可以再增加一个步骤,将点赞的日志数据采集下来,日志数据上可以很方便的带上我们需要分析的维度,且对业务方没太大影响。
三、前端埋点和后端埋点
有篇文档写的非常详细,这里直接copy过来,重点是能后端记录的优先后端记录。
前端埋点:收集数据在客户端进行,用户在客户端浏笕页面、点击按钮、滑动界面等均可采集。一般在用户动作发生时,采集数据后端埋点:收集数据在服务器端进行,收集的是http请求发生时的数据,更多的是数据层,业务逻辑层的数据。一般在http请求触发、或结果返回时采集数据
前端埋点
优势:直接了断,贴近用户在产品中的行为
劣势:
- App迭代更新有变化时,需要重新埋点
- 埋点更新需要伴随App更新,用户不更新App时,采集不到相应数据
- 涉及到本地缓存和公网传输,数据丢失率高于后端埋点,数据准确性低于后端埋点
- 事件发生时间使用客户端时间,时间记录存在与标准时间不同步的情况
- 数据经过公网传输,需要考虑安全性问题
- 数据时效性差
后端埋点
优势:
- 埋点的新增和修改均不受客户端发版的限制
- 数据仅在内网传输,时效性、安全性、可靠性问题迎刃而解
- 日志变更可以直接在服务端变更,不依赖客户端的发版与更新
劣势:
- 部分行为或者字段,一般情况下在后端采集不到,需要客户端传递给后端,如设备信息、网络信息等
- 与后端服务耦合,代码不合理时可能影响业务稳定性
如何选择
- 纯前端交互行为,如:下拉框选择、按钮点击等,选择前端埋点
- 业务行为多选择在后端埋点;如评论、点赞、购买、提交订单、支付等行为
- 前端、后端都可以获取数据时,优先后端接入数据
也可以参考这篇文章:客户端埋点 or 服务端埋点
四、埋点方案设计的四要素
1. 确认事件与变量
- 事件:指产品中的操作
- 变量:指描述事件的属性
2. 明确事件的触发时机
3. 规范命名
4. 明确优先级
五、埋点采集方式、触发时机、同步策略
前端触发就上报:点击“去支付”按钮就触发,这是最常见的前端采集方式,如果业务方是想了解的是“用户是否有 意愿支付”,那么当用户点击“支付订单”这个按钮时或者发出支付请求就触发采集即可。这是时机埋点采集时最常用的一 种方式。
前端获取后端结果后上报:这种方式一般是由于除了记录用户操作外,还需要获取用户操作的结果,比如需要收到 后端结果的返回,以判断用户是否支付成功,以及失败情况下具体的报错原因,那么其触发机制必须等到前端拿到后端服 务器处理结果后,再进行上报。
后端触发就上报:这种方式是指后端处理后直接上报,比如后端处理付款请求出结果时直接后端触发上报。采用这种方式的主要好处是数据不会出现漏报,但也由于是直接后端上报,基本是拿不到用户的设备终端及软硬件环境属性的,比 如用户在支付时用的是什么设备、网络环境是什么等信息。
后端获取前端属性且触发后上报:这种情况就是为了解决后端埋点的软硬件环境属性问题,让前端在用户点击“去 支付”时,将相应的属性一并传回服务器,服务器发生“支付成功”时,带上相应的前端属性上报数据。当然这种方式理 论上是数据准确度、完备性最高的,但同时这种方式的采集成本会比较高,意味着所有端的前后端接口需要做变更,建议是只在数据准确性、前端属性获取两个需求都非常强时采用。
通过以上的描述大家也能看得出来,每种触发时机有各自的优劣势,在具体设计触发时机中,决定具体采用哪种方式的因素,特别值得关注:业务含义、旧识别机制、前端软硬件环境属性获取、业务处理结果获取、数据准确性要求。神策团队在给企业做事件设计时也会格外关注这些点;在后续企业自己做事件设计时候,企业也应该从这几个方面给研发同学讲解清楚,以保证采集的数据更符合场景诉求。
为了最大限度的保证数据的完整性和准确性,SDK 采集的数据,一般会先缓存到本地,待符合一定条件之后再同步。
常见的数据同步策略:
- 事件先缓存到本地 sqlite3
- 本地缓存一定条数量的事件会同步(默认 100 条)
- 固定时间间隔同步(默认 15 秒)
- 核心事件发生同步(trackInstallation、login 等)
- APP 退出尝试同步
- 本地缓存太多事件时的处理
在 APP 退出时尝试同步数据,是为了防止用户之后长时间不启动 APP、不再启动 APP 或者直接卸载 APP。
六、埋点工作流程
七、如何标识用户与设备
在 Android 如何准确标识设备?各个方案有什么优缺点?
常用的设备唯一标识符有:UUID、MAC 地址、IMEI、AndroidId。
各自的优缺点
UUID:UUID 一般会配合 SharedPreferences 使用来标识一个设备,它的优点是不需要任何权限,也不会有任何机构认为 UUID 有过度窃取用户隐私的嫌疑,缺点在于如果用户卸载重装 App ,存储的 UUID 就会被抹掉。MAC 地址:MAC 地址就是设备网卡的唯一识别码,它的优点是 MAC 地址值不会改变并且值唯一,缺点在于需要获取权限并且在 Android 6.0 之后任何手机通过 getMacAddress() 都只能获取到 “02:00:00:00:00:00” 这个值,虽然有其他途径获取但很容易触犯到隐私条款。
IMEI:IMEI 是国际移动设备身份码,它的优点同样是值不会改变并且值唯一,缺点在于需要获取权限,并且在 Android 10 版本系统层面禁止了 IMEI 的获取,IMEI 同样也容易触犯到隐私条款。
AndroidId:AndroidId 是设备首次运行的时候,系统随机生成的一串 16 进制的数字,它的优点是不需要任何权限、每个设备值唯一且值也不像 UUID 那样容易变,缺点就是在用户恢复出厂设置的时候 AndroidId 会重新生成。在 Android 8 之前不同 App 对于同一设备取到的 AndroidId 甚至是相同的,在 Android 8 后 AndroidId 的生成开始与包名有关,不同包名的 App 对于同一个设备取到的 AndroidId 开始不同。
神策 Android SDK 默认正是采用了 AndroidId 来标识一个设备,如果 AndroidId 获取不到则获取随机的 UUID。
ios中的用户标识方案可以看这篇文章:iOS获取设备唯一标识的8种方法
现在苹果主推 IDFA 和 IDFV 这两种方法,分别对外和对内,但是 IDFV 在 APP 重新安装时会更改,所以我的方法是通过第一次生成的 IDFV 存储到 keychain 中,以后每次获取标识符都从 keychain 中获取。
如果开启 IDFA ,神策 SDK 会优先获取 IDFA,如果获取失败再尝试获取 IDFV。使用 IDFA 能避免用户在重装 App 后设备 ID 发生变化的情况。
这里其实还涉及到了oneid的内容,理想状态下是我们能够通过一个id准确的标识用户,但是实际情况会比较复杂,这块儿没什么特别完美的方案,oneid的实施方案可以参照oneid实现。
八、时长、时间戳采集方案
1、时长的采集方案
Android 和 iOS,都有一个 boot time 的概念,即手机启动了多长时间。可以理解为系统里有一个定时器,每次手机启动后,这个定时器就从零开始计时,与客户端时间无关,如果使用这个 time 来计算间隔,就是 100% 准确的,之后再在服务器端进行数据纠正。
2、时间戳的纠正
神策的时间纠正策略:
用户在手机时间戳 T1 时触发了一个事件(比如登录事件),然后事件存入本地缓存。数据采集 SDK 在用户手机时间戳 T2 时开始同步事件数据(包含登录事件),然后服务端通过 HTTP(S) 的 Request Header Date 可以获取到数据采集 SDK 发起 Request 时用户手机时间戳 T2 。
如果 T2 与当前服务端的时间戳 T3 的误差在一定的可接受范围之内(比如 30s,这是因为网络请求也需要一定的时间),就可以说明当前用户手机的时间戳是准确的(我们假设服务端时间戳是准确的,绝大部分情况下也都是准确的),同时说明登录事件发生时的时间戳 T1 也是准确的,服务端在接收到登录事件时无需做任何的特殊处理。
如果 T2 与 T3 相差比较大(比如上图中的 T2 为 15:00,T3 为 16:00),我们可以确定当前用户手机的时间戳 T2 是不准确的,即比服务端的时间戳晚了一个小时(16:00 - 15:00 = 一个小时),从而就可以假设登录事件发生时的时间戳 T1 也比服务端晚了一个小时,即 14:00 加上一个小时应该为 15:00。
因此,服务端在接收到事件时会把登录事件的时间戳 T1 再加上一个小时,变成 15:00,从而就达到了“时间纠正”的效果。
当然,“时间纠正”策略,也无法确保可以 100% 解决所有和时间戳相关的问题。比如,还是以上图为例,如果在时间戳 T1 和 T2 之间,用户手机的时间戳再次发生了人为变更,那么,该方案就无法正确的进行时间纠正了,这是因为时间戳 T2 和 T3 之间的误差额,与时间戳 T1 和当时服务端对应时间戳的差额就不相等了。
但从实际情况来看,由于数据采集 SDK 一般都会以较短的固定时间间隔同步数据(比如 15s),所以时间戳 T1 和 T2 之间的时间间隔会比较短,本身发生时间戳变更的可能性就比较小,即使真正发生变更了,影响到的事件数量也比较少(15s 内可能只会触发几条事件)。因此,“时间纠正”策略可以解决 99% 以上的和事件时间戳相关的问题。
九、解决埋点问题的根源性解决方案
把埋点采集当成独立的研发业务来对待。
实际上,造成埋点成本高、效率低下的真正原因,就在于没有找到合适的埋点管理和落地方法,埋点的全面性和复用性太低,导致整个埋点体系持续陷入拆东墙补西墙、每个采集的需求都要单独走完整的采集业务流程,沟通、验证的成本高,对团队的整体消耗过大。