在这篇文章里面,我们会对数据采集的一些基本概念进行阐述,然后,会针对目前市面上新增的一些前端埋点技术,如可视化埋点与“无埋点”的技术细节做一个具体的介绍,并且阐述我们自己对于这些技术的理解和认识。

1. 数据采集是核心问题

一个典型的数据平台,对于数据的处理,是由如下的5个步骤组成的: 

其中,我们认为,第一个步骤,也即数据采集是最核心的问题。数据采集是否丰富,采集的数据是否准确,采集是否及时,都直接影响整个数据平台的应用的效果。

在我们手册的典型场景的数据接入方案中,我们已经阐述了使用 Sensors Analytics 时,在确定数据采集方案时应该遵循的两个基本原则:

  1. 优先在后端收集数据;
  2. 属性尽可能采集全面。

虽然我们之前已经详细描述过前端埋点的一些问题。例如,需要等待网络情况良好才能发送数据,需要积攒一定的量才发送数据,需要在本地暂存而本地暂存空间有限等一系列在数据传输性和数据可靠性上的一些问题。但是,前端埋点毕竟有一些后端采集数据所无法替代的地方,例如,分析前端界面设计是否合理,分析一些在与后端没有交互的前端行为等,还是必须采用前端埋点方案的。前端埋点作为一个比较成熟并且被广泛采用的数据接入手段,Sensors Analytics 也提供了一系列相应的解决方案。因此,在这里,我们觉得有必要详细介绍一下目前市面上主流的前端埋点方案的技术细节,并且结合我们的产品,来阐述我们对于这些埋点方案的一些看法。

2. 前端埋点技术介绍

目前常见的前端埋点技术,有三类:在某个控件操作发生时通过预先写好的代码来发数据的代码埋点;通过可视化界面配置控件操作与事件发生关系的可视化埋点;先收集所有数据再在后端筛选需要分析的对象的“无埋点”。

下面,我们分别对这三种方案进行介绍,然后再阐述我们的观点。

2.1 代码埋点

代码埋点出现的时间很早了,在 Google Analytics 年代,就已经出现了类似的方案了。目前,国内的主要第三方数据分析服务商,如百度统计、友盟、TalkingData 等都提供了这一方案。Sensors Analytics 也一样提供了 iOS、Android、Web 等主流平台的代码埋点方案。

它的技术原理也很简单,在APP或者界面初始化的时候,初始化第三方数据分析服务商的SDK,然后在某个事件发生时就调用SDK里面相应的数据发送接口发送数据。例如,我们想统计APP里面某个按钮的点击次数,则在APP的某个按钮被点击时,可以在这个按钮对应的 OnClick 函数里面调用SDK提供的数据发送接口来发送数据。

下面,我们看友盟提供的两个例子。

第一个例子是在使用者的某个 Android APP 里面,统计某个由 Activity 构成的页面的访问次数,下面是友盟官方给出的例子:

public void onResume() {
    super.onResume();
    MobclickAgent.onPageStart("SplashScreen"); //统计页面(仅有Activity的应用中SDK自动调用,不需要单独写。"SplashScreen"为页面名称,可自定义)
    MobclickAgent.onResume(this);          //统计时长
}

public void onPause() {
    super.onPause();
    MobclickAgent.onPageEnd("SplashScreen"); // (仅有Activity的应用中SDK自动调用,不需要单独写)保证 onPageEnd 在onPause 之前调用,因为 onPause 中会保存信息。"SplashScreen"为页面名称,可自定义
    MobclickAgent.onPause(this);
}

这个例子其实非常简单,就是在 Activity 控件相应的触发器函数里面,调用友盟提供的接口统计数据即可。

第二个例子稍微复杂点,它不再是统计页面访问这样一个默认的事件,而是统计一个自定义事件。例如,一个电商APP,在用户点击“购买”按钮时,想统计“购买”这个自定义事件的相应信息,那么,可以使用下面的代码:

HashMap<String,String> map = new HashMap<String,String>();
map.put("type","book");
map.put("quantity","3");
MobclickAgent.onEvent(mContext, "purchase", map);

必须说明的是,友盟归根结底还是一个统计工具,并没有提供完整的多维分析功能,姑且不算数据传输的时效性以及对自定义属性上的各种限制,仅仅是为了统计某个数值,友盟还要单独区分出“计数事件”和“计算事件”,这一点上,就远远不如 Sensors Analytics 的灵活了。

从上面这两个例子可以看出,代码埋点的优点是一方面使用者控制精准,可以非常精确地选择什么时候发送数据;同时使用者可以比较方便地设置自定义属性、自定义事件,传递比较丰富的数据到服务端。

当然,代码埋点也有一些劣势。首先,埋点代价比较大,每一个控件的埋点都需要添加相应的代码,不仅工作量大,而且限定了必须是技术人员才能完成;其次是更新的代价比较大,每一次更新埋点方案,都必须改代码,然后通过各个应用市场进行分发,并且总会有相当多数量的用户不喜欢更新APP,这样埋点代码也就得不到更新了;最后,就是所有前端埋点方案都会面临的数据传输时效性和可靠性的问题了,这个问题就只能通过在后端收集数据来解决了。

2.2 可视化埋点

从前端埋点到可视化埋点其实是一个非常顺理成章的演进。既然埋点代价大,每一个埋点都需要写代码,那么,就参考 Visual Studio 等一系列现代 IDE 的做法,用可视化交互手段来代替写代码即可;既然每次埋点更新都需要等待APP的更新,那么,就参考现在很多手游的做法,把核心代码和配置、资源分开,在APP启动的时候通过网络更新配置和资源即可。

正是出于这种自然而然的做法,在国外,以 Mixpanel 为首的数据分析服务商,都相继提供了可视化埋点的方案,Mixpanel将之称作为 codeless。而国内的 TalkingData、诸葛IO 等也都提供了类似的技术手段。 顺带一提,Sensors Analytics 在1.3版本的更新中,也已经给使用者提供可视化埋点方案,以降低使用者的数据接入成本。

特别需要强调的是,Mixpanel 非常无私地开源了它们的iOS 和 Android 端的 SDK 的源代码,我们在开发中也参考了它们的贡献,并且也贡献了一些 bug 的提交,非常感谢 Mixpanel 对整个领域的贡献。

2.2.1 iOS 和 Android 平台的可视化埋点

下图是演示一个简单的 iOS SDK 使用 Mixpanel 的 codeless 埋点功能: 

从这个界面可以看出,使用起来还是非常简单的,点击某个支持的控件类型的实例,这个例子中是右上角的刷新按钮,然后在弹出的窗口中,设置点击这个按钮是发送 “Refresh” 事件。然后点击 Deploy 按钮,把这个配置下发下去。那么,所有安装有嵌入了 Mixpanel 的 SDK 的这个 APP ,则都会在 APP 启动时或者定时获取相应的配置。以后,真实的用户使用时,点击这个按钮,就会真正地发送 “Refresh” 事件到后端了。

下面我们以 iOS 端为例,进一步阐述可视化埋点的实现细节。

在嵌入了 SDK 的 APP 开启可视化埋点模式,与后端联通时,SDK 会应后端的要求,定期(例如每秒)做一次截图,而 SDK 在为 App 截图的同时,会从 keyWindow 对象开始进行遍历它的subviews(),得到当前视图下所有 UIView、UIResponder 对象的层级关系。对于屏幕上的任何一个UIView对象,如 Button、Textfield 等,它都有一条唯一的从 keyWindow 到它的路径,这个路径上每个节点,都由 ClassName、它是父节点的第几个subview、.text()等属性的值等标识。相对于父节点的坐标、长宽高等可视化方面的信息,是作为这个节点的属性存在。

服务端根据截屏和可视化信息来重新进行页面渲染,并且根据控件的类型,来识别哪些控件是可以增加可埋点的,并且将之标识出来。

当使用者在后台的截屏画面上点击了某个可埋点的控件时,后台会要求使用者做一些事件关联方面的配置,并且将配置信息进行保存和部署。

SDK 在启动或者例行轮询时拿到这些配置信息,则会通过.addTarget:action:forControlEvents:接口,为每个关联的控件添加的点击或者编辑行为的监听,并且在回掉函数里面调用 Sensors Analytics SDK 的接口发送相应事件的 track 信息。

整个 iOS 端的埋点的流程图,如下图所示: 

Android 端的可视化埋点方案,与 iOS 端基本一致。

必须说明的是,上面描述的这一套可视化埋点的配置方案,其实也可以让开发者在 iOS 或者 Android 的可视化 IDE 里面完成,但是考虑到可视化埋点主要面临的是非技术人员,所以最终业内都采用了 Mixpanel 的这种后台截屏操作的方案。

2.2.2 Web 端的可视化埋点

Mixpanel 没有提供 Web 端的可视化埋点方案,在这里,我们以 Sensors Analytics 的 Web 端可视化埋点方案来举例:

使用者在自己的网页引入 Sensors Analytics 的 JavaScript SDK 代码后,从 Sensors Analytics 的后台可视化埋点管理界面跳转到使用者的网站界面时,会自动进入到可视化埋点模式。在这个模式下,使用者在网页上点击任意 html元素时,Sensors Analytics 都会取到这个元素的url,层级关系等信息来描述这个 html 元素,当使用者设置了这个元素和某个事件相关联时,SDK 会把这些关联信息和客户生成配置信息,并且存放在 Sensors Analytics 提供的相应保存位置。当真正的用户以普通模式访问这个网页时,SDK 会自动加载配置信息,从而在相应的元素被点击时,使用 Sensors Analytics 的数据发送接口来 track 事件。

从上面我们介绍的可视化埋点的方案可以看出,可视化埋点很好地解决了代码埋点的埋点代价大和更新代价大两个问题。但是,可视化埋点能够覆盖的功能有限,目前并不是所有的控件操作都可以通过这种方案进行定制;同时,Mixpanel 为首的可视化埋点方案是不能自己设置属性的,例如,一个界面上有一个文本框和一个按钮,通过可视化埋点设置点击按钮为一个“提交”事件时,并不能将文本框的内容作为事件的属性进行上传的,因此,对于可视化埋点这种方案,在上传事件时,就只能上传 SDK 自动收集的设备、地域、网络等默认属性,以及一些通过代码设置的全局公共属性了;最后,作为前端埋点的一种方案,可视化埋点也依然没有解决传输时效性和数据可靠性的问题。

附带一提,虽然 Mixpanel 比较早就推出了可视化埋点方案,但是却一直没有重点宣传,并且也并不是它们的推荐数据接入方案,这种做法也是与 Mixpanel 一直强调的 "Actions speak louder than page views." 是一致的。

2.3 “无埋点”

与可视化埋点一样,“无埋点”这个方案也出来的比较早,Heap作为一个第三方数据分析服务商,在2013年就已经推出了“无埋点”这个技术方案。而如果不局限于第三方,百度在2009年就已经有了“点击猴子”这个技术,用无埋点的方案分析一个页面各个元素的点击情况;在2011年,百度质量部也推出了一项内部服务,用以录制安卓 App 的全部操作,并且进行回放,以便找出 App 崩溃的原因;而豌豆荚大约也在2013年左右,在自己的 App 内部,添加了对所有控件的操作情况的记录。第三方数据分析服务GrowingIO 在2015年,也推出了类似于 Heap 的服务。

下图是一个使用 Heap 的例子: 

从界面上看,和可视化埋点很像。而从实际的实现上看,二者的区别就是可视化埋点先通过界面配置哪些控件的操作数据需要收集;“无埋点”则是先尽可能收集所有的控件的操作数据,然后再通过界面配置哪些数据需要在系统里面进行分析。

“无埋点”相比可视化埋点的优点,一方面是解决了数据“回溯”的问题,例如,在某一天,突然想增加某个控件的点击的分析,如果是可视化埋点方案,则只能从这一时刻向后收集数据,而如果是“无埋点”,则从部署 SDK 的时候数据就一直都在收集了;另一方面,“无埋点”方案也可以自动获取很多启发性的信息,例如,“无埋点”可以告诉使用者这个界面上每个控件分别被点击的概率是多大,哪些控件值得做更进一步的分析等等。

当然,与可视化埋点一样,“无埋点”依然没有解决覆盖的功能优先,不能灵活地自定义属性,传输时效性和数据可靠性欠佳这几个缺点。甚至由于所有的控件事件都全部搜集,反而会给服务器和网络传输带来更大的负载。

2.4 各种不同采集方案的数据获取能力的对比

在前面,我们已经介绍了代码埋点、可视化埋点、“无埋点”三种前端埋点方案,而也强调了我们一直推荐在后端采集数据。因此,在这里,我们觉得有必要比较一些可视化埋点、代码埋点与后端采集数据三种方案在数据获取能力上的差异,“无埋点”的数据获取能力与可视化埋点基本相当,在这里不再单独罗列。

我们以京东的一个订单提交页面为例来进行对比: 

对于可视化埋点,在这个地方,基本只能采集到某时某刻某人提交了一个订单;对于前端代码埋点,则还能拿到订单金额、商品名称、用户级别等在前端有记录的一些信息;而如果在后端接入数据,则还能拿到商品库存、商品成本、用户风险级别等只在后端有记录的一些信息。

由此可以看出,可视化埋点虽然使用和部署比较简单,但是在数据获取能力上相比代码埋点还有一定的劣势;而前端埋点天然的劣势,则是拿不到在前端不保存的信息。这也是为什么,我们一直推崇后端数据采集数据这一方案的重要原因。

3. 我们的观点

Sensors Analytics 一贯认为,数据采集是构建数据平台的核心要素。为了方便使用者采集数据,我们完全开放了全功能的数据接入 API,基于 API 封装了代码埋点和可视化埋点两种前端接入方案,并且提供了 PHP、Java、Python 等常见后端语言的 SDK 以方便在后端接入数据,同时,为了满足使用者导入已有文件或者格式化数据的需要,我们也封装了 LogAgent、BatchImporter、FormatImporter 等各式导入工具。同时为了降低使用者的安全方面的疑虑,并且回馈业内,我们的相关 SDK 的代码也在github上全部开源可视化埋点的具体实现的代码会随着1.3版本的发布 release,敬请期待

我们认为,并不存在某种普遍完美的可以适应一切场景的数据接入方案,而是应该根据不同的产品,不同的分析需求,不同的系统架构,不同的使用场景,选择最合适的一种接入方案。下面是一些典型的例子:

  1. 仅仅是分析UV、PV、点击量等基本指标,可以选择代码埋点或者可视化埋点等前端埋点方案;
  2. 精细化分析核心转化流程,则可能需要利用后端 SDK 或者 LogAgent 接入后端日志;
  3. 活动/新功能快速上线迭代时的效果评估,则可以利用可视化埋点快速完成;
  4. 对客服服务质量的考核,或者不同快递在不同省份运送不同品类产品的速度的比较,则需要使用后端 SDK 来对接第三方系统以便导入数据。

一个产品首次使用 Sensors Analytics 时,初期采用可视化埋点方案,快速完成部署,以便快速评估分析效果,做出快速决策;而对可视化埋点得到的数据,在分析解读后,再针对性地逐步采用其它数据采集方案,获取更详尽、更全面的数据分析结果。

12-16 20:12