概要:AppsFlyerのiOS SDKは、 iOSアプリのアトリビューションとイベント計測の機能を提供し、iOS14で追加された変更についてもサポートしています。 このSDKバージョンでは、過去のバージョンと比べてメソッドの大幅な変更がありますので注意してください。
重要!
iOS SDK V5.4.4は、iOS14上でも問題なく動作することが確認できています。しかし、今後のiOSリリースとの互換性を確実にするためにも、SDK V6.Xへアップデートすることをお勧めします。 iOS SDK V6へのアップデートガイド も参照してください。
AppleのApp Clipsの計測はiOS SDK V6.0.8以降で利用可能です。
Appleの発表によると、App Tracking Transparency (ATT)の施行はiOS14.5 (2021年早春)から開始される予定です。ATTをサポートするためのiOS SDKの実装については、こちらを参照してください。
1. 概要
AppsFlyerのSDKを利用することで、アプリのインストールやアプリ内イベントを計測することができます。SDKは、堅牢、安全かつ軽量で、簡単に埋め込むことができます。
インストール、アップデート、セッションに加えて、インストール後イベント(アプリ内購入、ゲームレベル等)を計測し、ROIやユーザーの質も分析できます。
iOS バージョン | サポートされる計測方法 |
---|---|
11.3未満 |
|
11.3–13 |
|
14以上 |
|
* iOS SDK V5.4以下:
|
1.1 SDK実装 - 必須項目
タブ | 目的 | 結果 |
---|---|---|
SDK 実装 |
SDKの追加および設定方法について |
|
主要API |
SDKの主要APIの使用方法について: これらのAPIを使用すると、アプリ内イベントと収益を計測や、ディープリンクを実行してアプリ内でコンバージョンデータを取得できるようになります。 |
管理画面上でのアプリ内イベントと収益の計測 ディープリンクの実行 |
アンインストール計測、ユーザー招待(紹介)の計測、プッシュ通知計測など、オプションのAPIの実装および使用方法について |
アンインストール、ユーザー招待、プッシュ通知によるユーザーエンゲージメントの計測、ユーザーのプライバシーシナリオの処理などが可能になります。 |
|
開発者向けのSDK APIのクイックリファレンス |
|
1.2 iOSとのSDKの互換性
- 以下との互換性があります:
- iOSのversion8以降、tvOSのversion9以降の全iOS / tvOS端末(iPhone、iPod、iPad、Apple TV)
- AppleのIPv6 DNS64 / NAT64ネットワーク
注
AppleはiOS 14 App Clipの機能もリリースします。
開発者向けAppClipsガイドでその詳細を確認してください。
このタブでは、アプリ開発者向けにAppsFlyer SDKを実装および初期化する方法を説明しています。このタブの内容を完了すると、アプリの管理画面にオーガニックと非オーガニックの2つのインストールが表示されるようになります。
2. アプリへのSDKの追加
2.1 SDKをダウンロードとXcodeへの追加
- CocoaPods の最新バージョンをダウンロードしてインストールしてください。
Podfile
に次の行を追加してください。
pod 'AppsFlyerFramework'
pod install
を実行してください。- この時点以降、Xcode内でプロジェクトを開く際には
.xcodeproj
ではなく.xcworkspace
を使用してください。
注
tvOSのアプリを開発している場合、CocoaPodsは関連する依存関係をAppsFlyerFrameworkから自動的に追加します。
- Carthage の最新バージョンをインストールしてください。
- 次の行をCartfile binaryに追加してください:
https://raw.githubusercontent.com/AppsFlyerSDK/AppsFlyerFramework/master/Carthage/appsflyer-ios.json
注
上記のリンクは、Staticのライブラリにリンクしています。もし新しいiOSバージョンにアップグレードする場合には、次の手順を実行してください。
- copy-frameworksを実行するXcodeから、 Run Script のStageを削除してください。
- ライブラリが埋め込まれていないことを確認してください。
詳細については Carthageのドキュメントを参照してください。
現在、tvOSアプリはサポートしていません。
-
iOS SDKをStatic Frameworkとしてダウンロードしてください。
SDKのStatic Frameworkのダウンロードについて整合性を確認するには、 こちらをクリックしてください。 - 先程ダウンロードしたばかりのAppsFlyerLib.framework.zipファイルを解凍してください。
- AppsFlyerLib.frameworkをXcodeプロジェクトにドラッグ&ドロップしてください。
- 「Copy items if needed」(必要であればアイテムをコピー)が選択されていることを確認します。
注
このアプローチはiOS 8以降でのみ使用できます。
tvOSアプリの場合、異なるAppsFlyerFrameworkが必要です。
- このリポジトリのクローンを作成してください。
- クローンリポジトリのこのフォルダで、AppsFlyerLib.frameworkを見つけてください。
- ステップ3と4を繰り返してください。
2.2 ネイティブの iOS フレームワークの依存関係
このSDKでは、以下のネイティブフレームワークを自動的に追加して使用しています。
- AdSupport.framework
- このフレームワークは、端末からIDFAを収集するために必要です。
IDFAは、Facebook Ads、Twitter、Google Ads、およびその他ネットワークを計測する上で不可欠です。 - iAd.framework
- Apple Search Adsの成果を計測するために必要です。
- AdServices Framework (
V6.1.3以上のみ対応
) - Apple Search Adsの成果を計測するために必要です。
これらのフレームワークを削除してIDFAの取得を無効にしたい場合:
- IDFAの収集を無効にする
- iAd.frameworkを無効にする
StrictモードSDK
StrictモードSDKを使用して、IDFAの収集機能とAdsupport frameworkの依存関係を除外します。(たとえば、Kids向けアプリを開発する場合などに有効です。)
注意:IDFVは引き続き使用できます。
Podfile
内で、AppsFlyerLib
の依存関係を次のように置き換えてください:
pod 'AppsFlyerFramework/Strict','6.1.1'
注意: StrictモードSDKを利用している状態でdisableAdvertisingIdentifier
を呼び出すと、コンパイルエラーが発生します。
注
4.10.4より前のバージョンのSDKを使用している場合には、ad support frameworkを手動で追加する必要があります。
ad support frameworkを手動で追加するには:
- Xcodeのプロジェクト内で、プロジェクトのターゲットを選択してください。
- ターゲットの[全般(General)]タブを選択してください。
- Linked Frameworks and Librariesのセクションを展開してください。
- +をクリックして、フレームワークを追加してください。
- AdSupport.frameworkを検索してください。
- リストからAdSupport.frameworkを選択してください。
iAd.frameworkに対しても同じプロセスを繰り返します。
3. SDKの実装と初期化
このセクションでは、AppsFlyer iOS SDKの初期化方法および利用開始の方法について説明しています。
3.1 AppsFlyer Dev Keyの取得
AppsFlyerではdev keyを使用して個々のアカウントを一意に識別します。SDKがAppsFlyerアカウントに関するデータを安全に送受信できるようにするために、dev keyは必須です。
SDK Keyを取得するには:
- AppsFlyerの管理画面内で、左メニューから[設定] >[アプリ設定]へ移動してください。
- 次の作業で必要になるので、Dev Keyはコピーしておいてください。
3.2 SDKの初期化
注
SceneDelegate
を使用しているiOSアプリに対応するには、SceneDelegateでのSDKの初期化を参照してください。
以下のコードは実装例です。必要に応じて、<AF_DEV_KEY>
と <APP_ID>
の値を置き換えてください。
AppDelegate.h
ファイルにおいて:
AppsFlyerLib/AppsFlyerLib.h
ヘッダーをインポートしてください。AppDelegate
interface declarationにAppsFlyerLibDelegate
を追加してください。
#import <UIKit/UIKit.h>
#import <AppsFlyerLib/AppsFlyerLib.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate, AppsFlyerLibDelegate>
@end
AppDelegate.m
ファイルにおいて:
didFinishLaunchingWithOptions
内で、以下を設定してください。- 前の手順でコピーしたAppsFlyer Dev Key
- AppleのApp ID
- IDFAを収集するには、App Tracking Transparency (ATT)のサポートを実装してください。
- 追加の設定
onConversionDataSuccess
とonConversionDataFail
のコールバックをオーバーライドすることで、コンバージョン情報を処理してディファードディープリンクを有効にすることが可能です。onAppOpenAttribution
とonAppOpenAttributionFailure
のコールバックをオーバーライドすることで、計測情報を処理してダイレクトディープリンクを有効にすることが可能です。didReceiveRemoteNotification
のコールバック内で、handlePushNotification
を呼び出し、プッシュ通知のリエンゲージメント計測を行なうことが可能です。applicationDidBecomeActive
のコールバック内で、start
を呼び出してください。
#import "AppDelegate.h"
#import <UserNotifications/UserNotifications.h>
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
/** APPSFLYER INIT **/
[AppsFlyerLib shared].appsFlyerDevKey = @"<AF_DEV_KEY>";
[AppsFlyerLib shared].appleAppID = @"<APPLE_APP_ID>";
[AppsFlyerLib shared].delegate = self;
/* Set isDebug to true to see AppsFlyer debug logs */
[AppsFlyerLib shared].isDebug = true;
if (@available(iOS 10, *)) {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) {
}];
} else {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes: UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}
[[UIApplication sharedApplication] registerForRemoteNotifications];
return YES;
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[AppsFlyerLib shared] start];
}
// Deep linking
// Open URI-scheme for iOS 9 and above
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary *) options {
[[AppsFlyerLib shared] handleOpenUrl:url options:options];
return YES;
}
// Open URI-scheme for iOS 8 and below
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation {
[[AppsFlyerLib shared] handleOpenURL:url sourceApplication:sourceApplication withAnnotation:annotation];
return YES;
}
// Open Universal Links
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler {
[[AppsFlyerLib shared] continueUserActivity:userActivity restorationHandler:restorationHandler];
return YES;
}
// Report Push Notification attribution data for re-engagements
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[[AppsFlyerLib shared] handlePushNotification:userInfo];
}
// AppsFlyerLib implementation
//Handle Conversion Data (Deferred Deep Link)
-(void)onConversionDataSuccess:(NSDictionary*) installData {
id status = [installData objectForKey:@"af_status"];
if([status isEqualToString:@"Non-organic"]) {
id sourceID = [installData objectForKey:@"media_source"];
id campaign = [installData objectForKey:@"campaign"];
NSLog(@"This is a non-organic install. Media source: %@ Campaign: %@",sourceID,campaign);
} else if([status isEqualToString:@"Organic"]) {
NSLog(@"This is an organic install.");
}
}
-(void)onConversionDataFail:(NSError *) error {
NSLog(@"%@",error);
}
//Handle Direct Deep Link
- (void) onAppOpenAttribution:(NSDictionary*) attributionData {
NSLog(@"%@",attributionData);
}
- (void) onAppOpenAttributionFailure:(NSError *)error {
NSLog(@"%@",error);
}
@end
AppDelegate.swift
ファイルにおいて:
AppsFlyerLib
をインポートしてください。AppDelegate
のclass declarationに、AppsFlyerLibDelegate
を追加してください。didFinishLaunchingWithOptions
内で、以下を設定してください。- AppsFlyer dev key
- app ID
- IDFAを収集するには、App Tracking Transparency (ATT)のサポートを実装してください。
- 追加の設定
onConversionDataSuccess
とonConversionDataFail
のコールバックをオーバーライドすることで、コンバージョン情報を処理してディファードディープリンクを有効にすることが可能です。onAppOpenAttribution
とonAppOpenAttributionFailure
のコールバックをオーバーライドすることで、計測情報を処理してダイレクトディープリンクを有効にすることが可能です。didReceiveRemoteNotification
のコールバック内で、handlePushNotification
を呼び出し、プッシュ通知のリエンゲージメント計測を行なうことが可能です。applicationDidBecomeActive
のコールバック内で、start
を呼び出してください。
import UIKit
import AppsFlyerLib
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let defaults = UserDefaults.standard
//MARK: LifeCycle
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
AppsFlyerLib.shared().appsFlyerDevKey = "<AF_DEV_KEY>"
AppsFlyerLib.shared().appleAppID = "<APPLE_APP_ID>"
AppsFlyerLib.shared().delegate = self
AppsFlyerLib.shared().isDebug = true
// iOS 10 or later
if #available(iOS 10, *) {
UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .alert, .sound]) { _, _ in }
application.registerForRemoteNotifications()
}
// iOS 9 support - Given for reference. This demo app supports iOS 13 and above
else {
application.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
application.registerForRemoteNotifications()
}
return true
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Start the SDK (start the IDFA timeout set above, for iOS 14 or later)
AppsFlyerLib.shared().start()
}
// Open Univerasal Links
// For Swift version < 4.2 replace function signature with the commented out code:
// func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
print(" user info \(userInfo)")
AppsFlyerLib.shared().handlePushNotification(userInfo)
}
// Open Deeplinks
// Open URI-scheme for iOS 8 and below
private func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
AppsFlyerLib.shared().continue(userActivity, restorationHandler: restorationHandler)
return true
}
// Open URI-scheme for iOS 9 and above
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
AppsFlyerLib.shared().handleOpen(url, sourceApplication: sourceApplication, withAnnotation: annotation)
return true
}
// Report Push Notification attribution data for re-engagements
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
AppsFlyerLib.shared().handleOpen(url, options: options)
return true
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
AppsFlyerLib.shared().handlePushNotification(userInfo)
}
// Reports app open from deep link for iOS 10 or later
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
AppsFlyerLib.shared().continue(userActivity, restorationHandler: nil)
return true
}
}
//MARK: AppsFlyerLibDelegate
extension AppDelegate: AppsFlyerLibDelegate{
// Handle Organic/Non-organic installation
func onConversionDataSuccess(_ installData: [AnyHashable: Any]) {
print("onConversionDataSuccess data:")
for (key, value) in installData {
print(key, ":", value)
}
if let status = installData["af_status"] as? String {
if (status == "Non-organic") {
if let sourceID = installData["media_source"],
let campaign = installData["campaign"] {
print("This is a Non-Organic install. Media source: \(sourceID) Campaign: \(campaign)")
}
} else {
print("This is an organic install.")
}
if let is_first_launch = installData["is_first_launch"] as? Bool,
is_first_launch {
print("First Launch")
} else {
print("Not First Launch")
}
}
}
func onConversionDataFail(_ error: Error) {
print(error)
}
//Handle Deep Link
func onAppOpenAttribution(_ attributionData: [AnyHashable : Any]) {
//Handle Deep Link Data
print("onAppOpenAttribution data:")
for (key, value) in attributionData {
print(key, ":",value)
}
}
func onAppOpenAttributionFailure(_ error: Error) {
print(error)
}
}
3.2.1 SceneDelegateでのSDKの初期化
この初期化メソッドは、SceneDelegate
を使用している場合にのみ使用してください。
SceneDelegate
を使用している場合applicationDidBecomeActive
が呼ばれないので、以下の例にもあるように、UIApplicationDidBecomeActiveNotification
の回避策を使ってSDKを初期化してください。
以下のコードは実装例です。必要に応じて、<AF_DEV_KEY>
と <APP_ID>
の値を置き換えてください。
AppDelegate.h
ファイルにおいて:
AppsFlyerLib/AppsFlyerLib.h
ヘッダーをインポートしてください。AppDelegate
interface declarationにAppsFlyerLibDelegate
を追加してください。
#import <AppsFlyerLib/AppsFlyerLib.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate, AppsFlyerLibDelegate>
@end
AppDelegate.m
ファイルにおいて:
didFinishLaunchingWithOptions
のコールバック内で、以下を設定してください。- AppsFlyer dev key
- app ID
- IDFAを収集するには、App Tracking Transparency (ATT)のサポートを実装してください。
- 追加の設定
onConversionDataSuccess
とonConversionDataFail
のコールバックをオーバーライドすることで、コンバージョン情報を処理してディファードディープリンクを有効にすることが可能です。onAppOpenAttribution
とonAppOpenAttributionFailure
のコールバックをオーバーライドすることで、計測情報を処理してダイレクトディープリンクを有効にすることが可能です。didReceiveRemoteNotification
のコールバック内でhandlePushNotification::userInfo
を呼び出すことで、プッシュ通知によるリエンゲージメントの計測が可能になります。sendLaunch
のコールバック内で、start
を呼び出してください。
#import "AppDelegate.h"
#import <AppsFlyerLib/AppsFlyerLib.h>
#import <UserNotifications/UserNotifications.h>
@interface AppDelegate ()
@end
@implementation AppDelegate
// Start the AppsFlyer SDK
- (void)sendLaunch:(UIApplication *)application {
[[AppsFlyerLib shared] start];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
/** APPSFLYER INIT **/
[AppsFlyerLib shared].appsFlyerDevKey = @"<AF_DEV_KEY>";
[AppsFlyerLib shared].appleAppID = @"<APPLE_APP_ID>";
[AppsFlyerLib shared].delegate = self;
/* Set isDebug to true to see AppsFlyer debug logs */
[AppsFlyerLib shared].isDebug = true;
// Use UIApplicationDidBecomeActiveNotification to start the SDK
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(sendLaunch:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
return YES;
}
if (@available(iOS 10, *)) {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) {
}];
} else {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes: UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}
[[UIApplication sharedApplication] registerForRemoteNotifications];
return YES;
}
// Report Push Notification attribution data for re-engagements
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[[AppsFlyerLib shared] handlePushNotification:userInfo];
}
// AppsFlyerLib implementation
//Handle Conversion Data (Deferred Deep Link)
-(void)onConversionDataSuccess:(NSDictionary*) installData {
id status = [installData objectForKey:@"af_status"];
if([status isEqualToString:@"Non-organic"]) {
id sourceID = [installData objectForKey:@"media_source"];
id campaign = [installData objectForKey:@"campaign"];
NSLog(@"This is a none organic install. Media source: %@ Campaign: %@",sourceID,campaign);
} else if([status isEqualToString:@"Organic"]) {
NSLog(@"This is an organic install.");
}
}
-(void)onConversionDataFail:(NSError *) error {
NSLog(@"%@",error);
}
//Handle Direct Deep Link
- (void) onAppOpenAttribution:(NSDictionary*) attributionData {
NSLog(@"%@",attributionData);
}
- (void) onAppOpenAttributionFailure:(NSError *)error {
NSLog(@"%@",error);
}
// support for scene delegate
#pragma mark - UISceneSession lifecycle
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options API_AVAILABLE(ios(13)){
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
}
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions API_AVAILABLE(ios(13.0)){
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
@end
SceneDelegate.m
のファイル内で:
openURLContexts
のコールバック内で、handleOpenUrl
を呼び出してください。continueUserActivity
のコールバック内で、continueUserActivity
を呼び出してください。
#import "SceneDelegate.h"
@interface SceneDelegate ()
@end
@implementation SceneDelegate
- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts API_AVAILABLE(ios(13.0)){
NSURL* url = [[URLContexts allObjects] objectAtIndex:0].URL;
if(url){
[[AppsFlyerLib shared] handleOpenUrl:url options:nil];
}
}
- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity API_AVAILABLE(ios(13.0)){
[[AppsFlyerLib shared]continueUserActivity:userActivity restorationHandler:nil];
}
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
NSUserActivity *activity = [[connectionOptions userActivities] allObjects].firstObject;
if (activity) {
[self scene:scene continueUserActivity:activity];
}
[self scene:scene openURLContexts: [connectionOptions URLContexts]];
}
- (void)sceneDidDisconnect:(UIScene *)scene API_AVAILABLE(ios(13.0)){
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}
- (void)sceneDidBecomeActive:(UIScene *)scene API_AVAILABLE(ios(13.0)){
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
- (void)sceneWillResignActive:(UIScene *)scene API_AVAILABLE(ios(13.0)){
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
- (void)sceneWillEnterForeground:(UIScene *)scene API_AVAILABLE(ios(13.0)){
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
- (void)sceneDidEnterBackground:(UIScene *)scene API_AVAILABLE(ios(13.0)){
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
@end
AppDelegate.swift
ファイルにおいて:
AppsFlyerLib
をインポートしてください。AppDelegate
のclass declarationに、AppsFlyerLibDelegate
を追加してください。didFinishLaunchingWithOptions
のコールバック内で、以下を設定してください:- AppsFlyer dev key
- app ID
- IDFAを収集するには、App Tracking Transparency (ATT)のサポートを実装してください。
- 追加の設定
onConversionDataSuccess
とonConversionDataFail
のコールバックをオーバーライドすることで、コンバージョン情報を処理してディファードディープリンクを有効にすることが可能です。onAppOpenAttribution
とonAppOpenAttributionFailure
のコールバックをオーバーライドすることで、計測情報を処理してダイレクトディープリンクを有効にすることが可能です。didReceiveRemoteNotification
のコールバック内で、handlePushNotification
を呼び出し、プッシュ通知のリエンゲージメント計測を行なうことが可能です。sendLaunch
のコールバック内で、start
を呼び出してください。
import UIKit
import AppsFlyerLib
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, AppsFlyerLibDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
AppsFlyerLib.shared().appsFlyerDevKey = "<AF_DEV_KEY>"
AppsFlyerLib.shared().appleAppID = "<APPLE_APP_ID>"
AppsFlyerLib.shared().delegate = self
AppsFlyerLib.shared().isDebug = true
NotificationCenter.default.addObserver(self, selector: NSSelectorFromString("sendLaunch"), name: UIApplication.didBecomeActiveNotification, object: nil)
return true
}
@objc func sendLaunch() {
AppsFlyerLib.shared().start()
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
}
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
//MARK: -GCD
func onConversionDataSuccess(_ installData: [AnyHashable: Any]) {
print("onConversionDataSuccess data:")
for (key, value) in installData {
print(key, ":", value)
}
if let status = installData["af_status"] as? String {
if (status == "Non-organic") {
if let sourceID = installData["media_source"],
let campaign = installData["campaign"] {
print("This is a Non-Organic install. Media source: \(sourceID) Campaign: \(campaign)")
}
} else {
print("This is an organic install.")
}
if let is_first_launch = installData["is_first_launch"] as? Bool,
is_first_launch {
print("First Launch")
} else {
print("Not First Launch")
}
}
}
func onConversionDataFail(_ error: Error!) {
if let err = error{
print(err)
}
}
func onAppOpenAttribution(_ attributionData: [AnyHashable : Any]!) {
if let data = attributionData{
print("\(data)")
}
}
func onAppOpenAttributionFailure(_ error: Error!) {
if let err = error{
print(err)
}
}
}
SceneDelegate.swift
のファイルにおいて:
AppsFlyerLib
をインポートしてください。openURLContexts
のコールバック内で、AppsFlyerLib.shared().handleOpen
を呼び出してください。continue
のコールバック内で、AppsFlyerLib.shared().continue
を呼び出してください。
import UIKit
import AppsFlyerLib
@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Processing Universal Link from the killed state
if let userActivity = connectionOptions.userActivities.first {
self.scene(scene, continue: userActivity)
}
// Processing URI-scheme from the killed state
self.scene(scene, openURLContexts: connectionOptions.urlContexts)
guard let _ = (scene as? UIWindowScene) else { return }
}
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
AppsFlyerLib.shared().continue(userActivity, restorationHandler: nil)
}
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
if let url = URLContexts.first?.url {
AppsFlyerLib.shared().handleOpen(url, options: nil)
}
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}
3.3 SKAdNetwork計測のサポート
SKAdNetwork は iOS で使用されるクラスで、広告主アプリのインストールを検証します。アプリのインストール検証プロセスには、ソースアプリと広告主アプリが関係します。
ソースアプリとは、アドネットワークによって署名された広告を表示している、広告掲載面としてのアプリです。広告を表示するようにアプリに設定することは、AppsFlyer SDKのサポート範囲ではありません。設定する場合には、Appleのガイドに従ってください。
広告主アプリ (AppsFlyer SDKを実装しているアプリ) の場合、AppsFlyerの SKAdNetworkソリューション は SKAdNetworkを使用してアトリビューションのポストバックを提供し、AppsFlyerはユーザーのプライバシーを維持しながらデータを収集、翻訳、集計します。アプリを初回起動すると、AppsFlyerはマーケティング担当者が事前に設定した内容を使用して、SKAdNetworkのコンバージョン値の設定方法をSDKに指示します。
SKAdNetwork ソリューション を使用するには :
- 開発者は何も対応の必要がありません。
-
AppsFlyer SDKは、必要なSKAdNetwork API、つまり
registerAppForAdNetworkAttribution()
とupdateConversionValue()
を自動的にコールするため、開発者はそれらをコールしないでください。 - AppsFlyer以外のSDKが、SKAdNetworkのAPIを呼び出すことを許可しないでください。許可してしまうと、iOS が AppsFlyerに対してポストバックを送信するのを遅らせたり、SKAdNetworkの管理画面上でユーザーの質を算出するのに使用するコンバージョン値を変更してしまう可能性があります。
- 一方、マーケティング担当者はAppsFlyerの管理画面上でSKAdNetworkの計測設定を行う必要があります。
AppStoreにおいて、開発者、マーケティング担当者のどちらも、特別なアクションや登録プロセスは何も必要ありません。
SKAdNetworkの計測を無効にするには、disableSKAdNetwork APIを使用してください。
3.4 SDK初期化の遅延
GDPRやCOPPAへの同意など、ユーザーの同意が得られるまでSDKの初期化とデータの送信を遅延させたい場合があるでしょう。
注:これはiOS 14で導入されるATTとは無関係です。
SDKの初期化を遅延させるには:
- バックグラウンドからフォアグラウンドへの遷移時にセッションが送信されないようしてください。すべてのapplicationDidBecomeActive(セクション3.3に基づく)で呼び出されるsendLaunch()のメソッド内で、条件チェックの上
start
のコールをラップしてください。
たとえば、以下のようになります:
-(void)sendLaunch:(UIApplication *)application { if (consent_given) { // check the condition [[AppsFlyerLib shared] start]; // Start } }
-
遅延する理由がなくなったら、条件が変更された直後にすぐセッションを送信してください。 最初のセッションデータを送信する準備ができたら、
start
を呼び出してください。
たとえば、以下のようになります:
... consent_given = YES; // change the condition [[AppsFlyerLib shared] start]; // Start ...
4. インストール計測のテスト
ここまでで、オーガニックインストールと非オーガニックインストールをシミュレートすることによるSDK実装テストの準備ができました。
テストのシナリオと手順の詳細については、SDK実装テストを参照してくださ。
4.1 テスト端末の登録
インストールのテストを開始する前に:
- その端末がそのアプリをインストールしたことがないことを確認してください。
- 使用するテスト端末をホワイトリスト登録してください。
4.2 オーガニックインストールのテスト
オーガニックインストールは通常、アプリストアからの直接インストールであり何も紐付けがされないインストールです。
オーガニックインストールをシミュレートするには:
- コンピュータにテスト端末が接続されていることを確認してください。
- Xcodeで、デバッグターミナルを開いてください。
- Xcode Studioから、テスト端末またはシミュレーターにアプリをインストールしてください。
- アプリが起動するのを待ってください。
- デバッグターミナルで、アプリのパッケージ名を探してください。
以下が表示されるはずです。
ログ上でstart()を送信することは、SDKがインストールを計測していることを示しています。このデータは、app delegate内の onConversionDataSuccess
のメソッドから取得されます。コンバージョンデータの取得については、このガイドの後半で説明します。
注: SDK ver5以降、 onConversionDataSuccess
がコンバージョンデータを取得するメソッドの名称です。5.0.0より前のSDKバージョンを使用している場合、メソッドの名前は onConversionDataReceived
です。SDK ver5.0.0にアップグレードすることをお勧めします。詳細についてはこちらをクリックしてください。
オーガニックインストールが、管理画面の オーバービュー ページに表示されるはずです 。
管理画面にインストールが表示されない場合は、 SDKトラブルシューティングガイドを参照してください。
4.3 非オーガニックインストールのテスト
非オーガニックインストールは、通常は広告エンゲージメントに紐付けられたインストールです。計測URLを使用して、非オーガニックインストールをシミュレートできます。
取得方法
- あなたのアプリのiTunes IDが何かを調べてください。id123456789.
- 以下のURLの<APP_ID>を、あなたのアプリのiTunes IDに書き換えてください。:
例:https://app.appsflyer.com/<APP_ID>?pid=sdk_test&c=sdk_test
https://app.appsflyer.com/id0123456789?pid=sdk_test&c=sdk_test
pid
のパラメーターは、メディアソース名を表します。c
のパラメーターは、キャンペーン名を表します。 - このURLを端末に送信してください。(メールなど)
- 端末上で、URLをクリックしてください。
- アプリがアプリストアに掲載されている場合、アプリストアにリダイレクトされます。アプリストアからはアプリをダウンロードしないでください。ステップ5に進んでください。
- アプリがアプリストアに掲載されておらず、まだ開発中の場合、画面にはアプリがアプリストアで利用できないというメッセージが表示されます。そのままステップ5に進んでください。
- Xcodeで、デバッグターミナルを開いてください。
- USBケーブルを使用して端末をコンピューターに接続してください。
- Xcodeから、端末にアプリをインストールしてください。
- デバッグターミナルで、アプリのiTunes IDを探してください。
以下が表示されるはずです。
非オーガニックインストールが、管理画面の オーバービュー ページに表示されるはずです 。
注
SDK 実装のテストとデバッグが完了したら、SDK logsをオフにしてください。
このタブでは、アプリ内イベントと収益を計測する方法と、ディープリンクを設定する方法について説明しています。
アプリ内イベントと収益を記録することで、ユーザーの質を測定することが可能です。ディープリンクを使用すると、より優れたユーザー体験を提供できます。
このタブには開発者向けの内容が含まれていますが、マーケティング担当者からのインプットが不可欠です。
- マーケティング担当者は、ユーザーの質を計測するために、どのアプリ内イベントを計測する必要があるかを決定しなければなりません。
- マーケティング担当者はAppsFlyerの管理画面にアクセスでき、 ディープリンク用にOneLinkをセットアップ するために必要です。
5. アプリ内イベントの計測
アプリ内イベントにより、アプリ内でのユーザーの動きに関するインサイトを得ることができます。ROI(投資収益率)やLTV(顧客生涯価値)を計測するために、時間を取って計測するイベントを定義することをお勧めします。
アプリ内イベントを計測する方法はいくつかあります。最も一般的な方法は、SDKを介してのイベント送信です。これについてはこのページで説明しています。アプリ内イベントを記録する他の方法については、 アプリ内イベント概要ガイドを確認してください。
アプリの特定のカテゴリーに合わせて、たとえば、旅行、ゲーム、eコマースなど、業界毎の推奨するアプリ内イベントを使用できます。
5.1 アプリ内イベントの名前とパラメータ
SDKには、アプリ内イベントに関連する情報を表す、2種類の定数が含まれています。
- イベント名:これらの定数は、
AFEventEventName
という形式です。
例:AFEventPurchase
、AFEventAddToCart
- イベントパラメータ:これらの定数は、
AFEventParameterParameterName
という形式です。
例:AFEventParameterRevenue
、AFEventParamaterContentId
以下の理由から、これらの定数を使用することを強くお勧めします。
- これらの共通となるアプリ内イベント名ではAppsFlyerからFacebook、Google、TwitterやSnapchatなどに自動的にマッピングします。
- 下位互換性:AppsFlyerがイベント名またはイベントパラメーター名の変更を決定した場合、実装には下位互換性があります。
これら2つのインターフェイスを使用する際、Objective-Cを使用している場合はAppsFlyerLib.hをインポートし、Swiftを使用している場合はAppsFlyerLibをインポートしてください。
これをclass implementationファイルに入れてください。
#import AppsFlyerLib.h
これをSwift class ファイルに入れてください。
import AppsFlyerLib
推奨のアプリ内イベント名とパラメータのリスト をご確認ください。
5.2 収益の計測
収益はどのアプリ内イベントでも送信できます。 af_revenue
( AFEventParameterRevenue
)のイベントパラメーターを使用して、アプリ内イベントに収益の値を含めてください。プラス・マイナスを問わず、あらゆる数値を入力できます。
af_revenue
は、AppsFlyerのローデータと管理画面で収益としてカウントされる唯一のイベントパラメータです。詳細については、こちらをクリックしてください。
収益をアプリ内イベントで送る際には、次の点に注意してください。
- 通貨コード(例を参照)を設定する際は、ISO 4217コードの3文字を使用してください。(デフォルト設定はUSDです)。
- 次のプロパティを設定することにより、すべてのイベントの通貨コードを設定できます。
- Objective-C:
[AppsFlyerLib shared].currencyCode = @"ZZZ";
, - Swift:
AppsFlyerLib.shared().currencyCode = "ZZZ"
- Objective-C:
- コンマの値区切り、通貨記号、テキストなどは収益の値に含めないでください。たとえば、収益の値は「1234.56」のように設定してください。
(例)収益を伴うアプリ内イベント
[[AppsFlyerLib shared] logEvent: @"purchase"
withValues:@{
AFEventParamContentId:@"1234567",
AFEventParamContentType : @"category_a",
AFEventParamRevenue: @200,
AFEventParamCurrency:@"USD"
}];
AppsFlyerLib.shared().logEvent("purchase",
withValues: [
AFEventParamContentId:"1234567",
AFEventParamContentType : "category_a",
AFEventParamRevenue: 200,
AFEventParamCurrency:"USD"
]);
上記の購入イベントの収益は200ドルで、ダッシュボードにも収益として表示されます。
マイナス収益の計測
稀に、マイナスの収益を計測したいケースがあるかと思います。
たとえば、ユーザーは払い戻しを受け取ったり、サブスクリプションをキャンセルしたときです。
[[AppsFlyerLib shared] logEvent: @"cancel_purchase"
withValues:@{
AFEventParamContentId:@"1234567",
AFEventParamContentType : @"category_a",
AFEventParamRevenue: @-1.99,
AFEventParamCurrency:@"USD"
}];
AppsFlyerLib.shared().logEvent("cancel_purchase",
withValues: [
AFEventParamContentId:"1234567",
AFEventParamContentType : "category_a",
AFEventParamRevenue: -1.99,
AFEventParamCurrency:"USD"
]);
注
上記のコードについて次のことに注意してください。
- 収益値の前にはマイナス記号が追加されています。
- イベント名は「cancel_purchase(購入キャンセル)」で管理画面やローデータレポートでマイナスの収益イベントを確認できます。
5.3 アプリ内購入の検証
AppsFlyerのSDKでは、アプリ内購入をサーバーにて検証できます。アプリ内購入を検証したい場合には、validateAndLogInAppPurchase
を呼び出してください。
アプリ内購入が検証されると、af_purchase
のアプリ内イベントをこのコードの呼び出しで自動的に生成します。
この呼び出しには、「Success」と「Failure」(検証の失敗など、あらゆる理由によるもの)の2つのコールバックブロックがあります。成功すると、Appleのサーバーから提供されるレシート検証データと共にディクショナリが返されます。
購入検証の使用例:
- (void) validateAndLogInAppPurchase:(NSString *) productIdentifier
price:(NSString *) price
currency:(NSString *) currency
transactionId:(NSString *) tranactionId
additionalParameters:(NSDictionary *) params
success:(void (^)(NSDictionary *response)) successBlock
failure:(void (^)(NSError *error, id reponse)) failedBlock;
[[AppsFlyerLib shared] validateAndLogInAppPurchase:@"ProductIdentifier" price:@"price"
currency:@"USD"
transactionId:@"transactionID"
additionalParameters:@{@"test": @"val" , @"test1" : @"val 1"}
success:^(NSDictionary *result){
NSLog(@"Purchase succeeded And verified!!! response: %@", result[@"receipt"]);
} failure:^(NSError *error, id response) {
NSLog(@"response = %@", response);
if([response isKindOfClass:[NSDictionary class]]) {
if([response[@"status"] isEqualToString:@"in_app_arr_empty"]){
// retry with 'SKReceiptRefreshRequest' because
// Apple has returned an empty response
// <YOUR CODE HERE>
}
} else {
//handle other errors
return;
}
}];
AppsFlyerLib
.shared()?
.validateAndLogInAppPurchase ("productIdentifier",
price: "price",
currency: "currency",
transactionId: "transactionId",
additionalParameters: [:],
success: {
guard let dictionary = $0 as? [String:Any] else { return }
dump(dictionary)
}, failure: { error, result in
guard let emptyInApp = result as? [String:Any],
let status = emptyInApp["status"] as? String,
status == "in_app_arr_empty" else {
// Try to handle other errors
return
}
// retry with 'SKReceiptRefreshRequest' because
// Apple has returned an empty response
// <YOUR CODE HERE>
})
Sandbox環境で購入の検証をテストするときは、必ず以下のコードを追加してください。
[AppsFlyerLib shared].useReceiptValidationSandbox = YES;
AppsFlyerLib.shared().useReceiptValidationSandbox = true
このコードは、本番環境のビルドからは必ず削除してください。
アプリ内購入を検証するとアプリ内イベントが自動的にAppsFlyerに送信されます。event_valueのパラメーターで渡される次のサンプルデータを参照してください。
{
"some_parameter":"some_value", // from additional_event_values
"af_currency":"USD", // from currency
"af_content_id":"test_id", // from purchase
"af_revenue":"10", // from revenue
"af_quantity":"1", // from purchase
"af_validated":true // flag that AF verified the purchase
}
注
validateAndLogInAppPurchase
の呼び出しにより、af_purchaseのアプリ内イベントが自動的に生成されます。このイベントを別途送信すると、重複してイベントをレポートすることになるので注意してください。
5.4 アプリ内イベントの制限
- イベント名:最大45文字まで(半角)
- イベント値(Event Value):半角1000文字を超えないでください。 - 超えた場合には切り捨てる可能性があります。
- 価格(price)と収益(revenue):5または5.2など、数字と小数点のみを使用してください。
- 価格(price)と収益(revenue)の値は、小数点の後に最大5桁(=小数点第5位)まで設定できます。たとえば以下の様な形です。5.12345
- v4.8.1以降のSDKであれば、英語以外の文字もアプリ内イベントでサポートされています。
5.5 アプリ内イベントの計測例
アプリ内イベントの計測は、イベント名とパラメータを使用してlogEvent
を呼び出すことで実行されます。詳細については、 アプリ内イベントのページを参照してください。
以下は、購入イベントを計測する方法の簡単な例です。業種別の既製のコードスニペットの包括的なリストについては、 業種別のリッチアプリ内イベントのガイドを参照してください
例:アプリ内購入イベント
[[AppsFlyerLib shared] logEvent:AFEventPurchase
withValues: @{
AFEventParamRevenue: @200,
AFEventParamCurrency: @"USD",
AFEventParamQuantity: @2,
AFEventParamContentId: @"092",
AFEventParamReceiptId: @"9277"
}];
注
- イベントSDKに渡されるevent valueのディクショナリは、NSJSONSerializationによるJSON変換に対して有効でなければなりません。詳細については、こちらをご確認ください。
- 収益(revenue)の値については、通貨記号は認識しないので通貨記号を追加しないでください。
AppsFlyerLib.shared().logEvent(AFEventPurchase,
withValues: [
AFEventParamRevenue: "200",
AFEventParamCurrency: "USD",
AFEventParamQuantity: 2,
AFEventParamContent: "shoes",
AFEventParamContentId: "092",
AFEventParamReceiptId: "9277"]);
5.6 オフラインで発生したアプリ内イベントの計測
インターネット接続が利用できないときにユーザーがイベントを開始した場合でも、Appsflyerはそれを記録できます。裏側の仕組み:
- SDKはイベントをAppsFlyerのサーバーに送信し、応答を待ちます。
- SDKが200のサーバーレスポンスを受け取らなかった場合、イベントはキャッシュに保存されます。
- 次の200サーバーレスポンスが受信されると、保存されたイベントはサーバーに再送信されます。
- キャッシュに複数のイベントがある場合は、それらはイベントを次々にサーバーに送信されます。
注
SDKのキャッシュには最大40のイベントを保存できます。つまり、オフライン時に発生した最初の40のイベントのみが保存されます。次の200のサーバーレスポンスまでに発生した、41個目以降のイベント情報はすべては破棄されます。
ローデータに表示されるevent timeは、ユーザーの端末が再びオンラインになった後にイベントがAppsFlyerに送信された時間で、イベントが実際に発生した時間ではありません。
5.7 アプリ内イベント計測時の、成功と失敗の処理
- アプリ内イベントが正常に記録
- アプリ内イベントの記録中にエラーが発生
[[AppsFlyerLib shared] logEventWithEventName:AFEventPurchase
eventValues: @{
AFEventParamRevenue: @200,
AFEventParamCurrency: @"USD",
AFEventParamQuantity: @2,
AFEventParamContentId: @"092",
AFEventParamReceiptId: @"9277"
}
completionHandler:^(NSDictionary<NSString *,id> * _Nullable dictionary, NSError * _Nullable error){
if(dictionary != nil) {
NSLog(@"In app callback success:");
for(id key in dictionary){
NSLog(@"Callback response: key=%@ value=%@", key, [dictionary objectForKey:key]);
}
}
if(error != nil) {
NSLog(@"In app callback error:", error);
}
}];
AppsFlyerLib.shared().logEvent(name: "In app event name", values: ["id": 12345, "name": "John doe"], completionHandler: { (response: [String : Any]?, error: Error?) in
if let response = response {
print("In app event callback Success: ", response)
}
if let error = error {
print("In app event callback ERROR:", error)
}
})
}
アプリ内イベントの記録時にエラーが発生した場合には、次の表のようにエラーコードと文字列での説明が提供されます。
エラーコード | 文字列の説明 |
---|---|
10 |
"Event timeout. Check 'minTimeBetweenSessions' param" |
11 |
"Skipping event because 'isStopTracking' enabled" ( |
40 |
Network error: Error description comes from Android |
41 |
"No dev key" |
50 |
"Status code failure" + actual response code from the server |
6. OneLinkでのディープリンク
OneLinkは、AppsFlyerが提供するマルチプラットフォーム向けの計測と リダイレクトとディープリンクのためのソリューションです。
6.1 デバイスの検知とリダイレクト
OneLinkはクリック時に端末種別を検知し、ユーザーを適切なページ(Google Play、iOS AppStore、それ以外のストア、Webページなど)にリダイレクトします。
OneLinkリダイレクトのガイドでは、マルチプラットフォームの計測リンクの実装について説明しています(SDKのコーディングは不要です)。また、ディープリンクの基盤でもあります。
6.2 ディープリンク
ディープリンクを使用すると、ユーザーを特定のアクティビティに誘導し、カスタマイズされたコンテンツを提供できます。これは、リターゲティングキャンペーンを実行するときに特に役立ちます。
OneLinkでのディープリンクを設定するには AppsFlyerの管理画面へのアクセス権限を持つマーケティング担当者と、アプリの編集権限を持つ開発者担当者の協力が必須です。
OneLinkでのディープリンク設定 のガイドを参照してください。
6.3 ディファードディープリンク
ディファードディープリンクを使用すると、新規ユーザーをディープリンクさせ、アプリの初回起動時にカスタマイズされたコンテンツを提供できます。これは、ユーザーの端末に既にアプリがインストールされている必要がある、通常のディープリンクとは異なります。
OneLinkでのディファードディープリンクを設定するには、開発者担当者もAppsFlyerの管理画面へアクセスする必要があります。
ディファードディープリンクの設定は、ディープリンクと同じです。唯一の違いは、ユーザーがアプリをインストールして起動した後に、ユーザーをディープリンクさせてカスタマイズされたコンテンツを提供するために、アプリに追加のロジックを実装する必要がある点です。
詳細については、ディファードディープリンクのガイドを参照してください。
6.4 ディープリンクデータの取得
SDKは、すべてのインストールまたはディープリンクイベントに伴う、コンバージョンデータまたはエンゲージメントデータを提供します。このデータを使用することで、コンテンツとアプリの動作をプログラムしてカスタマイズできます。
ディープリンクが使用され、アプリが直接開かれたときにディープリンクデータを取得するには、onAppOpenAttributionのメソッドを実装してください。
ディープリンクのリエンゲージメントデータをいつでも手動で取得するには、performOnAppAttributionのメソッドを実装してください。これにより、新しいリエンゲージメントを記録せずにリエンゲージメントデータにアクセスできます。
詳細については、ディープリンクデータのガイドを参照してください。
6.5 プッシュ通知からのディープリンク処理の設定
addPushNotificationDeepLinkPath
のメソッドを使えば、プッシュ通知のペイロードからディープリンクに必要な情報を取得する方法を、柔軟なインターフェイス上で提供します。
デフォルトの設定では、AppsFlyerのSDK はプッシュ通知のJSON
ペイロード内で af
キーに紐付くディープリンクの値を検索します。プッシュ通知機能のプロバイダーの多くは、SDK側が追加の設定を行わないと解決できない独自の JSON
スキーマを使用します。
addPushNotificationDeepLinkPath
を使用すると、プッシュ通知の JSON ペイロードのどのキーをSDKがディープリンクの値に使用するかを設定できるようになります。
AppsFlyer SDK が想定する、デフォルトのプッシュ通知のJSONスキーマを使用しないプッシュ通知プロバイダーとアプリを連携する場合には、このメソッドを使用してください。
addPushNotificationDeepLinkPath
を呼び出すと、SDKは以下のことを検証します:
- 必要なキーがペイロード内に存在しているか
- そのキーに有効なOneLink URLが含まれているか
一般的な実装
addPushNotificationDeepLinkPath
の以下の呼び出しと
[AppsFlyerLib shared] addPushNotificationDeepLinkPath:@[@"deeply", @"nested", @"deep_link"]]
AppsFlyerLib.shared().addPushNotificationDeepLinkPath(["deeply", "nested", "deep_link"])
それに紐付くシナリオを確認してください。
シナリオ1
プッシュ通知経由でアプリが起動され、以下のような構造のペイロードが含まれていたとします。
{
...
"deeply": {
"nested": {
"deep_link": "https://yourdeeplink2.onelink.me"
}
}
...
}
この場合、SDKはdeep_link
の値を抽出し、ディープリンクのフローを続行します。
シナリオ2
プッシュ通知経由でアプリが起動され、以下のような構造のペイロードが含まれていたとします。
{
...
"deeply": {
"nested": {
"banana": "https://yourdeeplink2.onelink.me"
}
},
...
}
この場合、呼び出しが実行されても、SDKはペイロード内にdeep_link
のキーを見つけることができず、結果、何も起きません。(=ディープリンクしない)
シナリオ3
プッシュ通知経由でアプリが起動され、以下のような構造のペイロードが含まれていたとします。
{
...
"deeply": {
"nested": {
"deep_link": "Corrupted url or regular string"
}
},
...
}
この場合、SDKはdeep_link
のキーを検出しますが、そのディープリンクの値は無効です。そのため、上記の呼び出しが実行されても何も起こりません。
高度な設定
複数のペイロード構造を設定するには、addPushNotificationDeepLinkPath
を複数回呼び出してください:
- 有効なディープリンクの値を与えた最初のコールが使用されます。
- 他の呼び出しは無視されます。
一致するペイロードの構造がない場合や、有効なOneLink URLがペイロード内に見つからなかった場合には、何も起こりません。
たとえば、以下のペイロードの場合に
{
...
"deeply": {
"nested": {
“deep_link”: “https://yourdeeplink2.onelink.me”
}
},
“this”: {
“is”: {
"banana": "phone"
}
}
...
}
addPushNotificationDeepLinkPath
を呼び出した場合です。
// this.is.deep_link key isn’t found - nothing happens
[AppsFlyerLib shared] addPushNotificationDeepLinkPath:@[@"this", @"is", @"deep_link"]]
// this.is.banana key found, but contains invalid OneLink URL - nothing happens
[AppsFlyerLib shared] addPushNotificationDeepLinkPath:@[@"this", @"is", @"banana"]]
// deeply.nested.deep_link key found and contains valid OneLink URL - proceed deep linking flow
[AppsFlyerLib shared] addPushNotificationDeepLinkPath:@[@"deeply", @"nested", @"deep_link"]]
// this.is.deep_link key isn’t found - nothing happens
AppsFlyerLib.shared().addPushNotificationDeepLinkPath(["this", "is", "deep_link"]);
// this.is.banana key found, but contains invalid OneLink URL - nothing happens
AppsFlyerLib.shared().addPushNotificationDeepLinkPath(["this", "is", "banana"])
// deeply.nested.deep_link key found and contains valid OneLink URL - proceed deep linking flow
AppsFlyerLib.shared().addPushNotificationDeepLinkPath(["deeply", "nested", "deep_link"])
7. コンバージョンデータの取得
コンバージョンデータの取得
新規インストール毎に、リアルタイムにユーザーの計測データをSDKから直接取得できます。
これにより、ユーザーにパーソナライズされたコンテンツを提供したり、アプリ内の特定のアクティビティに遷移させたりすることができ(このページ内のディファードディープリンクを参照してください。)、ユーザーのアプリへのエンゲージメントを大きく高めることが可能です。
iOS SDKからAppsFlyerのコンバージョンデータを取得するには、次のメソッドを実装してください。
- (void) onAppOpenAttribution:(NSDictionary*) attributionData {
NSLog(@"onAppOpenAttribution");
for(id key in attributionData){
NSLog(@"onAppOpenAttribution: key=%@ value=%@", key, [attributionData objectForKey:key]);
}
}
- (void)onAppOpenAttributionFailure:(NSError *)error {
NSLog(@"%@", [error description]);
}
-(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");
}
}
-(void)onConversionDataFail:(NSError *) error {
NSLog(@"%@", [error description]);
}
class AppDelegate: UIResponder, UIApplicationDelegate, AppsFlyerLibDelegate{
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
AppsFlyerLib.shared().appsFlyerDevKey = "MY_DEV_KEY"
AppsFlyerLib.shared().appleAppID = "123456789"
AppsFlyerLib.shared().delegate = self
//AppsFlyerLib.shared().isDebug = true
//AppsFlyerLib.shared().appInviteOneLinkID = "ONELINK_ID";
return true
}
func applicationDidBecomeActive(_ application: UIApplication) {
AppsFlyerLib.shared().start()
}
func onConversionDataSuccess(_ installData: [AnyHashable: Any]) {
guard let first_launch_flag = installData["is_first_launch"] as? Int else {
return
}
guard let status = installData["af_status"] as? String else {
return
}
if(first_launch_flag == 1) {
if(status == "Non-organic") {
if let media_source = installData["media_source"] , let campaign = installData["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 onConversionDataFail(_ error: Error!) {
if let err = error{
print(err)
}
}
func onAppOpenAttribution(_ attributionData: [AnyHashable : Any]!) {
if let data = attributionData{
print("\(data)")
}
}
func onAppOpenAttributionFailure(_ error: Error!) {
if let err = error{
print(err)
}
}
最も重要な2つのメソッドは:
-
onConversionDataSuccess
- 新規インストール時のコンバージョンデータを提供します。
注: SDK ver5以降、
onConversionDataSuccess
がコンバージョンデータを取得するメソッドの名称です。5.0.0より前のSDKバージョンを使用している場合、メソッドの名前はonConversionDataReceived
です。SDK ver5.0.0にアップグレードすることをお勧めします。詳細についてはこちらをクリックしてください。 -
onAppOpenAttribution
- 手動またはディープリンクを介してインストール済みのアプリを起動したときに、リターゲティングコンバージョンデータを提供します。
コンバージョンデータの詳細については、コンバージョンデータのシナリオに関するガイドを参照してください。
8. アトリビューション
アンインストール計測
アンインストール計測の実装方法については、 こちらを参照してください。
SDK起動ハンドラーの設定
SDKが正常に起動し、AppsFlyerサーバーに通知されたことを確認したい場合には、 startWithCompletionHandler
というhandlerを実装してください。その後、SDK起動の成功または失敗を処理するロジックを適用できます。
実装例
[[AppsFlyerLib shared] startWithCompletionHandler:^(NSDictionary<NSString *,id> *dictionary, NSError *error) {
if (error) {
NSLog(@"%@", error);
return;
}
if (dictionary) {
NSLog(@"%@", dictionary);
return;
}
}];
AppsFlyerLib.shared()?.start(completionHandler: { (dictionnary, error) in
if (error != nil){
print(error ?? "")
return
} else {
print(dictionnary ?? "")
return
}
})
リクエストリスナー中にエラーが発生した場合には、次の表に示すように、エラーコードと文字列での説明が提供されます。
エラーコード | 文字列の説明 |
---|---|
10 |
"Event timeout. Check 'minTimeBetweenSessions' param" |
11 |
"Skipping event because 'isStopTracking' enabled" ( |
40 |
Network error: Error description comes from Android |
41 |
"No dev key" |
50 |
"Status code failure" + actual response code from the server |
カスタムデータの追加設定
Segment、Adobe、Urban Airshipなどの外部のパートナープラットフォームとSDKレベルで連携する際には、setAdditionalData
のAPIが必要です。このAPIは、各プラットフォームの連携のサポートページに、setAdditionalData
のAPIが必要であると記載されている場合にのみ、使用してください。
setAdditionalData
コード例:
NSDictionary* CustomDataMap = [[NSDictionary alloc] initWithObjectsAndKeys:@"value_of_param_1", @"custom_param_1", nil];
[[AppsFlyerLib shared] setAdditionalData:CustomDataMap];
let CustomDataMap: [AnyHashable: Any] = [
"custom_param_1" : "value_of_param_1"
]
AppsFlyerLib.shared().customData = CustomDataMap
自社Webサイト(ドメイン)から生まれたアプリ起動の計測
(OneLink以外で)ディープリンクのためにユニバーサルリンクを使用し、アプリに関連付けられたドメインを持っている広告主は、appendParametersToDeepLinkingURL
のメソッドを使用することで、それらのドメインを介して開始された起動を計測できます。
たとえば、ユーザーがGoogleで検索し御社のドメイン:www.example.comをクリックしたとします。
- ユーザーがアプリをインストールしていない場合には、そのままWebサイト(www.example.com)に遷移します。
- ユーザーが既にアプリを端末にインストールしている場合には、www.example.comに関連付けられたアプリがディープリンク起動されます。この起動イベントを
appendParametersToDeepLinkingURL
内で指定されたメディアソース (pid
パラメータ)に紐づけて計測することができます。
詳細は、iOS SDKのAPIリファレンスを参照してください。
Point: スマートバナーは、Webサイトに訪問したユーザーをアプリユーザーに変換するのにとても役立ちます。
9. セッション
カスタムのセッション間隔
デフォルトでは、それぞれ別のセッションとしてカウントされるには、2つのアプリ起動の間隔が少なくとも5秒以上あいている必要があります(詳細は 「セッション数のカウント」を参照してください)。
セッション間の最小時間を設定したい場合には、次のAPIを使用してください:
[AppsFlyerLib shared].minTimeBetweenSessions = <your_custom_time_in_seconds>;
AppsFlyerLib.shared().minTimeBetweenSessions = <your_custom_time_in_seconds>
セッション間のカスタム時間に大きい値を設定すると、ディープリンクなどのセッションデータに依存するAPI へ悪影響を与える可能性があるので注意してください。
ユーティリティ系アプリ向けバックグラウンドセッション
iOSでは利用できません。
10. 自社メディア
加工されたDeep Link URLsの解決方法
メールサービスプロバイダー(ESP)などの一部のサードパーティサービスは、独自のクリック計測用ドメインでメール内の計測リンクを変換してしまいます。一方で元々のクリック計測URLを設定できるものもあります。もしもOneLinkがクリック計測用に変換された場合、OneLinkの機能が制限される可能性があります。
この問題を解決するには、 setResolveDeepLinkURLs
のAPIを使用してください。このAPIを使用することで、アプリを起動するクリックドメインからOneLinkを取得することが可能です。このAPIはSDK初期化よりも前に必ず呼び出してください。
たとえば、あなたのOneLink(https://mysubdomain.onelink.me/abCD)にリダイレクトする3つのクリックドメインがあったときにも、このAPIを使用することでそのクリックドメインたちがリダイレクトするOneLinkを取得可能です。このAPIメソッドには、SDKが分析するクリックドメインのリストが必要です。
[AppsFlyerLib shared].resolveDeepLinkURLs = @[@"example.com",@"click.example.com"];
AppsFlyerLib.shared().resolveDeepLinkURLs = ["example.com", "click.example.com"]
上記のコードを使用すると、OneLinkの機能を維持しながらクリックドメインを使用できます。そのクリックドメインは、アプリの起動を担います。このAPIは、順番に、これらのクリックドメインからOneLinkを取得し、そのデータを使ってカスタマイズされたユーザーコンテンツへのディープリンクを可能にします。
プッシュ通知の計測
AppsFlyerでは、リターゲティングキャンペーンの一部として、プッシュ通知を計測できます。
この機能を有効にするには、AppDelegate.m内で handlePushNotificationData
のメソッドを呼び出してください。
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[[AppsFlyerLib shared] handlePushNotification:userInfo];
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
AppsFlyerLib.shared().handlePushNotification(userInfo)
}
プッシュ通知の計測に関する詳細は、こちらを参照してください。
ユーザー招待の計測
アプリの既存ユーザーがアプリに友人を招待できるようにすることが、アプリインストール増加のきっかけとなる場合があります。AppsFlyerを使用することで、アプリ内のユーザー招待から発生したインストールの計測を行うことが可能です。
詳細は、ユーザー招待の計測のガイドを参照してください。
相互送客(クロスプロモーション)の計測
注意! IDFVによるクロスプロモーションの実施には、SDK V6.0.2以上の実装が必要になります。なお、IDFVは自動的に収集されるので、アプリ開発者側での追加作業は不要です。
アプリのクロスプロモーションは、アプリのインストールを促進する重要な要素となる場合があります。AppsFlyerを使用することで、ユーザーが既に持っているアプリ内に表示された、別アプリのクロスプロモーションで発生したインストールの計測が可能になります。詳細は、クロスプロモーション計測のページを参照してください。11. ユーザー識別子
AppsFlyer IDの取得
AppsFlyer IDは、ユーザーがアプリをインストールする度に作成されるユニークなIDで、さまざまな目的に利用可能です。
- サーバー間(S2S)イベントを送信するとき
- 広告主側で持っているシステム上のユーザー情報と一致させるとき
- Pull APIとPush APIのデータをマージするときに、各データを突合させるとき
AppsFlyer IDを取得するには、次のAPIを使用してください。
NSString *appsflyerId = [AppsFlyerLib shared].getAppsFlyerUID;
let appsflyerId = AppsFlyerLib.shared().getAppsFlyerUID()
カスタマーユーザーIDの設定
カスタマーユーザーIDを設定するには:
[AppsFlyerLib shared].customerUserID = @"my user id";
AppsFlyerLib.shared().customerUserID = "my user id"
iOSでは、アプリを起動するたびにカスタマーユーザーIDを設定する必要があります。設定された後に計測されたイベントにしかカスタマーユーザーIDを紐付けられないので、AppsFlyerでは、 アプリ利用の一連の流れの中で、できる限り早いタイミングでカスタマーユーザーIDを設定することをお勧めしています。
start
を呼び出す前にsetCustomerUserId
が呼び出された場合には、インストールおよびイベントのローデータレポートにカスタマーユーザーIDが表示されます。- trackAppLaunchよりも後に設定された場合には、カスタマーユーザーIDはその設定後に計測されたイベントへのみ紐付けられます。
カスタマーユーザーIDの取得
最初の起動後にカスタマーユーザーIDの値を再度設定したり、IDを取得する通信をあなたのサーバーに必要以上にしないように、以下のコードを使用してIDの値が空かどうかを確認できます。
NSString *customerUserID = [AppsFlyerLib shared].customerUserID;
let customerUserID = AppsFlyerLib.shared().customerUserID
カスタマーユーザーIDの詳細については、こちらをクリックしてくだい。
customerUserIDのためのSDK初期化の遅延
Customer User IDが設定されるまで、SDKの初期化を遅らせることも可能です。これは、インストールデータとアプリ内イベントデータの両方にCustomer User IDを含めたい場合に有効です。
次のコードを実装してください。
- (void)applicationDidBecomeActive:(UIApplication *)application {
NSString *customUserId = [[NSUserDefaults standardUserDefaults] stringForKey:@"customerUserId"]; // Your custom logic of retrieving CUID
if (customUserId != nil && ![customUserId isEqual: @""]) {
[AppsFlyerLib shared].customerUserID = customUserId; // Set CUID in AppsFlyer SDK for this session
[[AppsFlyerLib shared] start]; // Start
}
}
func applicationDidBecomeActive(_ application: UIApplication) {
let customUserId = UserDefaults.standard.string(forKey: "customUserId") // your logic to retrieve CUID
if(customUserId != nil && customUserId != ""){
AppsFlyerLib.shared().customerUserID = customUserId // Set CUID in AppsFlyer SDK for this session
AppsFlyerLib.shared().start() // Start
}
}
カスタマーユーザーIDが利用可能になるまでSDKの初期化を遅らせる方法の詳細については、こちらを参照してください。
警告
ビジネスロジックに適している場合に限り、このAPIを使用してください。このAPIを使用すると、数値の乖離が発生する可能性が高くなるだけでなく、アプリに対して不正が行われる可能性も高くなります。
12. ユーザープライバシー
オプトアウト
稀ではあっても場合によっては、法律やプライバシー遵守のために、すべてのSDKにおける計測を停止しなければならないケースがあります。その場合、isStoppedのプロパティを利用可能です。一度このプロパティがtrueに設定されと、AppsFlyer SDKは動作を停止し、すべての情報はAppsFlyerサーバーに送信されなくなります。
ユーザーのオプトアウトには、さまざまなケースがあります。AppsFlyerでは、アプリに適したシナリオにあわせて正しい手順を守って実装するよう推奨しています。
警告
このAPIは、当該ユーザーに関する全計測において、一切計測しないという対応が必要な場合にのみ使用してください。このAPIの使用は、各種計測やデータ取得、ディープリンクの機能に大きな影響を与えますのでご注意ください。
[AppsFlyerLib shared].isStopped = true;
AppsFlyerLib.shared().isStopped = true
なお、同じAPIにてfalseを渡して呼び出すことにより、SDKを再アクティブ化することができます。
重要!
isStopped
がtrue
に設定されている場合には、start
を呼び出さないでください。
計測を再開するには、isStopped
をfalse
に変更してください。
ユーザーデータの匿名化
ユーザーのインストール、イベント、セッションの計測を明示的に匿名化するには、SDKの初期化中にこのAPIを使用してください。
[AppsFlyer shared].disableAdvertisingIdentifier= YES;
AppsFlyerLib.shared().disableAdvertisingIdentifier= true
anonymizeUser
を false に設定することで、データの計測を再開できます。
警告
ユーザーを匿名化することにより、アトリビューション情報に悪影響があります。ユーザーの情報を収集することが法的に禁じられている場合にのみ、このオプションを使用してください。
App Tracking Transparency (ATT)のサポートの実装
Appleの声明によれば、iOS14.5以降、IDFAの収集においてユーザーの同意が必要になると言われています。実際には、IDFAへのアクセスはApp Tracking Transparency (ATT) によって管理されることを意味します。そのため、iOS14.5以降の端末においては、AppsFlyerのiOS SDKもATTのフレームワークを利用して端末のIDFAへのアクセスを得ることになります。
IDFAを利用した計測が発生する場合には、IDFAが初回起動(first launch)のイベントとともに送信されることが重要になります。このため、AppsFlyer SDKではwaitForATTUserAuthorization
という機能を提供しています。
実装の概要
waitForATTUserAuthorization
を使用することで、ATTへの同意が完了するのを待って、AppsFlyerサーバーへデータ送信するのを延期する期間を設定することが可能です。ATTを完全にサポートするには以下が必要になります:
- アプリの初期化段階における
waitForATTUserAuthorization
の設定 - ATTの同意ダイアログを表示したときには、いつでも
ATTrackingManager.requestTrackingAuthorization
を呼び出す設定
waitForATTUserAuthorizationについて
ユーザーがアプリを起動した時、ATTステータスはundetermined(未確定)の状態です。waitForATTUserAuthorization
のタイムアウト中:
- SDKは、オフライン時のイベント計測方法と同様の方式で、起動イベントとその後のアプリ内イベントをメモリ内に待機させます。
- ユーザーがIDFAの取得に同意(=ATTに同意)した場合、SDKはメモリ内に待機させられたイベントにIDFAの情報を追加し、タイムアウトの終了を待たずに計測を開始します。
- タイムアウトが終了しATTの同意が得られなかった場合(=unauthorized)/未確定(=undetermined)だった場合、SDKはメモリ内に待機させられたイベントにIDFAの情報を追加せずに送信し、計測を開始します。
注意事項
-
タイムアウトが終了し、ATTの 同意ステータスが未確定(=undetermined)のままだった場合 :
- iOS 14.5未満: IDFAはデフォルトで収集されます。
- iOS 14.5以降: IDFAはデフォルトで収集されません。
- タイムアウト中にユーザーがアプリをバックグラウンドに移動した場合:
- ユーザーが再度アプリを表示させる(フォアグラウンドに戻す)まで、タイマーが一時停止します。
- イベントはメモリ内にキャッシュされます。
- タイムアウト中にユーザーがアプリをシャットダウンまたは強制終了(=キル)した場合:
- タイマーは、次回のアプリの起動時に再開されます。
- キャッシュされたイベントは削除されます。
注意点
-
iOS14.5以降のIDFA収集には、
waitForATTUserAuthorization
の実装が必要です。WaitForattUserAuthorization
を呼び出さないと、IDFAの欠けた状態で起動情報が送信されてしまうので注意してください。 requestTrackingAuthorization
のコールバック内でstart
を呼び出してしまうと、正しい計測が行われなくなってしまうので注意してください。
iOS SDKでのATTサポートの実装
iOS SDKでATTのサポートを実装するには:
-
初期化コードの中で、
waitForATTUserAuthorization
を設定してください。- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [[AppsFlyerLib shared] setAppsFlyerDevKey:@"<AF_DEV_KEY>"]; [[AppsFlyerLib shared] setAppleAppID:@"<APPLE_APP_ID>"]; [[AppsFlyerLib shared] setDelegate:self]; [[AppsFlyerLib shared] waitForATTUserAuthorizationWithTimeoutInterval:60]; return YES; }
class AppDelegate: UIResponder, UIApplicationDelegate, AppsFlyerLibDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { AppsFlyerLib.shared().appsFlyerDevKey = "<AF_DEV_KEY>" AppsFlyerLib.shared().appleAppID = "<APPLE_APP_ID>" AppsFlyerLib.shared().delegate = self AppsFlyerLib.shared().waitForATTUserAuthorization(timeoutInterval: 60) ... } ... }
-
アプリケーションのコード内で
ATTrackingManager.requestTrackingAuthorization
を呼び出して、ATTの同意ダイアログを表示してください。たとえば、特定の画面のロードが完了した際にATTの同意ダイアログをユーザーに提示したい場合には、以下のような実装になります:- (void)viewDidLoad { [super viewDidLoad]; [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) { NSLog(@"Status: %lu", (unsigned long)status); }]; }
override func viewDidLoad() { super.viewDidLoad() ATTrackingManager.requestTrackingAuthorization { (status) in } }
このコールでATTの同意ダイアログがトリガーされます。
ATTの同意ダイアログのカスタマイズ
子ども向けアプリ
Appleの審査を通過し、AppStoreで子ども向けアプリとして表示されるようにするには、アプリが個人を特定できる情報や端末情報を第三者に "送信してはいけません。"これを遵守するには、AdSupport および iAd frameworkを明示的に無効にする必要があります。
ad frameworkを無効にするには:
[AppsFlyerLib shared].disableCollectASA = YES [AppsFlyerLib shared].disableAdvertisingIdentifier = YES;
AppsFlyerLib.shared().disableCollectASA = true AppsFlyerLib.shared().disableAdvertisingIdentifier = true
データ取得からのパートナーの除外
場合によっては、アドネットワークやパートナーに対する特定ユーザーのユーザーレベルのデータ共有を停止したい場合があるかと思います。その理由としては:
- CCPAやGDPRのようなプライバシーポリシー
- ユーザーによるオプトアウト
- 一部パートナー(広告ネットワーク/第三者ツール)との競合
AppsFlyerでは、一部またはすべてのパートナーとのデータ共有を停止するための、2つのAPIメソッドを用意しています。
- SetSharingFilter:一部)(1社もしくは複数)のアドネットワーク/連携パートナーとのデータ共有を停止する際に使用します 。
- setSharingFilterForAllPartners : すべての アドネットワーク/連携パートナーとのデータの共有を停止する際に使用します。
これらのフィルタリングメソッドは、SDK V5.4.1からサポートされています。
このフィルタリングメソッドは、SDK が初期化される毎に呼び出されなければならず、セッション全体に影響を与えます。このフィルタを設定する必要があるかどうかを判断するのに時間がかかる場合には、SDKの初期化を遅延させてください。
最初のstartの呼び出しよりも前にこのメソッドがアクティブ化された場合 :
- SRN経由のユーザーはOrganicユーザーと見なされ、 そのユーザーのデータは連携パートナーとも共有されません。
- 通常のアドネットワーク (SRN以外)経由のユーザーは 、AppsFlyer上で正しく媒体へ紐付けされますが、ポストバック、API、ローデータレポート、またはその他の方法においてアドネットワークへデータは共有されません。
現在、これらのメソッドを使用してアンインストールに関するデータをフィルタリングすることはできませんが、AppsFlyerの連携設定ページ を使用して、各パートナーへのアンインストールイベントのポストバック送信は停止することができます。
continueUserActivity
説明 |
iOS9以降でアプリがユニバーサルリンクから起動されたときにonAppOpenAttribution を呼び出します。 |
メソッドのシグネチャ |
|
使用例: |
|
currencyCode
説明 |
収益イベントの通貨コードを設定します。ISO通貨コードを受け入れます。 |
メソッドのシグネチャ |
|
使用例: |
|
anonymizeUser
説明 |
ユーザーのインストール、イベント、およびセッションを匿名化します。より詳細は、 こちらを参照してください。 |
メソッドのシグネチャ |
|
使用例: |
|
disableCollectASA
説明 |
SDKバージョン4.8.11以降、AppsFlyer SDKはAppleのiAd.frameworkを動的に読み込みます。このフレームワークは、AppsFlyer上でApple Search Adsの成果を計測するために必要です。AppsFlyerSDKにこのフレームワークを動的に読み込ませたく場合には、このプロパティをtrueに設定してください。 |
メソッドのシグネチャ |
|
使用例: |
|
handleOpenUrl
説明 |
このメソッドは、アプリがURIスキームでのディープリンクによって開かれたに、そのURIスキームをAppsFlyer SDKに報告します。このメソッドはAppDelegate内に配置されます。 |
メソッドのシグネチャ |
|
使用例: |
|
handlePushNotification
説明 |
プッシュ通知キャンペーンからデータを測定して取得します。詳細については、 プッシュ通知の計測を参照してください。 |
メソッドのシグネチャ |
|
使用例: |
|
isDebug
説明 |
Xcodeのコンソール上でAppsFlyer SDKのログを表示します。デバッグは開発環境でのみ実施してください。デバッグを有効にしたまま、アプリストアへアプリを公開しないでください。重大なセキュリティとプライバシーのリスクをもたらします。 |
メソッドのシグネチャ |
|
使用例: |
|
isStopped
説明 |
すべてのSDK機能をシャットダウンします。詳細は、「 ユーザープライバシー:オプトアウト 」を参照してください。 |
メソッドのシグネチャ |
|
使用例: |
|
onAppOpenAttribution
説明 |
アプリがディープリンク起動されたときに、ディープリンクのデータを取得します。 |
メソッドのシグネチャ |
|
使用例: |
|
onAppOpenAttributionFailure
説明 |
ディープリンクデータを取得する際のエラーを処理します。 |
メソッドのシグネチャ |
|
使用例: |
|
onConversionDataSuccess
説明 |
インストール後にそのインストールのコンバージョンデータを取得します。ディファードディープリンクに役立ちます。 注: SDK ver5以降、 |
メソッドのシグネチャ |
|
使用例: |
|
onConversionDataFail
説明 |
インストールのコンバージョンデータを取得できない時のエラーを処理します。 |
メソッドのシグネチャ |
|
使用例: |
|
didResolveDeepLink
説明 |
アプリが開かれたらすぐに、アプリのインストールの有無に関係なく、特定のアプリ内アクティビティにユーザーを遷移させます。詳細はこちら |
メソッドのシグネチャ |
|
performOnAppAttribution
説明 |
開発者は、新しいリエンゲージメントが記録されない場合においても、特定のリンク (URIまたはURL) を使用してonAppOpenAttributionを手動で再度発火させることができます。この方法は、アプリが指定のリンクに基づいてユーザーをリダイレクトさせる必要がある場合、または 前景/開いたまま AppsFlyerの短いURLを解決する必要がある場合に必要になる場合があります。通常、 アプリがディープリンクで開かれた 場合にのみ、OnAppOpenAttributionのコールバックが呼び出されるため、こちらのAPIが必要になる可能性があります 。 |
メソッドのシグネチャ |
|
使用例: |
|
registerUninstall
説明 |
アンインストールを計測します。iOSのアンインストール計測を参照してください。 |
メソッドのシグネチャ |
|
使用例: |
|
resolveDeepLinkURLs
説明 |
クリックドメインからのOneLinkを解決します。詳細については、 変換されたディープリンクURLの解決方法を参照してください。 |
メソッドのシグネチャ |
|
使用例: |
|
setAdditionalData
説明 |
外部のパートナープラットフォームに送信されるデータを追加します。 |
メソッドのシグネチャ |
|
使用例: |
カスタムデータの追加設定を参照してください。 |
setAppInviteOneLink
説明 |
ユーザー招待用のカスタム計測リンクの作成に使用される、OneLinkテンプレートのIDを設定します。 |
メソッドのシグネチャ |
|
使用例: |
ユーザー招待の計測におけるOneLink設定を参照してください。 |
setAppleAppID
説明 |
SDKが正しいアプリ管理画面にデータを送信できるように、アプリID( iTunes ID )を設定します。SDKの初期化のときに使用します。 |
メソッドのシグネチャ |
|
使用例: |
|
appsFlyerDevKey
説明 |
SDKが正しいアプリ管理画面にデータを送信できるように、AppsFlyerのdev keyを設定します。 SDKの初期化のときに使用します。. あなたのdev keyの取得方法については、こちらを参照してください。 |
メソッドのシグネチャ |
|
使用例: |
|
setCustomerUserID
説明 |
カスタマーユーザーIDを設定します。詳細については、カスタマーユーザーIDの設定を参照してください。 |
メソッドのシグネチャ |
|
使用例: |
カスタマーユーザーIDの設定を参照してください。 |
setPartnerData
説明 |
パートナーと広告主側で、SDKイベントにデータを更に追加できるようになります。 |
メソッドのシグネチャ |
|
使用例: |
|
setSharingFilter
説明 |
広告主がデータ共有から除外するアドネットワーク/連携パートナーを設定するために使用します 。 |
メソッドのシグネチャ |
|
使用例: |
|
setSharingFilterForAllPartners
説明 |
広告主がすべてのアドネットワーク/連携パートナーに対して、データを共有しないようにするために使用します。 |
メソッドのシグネチャ |
|
使用例: |
|
setShouldCollectDeviceName
説明 |
SDKが端末名を収集するかどうかを決めます。デフォルト設定はfalseです。 |
メソッドのシグネチャ |
|
使用例: |
|
setUseUninstallSandbox
説明 |
開発中(AppleのAppStoreにまだ公開されていない)のアプリのアンインストールをテストする時には、このプロパティをtrueに設定してください。 |
メソッドのシグネチャ |
|
使用例: |
|
startWithCompletionHandler
説明 |
start が成功したかどうかを確認します。その後、SDK起動の成功または失敗を処理するロジックを実装できます。 |
メソッドのシグネチャ |
|
使用例: |
SDK が正常に起動したことを確認 するを参照してください。 |
logEvent
説明 |
アプリ内イベントのAppsFlyerへの送信詳細については、 アプリ内イベントの計測を参照してください。 |
メソッドのシグネチャ |
|
使用例: |
|
validateAndLogInAppPurchase
説明 |
SDKが正しい管理画面へデータを送信できるように、AppsFlyer Dev Keyを設定してください。Dev Keyの取得方法についてはこちらを参照し、 SDKを初期化するときに使用してください。 |
メソッドのシグネチャ |
|
使用例: |
アプリ内購入の検証を参照してください。 |
disableAdvertisingIdentifier
説明 |
SDKバージョン4.8.11以降、AppsFlyer SDKはAppleのadSupport.frameworkを動的に読み込みます。このフレームワークは、計測目的でIDFAを収集するために必要です。AppsFlyerSDKにこのフレームワークを動的に読み込ませたく場合には、このプロパティをtrueに設定してください。 |
メソッドのシグネチャ |
|
使用例: |
[AppsFlyerLib shared].disableAdvertisingIdentifier=YES; AppsFlyerLib.shared().disableAdvertisingIdentifier= true |
waitForATTUserAuthorization
説明 |
IDFAなど、ユーザーや端末を記録するためのアプリ関連データにアクセスする前に、ポップアップでユーザー認証を要求 する場合に使用します。ユーザーがオプトインした場合、IDFA が SDKに渡されます。 Timeout Intervalにより、IDFAの取得をオプトインするまでの一定の時間がユーザに対して提供され、このタイマーの期限が切れると、IDFAは取得されません。 |
メソッドのシグネチャ |
|
使用例: |
|
start
説明 |
このAPIが呼び出されると、SDKが起動され、セッションがすぐに送信され、すべてのバックグラウンドからフォアグラウンドへの遷移においてセッションが記録されます。 |
メソッドのシグネチャ |
|
使用例: |
|
logLocation
説明 |
ユーザーローケーションをマニュアルで記録します |
メソッドのシグネチャ |
|
使用例: |
|
appendParametersToDeepLinkingURL
説明 |
OneLinKは使用せず、ディープリンク用のユニバーサルリンクを使用して、アプリに関連付けられたドメイン経由で開始させたセッションを計測できるようになります。start を呼び出す前に、このメソッドを呼び出してください。 このメソッドには以下が必要になります。
|
メソッドのシグネチャ |
|
使用例: |
|
addPushNotificationDeepLinkPath
説明 |
SDKがプッシュ通知のペイロードからディープリンクの値を抽出する方法を設定してください。 |
メソッドのシグネチャ |
|
使用例: |
この呼び出しは、以下のペイロードの構造と一致します:
|
disableSKAdNetwork
説明 |
SKAdNetworkの計測を無効にすることができます。true に設定することで無効化できます。 |
メソッドのシグネチャ |
|
使用例: |
|
コメント
サインインしてコメントを残してください。