美文网首页iOS开发知识小集
ios -无埋点用户行为数据收集

ios -无埋点用户行为数据收集

作者: child_cool | 来源:发表于2018-11-19 10:21 被阅读45次
af 的方法交换处理
static inline void af_swizzleSelector(Class class, SEL originalSelector, SEL swizzledSelector) {
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
    if (class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))) {
        class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }

}

数据采集

  • uiviewcontroller的生命周期,用于测算页面停留时间加载时间等

1.viewDidAppear上报页面进入事件。
2.viewDidDisappear上报页面退出事件
即可得出用户访问页面路径,两个事件时间戳之差即为用户在页面停留的时间。

统计数据字段
1.PAGE_ID,当前页面的标识。 【一般用类名】
2.SOURCE_ID,当前页面的前一个页面的标识。【获取上一个页面的类名】
3.TYPE_ID,当前页面一些关键信息。
4.TIMESTAMP,当前事件生成的时间戳。
5.页面进入和退出的事件,均上报上述的数据结构。
6.跟进上面的记录通过计算可以获得VC的路径

+ (void)install {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [Tool replaceImplementationOfKnownSelector:@selector(viewDidAppear:) onClass:[self class]];
        [Tool replaceImplementationOfKnownSelector:@selector(viewDidDisappear:) onClass:[self class]];
    });
}

- (void)br_viewDidAppear:(BOOL)animated {
    NSLog(@"[%@--%@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
    [self br_viewDidAppear:animated];
}


- (void)br_viewDidDisappear:(BOOL)animated {
    NSLog(@"[%@--%@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
    [self br_viewDidDisappear:animated];
}
  • UIControl(UISwitch,UIStepper,UISegmentedControl, UINavigationButton,UISlider,UIButton)类控件的点击事件
+ (void)install {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [Tool replaceImplementationOfKnownSelector:@selector(sendAction:to:from:forEvent:) onClass:[self class]];
    });
}

- (BOOL)br_sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event {
    
    NSLog(@"=====");
    
    return [self br_sendAction:action to:target from:sender forEvent:event];
}
  • UIView上的GestureRecognizer触摸事件
 在uiview的分类中添加target
#import <objc/runtime.h>
+ (void)startTracker {
    Method addGestureRecognizerMethod = class_getInstanceMethod(self, @selector(addGestureRecognizer:));
    Method ddAddGestureRecognizerMethod = class_getInstanceMethod(self, @selector(dd_addGestureRecognizer:));
    method_exchangeImplementations(addGestureRecognizerMethod, ddAddGestureRecognizerMethod);
}

- (void)test:(UIGestureRecognizer *)gest {
    
}

- (void)dd_addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
    
    [gestureRecognizer addTarget:self action:@selector(test:)];
    
    [self dd_addGestureRecognizer:gestureRecognizer];

  • UICollectionView和UITableView的cell点击事件
@implementation UITableView (DDAutoTracker)

+ (void)startTracker {
    Method setDelegateMethod = class_getInstanceMethod(self, @selector(setDelegate:));
    Method ddSetDelegateMethod = class_getInstanceMethod(self, @selector(dd_setDelegate:));
    method_exchangeImplementations(setDelegateMethod, ddSetDelegateMethod);
}

- (void)dd_setDelegate:(id <UITableViewDelegate>)delegate {
    
    //只监听UITableView
    if (![self isMemberOfClass:[UITableView class]]) {
        return;
    }
    
    [self dd_setDelegate:delegate];
    
    if (delegate) {
        Class class = [delegate class];
        SEL originSelector = @selector(tableView:didSelectRowAtIndexPath:);
        SEL swizzlSelector = NSSelectorFromString(@"dd_didSelectRowAtIndexPath");
        BOOL didAddMethod = class_addMethod(class, swizzlSelector, (IMP)dd_didSelectRowAtIndexPath, "v@:@@");
        if (didAddMethod) {
            Method originMethod = class_getInstanceMethod(class, swizzlSelector);
            Method swizzlMethod = class_getInstanceMethod(class, originSelector);
            method_exchangeImplementations(originMethod, swizzlMethod);
        }
    }
}

void dd_didSelectRowAtIndexPath(id self, SEL _cmd, id tableView, NSIndexPath *indexpath) {
    SEL selector = NSSelectorFromString(@"dd_didSelectRowAtIndexPath");
    ((void(*)(id, SEL,id, NSIndexPath *))objc_msgSend)(self, selector, tableView, indexpath);
    
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexpath];
    
    NSString *targetString = NSStringFromClass([self class]);
    NSString *actionString = NSStringFromSelector(_cmd);
    
    NSString *eventId = [NSString stringWithFormat:@"%@&&%@",targetString,actionString];
    NSDictionary *infoDictionary = [cell ddInfoDictionary];
    
    [[DDAutoTrackerOperation sharedInstance] sendTrackerData:eventId
                                                        info:infoDictionary];
}

@end
@implementation UICollectionView (DDAutoTracker)

+ (void)startTracker {
    Method setDelegateMethod = class_getInstanceMethod(self, @selector(setDelegate:));
    Method ddSetDelegateMethod = class_getInstanceMethod(self, @selector(dd_setDelegate:));
    method_exchangeImplementations(setDelegateMethod, ddSetDelegateMethod);
}

- (void)dd_setDelegate:(id <UICollectionViewDelegate>)delegate {
    
    //只监听UICollectionView
    if (![self isMemberOfClass:[UICollectionView class]]) {
        return;
    }
    
    [self dd_setDelegate:delegate];
    if (delegate) {
        Class class = [delegate class];
        SEL originSelector = @selector(collectionView:didSelectItemAtIndexPath:);
        SEL swizzlSelector = NSSelectorFromString(@"dd_didSelectItemAtIndexPath");
        BOOL didAddMethod = class_addMethod(class, swizzlSelector, (IMP)dd_didSelectItemAtIndexPath, "v@:@@");
        if (didAddMethod) {
            Method originMethod = class_getInstanceMethod(class, swizzlSelector);
            Method swizzlMethod = class_getInstanceMethod(class, originSelector);
            method_exchangeImplementations(originMethod, swizzlMethod);
        }
    }
}

void dd_didSelectItemAtIndexPath(id self, SEL _cmd, id collectionView, NSIndexPath *indexpath) {
    SEL selector = NSSelectorFromString(@"dd_didSelectItemAtIndexPath");
    ((void(*)(id, SEL,id, NSIndexPath *))objc_msgSend)(self, selector, collectionView, indexpath);
    
    UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexpath];
    
    NSString *targetString = NSStringFromClass([self class]);
    NSString *actionString = NSStringFromSelector(_cmd);
    
    NSString *eventId = [NSString stringWithFormat:@"%@&&%@",targetString,actionString];
    NSDictionary *infoDictionary = [cell ddInfoDictionary];
    
    [[DDAutoTrackerOperation sharedInstance] sendTrackerData:eventId
                                                        info:infoDictionary];
}

@end
  • UITabBar、UIAlertView、UIActionSheet等的点击事件
hook delegate 然后hook点击事件的代理方法
唯一标识 使用title message 按钮内容 再加上路径
ios 9
if ([NSStringFromClass([view class]) isEqualToString:@"_UIAlertControllerView"]) {
    Ivar ivar = class_getInstanceVariable([view class], "_actionViews");
    NSMutableArray *actionviews =  object_getIvar(view, ivar);
    for (UIView *actionview in actionviews) {
        CGPoint point = [gesture locationInView:actionview];
        if ([NSStringFromClass([actionview class]) isEqualToString:@"_UIAlertControllerActionView"] &&
            point.x > 0 && point.x < CGRectGetWidth(actionview.bounds) &&
            point.y > 0 && point.y < CGRectGetHeight(actionview.bounds) &&
            gesture.state == UIGestureRecognizerStateBegan) {
           .........  //进行埋点操作
        }
    }
}
ios 10
if ([NSStringFromClass([view class]) isEqualToString:@"_UIAlertControllerInterfaceActionGroupView"]) {
    NSMutableArray *targets = [gesture valueForKey:@"_targets"];
    id targetContainer = targets[0];
    id targetOfGesture = [targetContainer valueForKey:@"_target"];
    if ([targetOfGesture isKindOfClass:[NSClassFromString(@"UIInterfaceActionSelectionTrackingController") class]]) {
        Ivar ivar = class_getInstanceVariable([targetOfGesture class], "_representationViews");
        NSMutableArray *representationViews =  object_getIvar(targetOfGesture, ivar);
        for (UIView *representationView in representationViews) {
            CGPoint point = [gesture locationInView:representationView];
            if ([NSStringFromClass([representationView class]) isEqualToString:@"_UIInterfaceActionCustomViewRepresentationView"] &&
                point.x > 0 && point.x < CGRectGetWidth(representationView.bounds) &&
                point.y > 0 && point.y < CGRectGetHeight(representationView.bounds) &&
                gesture.state == UIGestureRecognizerStateBegan) {
                .........  //进行埋点操作
                }
            }
    }
}
#import <objc/runtime.h>
#import <objc/message.h>
#import "DDAutoTrackerOperation.h"
#import "NSObject+DDAutoTracker.h"

@implementation UIAlertView (test)

+ (void)load {
    [self startTracker];
}

+ (void)startTracker {
    Method setDelegateMethod = class_getInstanceMethod(self, @selector(setDelegate:));
    Method ddSetDelegateMethod = class_getInstanceMethod(self, @selector(dd_setDelegate:));
    method_exchangeImplementations(setDelegateMethod, ddSetDelegateMethod);
}

- (void)dd_setDelegate:(id <UIAlertViewDelegate>)delegate {
    
    //只监听UICollectionView
    if (![self isMemberOfClass:[UIAlertView class]]) {
        return;
    }
    
    [self dd_setDelegate:delegate];
    if (delegate) {
        Class class = [delegate class];
        SEL originSelector = @selector(alertView:clickedButtonAtIndex:);
        SEL swizzlSelector = NSSelectorFromString(@"br_clickedButtonAtIndex");
        BOOL didAddMethod = class_addMethod(class, swizzlSelector, (IMP)br_clickedButtonAtIndex, "v@:@@");
        if (didAddMethod) {
            Method originMethod = class_getInstanceMethod(class, swizzlSelector);
            Method swizzlMethod = class_getInstanceMethod(class, originSelector);
            method_exchangeImplementations(originMethod, swizzlMethod);
        }
    }
}



void br_clickedButtonAtIndex(id self, SEL _cmd, id alertView, NSInteger buttonIndex) {
    SEL selector = NSSelectorFromString(@"br_clickedButtonAtIndex");
    ((void(*)(id, SEL,id, NSInteger))objc_msgSend)(self, selector, alertView, buttonIndex);

    NSLog(@"hook 点击的第几个 %ld", buttonIndex);
 }


@end
  • RN采集

  • app内OpenURL 主要是应用直接的跳转回调等

hook UIApplicationDelegate协议对象,直接hook appdelegate或者写它的分类,可能会失败(原因:某些用户可能会自定义文件名,默认加前缀,XXAppdelegate)
还有其生命周期方法一并hook

需要判断方法是否实现,未实现添加实现(本人一直操作失败),已实现进行交换

application:handleOpenURL:
application:openURL:options:
  • UItextview uitextfiled uisearchbar
    根据代理处理

数据缓存

  • 默认的存储模式【个人想法内存】
  • 考虑用户杀掉程序或者崩溃时数据如何持久化存储
  • 持久化保存方式【json?plist?db?】哪种性能更好?
  • 文件量限制,时间限制 【记录10条数据就开始上传一次,或者1分钟一次】
  • 缓存格式?

构建json协议

传输数据

相关文章

  • ios -无埋点用户行为数据收集

    数据采集 uiviewcontroller的生命周期,用于测算页面停留时间加载时间等 1.viewDidAppea...

  • Android全埋点

    什么是全埋点? 也叫做无埋点,预先收集用户的所有行为数据,然后根据实际需求,从中提取行为数据。 采集数据的点: $...

  • Android全埋点-页面浏览事件

    全埋点 全埋点也叫无埋点,自动埋点。是指预先自动收集用户的所有行为数据。然后就可以根据收集的数据从中筛选出所需的行...

  • iOS无埋点数据SDK的整体设计与技术实现

    iOS无埋点数据 SDK 实践之路 iOS无埋点SDK 之 RN页面的数据收集 本篇文章是讲述 iOS 无埋点数...

  • AOP无痕埋点技术

    使用AOP实现iOS应用内的埋点计数 - 简书 iOS用户行为追踪——无侵入埋点 - CSDN博客 iOS 无埋点...

  • 零侵入“无埋点”技术

    最近看了《揭开JS无埋点技术的神秘面纱》这篇文章,主要是讲解“无埋点”收集用户行为数据的技术要点,作者在最后总结时...

  • for OM——搭建数据化用户运营体系

    一、用户数据收集 1 用户属性数据:靠填写 2 用户行为数据:靠埋点 3 用户流量数据:靠工具 二、构...

  • 数据分析工具GrowingIO

    新一代用户行为数据分析工具,通过无埋点数据采集技术获取全量的用户行为数据,支持web、iOS、Android、微信...

  • iOS 最优无痕埋点方案

    iOS 最优无痕埋点方案 在移动互联网时代,对于每个公司、企业来说,用户的行为数据非常重要。重要到什么程度,用户在...

  • 埋点设计-埋点基础知识总结

    1 什么是埋点 (1)从功能上来讲,埋点就是用来收集用户行为数据的。一个用户在app里面干了什么,看了哪些页面,点...

网友评论

    本文标题:ios -无埋点用户行为数据收集

    本文链接:https://www.haomeiwen.com/subject/mffufqtx.html