segment-appsflyer-ios-qa 6.14.4-rc19

segment-appsflyer-ios-qa 6.14.4-rc19

Margot GuettaMoris Gateno 维护。



  • Appsflyer

Segment 的 AppsFlyer 集成。

这是一个用 iOS SDK v6.14.4 构建的 Segment 包装器,用于 AppsFlyer SDK。

Version Carthage compatible CI - Tests


🛠 为了提供最优支持,我们恳请您将任何问题提交到 [email protected]

提交问题时,请指定您的 AppsFlyer 注册(账户)电子邮件、您的应用 ID、生产步骤、日志、代码片段以及任何其他相关信息。


目录表

  • 从版本 6.3.2 开始,我们为 iOS 平台使用 xcframework,因此您需要使用版本 >= 1.10 的 CocoaPods。

Cocoapods

要安装 segment-appsflyer-ios 集成

  1. 只需将此行添加到您的 CocoaPods Podfile

生产版本

pod 'segment-appsflyer-ios', '6.14.4'

严格模式 SDK 版本

pod 'segment-appsflyer-ios/Strict', '6.14.4'

使用严格模式 SDK 可完全删除 IDFA 收集功能和使用 AdSupport 框架的依赖(例如,当为儿童应用开发时)。

  1. 在项目目录中运行 pod install

Swift Package Manager

在 XCode 中,转到 文件 > Swift 包 > 添加包依赖... 并将 https://github.com/AppsFlyerSDK/segment-appsflyer-ios 添加为包依赖的 URL。

从版本 6.8.0 开始,我们支持手动模式,以分离 AppsFlyer SDK 的初始化和 SDK 的启动。在这种情况下,AppsFlyer SDK 不会自动启动,这为开发者提供了更多自由来启动 AppsFlyer SDK。请注意,在手动模式下,开发者需要实现 API AppsFlyerLib.shared().start() 以启动 SDK。
如果您使用 CMP 收集同意数据,则此功能是必需的。有关说明,请参阅 此处

示例

objective-c

  SEGAppsFlyerIntegrationFactory* factoryWithManualMode = [SEGAppsFlyerIntegrationFactory createWithManualMode:YES];

swift

  let factoryWithManualMode = SEGAppsFlyerIntegrationFactory.create(withManualMode: true);

请查看以下示例,了解如何使用带有代理的手动模式。
要启动 AppsFlyer SDK,请使用 start() API,如下所示

objective-c

 [[AppsFlyerLib shared] start];
 [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification object:nil queue: nil usingBlock:^(NSNotification * _Nonnull note) {
     [[AppsFlyerLib shared] start];
 }]; 

swift

 AppsFlyerLib.shared().start()
 NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: nil) { Notification in
     AppsFlyerLib.shared().start()
 }

注意 - addObserver 调用确保正确记录每个应用的启动(从后台到前台)。
请参阅更详细的说明 此处

首先,您必须在 Segment 的 仪表板 中提供 AppsFlyer Dev Key、Apple App ID(iTunes)和客户端密码的值,以进行 AppsFlyer 集成。

打开 AppDelegate.h 并添加

#import "SEGAppsFlyerIntegrationFactory.h"

AppDelegate.m 中的 didFinishLaunchingWithOptions

    // For ApsFlyer debug logs
    [AppsFlyerLib shared].isDebug = YES;
    
//    [[AppsFlyerLib shared] waitForATTUserAuthorizationWithTimeoutInterval:60];
    /*
     Based on your needs you can either pass a delegate to process deferred
     and direct deeplinking callbacks or disregard them.
     If you choose to use the delegate, see extension to this class below
     */
    SEGAppsFlyerIntegrationFactory* factoryNoDelegate = [SEGAppsFlyerIntegrationFactory instance];
//    SEGAppsFlyerIntegrationFactory* factoryWithDelegate = [SEGAppsFlyerIntegrationFactory createWithLaunchDelegate:self];

// To use the manual mode, use the following method
//    SEGAppsFlyerIntegrationFactory* factoryNoDelegate = [SEGAppsFlyerIntegrationFactory createWithManualMode:YES];
//    SEGAppsFlyerIntegrationFactory* factoryWithDelegate = [SEGAppsFlyerIntegrationFactory createWithLaunchDelegate:self andManualMode:YES];

    
    SEGAnalyticsConfiguration *config = [SEGAnalyticsConfiguration configurationWithWriteKey:@"SEGMENT_KEY"];
    [config use:factoryNoDelegate];
//    [config use:factoryWithDelegate];  // use this if you want to get conversion data in the app. Read more in the integration guide
    config.enableAdvertisingTracking = YES;       //OPTIONAL
    config.trackApplicationLifecycleEvents = YES; //OPTIONAL
    config.trackDeepLinks = YES;                  //OPTIONAL
    config.trackPushNotifications = YES;          //OPTIONAL
    [SEGAnalytics debug:YES];                     //OPTIONAL
    [SEGAnalytics setupWithConfiguration:config];

AppDelegate.m 中的 applicationDidBecomeActive

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Getting user consent dialog. Please read https://dev.appsflyer.com/hc/docs/integrate-ios-sdk#enabling-app-tracking-transparency-att-support
    if (@available(iOS 14, *)) {
        [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
            //....
        }];
    }
}
  1. 打开/创建 <Your-App-name>-Bridging-Header.h 并添加
#import "SEGAppsFlyerIntegrationFactory.h"

image

  1. 在“构建设置”>“Swift编译器-常规”>“Objective-C桥接头”下添加路径

  2. 打开 AppDelegate.swift 并添加

import Segment
import AppsFlyerLib
import segment_appsflyer_ios
  1. didFinishLaunchingWithOptions 中添加
    // For AppsFLyer debug logs uncomment the line below
    // AppsFlyerLib.shared().isDebug = true
//    AppsFlyerLib.shared().waitForATTUserAuthorization(withTimeoutInterval: 60)

    /*
     Based on your needs you can either pass a delegate to process deferred
     and direct deeplinking callbacks or disregard them.
     If you choose to use the delegate, see extension to this class below
     */
//    let factoryWithDelegate : SEGAppsFlyerIntegrationFactory = SEGAppsFlyerIntegrationFactory.create(withLaunch: self)
    let factoryNoDelegate = SEGAppsFlyerIntegrationFactory()
    
    /* If you want to use the manual mode, please use the following methods
      with or without delegate */
     //  let factoryWithDelegate : SEGAppsFlyerIntegrationFactory = SEGAppsFlyerIntegrationFactory.create(withLaunch: self, andManualMode:true)
   // let factoryNoDelegate = SEGAppsFlyerIntegrationFactory.create(withManualMode: true)
    
    
    // Segment initialization
    let config = AnalyticsConfiguration(writeKey: "SEGMENT_KEY")
//    config.use(factoryWithDelegate)  // use this if you want to get conversion data in the app. Read more in the integration guide
    config.use(factoryNoDelegate)
    config.enableAdvertisingTracking = true       //OPTIONAL
    config.trackApplicationLifecycleEvents = true //OPTIONAL
    config.trackDeepLinks = true                  //OPTIONAL
    config.trackPushNotifications = true          //OPTIONAL
    
    Analytics.debug(false)
    Analytics.setup(with: config)

applicationDidBecomeActive 中添加

func applicationDidBecomeActive(_ application: UIApplication) {
    // If you want to collect IDFA, please add the code below and read https://support.appsflyer.com//hc/en-us/articles/207032066#integration-35-support-apptrackingtransparency-att
    if #available(iOS 14, *) {
        ATTrackingManager.requestTrackingAuthorization(completionHandler: { (status) in
            // ...
        })
    }
}

AppsFlyer集成对 identify 调用做出响应。了解更多信息,请访问 Segment identify 方法文档。在 identify 调用中,在 traits 字典中使用 setCustomerUserIDcurrencyCode

为了将转换数据发送到Segment,请确保您已启用“跟踪归因数据”,并在AppsFlyer目标设置中指定了应用ID

image

要获取转换数据,您需要

  1. SEGAppsFlyerLibDelegate 协议添加到您的 AppDelegate.h(或其他)类中
#import <UIKit/UIKit.h>
#import "SEGAppsFlyerIntegrationFactory.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate, SEGAppsFlyerLibDelegate>
  1. 配置Segment分析和AppsFlyer时传递AppDelegate(或其他)类。将行 [config use:[SEGAppsFlyerIntegrationFactory instance]]; 改为 [config use:[SEGAppsFlyerIntegrationFactory createWithLaunchDelegate:self]];
  2. 在上面的方法传递的类中(默认为AppDelegate.m)实现 SEGAppsFlyerLibDelegate 协议的方法。请参见下面的示例代码
#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

-(void)onConversionDataSuccess:(NSDictionary*) installData {
    BOOL first_launch_flag = [[installData objectForKey:@"is_first_launch"] boolValue];
    NSString *status = [installData objectForKey:@"af_status"];
    
    if(first_launch_flag) {
        if ([status isEqualToString:@"Non-organic"]){
            NSString *sourceID = [installData objectForKey:@"media_source"];
            NSString *campaign = [installData objectForKey:@"campaign"];
            NSLog(@"This is a non-organic install. Media source: %@ Campaign: %@", sourceID, campaign);
        } else {
            NSLog(@"This is an organic install");
        }
    } else {
        NSLog(@"Not first launch");
    }
};

/**
 Any errors that occurred during the conversion request.
 */
-(void)onConversionDataFail:(NSError *) error {
    NSLog(@"%@", [error description]);
};

/**
 `attributionData` contains information about OneLink, deeplink.
 */
- (void)onAppOpenAttribution:(NSDictionary *)attributionData{
    NSLog(@"onAppOpenAttribution");
    for(id key in attributionData){
        NSLog(@"onAppOpenAttribution: key=%@ value=%@", key, [attributionData objectForKey:key]);
    }
};

/**
 Any errors that occurred during the attribution request.
 */
- (void)onAppOpenAttributionFailure:(NSError *)error{
    NSLog(@"%@", [error description]);
};

// Rest of your AppDelegate code

要获取转换数据,您需要

  1. SEGAppsFlyerLibDelegate 协议添加到您的 AppDelegate(或其他)类中
  2. 配置Segment分析和AppsFlyer时传递AppDelegate(或其他)类。如果您使用上面的示例代码,将 config.use(factoryNoDelegate) 修改为 config.use(factoryWithDelegate)
  3. 在作为代理传递的类中实现协议的方法。请参见以下示例代码,其中AppDelegate被用于此目的
class AppDelegate: UIResponder, UIApplicationDelegate, SEGAppsFlyerLibDelegate {
  
  var window: UIWindow?
  
  func onConversionDataSuccess(_ conversionInfo: [AnyHashable : Any]) {
      guard let first_launch_flag = conversionInfo["is_first_launch"] as? Int else {
          return
      }
      
      guard let status = conversionInfo["af_status"] as? String else {
          return
      }
      
      if(first_launch_flag == 1) {
          if(status == "Non-organic") {
              if let media_source = conversionInfo["media_source"] , let campaign = conversionInfo["campaign"]{
                  print("This is a Non-Organic install. Media source: \(media_source) Campaign: \(campaign)")
              }
          } else {
              print("This is an organic install.")
          }
      } else {
          print("Not First Launch")
      }
  }
  
  func onAppOpenAttribution(_ attributionData: [AnyHashable : Any]) {
      print("Deep Link Data goes here:")
      if let data = attributionData{
        print("\(data)")
      }
  }

 func onConversionDataFail(_ error: Error) {
      }

  func onAppOpenAttributionFailure(_ error: Error?) {
  }
  //rest of you AppDelegate code
}

为了使用统一深度链接,您需要

  1. SEGAppsFlyerDeepLinkDelegate 协议添加到您的 AppDelegate(或其他)类中
  2. 配置Segment分析和AppsFlyer时传递AppDelegate(或其他)类。从上面的示例代码中,将 factoryWithDelegate 修改为
let factoryWithDelegate: SEGAppsFlyerIntegrationFactory = SEGAppsFlyerIntegrationFactory.create(withLaunch: self, andDeepLinkDelegate: self)
  1. 在作为代理传递的类中实现协议的方法。请参见以下示例代码,其中AppDelegate被用于此目的
extension AppDelegate: SEGAppsFlyerDeepLinkDelegate {
    func didResolveDeepLink(_ result: DeepLinkResult) {
        print(result)
    }
}

如果您正在与不允许将用户级别数据传递给第三方的网络协作,您需要在调用之前应用代码以过滤掉这些网络

// [self.analytics track:@"Install Attributed" properties:[properties copy]];
@import AppsFlyerLib;

...
@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(integrationDidStart:) name:SEGAnalyticsIntegrationDidStart object:nil];
    ...
}

...

- (void)integrationDidStart:(nonnull NSNotification *)notification {
    NSString *integration = notification.object;
    if ([integration isEqualToString:@"AppsFlyer"]) {
        /// Additional AppsFlyer SDK setup goes below
        /// All setup is optional
        /// To set Apple App ID and AppsFlyer Dev Key use Segment dashboard
        /// ...
        /// Enable ESP support for specific URLs
        [[AppsFlyerLib shared] setResolveDeepLinkURLs:@[@"afsdktests.com"]];
        /// Disable printing SDK messages to the console log
        [[AppsFlyerLib shared]  setIsDebug:NO];
        /// `OneLink ID` from OneLink configuration
        [[AppsFlyerLib shared]  setAppInviteOneLink:@"one_link_id"];
    }
}

有关DMA同意数据的简介,请参阅 此处。SDK提供两种收集同意数据的方法

  • 通过同意管理平台(CMP):如果应用程序使用符合透明度和同意框架(TCF)v2.2协议的CMP,SDK可以自动检索同意详细信息。



  • 通过专用SDK API:开发人员可以使用为该目的设计的特定API,直接将谷歌所需的同意数据传递到SDK中。

使用CMP收集同意数据

兼容TCF v2.2的CMP收集DMA同意数据,并存储在 NSUserDefaults 中。为了启用SDK访问此数据并将其包含在每个事件中,请按照以下步骤操作

  1. 调用 AppsFlyerLib.shared().enableTCFDataCollection(true) 指示SDK从设备收集TCF数据。
  2. 使用手动模式初始化 SEGAppsFlyerIntegrationFactory。这将允许我们延迟转换调用,以便为SDK提供用户同意。
  3. applicationDidBecomeActive 生命周期方法中,使用CMP决定是否需要在当前会话中显示同意对话框以获取同意数据。如果您需要同意对话框,请转到步骤4;否则,请转到步骤5。
  4. 从CMP获取确认,用户已做出同意决定,数据已存储在 NSUserDefaults 中。
  5. 调用 AppsFlyerLib.shared().start()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    // For AppsFLyer debug logs uncomment the line below
    AppsFlyerLib.shared().isDebug = true
    AppsFlyerLib.shared().waitForATTUserAuthorization(timeoutInterval: 60)
    AppsFlyerLib.shared().enableTCFDataCollection(true)
    let factoryWithDelegateAndManual: SEGAppsFlyerIntegrationFactory =SEGAppsFlyerIntegrationFactory.create(withLaunch: self, andDeepLinkDelegate: self, andManualMode: true)
  
    // Segment initialization
    let config = AnalyticsConfiguration(writeKey: "SEGMENT_KEY")
    config.use(factoryWithDelegateAndManual)
    config.enableAdvertisingTracking = true       //OPTIONAL
    config.trackApplicationLifecycleEvents = true //OPTIONAL
    config.trackDeepLinks = true                  //OPTIONAL
    config.trackPushNotifications = true          //OPTIONAL
  
    Analytics.debug(true)
    Analytics.setup(with: config)
    return true
}

func applicationDidBecomeActive(_ application: UIApplication) {
    if(cmpManager!.hasConsent()){
        //CMP manager already has consent ready - you can start
        AppsFlyerLib.shared().start()
    }else{
        //CMP doesn't have consent data ready yet
        //Waiting for CMP completion and data ready and then start
        cmpManager?.withOnCmpButtonClickedCallback({ CmpButtonEvent in
            AppsFlyerLib.shared().start()
        })
    }
    
    if #available(iOS 14, *) {
        ATTrackingManager.requestTrackingAuthorization { (status) in
            switch status {
            case .denied:
                print("AuthorizationSatus is denied")
            case .notDetermined:
                print("AuthorizationSatus is notDetermined")
            case .restricted:
                print("AuthorizationSatus is restricted")
            case .authorized:
                print("AuthorizationSatus is authorized")
            @unknown default:
                fatalError("Invalid authorization status")
            }
        }
    }
}

手动收集同意数据

如果您的应用程序未使用与 TCF v2.2 兼容的比较并合语言(CMP),请使用以下 SDK API,直接将同意数据传递给 SDK。

  1. 使用手动模式初始化 SEGAppsFlyerIntegrationFactory。这将允许我们延迟转换调用,以便为SDK提供用户同意。
  2. applicationDidBecomeActive 生命周期方法中确定 GDPR 是否适用于该用户。
    - 如果 GDPR 适用于该用户,请执行以下操作
    1. 鉴于 GDPR 适用于该用户,确定是否已经存储了此会话的同意数据。
      1. 如果没有存储同意数据,则显示同意对话框以捕获用户的同意决定。
      2. 如果已存储同意数据,请继续到下一步。
    2. 要传递同意数据到 SDK,请创建一个具有以下参数的 AppsFlyerConsent 对象
      - forGDPRUserWithHasConsentForDataUsage- 指示用户是否同意将数据用于广告目的。- hasConsentForAdsPersonalization- 指示用户是否同意将数据用于个性化广告。
    3. 调用 AppsFlyerLib.shared().setConsentData(AppsFlyerConsent(forGDPRUserWithHasConsentForDataUsage: Bool, hasConsentForAdsPersonalization: Bool))
    4. 调用 AppsFlyerLib.shared().start()

    - 如果 GDPR 不适用于该用户,请执行以下操作
    1. 调用 AppsFlyerLib.shared().setConsentData(AppsFlyerConsent(nonGDPRUser: ()))
    2. 使用手动模式初始化 SEGAppsFlyerIntegrationFactory 是可选的,不再是之前的强制要求。

该项目包含针对 Objective-C 和 Swift(《带故障排除》)的 4 个示例。要尝试使用,请克隆此仓库,并从每个示例开始,首先运行 pod install 来安装项目依赖项。