SDK无埋点数据采集-简单背后的复杂逻辑
⊙ 背景
⊙ 移动端埋点
⊙ 无痕埋点思路&流程
⊙ 系统类的hook
Delegate的hook|自定义的hook
⊙ SDK关键技术
⊙ 界面元素唯一标识—viewPath
UIWebView(WKWebView)
UITableViewCell&UICollectionViewCell
⊙ 可视化圈点
⊙找到正确的view
⊙总结
背 景
移动互联网已经席卷到社会的方方面面,移动支付、新闻阅读、视频节目、电商购物、公交出行等热门应用都出现在移动终端上,在iOS和Android的App Store中的下载已经达到数百亿次,而移动用户规模更是超过了PC用户。如今出行已经只需要带上手机,就能够应付自如。而在移动之后,大数据业务已经站在了当今的风口浪尖。
众安科技大数据旨在利用大数据技术提供专业的风控和精细化运营服务。信息核查、信贷风控、反欺诈、决策系统、流量分析都是基于大数据技术所推出的服务产品。其中“流量分析”采用自动化埋点服务,只需在第一次使用时加入一段SDK或者JS代码就可以采集全量、实时的用户行为数据;并提供访问者分析,渠道分析,内容分析等工具方便使用者查看产品及活动的整体情况;同时提供用户分群,漏斗转化,流量路径、监控预警等分析工具使得流量价值最大化,从而为客户打造可量化效果、高效管理的互联网流量管理平台。
移动端埋点
iOS和Android的SDK(简称SDK)为“流量分析”产品提供了数据采集功能。它具备不需要入侵业务就可以自动地、动态可配置地、全面正确地收集用户在使用App时的所有行为数据。除此之外,为了能够满足业务的多变性,SDK还为用研和产品人员提供了可视化圈点的功能——用来配置业务与界面元素的匹配关系。这样,既可以减少业务开发人员的工作量,又能够满足业务灵活多变的需求。
当前SDK已经具备两大功能:
用户行为、性能数据的采集:客户端的启动、页面切换、浏览、用户点击事件、网络请求、页面加载时长、贞率等等操作,SDK都能够自动完成采集。
可视化埋点:可以通过拖拽来圈点界面上的各个元素,并且可以为这些元素配置所需的业务别名,这样在后端进行数据分析时候更加精准。
无痕埋点思路
要实现无入侵的SDK埋点方案,我们采用的是AOP(Aspect-Oriented-Programming),即面向切面编程的思想。本质上就是在运行时,动态地将SDK的采集代码切入到类的指定方法、指定位置上。在iOS平台上,我们采用的Runtime和Method Swizzling这样的“黑魔法”。在Hook掉目标方法之后,我们就可以“为所欲为”了。为了达到采集数据的“原子性”,SDK将在最基础的地方埋点。
图1.AOP编程
(通过“代理”包裹“目标”对象,处理方法调用,执行额外的切面逻辑,然后调用“目标”方法)
无痕埋点流程
图 2. 无痕埋点流程
系统类的hook
系统类是指iOS系统框架Foundation中提供的类,其中大部分都在UIKit中。
App的启动、切换、结束:只需要监听App的UIApplicationWillTerminateNotification等广播通知。
页面的切换、显示、消失:UIViewController是iOS应用的界面的基本承载,因此SDK只要hook掉它的的生命周期的方法:
viewDidLoad、viewDidAppear、viewDidDisappear、dealloc就能采集到页面的加载、显示、消失的数据。
控件响应事件:用户与App交互最多的方式也就是点击、滑动,因此hook掉UIControl的sendAction:to:forEvent:方法,就可以采集到准确的用户操作数据。
Delegate的hook
iOS中还有一类事件上报给配置好的委托对象来处理,比如UITableView、UICollectionView等。想要在事件发生时候能够采集到数据,SDK需要在设置Delegete的时候,hook掉Delegate对象的这些协议方法。例如在实现列表元素点击事件的收集时,主要 hook 了 UITableViewDelegate 中的 tableView:didSelectRowAtIndexPath:方法。
自定义的hook
顾名思义就是开发在代码中自己添加的一些手势,比如给原本无法提供用户交互的UILabel、UIImageView和UIView添加手势。为了能够采集到自定义手势的数据,需要hook手势对象所指定的target的类的delegate方法。
SDK关键技术
后端为了对App中某个页面的某个控件进行“路径分析”、“漏斗分析”等业务,首先就要能够唯一标识与定位这个控件。SDK为页面上的每个元素都增加了一个“唯一标识”,可以说这是数据收集SDK与业务松耦合的重要前提。有了这个“唯一标识”,再加上“可视化埋点”提供的业务配置,采集到的离散数据就可以真实、有效、精准的反映出业务实际情况。
那么SDK如何唯一地标识每一个元素呢?SDK采用了viewPath。
界面元素唯一标识—viewPath
顾名思义,viewPath代表的是界面元素在界面显示层叠中的路径(path)。如图所示,在iOS的App中展现出来的界面元素之间的关系,其实是一棵“树”,根节点就是UIWindow,而其他的UIView就组成了这棵树的枝干的叶子。
图 3. App中的视图树和层叠关系图
这里就可以想到,不同的视图元素相对于根节点的相对路径就可以作为这个元素的“唯一标识”——就像我们的住址一样。
UIWebView(WKWebView)
如今的App中,为了方便多样化地呈现灵活的业务,越来越多地采用了内嵌H5页面的方式。这类H5的页面一般就是一个WebView控件,而这个WebView只是一个“相框”,其中的内容可以“包罗万象”。因此如果还是使用传统的ViewPath的方式,那么不同的URL内容的ViewPath都是一样的(都是WebView控件相对UIWindows的路径)。为了区分不同URL,我们需要把URL中的Domain信息添加到WebView的ViewPath中。
就好比同一个小区的地址都是一样的(xx市xx区xx街道xx号),因此我们在写地址时候还要增加x幢x单元xxx室。
UITableViewCell&UICollectionViewCell
在UITableView和UICollectionView中的Cell都是控件重用的,也就是说同一个Cell会出现在tableView的不同位置 。在针对这类Cell时候,SDK针对Cell额外增加了indexPath来区分。
indexPath表示Cell在TableView中的位置(section+row——第几段,第几行)
图 4. 不同位置的Cell,indexPath不同
可视化圈点
SDK还提供了可视化圈点的方案,以解决多变的业务和App相对固定的界面之间的矛盾。用研和产品人员可以通过SDK的圈点功能来动态配置每个元素对应的业务含义。
在可视化配置之前,App只能通过在需要的地方调用埋点接口的方式进行有效的业务信息采集。不但费时费力容易出错,而且业务变更还需要重新修改代码、编译、发布。
图 5. 手动埋点流程
自从有了可视化配置之后,只要在App上圈点需要采集的界面元素,即可生成采集配置信息。配合SDK无痕采集的数据,后端会根据当前App的配置来匹配得到业务关心的相关数据。这样既能够达到不入侵业务的要求,又能够满足特定业务数据的精准统计,大大减少了开发人员的工作量的同时,还避免修改代码增加了App的稳定性。
图6. 可视化圈点
找到正确的View
从图6视频可以发现,可视化圈点其中最重要的就是在圈点过程中,能够找到“正确的”的view(被红色圆角矩形覆盖的控件)。为了解决这个问题,我们需要用到“响应链”和UIView的hitTest方法。
响应链:由于篇幅问题,这里不再赘述“响应链”的概念和原理,有兴趣的同学可以查看苹果官方文档《UnderstandingResponders and the Responder Chain》。49 31159 49 15536 0 0 3437 0 0:00:09 0:00:04 0:00:05 3437>
图 7 . App事件响应顺序(自上而下)
hitTest:withEvent:方法 :我们重写了这个方法。在可视化圈选的过程中(小红点的拖拽过程),根据self的情况(是否有点击的手势、是否有 Target等等)来判断是否应该返回self。通过这个方法得到的View就是我们认为当前应该圈选的视图。
总 结
本次主要介绍了众安SDK无痕埋点&可视化埋点的iOS端的设计与实现。当然在开发过程中还遇到了各种各样的问题。有关一些问题的解决和关键技术的实现敬请关注【众安数盟】微信公众号,更多内容将会在后续文章中介绍。如果你觉得这篇文章让你有所收获,欢迎分享。