自动采集(\t统计数据APP开发一套数据采集SDK的功能:\页面访问流)
优采云 发布时间: 2022-03-03 21:09自动采集(\t统计数据APP开发一套数据采集SDK的功能:\页面访问流)
随着库存APP的不断迭*敏*感*词*发,数据和业务部门对客户端用户行为数据的需求越来越大;为了更好地监控APP的使用情况,客户端团队对APP本身的运行有越来越多的数据需求。变得紧急。迫切需要一套客户端数据采集工具,自动、完整地采集用户行为数据,满足各部门的数据需求。
\\
有货APP团队为此开发了一套数据采集 SDK。主要功能如下:
\\页面访问流。用户在使用应用程序时浏览了哪些页面。\\t浏览数据暴露。用户在页面上查看了哪些项目。\\t业务数据自动采集。用户在使用应用程序时单击了哪些位置,以及触发了哪些操作。\\t性能数据自动采集。用户使用APP时,页面加载时间多长,图片加载时间多长,网络请求多长时间等。\
另外,所有数据采集都应该是自动化的,非侵入式的,即不需要人工埋点,可以集成SDK使用,无需改动或改动原代码,只要可能的。
\\
基于以上需求,AOP是技术方案的最佳选择,而iOS上AOP的实现需要Objective-C中运行时的黑魔法Method Swizzle的实现。踏坑填坑的漫漫征途就此开始。接下来,让我们一一品尝其中的思路和方法。
\\页面访问流程\\
用户访问页面统计有两个问题需要解决:
\\统计事件入口点,即何时统计。\\tStatistics 数据字段,即统计哪些数据。\
总体流程如下:
\\
\\统计事件入口点\\
用户访问页面统计的大致思路是在 View Controller 生命周期方法中:
\\
可以得到用户访问页面路径,两个事件时间戳的差就是用户在页面停留的时间。
\\
通常我们APP中的ViewController会继承自某个基类,我们可以算入基类对应的方法中,但是对于不继承自基类的ViewController我们就无能为力了。
\\
借助AOP,我们可以更优雅地完成这项工作:在UIViewController的load方法中swizzle viewDidAppear和viewDidDisappear方法,原代码不需要改动。
\\统计字段\\
根据数据要求,设置以下统计字段:
\\
页面进入和退出的事件上报到上述数据结构。
\\
还有几个问题需要考虑:
\\1.PAGE_ID 和 SOURCE_ID 是如何定义的\\
因为iOS和Android的PAGE_ID需要统一,所以需要进行配置和分发。iOS端拿到一个plist文件,文件的key是ViewController类名的字符串表示,value是PAGE_ID。
\\2.如何获取 PAGE_ID 和 SOURCE_ID\\
PAGE_ID可以直接根据当前ViewController的类获取。SOURCE_ID 有点复杂。具体的获取方式需要根据APP页面的嵌套栈结构来确定。通常可以从 UINavigationController 的导航栈中获取上一个 View Controller 的 page id。.
\\
至此,页面访问流量统计基本完成。根据页面进出的PAGE_ID和SOURCE_ID,得到一个完整的用户浏览路径,得到用户在每个页面的停留时间。
\\浏览数据曝光\\
采集用户的浏览路径,以及每个页面的停留时间之后,在一些特定的页面,比如首页,产品列表页面,我们也想知道用户刷了多少屏页面和观看了哪些活动和产品可以更好地为用户推荐喜欢的产品。
\\
用户在屏幕上看到的一个区域被认为是一个资源位,那么用户看到的内容就是由资源位组成的。那么曝光的含义如下:
\\
我们知道iOS中页面元素的基本单位是视图,所以我们只需要判断视图是否在可见区域就可以知道当前视图上的资源位是否需要暴露,从而做出相应的曝光操作、采集数据、报表接口等
\\
从上面的分析可以看出,主要有两个问题需要解决:
\\view的知名度判断\\tview曝光数据采集\view的知名度判断\\
查询 UIView Class Reference 可以看到 setFrame: 和 layoutSubivews 方法,可以用来设置子视图的框架。每次更新视图名时都会调用此方法。因此,我们可以通过runtime swizzle来实现这个方法,并添加一些数据采集相关的操作。
\\
我们向 UIView 添加了以下属性:
\\
首先,明确以下术语的定义和规则:
\\
1.视图的子视图可以看到同时需要满足的三个条件:
\\
反之,只要不满足上述任何一个条件,我们就认为这个子视图当前是不可见的。
\\
2.将视图设置为可见
\\
3.将视图设置为不可见
\\
Swzzile setFrame:,它执行以下操作:
\\
\\
Swzzile layoutSubivews,调用 yh_updateVisibleSubViews 方法,该方法执行以下操作:
\\
\\
经过以上操作,我们就可以知道一个视图及其子视图是否可见。
\\查看曝光数据采集\\
为了获取视图对应的数据,UIView中还添加了如下属性:
\\
那么有两个问题:
\\view 曝光数据粒度\\tview 及其子view 节点的曝光数据组装时序\
视图曝光数据的粒度
\\
根据项目中的实际经验,UITableViewCell 或 UI采集ViewCell 一般是最小的粒度。同时在最后一个节点的yh_exposureData字典中,添加一个key:isEnd来标识是否是最后一个节点。
\\
视图及其子视图的曝光数据组装时序
\\
一般当最后一个节点的可见性发生变化时,从下往上遍历最后一个节点的superview,将所有数据组装起来。
\\
所以我们重写了setYh_viewVisible:方法,也就是yh_viewVisible的set方法。请执行下列操作:
\\
至此,我们解决了视图可见性判断和曝光数据采集的问题。数据报告和策略在此不再赘述。
\\
这种方案有几个缺点
\\需要手动设置曝光数据。\\t需要手动调用view.yh_viewVisible在合适的时间触发数据采集,如viewdidappear等。\\t可见区域计算和曝光数据需要消耗一定的资源采集。\
另外两个问题值得注意:
\\UITableView setBounds:时会改变view的frame,所以需要swizzle setBounds:方法,设置bounds后需要调用[self yh_updateVisibleSubViews];\\tUIScrollView setContentInset:时会影响view的可见区域,所以需要swizzle setContentInset:方法,设置contentInset后需要调用self.yh_viewVisibleRect = UIEdgeInsetsInsetRect(self.frame, contentInset);\Business data auto< @采集\\
业务数据自动采集即行业流行的非埋藏数据采集。
\\
传统的客户端用户点击数据采集是基于人工埋点。如果您对该位置的数据感兴趣,可以单击此处。用户操作后,立即触发数据报告。人工埋葬的弊端很明显:误埋、漏埋。新版本发布后,经常有数据部的小伙伴报某点未报,某点报错问题,开发同仁也苦不堪言。
\\
无负担的数据采集带来新的变化。首先,基本避免了人工嵌入,个别情况需要特殊处理。其次,选择性采集 数据成为完整采集 用户的所有点击和触摸数据。
\\
新的变化也会带来新的挑战。非地埋点数据采集成为现实的可能性仍然基于Objective-C的运行时特性。在实践过程中,我们在思路上借鉴了iOS无埋数据SDK的整体设计和技术实现,在实现上借鉴了Sensors Analytics iOS SDK和Mixpanel iPhone。接下来结合具体实践,介绍一下我们的实现思路和遇到的一些问题。主要分为以下三个方面:
\\如何保证自动采集点的唯一性。\t不同的点类型,哪些方法需要调配。在 \\tswizzle 过程中,坑踩到了。\Automatic 采集 如何保证唯一性 \\
自动采集与人工埋点分开,所以没有埋点的唯一标识。那么我们如何唯一定位自动采集点呢?一个很容易想到的解决方案是:基于页面视图的树状结构。这种情况可以分解为两个问题:
\\view 唯一标识符是如何定义的。\\t查看唯一 ID 是如何生成的。\
视图唯一标识符的定义(视图路径)
\\
我们指定一个典型的视图路径如下:
\\
\ViewController[0]/UIView[0]/UITableView[0]/UITableViewCell[0:2]/UIButton[0]
\\
在:
\\这个元素可以通过这个标识符在当前页面视图树结构中唯一确定。\\t标识的每一项由两部分组成:一是当前元素所属类的字符串表示,二是当前元素在同级元素中的序号,从0开始。例如,当前的第二个 UIImageView 是 UIImageView1。\\t 用 / 拼接标识不同的项目。\\t 标识的最顶层是当前视图所在的 ViewController。\\t对于UITableViewCell和UI采集ViewCell等类似的自定义组件,序数部分由section和row两部分组成,分别用:拼接。\t 符号的末尾是当前单击或触摸的元素。\
如何生成视图的唯一ID
\\
视图路径生成过程:从最后一个触发操作的元素向上查询,直到到达ViewController。假设当前点击的view是A_View,从当前A_View开始遍历view树,将每一层的数据存放在P_Array中。过程如下:
\\
\\如果A_View为UI采集ViewCell类型,获取A_View所在UI采集View的indexPath,P_Array推送路径信息[NSString stringWithFormat:@\"%@[%ld:%ld]\