前段時間,蘋果終於在大陸區開放了應用商店的競價廣告。毫無疑問又開啟了蘋果應用導量的新玩法,各大廠商都緊跟腳步吃螃蟹。本篇講解蘋果廣告中的歸因部分。

蘋果廣告其實在海外已執行多年,而因為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獲取,要等待彈窗被使用者授權後才能得到,所以需要延遲呼叫廣告歸因和啟用日誌:

  1. +(void)initSDK{
  2. //... ...
  3. //蘋果ASA;延遲4秒再發送,等ATT使用者操作結果,可能有IDFA
  4. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  5. [MySDK LogAds];
  6. });
  7. //啟用日誌;延遲6秒再發送,先讓Ads傳送完再發
  8. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  9. [MySDK LogOpen];
  10. });
  11. //... ...
  12. }

二、與第三方廣告的歸因的區別

1、第三方廣告(如頭條快手)使用的是廣告點選的監測短鏈,由廣告商回傳給我們後臺;蘋果採用的是iAd和AdServices,由接入的蘋果SDK傳送引數到我們後臺;

第三廣告的監測短鏈示例:

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

蘋果ASA的客戶端回傳示例:

  1. 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)

  1. /** 匯入上述3個框架*/
  2. #import <iAd/iAd.h>
  3. #import <AdServices/AdServices.h>
  4. #import <AppTrackingTransparency/AppTrackingTransparency.h>
  5.  
  6. /** 蘋果Ads廣告*/
  7. /** TODO:有些舊裝置新系統,會出現token為空的問題*/
  8. +(void)LogAds{
  9. // 14.3之後
  10. if (@available(iOS 14.3, *)) {
  11. NSError *error;
  12. NSString *token = [AAAttribution attributionTokenWithError:&error];
  13. NSLog(@"LogAds:AdServces,Token: %@", token);
  14. if (token != nil) {
  15. // 1、傳送POST給蘋果得到歸因資料
  16. [MySDK sendToken:[MySDK getANullableString:@"token" content:token] completeBlock:^(NSDictionary *attrData) {
  17. //非同步,會延後
  18. NSLog(@"LogAds:14.3+ Dict: %@", attrData);
  19. //TODO::傳送資料給服務端
  20. // ... ...
  21. }];
  22. }
  23.  
  24. // 14.3之前
  25. } else {
  26. if ([[ADClient sharedClient] respondsToSelector:@selector(requestAttributionDetailsWithBlock:)]) {
  27. NSLog(@"LogAds:iAd called");
  28. [[ADClient sharedClient] requestAttributionDetailsWithBlock:^(NSDictionary *attrData, NSError *error) {
  29. //非同步,會延後
  30. NSLog(@"LogAds:14- Dict: %@", attrData);
  31. //TODO::傳送資料給服務端
  32. // ... ...
  33. }];
  34. }
  35. }
  36. }
  37.  
  38. /** 讀取可能為空的字串*/
  39. +(nullable NSString *)getANullableString:(NSString *)desc content:(NSString *)content{
  40. if(content == nil){
  41. return @"";
  42. }
  43. return [NSString stringWithFormat:@"%@", content];
  44. }
  45.  
  46. /** 傳送歸因token得到資料 */
  47. +(void)sendToken:(NSString *)token completeBlock:(void(^)(NSDictionary* data))completeBlock{
  48. NSString *url = [NSString stringWithFormat:@"https://api-adservices.apple.com/api/v1/"];
  49. NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
  50. request.HTTPMethod = @"POST";
  51. [request addValue:@"text/plain" forHTTPHeaderField:@"Content-Type"];
  52. NSData* postData = [token dataUsingEncoding:NSUTF8StringEncoding];
  53. [request setHTTPBody:postData];
  54. NSURLSession *session = [NSURLSession sharedSession];
  55. NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
  56. NSDictionary * result = NULL;
  57. if (error) {
  58. //請求失敗
  59. NSLog(@"LogAds:sendToken ERR");
  60. if (completeBlock) {
  61. NSMutableDictionary *nulldict = [NSMutableDictionary dictionary];
  62. completeBlock(nulldict);
  63. }
  64. }else{
  65. // 請求成功
  66. NSError *resError;
  67. NSMutableDictionary *resDic = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&resError];
  68. result = [[NSDictionary alloc] initWithDictionary:resDic];
  69. if (completeBlock) {
  70. completeBlock(result);
  71. }
  72. }
  73. }];
  74. [dataTask resume];
  75. }

至此,蘋果ASA的廣告歸因接入告一段落

待後臺對接好廣告歸因邏輯程式碼,蘋果包上架應用商店,就可以了。

附:IDFA的新舊版本的接入

  1. #import <AppTrackingTransparency/AppTrackingTransparency.h>
  2.  
  3. -(void)initSDK{
  4. //... ...
  5. //IDFA iOS14不同方式
  6. if (@available(iOS 14, *)) {
  7. // iOS14及以上版本需要先請求許可權
  8. [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
  9. // 獲取到許可權後,依然使用老方法獲取idfa
  10. // iOS14以後,idfa在回撥之後才能獲得,應當等回撥後再發送日誌
  11. if (status == ATTrackingManagerAuthorizationStatusAuthorized) {
  12. self->_idfa = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString];
  13. }
  14. }];
  15. }else{
  16. _idfa = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
  17. }
  18. //... ...
  19. }
  1.