苹果ASA广告投放归因的接入

前段时间,苹果终于在大陆区开放了应用商店的竞价广告。毫无疑问又开启了苹果应用导量的新玩法,各大厂商都紧跟脚步吃螃蟹。本篇讲解苹果广告中的归因部分。

苹果广告其实在海外已运行多年,而因为IDFA的政策变动,现在苹果有新旧两套归因框架,通常我们都要接入。

一、iAd 和 AdServices 框架概述

iAd 框架:适用于iOS14.3以下版本,基于IDFA,需要用户允许使用IDFA。尤其iOS14.0起,IDFA的政策变动,要接入ATT追踪框架。

  归因流程:打开APP -> 调用iAd框架 -> 读取广告因素(JSON) -> 发送广告因素到后端 -> 发送激活日志到后端

AdServices 框架:适用于iOS14.3及以上版本,不需用户授权。

  归因流程:打开APP -> 调用AdServices框架 -> 读取token -> 发送token到苹果后端换取广告因素(JSON) -> 发送广告因素到后端 -> 发送激活日志到后端

两框架在流程上区别不大,得到数据也类似,主要区别是AdServices只有ID,没有具体的名字。详细JSON字段:

两套框架都要接,详细区别不大,主要是跟iOS版本相关

区别 iAd AdServices
归因窗口期 30天 30天
ATT影响 支持ATT Opt-In 不影响
归因误差率 15%-70%不等 10%左右或更低
数据延迟 三方MMP数据称3秒内返回结果比例大于50% 三方MMP数据称延迟0.5-1秒
参数丰富度 较全 较少(只返回ID)
是否支持展示归因和指纹信息归因 不支持 不支持
是否支持非AppStore上架APP(越狱包) 不支持 不支持

▲▲▲高版本(14.5+)的idfa获取,要等待弹窗被用户授权后才能得到,所以需要延迟调用广告归因和激活日志:

+(void)initSDK{
    //... ...
    //苹果ASA;延迟4秒再发送,等ATT用户操作结果,可能有IDFA
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [MySDK LogAds];
    });
    //激活日志;延迟6秒再发送,先让Ads发送完再发
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [MySDK LogOpen];
    });
    //... ...
}

 

二、与第三方广告的归因的区别

1、第三方广告(如头条快手)使用的是广告点击的监测短链,由广告商回传给我们后台;苹果采用的是iAd和AdServices,由接入的苹果SDK发送参数到我们后台;

第三广告的监测短链示例:

https://api.myhost.com/ad/toutiao/click?adkey=abcde&idfa=__IDFA__&ip=__IP__&os=__OS__&callback=__CALLBACK__

苹果ASA的客户端回传示例:

https://api.myhost.com/ad/asa/click?idfa=xxxx&orgId=1234&campaignId=123456&adGroupId=123456&keywordId=12345678

(注意客户端回传的参数,若没有增加IP地址的参数,则需要服务端读取请求者的IP地址,以作归因参数)

2、第三方广告在点击时回传,苹果广告在应用打开时回传;

3、第三方广告使用自定义的adkey作为广告依据,苹果广告建议使用苹果的广告组ID(adGroupId)作为后台广告依据;

广告组ID可以在苹果投放后台右上角查看,如图

    

自己BI后台的广告列表示例:

广告序号 广告名称 应用 渠道 adKey标识 广告短链 渠道广告ID
12323 头条广告001 游戏A 头条1 abcde https://api.myhost.com/... (无)
12324 苹果广告001 游戏A 苹果1     123456

 

三、苹果端SDK的接入

1、准备条件,开发环境 Xcode12.3+,MacOS11+。如果版本不满足,则需更新开发软件(和系统)。

2、接入方法,添加iAd到Xcode项目:

  1)选择项目主文件 > TARGETS > General

  

  2)引入 iAd.framework、AdServices.framwork、AdSupport.framwork

  

  3)进入 Link Binary With Libraries,将上述3个框架都改为Optional

  

 

4、代码  MySDK.m(Objective-C)

/** 导入上述3个框架*/
#import <iAd/iAd.h>
#import <AdServices/AdServices.h>
#import <AppTrackingTransparency/AppTrackingTransparency.h>

/** 苹果Ads广告*/
/** TODO:有些旧设备新系统(iPhone8),会出现token为空的问题*/
+(void)LogAds{
//    14.3之后
    if (@available(iOS 14.3, *)) {
        NSError *error;
        NSString *token = [AAAttribution attributionTokenWithError:&error];
        NSLog(@"LogAds:AdServces,Token: %@", token);
        if (token != nil) {
            // 1、发送POST给苹果得到归因数据
            [MySDK sendToken:[MySDK getANullableString:@"token" content:token] completeBlock:^(NSDictionary *attrData) {
                //异步,会延后
                NSLog(@"LogAds:14.3+ Dict: %@", attrData);
                //TODO::发送数据给服务端
                // ... ...
            }];
        }

//        14.3之前
    } else {
        if ([[ADClient sharedClient] respondsToSelector:@selector(requestAttributionDetailsWithBlock:)]) {
            NSLog(@"LogAds:iAd called");
            [[ADClient sharedClient] requestAttributionDetailsWithBlock:^(NSDictionary *attrData, NSError *error) {
                //异步,会延后
                NSLog(@"LogAds:14- Dict: %@", attrData);
                //TODO::发送数据给服务端
                // ... ...
            }];
        }
    }
}

/** 读取可能为空的字符串*/
+(nullable NSString *)getANullableString:(NSString *)desc content:(NSString *)content{
    if(content == nil){
        return @"";
    }
    return [NSString stringWithFormat:@"%@", content];
}

/** 发送归因token得到数据 */
+(void)sendToken:(NSString *)token completeBlock:(void(^)(NSDictionary* data))completeBlock{
    NSString *url = [NSString stringWithFormat:@"https://api-adservices.apple.com/api/v1/"];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
    request.HTTPMethod = @"POST";
    [request addValue:@"text/plain" forHTTPHeaderField:@"Content-Type"];
    NSData* postData = [token dataUsingEncoding:NSUTF8StringEncoding];
    [request setHTTPBody:postData];
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSDictionary * result = NULL;
        if (error) {
             //请求失败
            NSLog(@"LogAds:sendToken ERR");
            if (completeBlock) {
                NSMutableDictionary *nulldict = [NSMutableDictionary dictionary];
                completeBlock(nulldict);
            }
        }else{
            // 请求成功
            NSError *resError;
            NSMutableDictionary *resDic = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&resError];
            result = [[NSDictionary alloc] initWithDictionary:resDic];
            if (completeBlock) {
                completeBlock(result);
            }
        }
    }];
    [dataTask resume];
}

 

至此,苹果ASA的广告归因接入告一段落

待后台对接好广告归因逻辑代码,苹果包上架应用商店,就可以了。

附:IDFA的新旧版本的接入

#import <AppTrackingTransparency/AppTrackingTransparency.h>

-(void)initSDK{
    //... ...
    //IDFA iOS14不同方式
    if (@available(iOS 14, *)) {
// iOS14及以上版本需要先请求权限
        [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
            // 获取到权限后,依然使用老方法获取idfa
            // iOS14以后,idfa在回调之后才能获得,应当等回调后再发送日志
            if (status == ATTrackingManagerAuthorizationStatusAuthorized) {
                self->_idfa = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString];
            }
        }];
    }else{
        _idfa = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
    }
    //... ...
}


参考博文 https://juejin.cn/post/6978116612326948894

posted @ 2021-09-17 10:48  北七星  阅读(3015)  评论(0编辑  收藏  举报
F**k me on Gitee