一、解决方案
1. 埋点历程
(1)无日志采集
2013 年以前,抖音集团自身不收集流量日志,而是依赖于外部工具做统计与流量数据分析。
(2)Log 1.0
2013 到 2016 年期间,开始复用友*事件格式,自己做采集,主要是为了支撑推荐场景和围绕推荐的分析场景。在这些场景下,流量的埋点主要用于构建推荐系统,对数据分析的支持则较为有限。
(3)Log 2.0(未上线)
2015 到 2016 年期间,是业务的高速发展阶段。除了推荐系统外,各种业务场景也陆续加入,引发了对分析归因的需求。在这个过程中,埋点侧尝试使用 Log 2.0。Log 2.0 是从底层出发的框架升级,引入了统一的页面标识,并对其中所有模块的传递方式进行了强约束。
但当时还面临着两个重大问题,其一是业务在迅速地发展,此时从底层推动框架落地,即使是一个看似完美的框架,也会带来巨大的投入成本;其二是各团队缺乏配合,埋点是一个广泛的业务场景,基本上会涉及所有端团队。如果没有团队配合,项目既难以落地,也无法获得足够的推动资源。因此,最终该项目未能上线,数据团队将其定义为一次失败的经历。
(4)Log 3.0
2017 年至今,数据团队则一直处于 Log 3.0 状态。Log 3.0 汲取了 Log 2.0 失败的原因,进行了大幅度简化。其核心分为两块,一块是事件,另一块是参数。简化的定义使 Log 3.0 更为灵活,且约束性更小。
底层的参数管理并未通过框架来实现,而是通过相应的埋点平台进行。使用方可以在埋点平台上注册事件、约束参数,从而提高整体约束能力,实现更好的适配。在足够灵活和适配的情况下,大家的切换成本就会降低。
旧的 Log 1.0 在这个足够灵活的版本中完全兼容。此外还可以通过埋点平台对后续新增的埋点进行管理。在此阶段,除了底层的埋点平台的约束外,还有适配的行为分析平台来形成一整套解决方案,提供从管理到分析的所有流量日志相关能力。
2. 场景迭代
(1)从推荐信息流到综合性生态
在一个综合性 APP 的发展过程中,功能日益强大,内容越发丰富。在其电商场景下,用户操作路径和链路的复杂度也逐步提升。
场景变化导致了用户链路深度增加,链路复杂性提升,电商场景的用户链路涉及到商城、搜索,而且在这个过程中还会有很多大促和营销活动不断推出新的页面,迭代频繁。
(2)变化引发的问题
在场景迭代下,业务的分析诉求主要集中在整个流量场的承接转化和交易的拆分归因上,因此需要具备对应的归因能力。在 Log 3.0 时代,这种强烈的诉求导致了埋点的变化,即参数变得复杂,而整体长链路的传参诉求也随之增多。
场景、分析诉求和埋点的三方面变化带来了以下问题:
- 质量问题开始凸显,漏传、错传现象频繁发生,进而引发线上事故;
- 归因未知场景增多,业务分析困难;
- 维护成本高,埋点效率低下。
3. 电商业务痛点
在电商场景中,数据埋点遇到的问题可大致归为用户、分析、工程和数据三个层面。
(1)用户层面
埋点除了供给数据分析外,还可能对线上推荐产生影响。如果埋点参数错误,则可能导致推荐相关链路的订单交易下滑。此外在分佣场景中,如果未埋对参数,那么带货达人的利益收入将会降低,从而导致大量资损和客诉。
(2)分析层面
电商场景的归因需要进行拆分,例如,一笔订单究竟是如何产生的?是商城带来的,还是搜索带来的?是某个活动带来的,还是某些转化卡片带来的?
在进行拆分后,还需要进行灵活的归因分析,这类似于路过原则的分析。通过这些分析,我们的数据现状暴露出“未知”情况越来越多的问题,即当前的规则无法识别这笔订单是由哪个来源所带来的。
如果“未知”占比在 1% 以下,则可以先忽略,但这个占比可能会逐渐增加到 5%、7%。那么这种模糊不清的情况将给业务带来痛点,最终影响业务的分析和决策。
(3)工程和数据层面
工程和数据层面的主要问题在于,整体维护成本很高,埋点流程效率很低下,新增参数所涉及到的前端团队会越来越多。例如,增加一个埋点,以期在交易上识别由搜索新增场景带来的影响。那么搜索的前端同学就需要进行埋点,而商详的前端同学和交易链路的同学也都需要介入,由此导致整体成本和迭代效率低。
二、解决方案
1. 总体框架
在从 Log 1.0 迭代到 3.0 的变化背景下,电商数据团队针对前述问题,构建了一套解决方案。
解决方案框架示意图
- 埋点管理
解决方案框架的底层主要是管理埋点,并通过 BTM 和 BCM 的定义来建立规范,确保相关信息的透出能够得到充分约束,还会针对一些关键事件,如页面访问和商品曝光点击信息等进行优化,然后将其输出到 SDK 中。 - SDK
多个前端团队协同合作,其实并不是实现目标的可靠方式。因为参与者越多,不可控性就越高。因此引入了通用化能力,选择以 SDK 来简化这部分的实施过程。 - 归因平台
实际上,在抖音集团内部的工程团队、分析师团队、策略团队和数据团队的协作过程中,经常会出现信息遗漏和关键迭代无法同步的问题,此时,会通过归因平台来解决这些问题。 - 分析产品
框架的最上层原本由行为分析平台提供支持,但针对电商埋点升级的情况,可以利用新定义的 BTM、BCM 和 SDK 的链路生成能力,提供更简化的分析,降低用户的分析和操作门槛。
2. 埋点管理
埋点管理分为 BTM 和 BCM,BTM 参考了 SPM(Swift Package Manager) 的概念进行设计,而 SPM 则由业务、页面、区块、坑位这四个点位组成。
来看一个例子:btm:a5425.b8692.c2154.d8060,其中的 a5425 代表一个电商的点位,b8692 是个人页的信息,c2154 是订单模块,d8060 是待评价的按钮。通过这些点位信息,我们就能够清楚地描述出整个页面上的固定位置信息。
BCM 希望能够统一关键信息,关键信息主要指的是数仓中的维度信息,如 product_id、shop_id、author_id、promotion_id 等。这一行为的核心目的是避免关键参数的同义不同名表达,类似于在数据表中进行维度命名的统一。通过统一关键参数的命名,我们能够在全局范围内收敛核心关注点,降低理解和处理关键信息的成本。
这一套定义和约束即作为我们的治理基础,用以解决商品曝光的下列问题。
- 事件名称不统一
Log 3.0 是一个事件加参数框架,其下有大量的事件发生。以商品曝光事件为例,该通常命名为 show_product,而搜索前端团队则的埋点则命名为 search_result_show。电商团队购买商品卡时,会命名为 show_ecom_card。
由于不同的前端团队以及其自身的架构层面不属于同一架构下,存在理解不统一、规范不统一的问题,造成了很高的事件处理成本。此外,重复发送事件也会带来额外的成本。 - 事件参数杂乱
事件参数杂乱的主要原因是命名规则不一致。比如,搜索、猜你喜欢、商业化等各业务都会独立设计参数传递方案,尽管有时大家的诉求是一致的,但由于规则不统一,仍然需要重复开发,造成了额外的成本。
那么,不一致的诉求会如何影响埋点呢?目前各团队都是各自添加自己的埋点,导致整体埋点参数疯狂膨胀。这不仅增加了传输成本,还可能导致用户体验卡顿。当卡顿达到一定程度时,就需要进行治理。此外,传输还会带来数仓的存储成本。在流量很大且参数很多的情况下,存储成本会非常高。 - 发送时机不统一
以商品曝光为例,来理解发生时机的不统一,即不同业务团队对于商品曝光的上报有不同定义,到底是每次展示都上报,还是仅首次展示上报,亦或只要有加载就上报(虚曝光)?
这就可能导致三种不同的上报逻辑。此外,上报的比例也可能不同,到底是展示 25%,还是 50%,亦或 100% 上报,也并未达成一致。可能每个团队的逻辑都不统一,而这种不统一在数据层上可能影响不大,但在业务层上就可能导致某些 AB 实验或分析无法达到预期效果。
上述的一切杂乱问题,要求我们统一事件名称;将整体参数从杂乱变为有序;统一整体发送时机;并治理整体商品曝光。这些操作听上去自然而然,但如何实现轻量化,避免过多前端团队的高投入,就涉及到 SDK 能力。
3. SDK 能力
(1)传统长链路参数层层透传的局限
传统的参数传递方式是通过 URL 一层一层向下传递的。
例如,在页面 1 调用页面 2 时,会在 URL 中拼接一些参数。页面 2 的同学再调用页面 N ,将这些参数一层一层向下传递,最终传递到提单页。提单页将这些信息导入订单后,埋点侧就能够识别一笔订单的来源。
然而,在电商场景中,这种长链路可能导致新问题随新页面增加而产生。如果某个页面没有传递参数,就会变成一个未知问题。如果传递的参数被覆盖,就会导致归因混乱,增加了查问题的难度。
SDK 能够统一处理链路信息,其底层是 BTM Mode,其核心作用是将页面之间的层级通信转化为 BTM Mode 之间的信息传递。具体来说,页面 1 和页面 2 不再直接相互通信,而是将通信内容告知 BTM Mode,由 BTM Mode 来组织和传递这些信息。
(2)SDK的三大能力
从整个框架的角度来看,SDK 具备以下三大能力。
①关键事件处理
例如,若要上报产品曝光内容,调整 SDK 即可。SDK 会负责将产品曝光的所有内容进行上报。同时,SDK 还具备实现各种约束的能力,SDK 能够对“首次曝光上报,还是上报单位体积内的曝光次数”等内容进行整体约束处理。
②串联链路、整合参数
SDK 具备串联链路和整合参数的能力。BTM Mode 能获知并将整个链路上的参数层层传递,最终将所需信息提供给相关页面。在信息从页面 1 到页面 2,再到页面 N ,最终到提单页的过程中,即使中间经过了 N 个页面,也无需担心信息丢失。BTM Mode 会处理好信息传递的问题,确保信息能准确无误地到达提单页。这样一来,前端团队就不再过分依赖其他团队帮忙传递参数。
③整理链路、输出归因
举例而言,在页面 2 和页面 3 都想为订单打上标记的情况下,在过去,页面 3 的标记可能会覆盖页面 2 的标记,导致页面 2 的归因出现问题。
但现在,SDK 可以处理并得出所需的结果。即假设提单入口在页面 2,那么最终的提单页面在页面 3,SDK 能够整理并输出这样的归因结论。
(3)SDK 统一处理链路信息
如何理解不同用户的操作链路?先以 PC 端浏览器这一比较复杂的程序为例,当用户打开一个网站首页时,可能看到一个感兴趣的视频。用户可以点击进入这个视频页面,也可以右键新开一个窗口。在新开窗口后,用户还可以回到之前的窗口继续浏览。
在这个过程中,用户操作路径是不可控的,埋点侧无法知道用户当前聚焦在哪个页面,以及从哪个页面发起新的页面操作。对于用户在不同使用场景的操作链路,会进行抽象处理。
- APP 动线抽象处理
APP 相对 PC 来说比较简单,一次只能显示一个页面,若要查看之前的页面,则只能回退操作。由于用户只能聚焦在一个页面,可以将其理解为一个队列的数据结构。用户可能进入 A ,然后进入 B ,再返回 A ,然后进入 C ,进入 D,可以把它理解为一个简单的进出原则,SDK 会处理这些进出信息。 - WAP & PC 抽象处理
在抽象 WAP&PC 时,由于用户可以多窗口操作,每个窗口也可以有自己的链路,所以用户动线可以抽象为一棵“树”的数据结构。用户进入 A 后,可以打开一个新页面 B,也可以在 A 上直接进入 C,然后回到这个 A 里面,可能去打开两个不同的页面。
按照树的结构,至少能够有一个推导的过程。例如从 K1 路径来看,经过了 A、B、D、E 四个节点,最后进入 K1。于是我们就无需纠结页面关闭或重新加载的问题。在此情况下,我们可以将重新加载视为仍在当前页,而非新页面,从而简化用户的动线。
通过这样的抽象处理,可以发现其中一个关键内容,即每个节点都要与 SDK 交互,而 SDK 能够通过处理获取它的访问路径,以及根据规则处理过程中 BCM 的传递更新。
在 SDK 中使用任意一个节点进行调试,都可以发现节点的来源路径。因为前面有 A 节点、C 节点的调用,所以当 E 节点进行调用时,就可以知道可能的来源路径是 ACE,也知道整体 ABDE 的路径。
整体来看,通过对链路进行数据格式的抽象,将其添加到队列存储数,并在 SDK 中存储这些数据格式,从而最终实现了用户路径的还原。
(4)SDK 归因处理
SDK 按照规则输出归因结果,适用于规则稳定、通用性强的场景。电商场景会进行体裁判断,这个判断主要是用来确定一笔订单是由直播、短视频还是货架场的商品卡带来的,以上三个题材也是电商场景的主要关注点。
这是一个固定的规则,适用于任何场景。基于这个规则,我们可以通过用户路径,将规则的结果直接在 SDK 中进行封装处理,而不涉及数仓加工。
SDK 能够直接告知该笔订单的具体类型,这 SDK 较为重要的一项能力。这意味着它能够输出你所需的归因结果,并对整个链路进行相应处理。但需要注意的是,SDK 处理规则最好保持相对稳定,否则 SDK 处理规则可能需要频繁变更或调整。
SDK 直接输出用户关键路径信息,由数据侧按照业务口径加工归因结果,这适用于调整频繁、定制化强的场景。举个例子,如果某个用户的操作路径非常复杂,SDK 会对其进行裁剪,通过队列或树状结构,去掉闭环链路或不必要的返回链路,最终得到一个较为纯粹的用户访问路径链路。
基于这样的链路,数仓就可以进行归因分析。无论是首次归因、末次归因、线性归因还是 U 型归因,只要提供相应规则,都可以基于 SDK 给出的完整用户路径进行加工,而无需考虑关联或页面推导成本。
4. 归因平台
(1)归因平台的构建原因
归因平台目前仍处于落地过程中,下文主要对当前较为明确的方向进行阐述。
首先,要明确构建归因平台的原因,这主要是为了解决以下两个问题:
- 产品的迭代影响归因逻辑,归因数据问题滞后。
产品迭代会影响归因逻辑,数据问题通常出现较晚。当前产品有许多策略,如调整用户路径结构、增加实验等,但这些实验往往无法及时同步到数据侧处理。只有当需要查看数据时,才会发现并询问数据缺失或错误的问题。
这种后置问题会给数仓带来很高的成本,一种情况是埋点遗漏,需要通过其他参数来弥补;另一种情况是虽然进行了埋点,但规则没有更新,因此需要更新规则,并涉及数据回溯。电商拥有庞大的流量数据,问题发现得越晚,处理回溯的成本就会越高。下游链路有上万个任务,我们需要决定是全部回溯还是只回溯其中一部分,这就会带来巨大的成本,因此我们需要建立一个流程来评估和审批相关点位变更。 - 归因策略只能靠文档管理,口径不易理解,问题难排查。
在归因的落地过程中,数据团队发现很多归因口径只能通过文档来管理。业务方通常会提供一份归因说明文档,这是一份业务层面的说明,并非代码层面的说明。负责代码编写的同学可能会有自己的一套代码化口径理解,二者之间有时会出现无法对齐的情况。
此外,当遇到问题时,工程师往往无法直接从文档中查询到答案,而只能去查看代码,再层层分析数据,最终才能定位问题。因此从整体来看,我们希望有一套易于维护的归因策略配置信息。
基于以上两个问题的解决诉求,电商数据团队正在构建归因平台。在埋点平台上,将进行点位信息的新增和变更。由于 BTM 和 BCM 的框架限制,埋点侧希望这些点位信息的新增和变更能够同步到整个归因平台。
(2)归因平台的核心要素
归因平台主要通过 3 个核心要素来解决整体的归因问题。
- 标签化
对于新增的点位,需要确定它的性质。如果在业务层面上不涉及任何归因,那么它可能只是一个路过页。归因平台会提供丰富的标签,为这个点位打上合适的标识,比如入口页或末次归因等。 - 对应策略配置
根据不同的页面类型,需要决定如何处理。例如,当遇到一个入口页时,是将其截断,还是根据其类型定义相应的业务逻辑,这可能涉及到因子数的配置。 - 生成对应数据加工任务
最后,将入仓的硬编码转化为整个归因平台上的配置信息,然后通过 UDF 管控进行落实。
5. 分析产品
(1)页面模块分析
以下将提供一段代码示例来说明“如何基于新规则提供低操作成本的分析能力”。该示例类似于访问事件集,可以根据这个访问事件集和 BTM 的命名信息(页面、区块、坑位),加工出一个模块的效果数据,包括 PV 数据、UV 数据、停留时长数据和页面流失率等。
代码示例
其核心能力可分为 3 个部分:
- 首先将访问明细表进行拆分,通过 A 点位就能够获取到页面力度的基本信息和站点信息;
- 框选到 B 点位时,可以获取页面信息;
- 框选到 C 点位时,可以获取模块信息。
这个简化能力在原有的行为分析平台上是缺失的,产品相当于将其补充完整了。
(2)路径分析
前文提到,SDK 可以处理一些复杂链路的最终输出,那么如何对复杂链路进行路径分析呢?以“XXXSXXXXSXXXE”这样一个路径过程为例,假设我们想找一个以 S 开头、以 E 结尾的路径段,我们应该如何去截取呢?这其实比较复杂。
下面提供了一个案例,对于许多这类相似路径,如何进行解体和管理是不可控的。正由于用户的访问动线不可控,埋点侧需要进行信息收敛,以确保最终输出的数据相对结构化。
这里存在一个完整的处理过程,首先找到所有的终点(E 点),然后找出所有的起点(S 点),再找出所有 E 节点中最近的 S 节点。
接着通过反向查找,将找到的起点和终点进行匹配,确保每个起点都能与终点一一对应。这其中会涉及到一些解析过程,也就是用户路径收敛的过程。最终,将得到一个简化后的用户路径。
然后,基于简化后的用户路径,可以通过树形结构进行反馈。将第 1 到第 4 个节点视为根节点,第 5 到第 8 个节点为一级节点,第 9 到第 12 个节点为三级节点。通过节点整合,能够将用户路径进行抽象,从而明确起点和终点,进行分析。
根据强大的聚合能力,可以得知可能有多少用户是通过什么路径进入订单页面的,例如可能有 50% 的用户是从商城进入商品详情页面,然后提交订单,这种路径分析能力有助于产品规划。
此外,产品能力可支持通过点击一个路径来查看具体的用户信息,以及他们在何种设备或情境下访问该路径。同时,也支持用户属性筛选或页面筛选,以协助信息整合。
三、总结规划
收益总结
- 埋点质量提升
在业务层,“其他”分类降低,无法归类的数据控制在 0.X% 以下,与原数据规模(X%)相比,实现了大幅减少。由于埋点质量有保障,埋点所引起的线上事故大大减少,归因系统的相对稳定性也得到提升。 - 开发效率提升
归因平台目前还在落地阶段,但在整个约束落地之后,分析师将通过该平台,在口径制定、端上埋点实施以及数仓加工等方面实现成本降低。 - 归因能力提升
过去,数据团队根据业务需求,通过这些参数层层传递信息,最终生成订单。但现在,相关数据团队有能力提供各种归因口径的支持,这得益于还原用户访问路径的能力。