要作数据分析不外乎就两种,一种服务器经过接口调用状况统计,另一种就是前端埋点统计,固然前端埋点统计能够更精准的统计更多数据信息~html
大体分为三种,代码埋点、可视化埋点,无埋点前端
很简单明了就是在须要统计埋点的控制器和按钮事件等地方作好埋点处理git
根据标识来识别每个事件, 针对指定的事件进行取参埋点。而事件的标识与参数信息都写在配置表中,经过动态下发配置表来实现埋点统计github
无埋点是指开发人员集成采集 SDK 后,SDK 便直接开始捕捉和监测用户在应用里的全部行为,并所有上报,不须要开发人员添加额外代码json
想关于这三种的介绍,网上资料一大堆,感兴趣的朋友能够本身去搜索看看,安全
美团点评前端无痕埋点实践服务器
下面是一个很简单的统计用户浏览埋点方式,其实就是利用Runtime交换viewDidLoad
方法markdown
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
kMethodSwizzling(self.class, @selector(viewDidLoad), @selector(kj_viewDidLoad));
});
}
- (void)kj_viewDidLoad{
[self kj_viewDidLoad];
NSString *clazz = NSStringFromClass([self class]);
NSDictionary *dict = @{
@"userid":KJHookInfo.shared.userid,
@"viewController":clazz
};
NSString *parameter = dict.jsonString.kj_aesEncryptKey(@"key");
//TODO:上传数据
}
复制代码
升级一下,浏览指定控制器埋点,经过接口动态返回须要统计的界面控制器,储存在hookViewControllers
,而后统计网络
- (void)kj_viewDidLoad{
[self kj_viewDidLoad];
NSString *clazz = NSStringFromClass([self class]);
BOOL isHook = ({
BOOL isHook = NO;
for (NSString *name in KJHookInfo.shared.hookViewControllers) {
if ([name isEqualToString:clazz]) {
isHook = YES;
break;
}
}
isHook;
});
if (isHook) {
NSDictionary *dict = @{
@"userid":KJHookInfo.shared.userid,
@"viewController":clazz
};
NSString *parameter = dict.jsonString.kj_aesEncryptKey(@"key");
//TODO:上传数据
}
}
复制代码
再介绍一个统计页面停留时长的埋点处理 简单讲就是交换viewWillAppear:
和viewDidDisappear:
app
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
kMethodSwizzling(self.class, @selector(viewWillAppear:), @selector(kj_viewWillAppear:));
kMethodSwizzling(self.class, @selector(viewDidDisappear:), @selector(kj_viewDidDisappear:));
});
}
- (void)kj_viewWillAppear:(BOOL)animated{
[self kj_viewWillAppear: animated];
// 记录进入时间
KJHookInfo.shared.time = CFAbsoluteTimeGetCurrent();
}
- (void)kj_viewDidDisappear:(BOOL)animated{
[self kj_viewDidDisappear: animated];
NSString *clazz = NSStringFromClass([self class]);
BOOL isHook = ({
BOOL isHook = NO;
for (NSString *name in KJHookInfo.shared.hookViewControllers) {
if ([name isEqualToString:clazz]) {
isHook = YES;
break;
}
}
isHook;
});
if (isHook) {
NSTimeInterval time = CFAbsoluteTimeGetCurrent() - KJHookInfo.shared.time;
NSDictionary *dict = @{
@"userid":KJHookInfo.shared.userid,
@"time":time,
@"viewController":clazz
};
NSString *parameter = dict.jsonString.kj_aesEncryptKey(@"key");
//TODO:上传数据
}
}
复制代码
大多数可点击UI控件都是基于UIControl,核心仍是交互方法sendAction:to:forEvent:
,下面提供一种统计到某个具体页面的按钮
@implementation UIControl (KJHook)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
kMethodSwizzling(self.class, @selector(sendAction:to:forEvent:), @selector(kj_sendAction:to:forEvent:));
});
}
- (void)kj_sendAction:(SEL)action to:(nullable id)target forEvent:(nullable UIEvent *)event {
[self kj_sendAction:action to:target forEvent:event];
_weakself;
kGCD_async(^{
if ([NSStringFromClass(weakself.class) isEqualToString:@"UIButton"]) {
void (^kDealButton)(NSString *) = ^(NSString *clazz){
NSDictionary *dict = @{
@"userid":@"userid",
@"centerX":[NSString stringWithFormat:@"%.2f",weakself.centerX],
@"centerY":[NSString stringWithFormat:@"%.2f",weakself.centerY],
@"viewController":clazz
};
NSString *parameter = dict.jsonString.kj_aesEncryptKey(@"key");
NSLog(@"%@",parameter);
//TODO:上传数据
};
kGCD_main(^{
kDealButton(NSStringFromClass([[target viewController] class]));
});
}
});
}
@end
复制代码
这里若是想更准确,还可给每一个按钮编tag值,固然这个工程量就比较大,这边只是提供思路,具体怎么作示实际状况为准
这里值得一提的就是,在交换方法的时候,必定要全局查询是否命名冲突(有没有方法名重复),不然可能会出现你埋点的方法压根不执行,原理能够参考我另一篇关于Category介绍的文章iOS Category类别的使用及工具封装
一般咱们埋好点以后,采起的方式都是调用服务器的一个指定接口,可是有一个缺陷就是在高峰期时刻访问量会很是巨大,就有超出服务器范围的可能
先来介绍网址连接的构成,https://upload-images.jianshu.io/upload_images/1933747-82138031f05852ab.gif?tR8XBkv3BaBjjEeck9VbeiZauP73MdXWlhvmUq+BAFY=
scheme:https
host:upload-images.jianshu.io
path:/upload_images/1933747-82138031f05852ab.gif
query:tR8XBkv3BaBjjEeck9VbeiZauP73MdXWlhvmUq+BAFY=
复制代码
正常咱们访问一张图片,其实只须要scheme://
+ host
+ path
三部分就能够正常访问
可是下面这张格式组成 scheme://
+ host
+ path
+ ?
+ query
也是能够正常访问
因此咱们能够将埋点信息放在query
当中,而后只须要统计这张图片的访问记录就能够简单快捷的拿到埋点的内容
1像素
的图片,这样也不会怎么占用服务器的带宽NSDictionary *dict = @{@"app":@"appname"};
NSString *parameter = dict.jsonString.kj_aesEncryptKey(@"key");
复制代码
一样也是能够访问到图片地址 https://upload-images.jianshu.io/upload_images/1933747-82138031f05852ab.gif?tR8XBkv3BaBjjEeck9VbeiZauP73MdXWlhvmUq+BAFY=
咱们都知道访问获得的图片都是data数据,那么咱们是否也能够把咱们想要反馈给客户端的数据藏于data当中解析呢?
那么你们还有什么比较优秀的埋点方式呢?欢迎分享,谢谢~
pod 'KJEmitterView'
引入便可