有码埋点相比较便于领悟,近期在负责店铺的哈勃勒Data的埋点SDK的支出任务

0 引言

前不久在承担公司的哈勃勒Data的埋点SDK的付出职分,产品的雏形其实在几年前就已经有了,公司里面的诸如考拉、易信、LOFTE奥德赛、美学、漫画等多款产品都已连接使用。

下图给出哈勃勒Data SDK某些应用的片段分析的显得页面:

(1)概览示意图

事件

(2)事件分析示意图

事件

(3)实时分析示意图

事件

除此以外哈勃勒Data平台还有着留存分析、漏斗分析、粘性分析、数据看板等种种效益,方便有关管事人士对成品用户作为举办更进一步的切磋分析。

老版本的SDK的统筹是代码埋点落成的,固然对于一些比较成熟的成品,代码埋点完全可以达到产品方的须要,可是对于一些新运转或然需频仍变动的须求的新产品等,考虑到其保险的资金大,代价高等缺点,哈勃勒Data无埋点SDK的统筹就浮现越发首要了。

自个儿根本担负iOS端无埋点以及可视化圈选的办事,小说紧要系统讲授一下哈勃勒Data无埋点SDK在iOS端的设计与落实和局地连锁题材的消除,后续将对准任何埋点的落到实处流程与可视化圈选等内容再作分享。

① 、埋点简介

By Cobub OP
Team
 in 博客未分类

1.1 三种埋点的贯彻格局简介

埋点的办法分为三类:代码埋点、可视化埋点和无埋点。那里大约的牵线一下二种埋点形式:

(1)
代码埋点即是在代码的关键部位植入所要收集数据的N行代码,要求挖开产品小编,深刻摸底产品的政工逻辑及项目社团,上边代码模拟突显的即是点击提交订单的时候哈勃勒Data
SDK代码埋点;

代码埋点示例

(2)
可视化埋点即用可视化交互的方法圈选出所要采集数据的控件,当用户作为发出时,即可收集到对应的埋点数据。相比较于前方的代码埋点而言,可视化埋点可以缓解代码埋点代价大开销高的难点,可是不可以灵活的自定义埋点属性。

可视化埋点流程

(3)
无埋点也叫全埋点,即不需求用户主动埋点,可以搜集用户拥有的操作行为,同样运用可视化圈选,用户能够得到所想采集的埋点数据,可以解决可视化圈选中多少不可回溯的标题。下图给出了无埋点数据收集的简练流程。

无埋点数据收集流程

哈勃勒Data
SDK的布置重点是代码埋点结合无埋点的数目收集格局,其中也涉嫌到可视化埋点中的显示屏种类化及事件绑定机制,本文主要介绍一下无埋点的设计与贯彻。

11
hours ago  0  59

1.2 无埋点SDK设计详细流程

下图给出哈勃勒Data无埋点SDK在iOS端的设计落成:

无埋点详细规划流程

从上图能够看出,哈勃勒Data的无埋点是在代码埋点的功底上落到实处的,所处无埋点的难关也就集中在以下多个方面:

(1)自动获取埋点的EventID
(2)自动获取埋点的时机
(3)自动获取埋点需采集的属性

正文主要就那个地点进行分析,第②部分珍贵讲一下事变唯一ID的规定,第叁有的相当主要讲一下无埋点的收集的落到实处,主假设各个风浪时有暴发采集的火候以及待采集的性质的配置。

哈勃勒Data
SDK还涉及到无数任何职能,包涵显示器连串可视化、代码埋点、精准渠道追踪等,那里不再介绍,前面会陆续分享相关的技巧完结。

乘胜大数额时代的来临,数据搜集也一度变的越来越主要。前端埋点作为1个相比成熟的数码连接手段被广泛应用着。如今埋点分为三种方式,有码与无码埋点。有码埋点相比较便于明白,即调用SDK的API,在代码中插入埋点的相干代码,完成用户作为采集。由于咱们在支付品种的时候,埋点都以手动的,每一次业务须求的改观都要随地埋点,而无码埋点,即不要求手动插入代码,只须求早先时期开展连锁安顿,SDK自动收集用户作为,极大程度幸免了因要求变动、埋点错误等原因造成的再次埋点繁复工作。本文主要介绍无码埋点的技巧达成。

贰 、事件唯一ID的显然

为了促成在可视化圈选的时的轩然大波的唯一性,每三个无埋点的事件采访都必须有且仅有3个唯一的标识符来区分差别的轩然大波。差别于代码埋点,用户可以自定义的配备本身所需的伊芙ntID,无埋点进程中,要求SDK本身布置每三个采集事件的伊夫ntID,通过可视化圈选的操作,筛选出相应的伊夫ntID所对应的多寡新闻。哈勃勒Data接纳的是构造view唯一标识字符串的章程去唯一的标识那样的2个风浪,主要由view的层级结构path路径、该view的随处页面类名以及view所带的有个别本人定位属性等结合,并透过SHA256编码来博取唯一的伊芙ntID。

下边将一体化系统介绍部分事件唯一ID的浮动进度。

无码埋点的完结流程

图片 1
1.可视化视图圈选,在页面上会出现变化的圈子,拖动圆圈至想布署事件的控件上,将会弹出输入事件的弹框。
2.在上一步的弹框中输入自定义的轩然大波名称,名称将会和视图的viewPath绑定起来。viewPath是视图的绝无仅有标识,在下文上将详细讲解。
3.用户点击了控件,判断控件是或不是绑定过事件,如绑定则开展事件上传。

2.1 控件的层级结构path构造

大吉大利流程中的技术点

2.1.1 普通view的层级结构path构造

层级结构path紧借使根据页面的控件树构造而成,每一种view都有superview与subviews的属性,将每3个view的superview作为树的父节点,将其subviews作为子节点,那样就能把整个app上的富有view组成一棵巨大的控件树,其中树的顶层是UIWindow,然后是每二个view节点依次向下举行。下图给出2个简便的控件树的构造图。

空中树结构

上面会详细介绍一下哈勃勒Data的唯一标识路径的结构格局。

不同类

同类

像上图1所示,假使二个view的subviews中都以例外类其他,比如像下图图1所示的控件树那样,可以唯一标识UILabel和UIButton控件为:

UIView_UILabel
UIView_UIButton

可是真的的页面是不会像可以中的全部控件都是见仁见智品种的,可以说那种极其景况基本不设有,若是依然遵从上述的点子来社团路径的话,五个UILabel都会被标识成UIView_UILabel,那明摆着无法区分七个控件。因而只有是各种控件节点的路径名称是力不从心唯一标识这几个控件的,那里HubbleData加入了此控件节点在父视图中的index。比如上图2,能够将七个UILabel标识为:

UIView(0)_UILabel(0)
UIView(0)_UILabel(1)

那里假诺父视图是index为0的二个节点,那样就足以完全的界别出八个控件了。

那么余下的标题就是每一种UIView index索引值的显然。

各个UIView都有subviews属性,各个子视图都有三个被addsubView的次序,其实要拿的这些index就是子视图被add的程序,那么该怎么得到那些顺序呢,在苹果的合法表达文档中,岁UIView的subviews属性,是那样介绍的:

@property(nonatomic, readonly, copy) NSArray *subviews

You can use this property to retrieve the subviews associated with your custom view hierarchies. 
The order of the subviews in the array reflects their visible order on the screen.

即每贰个子视图在这么些subviews数组中的索引就是哈勃勒Data要拿的index。

针对复杂的视图方式,如下图所示,根据上述的层级结构路径构造方法获得的唯一层级路径为:

UIView(0)_UILabel(0)
UIView(0)_UIButton(1)
UIView(0)_UIButton(2)  

混合

从上述的辨析可见,依照上述介绍的不二法门进行view的唯一层级路径标识,对绝大部分的页面来说已经充足,不过对于某些更是灵活点的页面,由于有个别业务须求等原因,开发人士常常会调用removeFromSuperview,
insertSubview:atIndex:, insertSubview:
belowSubview:等函数,都会大幅的震慑总体页面的subviews的索引值,比如将来自身将上图所示的UILabel移动到七个UIButton的背后,那么拿到的唯一层级路径为:

UIView(0)_UIButton(0)
UIView(0)_UIButton(1)
UIView(0)_UILabel(2)  

混合

可以发现,唯一层级路径已经被改动,可是整个页面却不曾暴发变化,不仅会发出新的风浪(比如UIButton(0),UILabel(2)),连UIButton(1)事件的搜集也会出错,即使是不一致的事件,却拿到了差其他eventID,所以必要提升社团的层级结构路径的稳健型。

正像刚刚提到的,不相同档次的UIView不需求做index的界别,那么在拿到那个index的时候,不是粗略的从subviews那几个数组中拿到其相应的索引值,而是举办三个简练的同类归并再取索引值,3个很简单的拍卖。

for (UIView *view in subviews) {
    if ([NSStringFromClass([subview class]) isEqualToString:NSStringFromClass(class)]) { //class为待筛选的类
        [array addObject:view];
    }
}

如此那般就可以赢得array中的index作为其真正的索引值,拿到的层级结构路径为:

UIView(0)_UILabel(0)
UIView(0)_UIButton(0)
UIView(0)_UIButton(1) 

那时无论UIlabel的位置放在哪里,都不会转移那几个途径的协会样式,大大增添了稳健型。其实也能发现,那可是只好升高稳健型,并不可以从根本上化解这么些题材,比借使本人把七个UIButton的相继交流了,可能去除了第3个,此时照旧会获取一些不纯粹的层级路径。此题材会一而再解决,会日益引入误差体量和相似度那几个定义,即要是在误差范围内,则会进展进一步的合营,具体的缓解方案本篇不在介绍。

可视化视图圈选完结

自定义UIWindow的子类,当做悬浮小圆圈,添加UIPanGestureRecognizer手势,依照手势的移动,设置悬浮框的移动。手势甘休时取得悬浮窗大旨点的坐标。
遍历主window上的子视图,找到包罗上述悬浮窗核心点且能响应用户交互的最里层视图,即为用户可以圈选的视图。
参考iOS控件的消息传递链,有个中央措施。UIView hitTest:(CGPoint)point
with伊夫nt:(UI伊夫nt
*)event。此API自动遍历子视图,找到包罗point的视图,event传nil。由于event参数是nil,最终找到的视图并不一定是能响应用户手势的视图,如若不能响应则遍历其父视图,直到找到能响应用户作为的视图。

2.1.2 两种特有景况的处理

2.1.1关键讲的是有些平凡view的层级结构的path构造方式,不过有一对异样情状须要特地的设想处理:

  • UITableViewCell

出于UITableViewCell具有可复用的机制,当一个页面中在时时刻刻滚动的时候,cell在时时刻刻的复用,借使还拔取2.1.1中牵线的点子来收获index索引值话,那么会挑起整个页面无埋点数据搜集的眼花缭乱。

当得到当前UITableViewCell的index时,可以动用indexPath参数举行轮换,那些参数可精确的收获section和row的值,唯一的对应每3个cell。唯一层级路径的样式可以自定义配置,哈勃勒Data的装置格局为:类名+(section:
row:),上边给出一个演示:

MyTableViewCell(section:0 row:7)
  • UICollectionViewCell

UICollectionViewCell的path生成原理同UITableViewCell,哈勃勒Data的装置方法为:类名+(section:item:),下边给出多个演示:

MyCollectionViewCell(section:0 item:7)
  • UIControl

事实上UIButton也终归一种常见view的一种,大部分动静下,使用上述的层级结构path以及页面类名的三结合可以唯一的鲜明当前UIControl的唯一标识符,不过有一种特殊的场馆,当作为UINavigationItem时会出现相当情状,下边的所提交的多少个例证。

bar1

bar2

当点击第四个NavigationBar的左边的按钮时,得到的层级路径为:

...UIViewControllerWrapperView(0)_UIView(0)_UILayoutContainerView(0)_UINavigationBar(0)_UIButton(1)

浅析可见,左边的设置按钮的目录为0,所以左侧的按钮索引为1。同时得到的目前页面为:UINavigationController。

当点击第二个页面的同3个项目标按钮时,即一律标有数字7的item时,此时到手的层级路径为:

...UIViewControllerWrapperView(0)_UIView(0)_UILayoutContainerView(0)_UINavigationBar(0)_UIButton(2)

可以窥见此时的按钮的目录变成了2,已经差异于上述第二个NavigationBar的同2个按钮的层级路径了,经过分析,索引值为1的按钮是最左侧的报表的那一个item,经过证实可以拿到其层级路径:

...UIViewControllerWrapperView(0)_UIView(0)_UILayoutContainerView(0)_UINavigationBar(0)_UIButton(1)

赢得的页面为:UINavigationController。

实在那种页面很宽泛,由于页面的切换,NavigationBar上的片段按钮的职位可能顺序会打乱,导致同三个效益的NavigationItem已经力不从心明确标识唯一,即使是得到了眼前按钮所在的页面也无能为力区分,因为获取的皆以UINavigationController。从地点的辨析能够看看,这种景况甚至会造成惨重混乱的数据搜集。

其实仔细分析一下,若是条分缕析得出该UIControl是在UINavigationBar上,则无需安装其对应的index值,即上述的持有navigationItem的层级结构路径都为:

...UIViewControllerWrapperView(0)_UIView(0)_UILayoutContainerView(0)_UINavigationBar(0)_UIButton

即都不做区分。

哈勃勒Data接纳增加一种新的习性来不相同各样item,其实很精晓可以看出来,那几个item的施行的action肯定是不相同的,所以取其action属性来分化,最后的区分方式如下:

path(...UIViewControllerWrapperView(0)_UIView(0)_UILayoutContainerView(0)_UINavigationBar(0)_UIButton)&actions(button1Click:)
path(...UIViewControllerWrapperView(0)_UIView(0)_UILayoutContainerView(0)_UINavigationBar(0)_UIButton)&actions(button2Click:)

这么,哈勃勒Data就足以精确的差别差其余item了,同时完结平等种意义的item,由于其action相同,所以也会准确的标识其唯一性。

  • UIAlertController

出于差别的UIAlertController在甄选鲜明、打消等选拔时,采纳的开展唯一层级路径判定的view需求开展自然的拍卖,同时为了保证差其他UIAlertController处于同一职位的挑三拣四的埋点伊芙ntID不一样,那里在结构唯一标志字符串的时候还要插手该UIAlertController的message和title新闻。3.5小节中会举办相关无埋点采集的牵线。

  • viewController的嵌套

貌似情况下,普通的view只需依据一般的层次路径收集index即可,不过当存在pageViewController时,如下图所示分别交付了三个横向滚动(以公司考拉app为例)和纵向滚动(以集团严选app为例)的app的截图的示范:

其实可以看来,pageViewController会应用到见惯不惊app中,所以那类app在利用进程中的无埋点难题越来越要考虑。

圈选视图绑定事件

视图唯一标识viewPath生成,上述手续已经拿到了圈选的视图。如何明确视图的viewPath也是非同儿戏。viewPath须要全体应用唯一,才方可分别不相同的风浪。由于是无码,所以不得不从视图本身的本性去分析。我们可以把App的视图结构掌握成树的概念,树的根节点是UIWindow,树的枝条由UIViewController和UIView组成,叶子节点都以UIView。那么从根节点到叶子节点的门径可以作为是绝无仅有的。约等于视图的viewPath。上边介绍下已毕的逻辑,viewPath由两部分组成,第②有个别是节点路径,另一有些是与之对应的节点index。节点路径是由各种节点的Class拼接而成,节点index,就是节点在父节点中的下标,比如子视图在父视图的subviews数组中的下标。下图是遍历节点的逻辑图。
图片 2
算算节点的index,那几个手续,有种特殊的视图要求留意,可复用视图的index是跟数据源相关的,比如UITableViewCell,此类视图的index不恐怕利用父视图的subviews的下标代替,应该使用数据源的下标代表,比如cell的index帕特h.section:indexPath.row。上面给出2个总结视图和可复用视图的viewPath的事例。TestViewController-UIView-UIButton&0-0-0和TableViewController-UITableView-UITableViewCell&0-0-1:0。
怎么检测用户触发了绑定了风云ID的视图也是第叁,此处运用的焦点技术是runtime中Method
Swizzle。下边介绍一下对准分化品类的控件,怎么样hook相应的章程。

  1. UIControl类型的控件hook – (void)sendAction:(SEL) to:(id)target
    for伊芙nt:(UI伊芙nt *)event
  2. UIScrollView,UITextView,UITableView,UICollectionView
    类型的控件,先hook -(void)setDelegate:(id)delegate
    方法,然后再hook想要采集事件的代办方法,例如 textViewDidBegin艾德iting
    、tableview:(UITableView *)tableview
    didSelectRowAtIndexPath:(NSIndexPath *)indexPath 等。
  3. 带手势事件的视图 hook
    -(void)addGestureRecognizer方法,并在章程落成中给手势对象添加新的target和action
    ,- (void)addTarget:(id)target action:(SEL)action。
(1) 各样子页面的controller不一样?

万一pageViewController中的各样子页面不相同,尽管持续2.2节哈勃勒Data会加盟页面controller的音讯来分裂那几个区其他子页面,不过只怕会出于逐个子页面插足的依次分化,导致每一次app进来的时候同二个页面的轩然大波会获得区其他伊芙ntID,举例来表达一(Wissu)下,如上图1所示,比如前五个子页面是ViewController1,
ViewController2, ViewController3,
ViewController4,那类pageViewController除非设置多少个子页面同时预加载出来,那么此时的得到的层级路径为:

ViewController1对应路径为:superview(0)_subControllerView(0) 
ViewController2对应路径为:superview(0)_subControllerView(1)
ViewController3对应路径为:superview(0)_subControllerView(2)
ViewController4对应路径为:superview(0)_subControllerView(3)

不过app基本都不会预加载出装有页面,对于用户不感兴趣的页面完全没须要三回性全体加载处理,唯有当用户挑选了该条款时,该对应的子页面才会加载出来,借使将来用户点击的逐一是ViewController1,ViewController3,ViewController4,ViewController2,由于addChildViewController只怕addSubView的一一的改观,那么此时到手的层级路径为:

ViewController1对应路径为:superview(0)_subControllerView(0) 
ViewController2对应路径为:superview(0)_subControllerView(3)
ViewController3对应路径为:superview(0)_subControllerView(1)
ViewController4对应路径为:superview(0)_subControllerView(2)

可以发现,index值变了,层级路径不唯一了,那么无埋点采集的伊夫ntID只怕会由于用户挑选页面顺序的不等而各异,造成埋点数据的杂乱。

哈勃勒Data对于此类页面的拍卖是,遭遇此类页面,即不用index标注,所以会联合的标识成:

ViewController1对应路径为:superview(0)_subControllerView 
ViewController2对应路径为:superview(0)_subControllerView
ViewController3对应路径为:superview(0)_subControllerView
ViewController4对应路径为:superview(0)_subControllerView

三番五次可以经过分歧的页面的controller的类名获取其不一致的唯一标识字符串。

总结

无码埋点的关键技术,就是以上分析的几点,首先通过可视化圈选得到需求绑定事件视图,并生成唯一标识viewPath,通过hook系统控件的点子,拿到用户触发的视图,生成视图的viewPath与本地的轩然大波列表比对,比对成功则上传view帕特h对应的事件。

(2) 各种子页面的controller相同?

事实上做过此类页面的为主应该都如数家珍,很多景况下子页面都是集体的,只但是是填写的model差距而已,那么碰到那种地方,借使是遵循难点1的化解思路,尽管如约2.2获得了近期页面的controller,那么依然无法区分出那个页面,所以依然须要安装新的全部辨识度的index。

其实通过pageViewController可以窥见,用户可以经过左右滑行只怕前后滑动来切换子页面,表明全数的子页面都以放置在一个scrollView之中,那么就可以从这一个scrollView出手,重新明确index。下边给出哈勃勒Data化解这一个难题的法门。

一起首想行使当前scrollView的contentOffset整除此pageViewController的页面宽度和冲天所拿到的值作为区分子页面的index,不过考虑到只怕contentOffset的连接变化以及子页面横跨pageViewController整数倍宽度的界限时,恐怕会促成获取的index不唯一的情事,所现在来利用该子页面的苗头地点整除pageViewController的附和地宽度和惊人得到相应地index。具体的落到实处如下,其中controller为当下的页面:

 if (view == controller.view || view == controller.view.superview) {
      NSInteger index_x = view.center.x / [view superview].frame.size.width;
      NSInteger index_y = view.center.y / [view superview].frame.size.height;
      NSString *path = [NSString stringWithFormat:@"%@(indexx:%ld indexy:%ld)",  
                        NSStringFromClass([view class]), index_x, index_y];
  } 

从而同样针对上述(1)所付出的两个ViewController1,优化后的到的唯一的标识为:

ViewController1对应路径为:superview(0)_subControllerView(indexx:0 indexy:0)
ViewController2对应路径为:superview(0)_subControllerView(indexx:1 indexy:0)
ViewController3对应路径为:superview(0)_subControllerView(indexx:2 indexy:0)
ViewController4对应路径为:superview(0)_subControllerView(indexx:3 indexy:0)

这么即便种种子页面的controller相同,也能由此优化后的index来分别种种不一样的子页面。当然那种只是指向嵌套scrollView的子页面的情景,可是能化解一大半的此类难点,对于一些其余的独特景况等,需详细分析页面布局举行辨析。

2.2 当前页面controller的拿走

看上去,大部分意况下2.1的view的层级结构path已经基本规定view的唯一标识字符串,不过普遍存在这么一种情形,当同五个页面跳转多个例外的页面时,借使那八个差异的页面上都取第2个按钮的层级路径,拿到的简化后的结果都如下所示:

.../UINavigationTransitionView(0)/UIViewControllerWrapperView(0)/UIView(0)/UIButton(0)

是无力回天开展那七个页面上的按钮区分的,其实页面的类名是分别的2个最直接的不二法门。哈勃勒Data是依照上面的不二法门拿到有个别view所在的controller的类名的。

收获当前controller示例

将view的层级路径结合当下页面的称号,已经可以消除掉一大半的唯一标识字符串的难题了。

此间须要小心的一些是,当页面类型一样,只是填充的model不一致时,比如浏览商品详情时,所进入的页面都以一个,只是model差异,近期哈勃勒Data对那种景色暂且未做处理。后续可参看作品3.2节UIViewController的无埋点采集,对有些页面,用户可以自定义诸如screenTitle的字段,定义该页面的称号,比如screenTitle蕴含产品唯一ID时,此时将该字段参加唯一标识字符串中即可区分。近来那块还未做连锁处理,这里只是提供三个总结的搞定思路。

>③ 、无埋点的采集的完结

3.1 AOP 简介

下边讲一下无埋点的具体贯彻,用到的重假使AOP(Aspect-Oriented-Programming),面向切面编程,面对的是处理进程中的有些步骤和格局。在运作时,动态的将代码插入到类的制定措施、指定地点上的编程思想就是面向切面编程。纯熟iOS
Runtime的应有很驾驭,相关的介绍文章也很多,那里不再过多的废话。

HubbleData无埋点的贯彻重点就是借助AOP,hook对应类的办法,并在原完结代码的底子上插入自个儿定义的埋点的代码,当该类的被hook的函数执行时,就能完毕无埋点数据收集的出力。下边给出哈勃勒Data里面Method
Swizzling的二个简约的贯彻。

Method Swizzling

上述代码只是给出了1个回顾的贯彻的逻辑结构,new_swizzledMethod也只是selector没有参数的动静(除去self和_cmd),真正在埋点的处理进程需求考虑的图景比较多。

3.2 UIViewController的无埋点采集

要害是收集页面的生命周期,那里哈勃勒Data选用的是hook
UIViewController的view威尔Appear方法,依照3.1付给的主意:

 [DASwizzler swizzleBoolSelector:@selector(viewWillAppear:)
                         onClass:[UIViewController class]
                       withBlock:executeAppearBlock];

当view威尔Appear函数执行时,插入埋点的代码。哈勃勒Data的统筹艺术为:

伊芙ntID设置为一定的da_screen,即不会经过伊夫ntID来不同种种页面的新闻,哈勃勒Data将相继页面的界别音讯放在了properties中,其中properties的安装为:

(1) $screenName 为当前页面的名称;
(2) $screenTitle 为当前页面的title,可为空;

并且哈勃勒Data SDK提供了八个protocol <DAScreenAutoTracker>

即用户可以透过兑现该protocol,哈勃勒Data
SDK会将screenTitle重返的值作为页面的名号,trackProperties重返的性质参加对应页面的da_screen事件的性质中,作为用户访问该页面时的轩然大波性质,screenUrl再次回到的字符串作为页面的Url,用于做一些页面之间相互跳转的辨析等。

再就是增添了白名单设置,有一些UIViewController的信息用户不想采访,可以由此设置白名单的措施,将部分不想征集的UIViewController过滤掉,比如说SFBrowserRemoteViewController,UIInputWindowController等种类自带的某些。

说到底会调用track伊夫nt记录该征集的事件,同上述介绍的代码埋点一样,调用的点子如下:

[[DATracker sharedTracker] trackScreenEvent:@“da_screen” withAttributes:properties];

里头properties即为上述要采访的局地品质。

3.3 UIControl的无埋点采集

针对UIControl,哈勃勒Data采取的是hook
UIControl的sendAction:to:for伊夫nt:方法。由官方文档可见,在UIControl执行相应的action时都会首先调用sendAction:to:for伊夫nt:方法,达成如下:

control

考虑到UIControl的子类较多,所以哈勃勒Data选择了内部使用较多的二种举行了独特的辨析:主假若UITextField、UIButton和UISwitch,其他的一时未做特别分析。具体的埋点的采访安插为:

任凭哪一类UIControl,伊夫ntID均采纳的是第二部分介绍的唯一标识字符串的SHA256编码值,不过相关采访properties有所出入。

3.3.1 UITextField

UIText菲尔德是UIControl的2个子类,由于UITextField涉及到用户的隐情相比较多,比如用户名、密码、聊天文本等,所以HubbleData不会对该类的UITextField举办埋点的采集。

哈勃勒Data首要收集的是UISearchBar中的UITextField,即UISearchBarTextField,并获取搜索的公文内容,那对于一些电商类的App来说,能够较好的辨析用户感兴趣的货色等,这是作为哈勃勒Data
SDK无埋点的一个急需。

hook住sendAction:to:forEvent:后,如果对UISearchBarTextField的所有actions都进行hook的话,那么_searchFieldBeginEditing、_searchFieldEnd艾德iting等具有的action产生的时候都会进行多少的采访,会征集到不少无效的音信,导致采集的数码错乱。哈勃勒Data
SDK唯有当_searchFieldEndEditing
action爆发时才会展开埋点,收集的properties为:

(1) type 为UIControl采集的事件类型,这里设置为searchBarEvent;
(2) page 为当前页面的名称,用于前端显示用;
(3) searchText 为_searchFieldEndEditing发生时采集到搜索框的搜索文字(此字段不为空);

如此就能对搜索框进行无埋点采集,并能收集搜索的公文内容。此方法只是在_searchFieldEnd艾德iting暴发时采访数据,有或然该action执行风尚未尽兴真正的搜寻操作,或许会与业务数据库的数额有出入,可是也可以比较准确的分析用户感兴趣的查找内容。

3.3.2 UIButton

UIControl中应用最多最广大的是UIButton,由此对UIButton的募集极度重大。在拔取UIButton的时候可以无限制的安装其title等脾气来表示事情逻辑的差距景况。那里可以举二个回顾的例证:基本app的报到页面,在用户名和密码都未输入时、都输入时以及登录中逐一状态,登录按钮的title、titleColor等个性恐怕都以不一样的,即每种button的样式都意味着一种体制,不过得到的伊芙ntID是千篇一律的。针对此种景况,哈勃勒Data会加盟title、titleColor作为属性值,以利于后台举办更为的解析。

当按钮的二种意况只是三种不相同的背景图片时,比如和讯依旧微信的点赞等,其实是更换了一种背景图片,针对对那种景况处理,哈勃勒Data则会得到图片的imageName作为其中壹性情能。

(1) type 为UIControl采集的事件类型,这里设置为buttonEvent;
(2) page 为当前页面的名称,用于前端显示用;
(3) title 为当前按钮的title;
(4) titleColor 为当前title的color,会转换成字符串的形式,rgba(r, g, b, alpha);
(5) imageName 为当前按钮的背景图片的name;
(6) frame 为UIButton的frame,用于分析同类元素,会转换成字符串的形式,rect(x, y, width, height);

可以看出,哈勃勒Data还搜集了该view的frame信息,紧借使用来分析同类成分用的,下图给出三个简便的言传身教:

button

近期有几个已关心的出品,当想计算用户拥有点赞的轩然大波时,由于各样点赞的按钮都远在三个UITableViewCell中,在前边介绍的收获层级唯一路径UITableViewCell时的特有处理,由于各个按钮所在的cell的row不同,所以博得的每一个按钮的风浪的唯一EventID都是例外的,那样后端在解析的时候,不可能归类同类成分。当哈勃勒Data给出frame时,后端能够依照frame归类出同一类按钮的轩然大波,具体的归类策略那里不再介绍。

3.3.3 UISwitch

看似于UIButton,只然而那里要采访switchState,即日前的开关状态,具体的收集属性为:

(1) type 为UIControl采集的事件类型,这里设置为switchEvent;
(2) page 为当前页面的名称,用于前端显示用;
(3) switchState 为switch的开关状态;
3.3.4 其余UIControl

其他的只是收集type,page属性,近年来未做过多的拍卖。

3.4 UITableView和UICollectionView的无埋点采集

针对UITableView和UICollectionView,哈勃勒Data选择的是先hook
UITableView和UICoolectionView的setDelegate:方法,然后找到呼应的delegate,然后再hook
delegate类中的tableView:didSelectRowAtIndexPath:方法和UICollectionView的collectionView:didSelectItemAtIndexPath:方法。那里以UITableView为例:

tableview

伊芙ntID按照上述介绍的法子得到,只但是这里要留心的是,获取的并不是UITableView的绝无仅有标识字符串而是对应的点击的cell的唯一标识字符串。采集的properties为:

(1) type 为UITableView采集的事件类型,这里设置为tableViewSelectEvent;
(2) page 为当前页面的名称,用于前端显示用;
(3) section 为点击的cell所在的section;
(4) row 为点击的cell所在的row;

3.5 UIGestureRecognizer的无埋点采集

在iOS开发中,日常会接纳一些手势来拍卖部分点击的操作,所以也有必不可少对UIGestureRecognizer进行hook。哈勃勒Data
并不是直接针对UIGestureRecognizer这么些类举行hook,而是hook
UIView类的addGestureRecognizer:方法,已毕如下:

gesture

通过hook
addGestureRecognizer:方法,可以拿到该UIView所添加的UIGestureRecognizer,那里只对UITapGestureRecognizer和UILongPressGestureRecognizer进行拍卖,其他的手势暂未做处理。拿到相应的UIGestureRecognizer,添加多个action,当该手势执行的时候,同样会履行该action,在action中执行埋点的操作。

那边得到的是UIGestureRecognizer所在的UIView的绝无仅有标识标识字符串编码作为伊夫ntID,采集的属性为:

(1) type 为UIGestureRecognizer采集的事件类型,这里设置为gestureTapEvent;
(2) page 为当前页面的名称,用于前端显示用;

UIAlertController的相当处理

此间需求对UIAlertController做二个详实的验证,因为UIAlertController在点击诸如打消、鲜明的选项按钮时,也会进行手势的埋点采集,然而在iOS9和iOS10上稍加某些分裂。

那里先以iOS9为例,其target是功能在_UIAlertControllerView这些体系的私有类上的,如若直接对这么些_UIAlertControllerView举办唯一标识字符串的构造,则打消和明确选项得到的伊芙ntID是同等的,那样将不大概精确的解析出用户的精选,所以必须以每一种选项view作为单身的绝无仅有标识字符串举行辨析才能纯粹区分。通过拿到_UIAlertControllerView的_actionViews变量,就能拿到各样选项的view,那里要做二个简单易行的点击坐标获取,判断所点击的区域位于的actionView,具体落到实处如下:

这里在原则判断时设定gesture.state ==
UIGestureRecognizerStateBegan,是由于UILongPressGestureRecognizer会延续四次调用action,因而这里必要投入事件的景况进行区分,幸免举行一次相同的数目搜集。

iOS10下的UIAlertController的中间贯彻做了一些改观,其target变换到在_UIAlertControllerInterfaceActionGroupView这几个种类的私有类上的,然后须要开展自然的拍卖,获取UIInterfaceActionSelectionTrackingController的_representationViews变量,遍历得到种种选项的view,具体落实如下:

透过上述的剖析可以窥见,这样即便能分别同2个UIAlertController的不等的操作选项,但是只怕不可以区分出分歧UIAlertController的介乎相同地方的选项,所以那里还要投入UIAlertController额外的习性新闻来分别。

后边也有提过,可以很不难的想到UIAlertController的message和title可以较好的展开区分,所以在原始的层级路径和脚下页面的底子上,还要加上message和title以整合唯一标识字符串。给出3个样例:

path(UIWindow(0)__UIAlertControllerView(0)_UIView(0)_UIView(0)_UIView(0)_UICollectionView(0)__UIAlertControllerCollectionViewCell(section:0 item:0)_UIView(0)__UIAlertControllerActionView(0))&controller(UIAlertController)&message(确认退出群聊吗?)&title(退群)

四、总结

小说主要介绍了哈勃勒Data无埋点SDk在iOS端的设计与落到实处,涉及的最重要内容:事件唯一ID的规定和有些无埋点的落到实处,当然在无埋点SDK的规划开发中还碰到了五花八门的题材。鉴于小说的篇幅已经较长,一些标题标消除以及关键技术的落到实处,比如精准渠道追踪、hook争执解决、代码埋点的已毕、显示屏种类化以及可视化圈选部分的情节,本篇小说不再介绍,将会在屡次三番小说中继承介绍。