LoginSignup
2

Flutter✖️AppsFlyerでディープリンク・ディファード(遅延)ディープリンクを実現する

Last updated at Posted at 2023-12-02

 
Firebase Dynamic Linksが非推奨となったことにより、AppsFlyerAdjustがその代替手段として上がっています。今回はAppsFlyerについて実装したことを紹介します。

背景

QRコード(URL)の読み込みから、アプリの特定の画面へ遷移させたい
例:QRコードを読み取ったユーザーに、アプリの画面で割引クーポンを取得したことを表示

  • アプリをインストールしている場合は特定の画面へ遷移させる
  • アプリをインストールしていない場合はストアへ遷移させる
    • iOSであればAppStoreへ、AndroidであればGooglePlayストアへ遷移させる
    • インストール後に特定の画面へ遷移させる

用語の整理

ディファード(遅延)ディープリンクについての参考サイト

ユニバーサルリンク/AppsLink/URIスキームなどの参考サイト

AppsFlyer Onelink

公式ドキュメント

料金

上記要件であれば基本的に無料。
(※細かい料金発生条件はご自身の責任で確認してください。)

複数のURLを一度に発行するためのAPI利用に料金がかかるよう。
手動でまかなえる範囲で必要な場合は、管理画面で手動で追加していけば良いと思います。

導入までの流れ

大まかにいうと下記になる

  1. AppsFlyer管理画面でアカウント作成・Onelink作成
  2. アプリの設定でユニバーサルリンク/AppsLink/URIスキームの設定
  3. アプリ側でディープリンクのためのリスナーを設定
  4. リスナーの中で特定の画面へ遷移させるロジックを実装

1. AppsFlyer管理画面でアカウント作成・Onelink作成

アカウント作成については省略。

「Onelinkテンプレート」を設定して、それに紐づくURL(QR)を個別に発行していく形になる。

iOSとAndroidのアプリをid入力で識別させる

リリースされてなくてもOKだが、アプリIDが必要なのでストアには上がっている必要がある。

スクリーンショット 2023-12-02 13.58.44(2).png

サブドメインを設定

.onelink.meは固定。アプリ専用の名称を設定できる。(myservice-onelink.onelink.meなど)

スクリーンショット 2023-12-02 14.00.31(2).png

アプリインストールしていた場合の遷移方法を定義

ユニバーサルリンク・AppLinksまたはURIスキーム を設定

※管理画面上だとユニバーサルリンク・AppLinksのフォールバックとしてURIスキームが提供されているよう
※画像の例はAppLinks未対応

スクリーンショット 2023-12-02 14.01.56(2).png

iOSユニバーサルリンクの設定にはチームIDが、
AndroidAppLinksの設定にはSHA256 フィンガープリントがそれぞれ必要です。

app-site-associationファイルなどを置くのはAppsFlyer側で自動で対応されるため、
そこを自前でサーバー立ててファイル配置してドメイン設定して・・としなくていいのは助かります。

アプリインストールしていない場合の遷移先を定義

基本アプリストアだが、WebページなどでもOK

2. アプリの設定でユニバーサルリンク/AppsLink/URIスキームの設定

iOS設定
Android設定

ここは通常のユニバーサルリンクやAppLinksの設定と特に変わらないので他の記事に譲ります。

3. アプリ側でディープリンクのためのリスナーを設定

SDKの設定と、リスナーの設定に分かれます。
GitHubのREADMEが非常によくまとまっているので、迷ったら訳しながら読むことをお勧めします。

SDKの初期化

flutter pub add appsflyer_sdk
import 'package:appsflyer_sdk/appsflyer_sdk.dart';

AppsFlyerOptions appsFlyerOptions = AppsFlyerOptions(
    afDevKey: Env.readEnv(name: "AF_DEV_KEY"),
    appId: Env.readEnv(name: "AF_APP_ID"),
    showDebug: true,
    timeToWaitForATTUserAuthorization: 50,
    disableAdvertisingIdentifier: true,
    disableCollectASA: true);

AppsflyerSdk appsflyerSdk = AppsflyerSdk(appsFlyerOptions);
  • afDevKey
    AppsFlyer管理画面のアプリ設定>SDK認証ページのDevキー。
    Envから取得するようにしていますが、お好きに調整してください。

  • appId
    AppsFlyerのダッシュボードで設定したアプリケーションのApp ID(iOSのみ必須)
    管理画面のURLでも確認できます。
    "id"は不要。stgなどでテストアプリがある場合は、デバック用にそのidを入れる。

  • timeToWaitForATTUserAuthorization
    ATT要求ダイアログ表示後に許諾が取れるまではAppsFlyerへのデータ送信が許可されないため、その遅延をどれくらい許容するかの数値?
    許可されれば、その前に取得していたデータも送信されるので、インストール情報やディープリンク情報も取得できる

  • disableAdvertisingIdentifier,disableCollectASA
    今回は不要なのでtrueにした。マーケティング目的で取得することが多いと思うが、(限りなく?)個人情報だと思うので不用意な取得は避けたい。

その他のオプション引数もあるが省略。
初期化処理は以下

appsflyerSdk.initSdk(
    registerConversionDataCallback: true,
    registerOnAppOpenAttributionCallback: true,
    registerOnDeepLinkingCallback: true
);

3つともtrueにする必要はなさそうだが、とりあえずtrueにしている。
ドキュメントを読む感じ1番下のOnDeepLinkingCallbackだけでも良さそう。

リスナーの設定

動作や仕組みは公式docが非常に分かりやすいので、詳細はそちらを参照ください。

 appsflyerSdk.onDeepLinking((DeepLinkResult dp) {
      switch (dp.status) {
        case Status.FOUND:
          print(dp.deepLink?.toString());
          print("deep link value: ${dp.deepLink?.deepLinkValue}");
          break;
        case Status.NOT_FOUND:
          print("deep link not found");
          break;
        case Status.ERROR:
          print("deep link error: ${dp.error}");
          break;
        case Status.PARSE_ERROR:
          print("deep link status parsing error");
          break;
      }
    }

ディープリンクからアプリを起動した場合は、このStatus.FOUNDを通ることになります。

dp.deepLinkというDeepLinkインスタンスから、管理画面で設定したURLパラメータなどの情報が取得できます。例えば、dp.deepLink?.deepLinkValueなど。

dp.deepLink?.isDeferredでディファードディープリンクかどうかも判定可能です!

initSdk処理の前にリスナーを設定しましょう

Note: The code implementation for onDeepLinking must be made prior to the initialization code of the SDK.

サブパラメータの「af_sub_1」がなぜかディファードディープリンクの時だけ取得できないようでした。「deep_link_sub1」のパラメータの方は取得できたので、同じ現象が起きた方はdp.deepLink?.getStringValue('deep_link_sub1')
の方で取得するのをお勧めします。
(自分の勘違いかもしれないですが、詳しく調査していません)

4. リスナーの中で特定の画面へ遷移させるロジックを実装

ご自身のアプリの設計に合わせて設定してください。

Navigato1.0の場合Buildcontextが必要になるため、
AppsFlyer関係の処理は別でまとめて、メソッドを呼び出すのが良いのではないでしょうか。

以下は例です。

.app.dart
  @override
  void initState() {
    AppsFlyerService.addAppsFlyerDeepLinkListener((params) {
      _handleNavigation(params);
    });
    AppsFlyerService.init();
  }

  Future<void> _handleNavigation(Map<String, String?> params) async {
    if (_isAfterLogin) {
      Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) => QRReadedScreen(params: params),
          ));
    }
  }

.appsflyer_service.dart
 static void addAppsFlyerDeepLinkListener(
      Function(Map<String, String?>) callback) {
    return _appsflyerSdk.onDeepLinking((DeepLinkResult dp) {
      switch (dp.status) {
        case Status.FOUND:
        // 遅延ディープリンクの場合に特定の処理を挟む場合はここで対応
          bool? isDeferred = dp.deepLink?.isDeferred;
        // 特定の画面へパラメータ付きで遷移させる処理を受け付ける
          callback(params);
          break;
        // 以下省略
      }

URL・QRコードの発行

URL(QRコード)の発行は管理画面の説明に従っていけば特に迷うことはないので、省略します。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2