这是我参与「第三届青训营 -后端场」笔记创作活动的第5篇笔记
前端日志一般需要依托native层提供接口来实现日志本地化文件存储,不过目前也可以使用立即发送和web持久化的方式来给后端传送前端日志,但需要耗费一些网络资源。
埋点
为什么要埋点?现在的互联网公司越来越关注转化、新增、留存,而不是简单的统计PV、UV。而完整的数据采集是一切的前提。
埋点包括在IOS、Android、H5、小程序等前端埋点,也包括后端业务埋点。这里仅仅讲讲这些年和产品经理、运营撕逼上百个回合的前端埋点内容。
说说手工埋点、可视化埋点、无埋点区别
手动埋点(代码埋点)
纯手动写代码,调用埋点SDK的函数,在需要埋点的业务逻辑功能位置调用接口上报埋点数据,友盟、百度统计等第三方数据统计服务商大都采用这种方案;
手动埋点让使用者可以方便地设置自定义属性、自定义事件。所以当你需要深入下钻,并精细化自定义分析时,比较适合使用手动埋点。
手动埋点的缺陷就是,项目工程量大,需要埋点的位置太多,而且需要产品开发运营之间相互反复沟通,容易出现手动差错,如果错误,重新埋点的成本也很高。这会导致整个数据收集周期变的很长,收集成本变的很高,而且效率很低。因为手动埋点需要开发人员完成,所以每次有埋点更新,或者漏埋点,都需要重新走上线发布流程,更新成本也高,对线上系统稳定性也有一定危害。
手动埋点的技术本质是什么呢?
我们看看从javascript中能轻松获得哪些信息:
- 域名:document.domainURLdocument.URL
- 页面标题:document.title
- 分辨率:window.screen.height & window.screen.width
- 颜色深度:window.screen.colorDepth
- Referrer:document.referrer
- 客户端语言:navigator.language 除了上面的列举的常规信息以外,还有大量的业务数据,都需要通过手动写javascript去实现。
代码手动埋点常用的方式有以下几种:
- 命令式
$(document).ready(()=>{
1. // ... 这里是你的业务逻辑代码
2. sendData(params); //这里是发送你的埋点数据,params是你封装的埋点数据
3. });
4. // 按钮点击时发送埋点请求
5. $('button').click(()=>{
6. // ... 业务逻辑
7. sendData(params); //同上
8. })
这里的sendData有很多种方式,比如基于ajax发送json数据,或者使用url连接带上params,或者使用一像素图片带上数据,在或者使用head带上埋点也可以。封装方式多种多样。
- 声明式
<button data-mydata="{key:'uber_comt_share_ck', act: 'click',msg:{}}">打车</button>
这里声明了自定义属性data-mydata,你可以在你的SDK中去扫描和识别这些自定义属性,并解析封装数据,在SDK中按照自定义规则去绑定事件并发送埋点数据。
- 前端框架式
如果使用Vue或者React等前端框架,这些框架都有自己的各种生命周期,为了减少重复性的手动埋点次数,可以在各个生命周期位置,根据你的需求封装你所需的埋点。比如你是SPA单页应用,你希望在每一个页面的componentDidMount埋点,并由此确定用户已经打开了页面。 - css埋点:
1. .link:active::after{
2. content: url("http://www.example.com?action=yourdata");
3. }
4. <a class="link">点击我,会发埋点数据</a>
- 这里使用了很巧妙的css的某些特征,这些可以触发发送请求的特征。
以上是比较常见的手动埋点方案,当然还有很多其他方式和有待挖掘的方案。也请大家补充。
可视化埋点(框架式埋点、无痕埋点)
解决了纯手动埋点的开发成本和更新成本,通过可视化工具快速配置采集节点(圈点),在前端自动解析配置,并根据配置上传埋点数据,比起手动埋点看起来更无痕,这里的配置数据可以设置过滤条件,避免针对所有元素(比如全埋点),可以在调用开启自动监控API时通过设置一些特征属性,来过滤不符合条件的元素,实现只针对某些元素进行自动上报数据的需求。
比如国外比较早做可视化的是Mixpanel,国内较早支持可视化埋点的有TalkingData、诸葛IO,2017年腾讯的MTA也宣布支持可视化埋点;相比于手动埋点更新困难,埋点成本高的问题,可视化埋点优化了移动运营中数据采集的流程,能够支持产品运营随时调整埋点,无需再走发版流程,直接把配置结果推入到前端,数据采集流程更简化,也更方便产品的迭代。
可视化埋点中多数基于Xpath的方案,XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。
比如上图中标识的位置,其中的xpath是://*[@id="projects"]/a4/img,如果换成DOM的selector:#projects > a:nth-child(4) > img。通过这些信息可以精准定位到一个DOM节点,xpath方案分为精确路径和概略路径两种做法,精确路径从被点击的元素不断向上冒泡查找到根节点,并记录过程中每个节点的。如果用户阻止了冒泡会导致失效,概略路径是在前者的基础仅仅向上查找白名单中的节点。但是如果DOM节点有任何变化,对应的xpath数组就是被打乱,很容易影响采集。
可视化埋点配置化能力相对手动埋点更强,是对手动埋点的补充而不是代替,很多手动埋点点都可以通过好的规划和架构变为可视化埋点。
无埋点(自动埋点、全埋点)
无埋点并不是没有任何埋点,所谓无只是不需要工程师在业务代码里面插入侵入式的代码。只需要简单的加载了一段定义好的SDK代码,技术门槛更低,使用与部署也简单,避免了需求变更,埋点错误导致的重新埋点。
通过这个SDK代码,前端会自动全量采集全部事件并上报埋点数据,能够呈现用户行为的每一次点击、每一次跳转、每一次登录等全量、实时用户行为数据,这些数据传到后端后,可通过用户分群、漏斗对比等功能,分析不同访问来源、不同城市、不同广告来源等多维度的不同转化细节,细而全。
无埋点相比可视化埋点,在解决数据“回溯”问题上更有优势,如果你想分析某一天某个控件的点击情况,如果你没有针对这个按钮做可视化埋点,则只能从你针对这个按钮做可视化配置的这一时刻之后才有埋点数据,而无埋点,则从你部署SDK那一刻就一直有数据在收集;无埋点做热力图也更有优势,无埋点可以告诉使用者这个界面上每个控件分别被点击的概率是多大,通过热力图清晰可见。
无埋点的劣势是自定义属性不灵活,传输时效性差,数据可靠性欠佳,耗费网络流量,还会增加服务器负载,而且兼容性也不佳。
据说Heap Analytics在2013左右较早推出了无埋点方案,但是网上有人透露百度在2009年就有类似技术,后来2011年,百度质量部也推出过一个内部服务,用以录制安卓 App 的全部操作,通过回放定位App崩溃的原因;豌豆荚也在2013年左右在自己的 App 内,也记录了所有控件操作情况。国内GrowingIO在2015年也较早支持了无埋点方案,后面神策等其他第三方也陆续支持了此技术。
我们看看神策和Mixpanel对无埋点的实现方案。
- 神策: 根据官方的介绍,设置AutoTrack之后,SDK就会自动解析HTML页面上的( a 、 button 、 input )标签。 并记录这些标签的点击情况,一旦页面某一个按钮发生了点击行为,SDK就会去采集此按钮的一些信息,例如: 这个按钮的标签类型,这个按钮的文本内容,这个按钮的 name ,这个按钮的 id 、 class 名,还有一些按钮特有的属性如 href等。
- Mixpanel: 设置AutoTrack之后,SDK会监测页面上的所有 form表单 、 input标签 、 select和textarea标签 产生的 submit 、 change 、 click 事件,并采集这些标签上的属性一起上报。
无埋点确实发送的埋点数量很巨大,比如知乎上就有很多人质疑无埋点解决方案。很多用户对无埋点发送大量埋点请求表示不理解,但是由于无埋点技术方案的限制,无埋点的可交互元素众多,每一次交互都会发送请求,所以会导致网络请求过重。神策等官方文档中也建议无埋点最好使用在那些按钮不是很多的,相对简单的页面。
数据采集能力比较
比如这个页面,点击确认按钮,如果使用无埋点和可视化埋点,在这里可能只能获取到某时刻某个人点击了确认,提交了一个订单,仅此而已。如果你希望拿到里面的首付款,月供,车型车款、用户详情等深度业务信息,就只能靠手动埋点获取。
无埋点和可视化埋点虽然使用和部署都很简单,但是在数据精确度和详细程度的获取能力上代码埋点更强大。一般来说,我们的产品都是根据业务场景混合使用三种埋点模式来完成我们的数据收集。
感性认识一些数据上报格式和接入代码
上报方式提到过,基本就是json、url params、head等,为了数据分析的关联性,会带上cookie、还有一些数据可能是在localstorage等具有生命周期管控的客户端存储里。 埋点技术除了刚才的方式划分,还可以划分为前端埋点和后端埋点,后端埋点数据更可靠、更集中(且没有前端的多端问题)、更实时。这篇文章主要是讨论前端埋点。
根据工作中对埋点的对比和整理,我们简单比较部分埋点方案:
对于语义明确的UI事件,自动埋点的数据一般会比手动埋点更加准确,更贴近用户行为,也更节省开发成本,侵入性更低。
主要是因为自动埋点语义简单明确,不像手动埋点由于开发习惯、代码风格、人的理解误差、分支处理等各种不确定因素变得没那么清晰明了。
比如:“下单”事件,自动埋点的PV肯定是>=手动埋点的,而UV差别可能不大。分析开发代码发现在onClick Listener中包含其他未覆盖到的分支,差别很可能就在代码分支当中。如果更进一步分析下代码可以发现,为什么开发不在分支当中埋点?可能这个分支会认为用户的这一次点击是“无效”的,但这只是程序逻辑的看法,用户可能不这么认为,用户很可能会觉得很奇怪没反应,然后再点一次。这些手动埋点不易察觉的细节,自动埋点都能记录,所以说,自动埋点在这些情况下会更贴近真正的用户行为。
自动埋点可降低原来手动埋点的个数和复杂性,使之更简化
比如:进入“商品详情页面”(展现),目前包括5个手动埋点,实际上用自动埋点只需要一个就够了,而且自动埋点不会遗漏。从数据来看,一个自动埋点的PV已经超过5个手动埋点之和。
自动埋点可采集界面环境数据,但是数据不够纯,需要进一步去噪
自动埋点能采集到大部分用户“看到的而且有用数据”。比如:“价格”这一属性,手动埋点可直接定义“amout: 5.2“来轻松获取数据,而自动埋点获取的是一串文本: “价格预估5.2元”,若要获取精确的5.2这个数值,就需要进一步解析。
自动埋点无法替代手动埋点,但可大大减少手动埋点工作量可预想的是,在用户行为分析上,自动埋点可以满足很大一部分需求函数级的埋点无法用自动埋点代替,后台非UI的事件也无法用自动埋点代替,自动埋点无法携带当时的业务场景数据,这些都表明了自动埋点无法完全替代手动埋点。
但单就用户行为分析来讲,自动埋点是可以覆盖用户的一些基本行为路径的,并能做一些较浅层次的分析。如果需要探究用户行为背后的原因、或需要进一步深入分析行为的时候,就是需要更多的后台逻辑事件、需要携带更多属性值的时候,就需要通过手动埋点来完成。所以,但是深层次的分析是你的重点,就需要使用手动埋点来解决。
埋点类型虽然当前也就这几类解决方案,而且真实的使用请求会根据业务混合使用多种埋点类型。但是我们除了选择好埋点类型外,要展开埋点工作,面临的沟通协调,如何准确多团队达成共识,并确保各方对业务和埋点深度理解,做要的工作和面临的挑战会更大。想要做好埋点工作,埋点需求的整理很重要,且需要遵守一定的原则。