前段時間,蘋果終於在大陸區開放了應用商店的競價廣告。毫無疑問又開啟了蘋果應用導量的新玩法,各大廠商都緊跟腳步吃螃蟹。本篇講解蘋果廣告中的歸因部分。
蘋果廣告其實在海外已運行多年,而因為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]; } //... ... }