• 苹果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

  • 相关阅读:
    Linux .o a .so .la .lo的区别
    linux源码Makefile详解
    Kconfig详解
    如何将驱动程序静态编译进内核
    getpeername
    Socket programming in C on Linux | tutorial
    C Socket Programming for Linux with a Server and Client Example Code
    UDP protocol
    TCP protocol
    How to learn linux device driver
  • 原文地址:https://www.cnblogs.com/batsing/p/asa.html
Copyright © 2020-2023  润新知