こんにちは、株式会社PentagonでFlutterエンジニアをしているTakayaです。

モバイルアプリの成長において、適切なアトリビューション計測とディープリンク実装は欠かせません。しかし、AppsFlyerのFlutter導入は管理画面設定から実装まで多岐にわたり、特にATT(App Tracking Transparency)対応やプライバシー保護の観点で迷いやすいポイントが多数存在します。

【こんな人に読んでほしい】

  • FlutterでiOS/Androidアプリを開発・運用しているエンジニア
  • 広告計測/ディープリンク実装をこれから行う、または改善したいチーム
  • ATTやストア申請の観点を踏まえたプライバシー実装も押さえたいPM/EM

【この記事を読むメリット】

  • 管理画面の初期設定(マイアプリ登録/OneLinkテンプレート)の具体的手順と要点を理解する
  • Flutter SDK実装(初期化、ATT遅延、DeepLinkハンドリング)をコード付きで再現できる
  • プライバシー保護方針アトリビューション計測の実務注意点を把握する

【結論】 AppsFlyerの導入は管理画面設定→SDK実装(初期化、計測、ディープリンク)→プライバシー対応の3ステップで構成されます。適切な実装により、正確なアトリビューション計測とスムーズなディープリンク体験を実現できます。

【この記事の前提】

  • Flutter: 3.24.0以降
  • appsflyer_sdk: 6.14.0以降
  • iOS: 14.0以降(ATT対応)
  • Android: API Level 21以降

1. 初期設定(管理画面)

マイアプリ登録

AppsFlyerでの計測を開始するには、まず管理画面でアプリを登録する必要があります。

  • Devキー発行:アプリ実装で使用するアカウント識別子
  • 一般設定
    • Android:未公開でもパッケージ名で登録可能
    • iOS:アプリIDまたはストアURLが必要(開発時点でアプリIDはダミーでOK)

詳細な手順については、AppsFlyerマイアプリ登録ガイドを参照してください。

OneLinkテンプレート

OneLinkは、AppsFlyerが提供するディープリンク機能です。事前にマイアプリ登録が完了している必要があります。

設定項目

  • xxxx.onelink.meサブドメインを決定
  • 未インストール時の遷移先URLなどを設定

詳細な設定方法はOneLinkテンプレートガイドをご確認ください。

2. 実装仕様(Flutter SDK)

依存関係の追加

# pubspec.yaml
dependencies:
  appsflyer_sdk: ^6.14.0

AppsFlyer機能の実装

以下は、Flutterでよく用いられる状態管理ライブラリのRiverpodを使用した、AppsFlyer管理クラスAppsFlyerManagerの実装例です。


@Riverpod(keepAlive: true)
AppsFlyerManager appsFlyerManager(Ref ref) {
  final appsFlyerOptions = AppsFlyerOptions(
    afDevKey: 'YOUR_DEV_KEY', // 管理画面から取得
    // iOSのみAppIDが必要
    appId: Platform.isIOS ? 'YOUR_APP_ID' : '',
    // AppsFlyerへのデータ送信前に、ユーザーによるATT同意をどれくらいの時間待つか(60秒)
    timeToWaitForATTUserAuthorization: 60,
  );
  final appsFlyerSdk = AppsflyerSdk(appsFlyerOptions);
  return AppsFlyerManager(appsFlyerSdk);
}

class AppsFlyerManager {
  AppsFlyerManager(this._appsFlyerSdk);

  final AppsflyerSdk _appsFlyerSdk;

  Future<void> initialize() async {
    /// ディープリンクの初期化
    /// initSdk(SDKの初期化)より前に処理する必要あり
    _appsFlyerSdk.onDeepLinking((deepLinkResult) {
      if (deepLinkResult.status == Status.FOUND) {
        final deepLink = deepLinkResult.deepLink;
        if (deepLink != null) {
          _handleDeepLink(deepLink);
        }
      } else {
        print('AppsFlyerディープリンクエラー: ${deepLinkResult.error}');
      }
    });

    /// SDKの初期化
    await _appsFlyerSdk.initSdk(
      registerConversionDataCallback: true,
      registerOnAppOpenAttributionCallback: true,
      registerOnDeepLinkingCallback: true,
    );
  }

  /// 画面表示などのイベントログの送信
  Future<void> logEvent(
    String name, {
    required Map<String, dynamic> parameters,
  }) async {
    try {
      await _appsFlyerSdk.logEvent(name, parameters);
      print('AppsFlyerイベントログ送信成功: name=$name parameters=$parameters');
    } on Exception catch (e) {
      print('AppsFlyerイベントログ送信失敗: $e');
    }
  }

  /// ディープリンクハンドリング
  void _handleDeepLink(Map<String, dynamic> deepLinkData) {
    final deepLinkValue = deepLinkData['deep_link_value'] as String?;
    final deepLinkSub1 = deepLinkData['deep_link_sub1'] as String?;

    // アプリ内ナビゲーション処理
    if (deepLinkValue != null) {
      // 例:商品詳細画面への遷移
    }
  }
}

SDK起動遅延(ATT対応)

ATT(App Tracking Transparency)とは、ユーザーのアプリ内トラッキングを制御するプライバシー機能です。ユーザーが許可しない限り、アプリはデバイスの広告識別子(IDFA)にアクセスできず、ユーザー単位の分析が難しくなります。

重要な仕様

  • AppsFlyerへのデータ送信前に、ユーザーによるATT同意をどれくらいの時間待つかを設定
  • 遅延タイマーカウントはSDK初期化時に開始
  • 遅延待機中の挙動:
    • バックグラウンド遷移でフォアグラウンドに戻るまでタイマー一時停止イベントはキャッシュ保持
    • アプリキルで次回起動まで一時停止キャッシュは削除

ATT同意状況別のIDFA送信パターン

待機状況同意状況IDFA送信
待機内同意あり
待機内拒否なし
待機内無回答→満了なし
待機後同意あり(以降継続)
待機後拒否なし(以降継続)

3. アトリビューション計測

インストール計測AppsFlyerのSDKで自動取得されるため実装不要です。CUIDとして任意のIDを送信することで社内システムなどと連携させた分析も可能です。

// ユーザーID設定例
await _appsFlyerSdk.setCustomerUserId('user_123456');

4. アプリ内イベント計測

命名・文字数制約

イベント送信に含められるkeyは45文字以下とする必要があります。

実装例

Future<void> sendPurchaseEvent({
  required String productId,
  required double revenue,
  required String currency,
}) async {
  final eventParameters = {
    'af_revenue': revenue,
    'af_currency': currency,
    'af_content_id': productId,
    'af_content_type': 'product',
  };

  try {
    await _appsFlyerSdk.logEvent('af_purchase', eventParameters);
    print('購入イベント送信成功: $eventParameters');
  } catch (e) {
    print('購入イベント送信失敗: $e');
  }
}

5. OneLinkによるディープリンク

URL構造とパラメータ

URL例https://your-app.onelink.me/

主要パラメータ

  • deep_link_value:メインの値(画面名など)
  • deep_link_sub1〜10:追加パラメータ(商品ID、記事IDなど)

具体例

https://your-app.onelink.me/ABC1/screen?deep_link_value=product&deep_link_sub1=item_123&deep_link_sub2=campaign_summer

Flutterでのディープリンクハンドリング

void _handleDeepLink(DeepLink deepLink) {
  final deepLinkValue = deepLink.deepLinkValue;
  final deepLinkSub1 = deepLink.getStringValue('deep_link_sub1');
  final deepLinkSub2 = deepLink.getStringValue('deep_link_sub2');
  
  print('ディープリンク受信: screen=$deepLinkValue, deep_link_sub1=$deepLinkSub1, deep_link_sub2=$deepLinkSub2');
  
  // アプリ内ナビゲーション
  switch (deepLinkValue) {
    case 'product':
      _navigateToProduct(deepLinkSub1, deepLinkSub2);
      break;
    case 'article':
      _navigateToArticle(deepLinkSub1);
      break;
    default:
      _navigateToHome();
  }
}

6. プライバシー保護実装

AppsFlyerでは、プライバシー保護のための複数の設定が用意されています。詳細はプライバシー設定ガイドをご確認ください。

// プライバシー設定例
await _appsFlyerSdk.anonymizeUser(true); // ユーザー匿名化
await _appsFlyerSdk.stop(true); // データ収集停止

まとめ

AppsFlyerのFlutter導入において重要なポイントをまとめると:

  • 管理画面設定:アプリ登録とOneLinkテンプレートの事前準備が必須
  • ATT対応:SDK起動遅延の適切な設定で、プライバシー要件とデータ精度のバランスを実現
  • イベント設計:分析目的を果たすための出力箇所、文字数制約を考慮したイベント命名規則の策定
  • ディープリンク:OneLinkパラメータの活用で柔軟なユーザー体験を提供

これらの実装により、効果的な広告計測とユーザー導線の最適化を実現できます。AppsFlyerの強力な機能を活用して、アプリの成長を加速させていきましょう!

参考リンク