Firebase Dynamic Links
が非推奨となったことにより、AppsFlyerやAdjustがその代替手段として上がっています。今回はAppsFlyerについて実装したことを紹介します。
背景
QRコード(URL)の読み込みから、アプリの特定の画面へ遷移させたい
例:QRコードを読み取ったユーザーに、アプリの画面で割引クーポンを取得したことを表示
- アプリをインストールしている場合は特定の画面へ遷移させる
- アプリをインストールしていない場合はストアへ遷移させる
- iOSであればAppStoreへ、AndroidであればGooglePlayストアへ遷移させる
- インストール後に特定の画面へ遷移させる
用語の整理
ディファード(遅延)ディープリンクについての参考サイト
ユニバーサルリンク/AppsLink/URIスキームなどの参考サイト
AppsFlyer Onelink
料金
上記要件であれば基本的に無料。
(※細かい料金発生条件はご自身の責任で確認してください。)
複数のURLを一度に発行するためのAPI利用に料金がかかるよう。
手動でまかなえる範囲で必要な場合は、管理画面で手動で追加していけば良いと思います。
導入までの流れ
大まかにいうと下記になる
- AppsFlyer管理画面でアカウント作成・Onelink作成
- アプリの設定でユニバーサルリンク/AppsLink/URIスキームの設定
- アプリ側でディープリンクのためのリスナーを設定
- リスナーの中で特定の画面へ遷移させるロジックを実装
1. AppsFlyer管理画面でアカウント作成・Onelink作成
アカウント作成については省略。
「Onelinkテンプレート」を設定して、それに紐づくURL(QR)を個別に発行していく形になる。
iOSとAndroidのアプリをid入力で識別させる
リリースされてなくてもOKだが、アプリIDが必要なのでストアには上がっている必要がある。
サブドメインを設定
.onelink.meは固定。アプリ専用の名称を設定できる。(myservice-onelink.onelink.meなど)
アプリインストールしていた場合の遷移方法を定義
ユニバーサルリンク・AppLinksまたはURIスキーム を設定
※管理画面上だとユニバーサルリンク・AppLinksのフォールバックとしてURIスキームが提供されているよう
※画像の例はAppLinks未対応
iOSユニバーサルリンクの設定にはチームIDが、
AndroidAppLinksの設定にはSHA256 フィンガープリントがそれぞれ必要です。
app-site-associationファイルなどを置くのはAppsFlyer側で自動で対応されるため、
そこを自前でサーバー立ててファイル配置してドメイン設定して・・としなくていいのは助かります。
アプリインストールしていない場合の遷移先を定義
基本アプリストアだが、WebページなどでもOK
2. アプリの設定でユニバーサルリンク/AppsLink/URIスキームの設定
ここは通常のユニバーサルリンクや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関係の処理は別でまとめて、メソッドを呼び出すのが良いのではないでしょうか。
以下は例です。
@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),
));
}
}
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コード)の発行は管理画面の説明に従っていけば特に迷うことはないので、省略します。