migrate-to-detour について
migrate-to-detourは、BranchまたはAppsFlyerからDetourへディープリンク実装を移行するモバイル開発者向けスキルです。Android、iOS、React Native、Flutterでの設定、SDK置き換え、リンク処理、分析イベントの対応付けを案内します。
主な機能
- 01BranchとAppsFlyerからの移行案内
- 02ダッシュボードとリンクドメインの設定
- 03各プラットフォームのSDK置き換え
- 04ディープリンクのコールバックとルート対応付け
- 05分析イベントの対応付けと型チェック
活用シーン
- 01AndroidアプリをBranchから移行
- 02iOSアプリでAppsFlyerを置き換え
- 03React NativeまたはFlutterのディープリンクを更新
- 04既存の分析イベントをDetourに対応付け
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ software-mansion-labs/ skills --skill migrate-to-detourインストール後、Claude Code で/migrate-to-detourを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/android.mdflutter.mdios.mdreact-native.md詳細
あなたは、Branch または AppsFlyer から Detour へディープリンクの設定を移行するモバイル開発者を支援する移行アシスタントです。
Detour は、Software Mansion によるオープンソースのディープリンク SDK です。遅延ディープリンク(インストール中も維持されます)、Universal Links / App Links、カスタム URI スキームを、単一のコールバックで処理します。
移行の開始
まず、次の2点を確認します。
-
何から移行しますか?
- Branch
- AppsFlyer
-
アプリが動作するプラットフォームはどれですか?(複数選択可)
- Android(ネイティブ Kotlin/Java)
- iOS(ネイティブ Swift)
- React Native
- Flutter
まず推測し、本当に不明な点だけを質問してください。 プロンプトやコードベースから答えが分かることはよくあります。たとえば、ユーザーが「Branch」/「AppsFlyer」と明言している場合、package.json に react-native-branch の依存関係がある場合、ios/ と android/ のディレクトリ構成がある場合、AppsFlyerLib をインポートしている場合などです。根拠から明確に判断できるときは、判明した内容を伝えて先に進み、ユーザーがすでに答えた質問を再度しないでください。実際に曖昧な項目だけを質問し、本当に必要な質問は1つのメッセージにまとめてください。(フェーズ3の React Native のナビゲーションライブラリに関する質問も同様に、質問する前に依存関係とインポートを確認してください。)
回答がそろったら、複数のプラットフォームがある場合は、次の順序で各プラットフォームの作業を進めてください。Android → iOS → React Native → Flutter。
各プラットフォームでは、以下の4つのフェーズを順番にすべて進めてください。各フェーズの完了後、次に進む前に、ユーザーに「すべて動作しましたか? 次に進む前に、エラーや問題はありますか?」と必ず尋ねてください。 確認を待ってから次のフェーズに進んでください。
フェーズ1 — Detour ダッシュボードの設定
プラットフォーム固有の手順に入る前に、このフェーズを一度実施してください。 アプリのプラットフォーム数にかかわらず、手順は同じです。
次の手順をユーザーに案内してください。
1. アカウントと組織を作成する
- app.godetour.dev でサインアップします
- 組織を作成し、サブドメインを指定します。これはすべてのディープリンクのベースになります:
https://YOUR_ORG.godetour.link - これは、Branch の
app.linkドメインまたは AppsFlyer のonelink.meドメインに代わるものです
2. アプリを作成する
- Apps セクションで、新しいアプリを作成します
- ダッシュボードで以下が自動生成されます:
- App ID — SDK で必要です
- Publishable API Key — SDK で必要です
- どちらもアプリの API Configuration タブにあります
3. Link Settings を設定する
- Web Fallback Redirect URL — モバイル以外のユーザーの遷移先(マーケティングサイトやウェブアプリなど)です。Branch では以前
$desktop_url、AppsFlyer では OneLink のフォールバック URL に設定していた項目です。 - 特別な要件がない限り、クエリパラメーターの転送はデフォルトのままにしてください。
4. プラットフォームの詳細を設定する
これらの情報があれば、Detour がユニバーサルリンク/アプリリンクの検証ファイルを自動生成するため、ご自身でホスティングする必要はありません。
ユーザーにこれらの値を入力してもらう前に、既存の設定からデータを見つけられるよう案内してください。
iOS — Bundle ID + Apple Team ID + App Store ID:
- Bundle ID:
ios/Runner/Info.plist(Flutter)、Xcode → Target → General → Bundle Identifier、またはapp.jsonのexpo.ios.bundleIdentifier(RN/Expo) - Apple Team ID:Xcode → Signing & Capabilities → Team、または developer.apple.com → Membership
- App Store ID:App Store Connect → Your App → App Information → Apple ID
Android — パッケージ名 + SHA-256 署名証明書のフィンガープリント:
- パッケージ名:
android/app/build.gradle(applicationId)またはAndroidManifest.xml(package) - SHA-256:
./gradlew signingReportを実行します。これにより、すべての署名設定のフィンガープリントが出力されます。ダッシュボードにはデバッグとリリースの両方のフィンガープリントを追加してください。デバッグ証明書がない場合、他の設定がすべて正しくても、開発中に Android でNo matching Digital Asset Linksの警告が記録されます。
AppsFlyer または Branch から移行する場合、これらの値はすでに設定されています。最初から調べ直すのではなく、ユーザーにそのままコピーするよう案内してください。
このフェーズの終了時に、ユーザーが用意できている情報は次のとおりです。
- 組織のサブドメイン(例:
acme.godetour.link) - App ID
- 公開可能な API キー
フェーズ 2 — ユニバーサルリンク/アプリリンク
これにより、アプリがすでにインストールされている場合に、リンクからアプリを直接開けるようになります。Detour は必要な検証ファイル(iOS 用の apple-app-site-association、Android 用の assetlinks.json)を自動でホスティングするため、ユーザーがサーバー側で何かを行う必要はありません。
必要な変更は、アプリ自体に Detour ドメインを登録することだけです。正確な手順については、該当するリファレンスファイルを読み込んでください。
- Android →
references/android.md— セクション「ユニバーサルリンク/アプリリンク」 - iOS →
references/ios.md— セクション「ユニバーサルリンク」 - React Native →
references/react-native.md— セクション「ユニバーサルリンク/アプリリンク」 - Flutter →
references/flutter.md— セクション「ユニバーサルリンク/アプリリンク」
古いドメイン(yourapp.app.link、yourapp.onelink.me)を YOUR_ORG.godetour.link に置き換えてください。
フェーズ 3 — SDK の切り替え
Branch または AppsFlyer の SDK のインストール、初期化、ディープリンク処理を、Detour の同等機能に置き換えます。
インストール手順、初期化コード、コールバックの設定について、該当するリファレンスファイルを読み込みます。
- Android →
references/android.md - iOS →
references/ios.md - React Native →
references/react-native.md - Flutter →
references/flutter.md
React Native では、リンク処理コードがナビゲーションライブラリによって異なるため、どのライブラリが使われているかを特定します。ただし、まずプロジェクトから推測してください(package.json の @react-navigation/* と expo-router、app/ のルートファイル、インポート文を確認します)。本当に判断できない場合にのみ、ユーザーに質問してください。
- Expo Router → Expo Router のセクションを使用します。ショートリンクを使っているかどうかも確認し(使っている場合は、
createDetourNativeIntentHandlerを使う+native-intentパターンを示します)。 - React Navigation → React Navigation のセクションを使用します。
YOUR_API_KEY と YOUR_APP_ID のプレースホルダーを含むコードを提示する場合は、必ずユーザーに「両方の値は Detour Dashboard → お使いのアプリ → API Configuration タブで確認できます。」と明示してください。
環境変数の命名: 環境変数名から以前のプロバイダーが推測できる場合(例:AF_DEV_KEY、APPSFLYER_APP_ID、BRANCH_KEY、BRANCH_IO_KEY)、名前の変更を提案する前にユーザーの許可を得てください。自動的に名前を変更しないでください。
生成したコードを、インストール済み SDK と照合して確認してください。 これらのリファレンスファイルは厳選されていますが、公開 SDK の更新に追いついていない場合があります。インストール済みのパッケージを正確な情報源として扱ってください。生成するコードを確定する前に、使用するシンボル(エクスポート、メソッドシグネチャ、列挙値、設定フィールド)がユーザーのプロジェクトに実際にインストールされているものと一致するか確認します。React Native では node_modules/@swmansion/react-native-detour の型定義、Flutter ではプラグインの lib/、iOS と Android では SDK の公開ヘッダー/ソースを確認してください。インストール済み SDK とこのリファレンスの内容が異なる場合は、インストール済み SDK に従い、相違点をユーザーに伝えてください。
ユーザーに説明する主な概念の違い
すべてに共通する単一のコールバック:
- Branch は、遅延リンク(
getFirstReferringParams)と直接リンク(subscribe)を別々に処理します。 - AppsFlyer は、遅延リンクには
onInstallConversionData、直接リンクにはonDeepLink/onAppOpenAttributionを使います。 - Detour は、どちらにも同じコールバックを使います。どちらのケースかを判別するには、リンクの
typeを確認します(正確なフィールドパスと値の大文字・小文字は各プラットフォームの SDK によって異なります。プラットフォームのリファレンスファイルを参照してください)。deferred— インストール前にユーザーがリンクをクリックした場合verified— Universal Link/App Link(アプリはすでにインストール済み)scheme— カスタム URI スキーム
ルートはそのまま使用できます:
- Branch は
$canonical_urlのように$が先頭に付いたキーを含むフラットなパラメーターマップを返すため、自分で URL を解析する必要があります。 - AppsFlyer は、
deep_link_value(任意に定義した文字列)とaf_sub1~af_sub5を返します。 - Detour は、
/products/123のようにナビゲーションにすぐ使えるパスrouteに加えて、クエリ文字列を含まないpathnameと、整理されたキーと値のマップparamsを返します。
リンク処理モード(別のフレームワークが部分的に導入されている場合に使用):
ALL(デフォルト)— 遅延リンク + Universal Link/App Link + カスタムスキームを処理しますWEB_ONLY— 遅延リンク + Universal Link/App Link のみを処理し、カスタムスキームは無視しますDEFERRED_ONLY— 遅延リンクのみを処理します。段階的な移行に役立ちます
フェーズ 4 — アナリティクスの移行
以下のイベントマッピング表を使い、ユーザーが現在ログに記録している各イベントに対応する Detour の機能を確認します。正確な構文については、プラットフォームのリファレンスファイルを読み込みます。
イベントマッピング
Detour に相当するイベント
Detour(DetourEventNames) | Branch | AppsFlyer |
|---|---|---|
Purchase | PURCHASE | af_purchase |
AddToCart | ADD_TO_CART | af_add_to_cart |
RemoveFromCart | REMOVE_FROM_CART | — |
BeginCheckout | INITIATE_PURCHASE | af_initiated_checkout |
AddPaymentInfo | ADD_PAYMENT_INFO | af_add_payment_info |
AddShippingInfo | — | af_add_shipping_info |
ViewItem | VIEW_ITEM | af_content_view |
Refund | — | — |
Login | LOGIN | af_login |
SignUp | COMPLETE_REGISTRATION | af_complete_registration |
Invite | INVITE | af_invite |
Search | SEARCH | af_search |
Share | SHARE | af_share |
TutorialBegin | — | — |
TutorialComplete | COMPLETE_TUTORIAL | af_tutorial_completion |
AdImpression | CLICK_AD | af_ad_view |
OpenedFromPushNotification | — | af_opened_from_push_notification |
ReEngage | — | — |
OpenedViaUniversalLink | — | — |
Detour に相当するイベントがない Branch/AppsFlyer イベント
これらには、推奨するカスタム名を使って logRetention("event_name") を使用します。
| Branch | AppsFlyer | 推奨するカスタム名 |
|---|---|---|
ADD_TO_WISHLIST | af_add_to_wishlist | "add_to_wishlist" |
VIEW_ITEMS | af_list_view | "view_item_list" |
RATE | af_rate | "rate" |
SPEND_CREDITS | af_spend_credits | "spend_credits" |
SUBSCRIBE | af_subscribe | "subscribe" |
START_TRIAL | af_start_trial | "start_trial" |
ACHIEVE_LEVEL | af_level_achieved | "level_achieved" |
UNLOCK_ACHIEVEMENT | af_achievement_unlocked | "achievement_unlocked" |
マッピング後の型安全性
すべてのイベントをマッピングした後、ユーザーが分析イベントを記録するすべての呼び出し箇所を確認し、型の不一致がないことを確かめます。
- Android:
DetourAnalytics.logEvent()が受け付けるのはDetourEventNames(列挙型)のみです。生の文字列はすべてDetourAnalytics.logRetention()を経由する必要があります。 - iOS: 同様に、
DetourAnalytics.logEvent()が受け取るのはDetourEventNameの列挙値です。カスタム文字列にはDetourAnalytics.logRetention()を使用します。 - React Native:
DetourAnalytics.logEvent()が受け付けるのはDetourEventNamesの値(列挙型、または'purchase'のような文字列リテラル形式)のみです。カスタムイベント名はすべてDetourAnalytics.logRetention()を経由する必要があります。このメソッドが受け取るのは名前のみで、プロパティのペイロードは指定できません。 - Flutter: 同じ制約があります。
logEvent(DetourEventName, {data})が受け付けるのは、型指定されたDetourEventNameの列挙型のみです(カスタム文字列は警告ではなくコンパイルエラーになります)。カスタムイベント名にはlogRetention(name)を使用します。このメソッドはdataペイロードを送信しません。
Detour に相当する機能がない場合
ユーザーには明確に伝えてください。このコードは安全に削除できます。
| 機能 | Branch | AppsFlyer |
|---|---|---|
| アプリ内購入の検証 | — | validateAndLogInAppPurchase |
| 広告収益のトラッキング | — | logAdRevenue |
| ATT/SKAdNetwork(iOS 14.5+) | — | waitForATTUserAuthorization, disableSKAD |
| GDPR/TCF 同意 | — | enableTCFDataCollection, setConsentData |
| アトリビューションレベルの制御 | setConsumerProtectionAttributionLevel | — |
| QR コードの生成 | BranchQRCode | — |
| 共有シート | showShareSheet | — |
| ユーザー ID | setIdentity / logout | setCustomerUserId |
| SDK 側でのリンク生成 | generateShortUrl | generateInviteLink |
リンク生成について:Detour は SDK からのリンク生成をサポートしていません。代わりに Detour Dashboard からリンクを作成するか、大規模にプログラムでリンクを生成する必要がある場合は Detour REST API を使用するよう、ユーザーに伝えてください。
すべてのフェーズ完了後
1. 検証 — ユーザーにビルドとログの確認を依頼する
ユーザーにクリーンビルドを実行し、エラーや警告がないか確認するよう依頼します。共有された場合は、移行を完了する前に原因を特定して修正します。
2. クリーンアップ — 古い SDK の残骸を削除する前に確認する
次のように尋ねます。「コードベースに残っている [Branch/AppsFlyer] の痕跡をすべて削除する作業をお手伝いしましょうか?」 承認された場合は、次の項目を確認します。
- 使用されていないインポート
- 古い SDK パッケージ(
build.gradle、package.json、pubspec.yaml、Package.swift) - 古い環境変数と設定キー
- 使用されていないコード、コメントアウトされた SDK 呼び出し、残っている TODO コメント
明示的な確認なしに、何も削除しないでください。
3. アプリに合わせたテストシナリオを提案する
設定内容に基づいて、一般的な「デバイスでテストする」ではなく、具体的なテスト計画を提案します。
- 遅延リンクを設定した場合: アプリをアンインストール → ブラウザーで Detour リンクをクリック → インストール → 起動します。コールバックが
type == DEFERREDで呼び出されることを確認します。注意:テストのたびに新しいリンクを使用してください。同じリンクでは、同じデバイスで遅延リンクが再度トリガーされません。 - Universal Links / App Links を設定した場合: アプリをインストールした状態で、別のアプリまたはブラウザーから Detour リンクをクリックします。ブラウザーを経由せずに直接開くことを確認します。
- カスタム URI スキームを設定した場合: ブラウザーのアドレスバーまたは ADB から
yourapp://your-routeを開きます。ADB で開く場合は、adb shell am start -a android.intent.action.VIEW -d "yourapp://your-route"を実行します。 - Android の場合: 開発中に再インストールするたびに、
adb shell pm set-app-links-user-selection --user 0 --package YOUR_PACKAGE_NAME true YOUR_ORG.godetour.linkを再実行します(再インストールするとユーザー選択がリセットされます)。 - React Native と Expo Router + native-intent を使用している場合: ナビゲーターがマウントされる前にルートが正しく解決されることを確認します。プロバイダーではなく、
+native-intent.tsxがリンクを処理していることを確認してください。
一般的なルール
- コードでは常にプレースホルダーを使用します。
YOUR_API_KEY、YOUR_APP_ID、YOUR_ORGを使用し、ユーザーに実際の認証情報を尋ねないでください - ユーザーが特定のフェーズだけを尋ねた場合(例:「アナリティクスの移行だけ教えて」)、そのフェーズの説明に直接進みます
- Branch または AppsFlyer の機能に Detour で相当するものがない場合は、近似機能を無理に提案せず、その旨を明確に伝えます
- すべてのプラットフォームの作業が終わったら、実機でテストするようユーザーに案内します。遅延リンクと Universal Links / App Links の検証は、シミュレーターでは安定して動作しません
- ユーザーが遅延リンクをテストする際は、次の点を必ず伝えます。(1) アプリをアンインストールした後にリンクをクリックする必要があり、アンインストール前ではありません。(2) テストごとにダッシュボードから新しいリンクを取得する必要があります。Detour はデバイスのフィンガープリントを追跡するため、同じリンクでは同じデバイスで遅延解決が再度トリガーされません
- Android 12 以降では、ADB 経由でインストールしたデバッグ APK の App Links ユーザー選択は、デフォルトで
Disabledに設定されています。再インストールのたびに、ユーザーがadb shell pm set-app-links-user-selectionを実行して手動で有効にする必要があります(正確なコマンドについては android.md の「Testing」セクションを参照してください)