adstage
モバイル SDKディープリンク

React Native

AdStage DeepLink 統合ガイド (React Native)

目次

  1. 概要
  2. インストール
  3. プラットフォーム別の設定
  4. SDK の初期化
  5. ディープリンクの受信処理
  6. ディープリンクの作成
  7. トラブルシューティング

概要

AdStage DeepLink SDK for React Native は、次の機能を提供します。

  • リアルタイムディープリンク:URL Scheme、App Link/Universal Links による即時処理
  • ディファードディープリンク:アプリのインストール後、初回起動時に自動で復元
  • 動的ディープリンクの作成:サーバー API によるトラッキング可能なリンクの作成
  • アトリビューションのトラッキング:UTM パラメータに基づくマーケティング分析
  • クロスプラットフォーム:Android/iOS で同一の API

対応するディープリンクの種類

  • URL Scheme: myapp://promo/summer
  • Android App Links: https://go.myapp.com/abc123
  • iOS Universal Links: https://go.myapp.com/abc123
  • ディファードディープリンク:アプリ未インストール時 ストア → インストール → アプリ起動時に復元

インストール

npm / yarn でのインストール

# npm
npm install @adstage/react-native-sdk
 
# yarn
yarn add @adstage/react-native-sdk

iOS の依存関係のインストール

cd ios && pod install

プラットフォーム別の設定

iOS の設定

1. ATT (App Tracking Transparency) の権限(必須)

ios/YourApp/Info.plist に次を追加します。

<key>NSUserTrackingUsageDescription</key>
<string>広告の成果測定およびパーソナライズされた広告の提供に使用されます。</string>

2. URL Scheme の設定

ios/YourApp/Info.plist に次を追加します。

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLName</key>
        <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>your_app_scheme</string>
        </array>
    </dict>
</array>

ios/YourApp/YourApp.entitlements に次を追加します。

<key>com.apple.developer.associated-domains</key>
<array>
    <string>applinks:go.yourapp.com</string>
</array>

4. AppDelegate.mm の修正

ios/YourApp/AppDelegate.mm ファイルに、ディープリンク処理用のメソッドを追加します。

#import <AdapterAdStage/AdapterAdStage-Swift.h>
 
// URL Scheme の処理
- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
    // AdStage ディープリンクの処理
    [[DeepLinkManager shared] handleDeepLink:url];
    return YES;
}
 
// Universal Links の処理
- (BOOL)application:(UIApplication *)application
    continueUserActivity:(NSUserActivity *)userActivity
      restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
    if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
        [[DeepLinkManager shared] handleUniversalLink:userActivity];
        return YES;
    }
    return NO;
}

Android の設定

1. Maven リポジトリの追加(必須)

android/settings.gradle または android/build.gradle に追加します。

dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' }
        maven { url 'https://devrepo.kakao.com/nexus/content/groups/public/' }
        maven { url "https://maven.adstage.io/repository/public" }
    }
}

2. minSdkVersion の設定

android/build.gradle で確認します。

buildscript {
    ext {
        minSdkVersion = 24  // 最低 24 以上が必要
    }
}

3. AndroidManifest.xml の設定

android/app/src/main/AndroidManifest.xml に Intent Filter を追加します。

<activity
    android:name=".MainActivity"
    android:launchMode="singleTask"
    android:exported="true">
    
    <!-- デフォルトのランチャー -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    
    <!-- URL Scheme ディープリンク -->
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="your_app_scheme" />
    </intent-filter>
    
    <!-- App Links (HTTPS) -->
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
            android:scheme="https"
            android:host="go.yourapp.com" />
    </intent-filter>
</activity>

4. launchMode の重要事項

android:launchMode="singleTask"
  • ✅ singleTask:既存の Activity を再利用(推奨)
  • ⚠️ singleTop:スタックの最上位にある場合のみ再利用
  • ❌ standard:毎回新しいインスタンスを作成(ディープリンクの重複が発生)

SDK の初期化

基本の初期化

import { AdStage } from '@adstage/react-native-sdk';
 
// アプリ起動時に初期化
const initializeAdStage = async () => {
  try {
    await AdStage.initialize({
      apiKey: 'your-api-key-here'
    });
    
    // ディープリンクリスナーの設定
    setupDeepLinkListener();
    
    // Pending ディープリンクの確認(コールドスタート)
    AdStage.deepLink.checkPendingDeepLink();
    
    console.log('✅ AdStage SDK 初期化完了');
  } catch (error) {
    console.error('❌ AdStage 初期化失敗:', error);
  }
};
 
// App.tsx から呼び出す
useEffect(() => {
  initializeAdStage();
}, []);

ディープリンクの受信処理

1. ディープリンクリスナーの設定

import { AdStage } from '@adstage/react-native-sdk';
 
const setupDeepLinkListener = () => {
  // 統合ディープリンクリスナー
  AdStage.deepLink.setListener((data) => {
    console.log('✅ ディープリンク受信:', data);
    console.log('  - Short Path:', data.shortPath);
    console.log('  - Link ID:', data.linkId);
    console.log('  - Parameters:', data.parameters);
    
    // ビジネスロジックの処理
    handleDeepLink(data);
  });
};
 
const handleDeepLink = (data: DeepLinkData) => {
  const { shortPath, parameters } = data;
  
  // パラメータに応じた画面遷移
  if (parameters?.product_id) {
    // 商品詳細画面へ移動
    navigation.navigate('ProductDetail', { 
      productId: parameters.product_id 
    });
  } else if (parameters?.campaign) {
    // キャンペーン画面へ移動
    navigation.navigate('Campaign', { 
      campaignId: parameters.campaign 
    });
  } else if (parameters?.promo) {
    // プロモーションコードを適用
    applyPromoCode(parameters.promo);
  } else {
    // デフォルト: ホーム画面
    navigation.navigate('Home');
  }
};

2. DeepLinkData の構造

interface DeepLinkData {
  linkId: string;              // ディープリンクの固有 ID(サーバー発行)
  shortPath: string;           // ディープリンクの short path(例: "abc123")
  parameters: Record<string, string>; // カスタムパラメータ
  source: DeepLinkSource;      // ディープリンクのソース(リアルタイム/ディファード)
  eventType: string;           // イベントタイプ(例: "OPEN", "INSTALL")
  timestamp?: string;          // タイムスタンプ
}
 
type DeepLinkSource =
  | 'realtime'   // リアルタイムディープリンク(アプリ実行中/URL・Universal Link 受信)
  | 'install'    // ディファードディープリンク(インストール後の初回起動時に復元)
  | 'unknown';   // 不明

3. Pending ディープリンクの処理

アプリが完全に終了した状態からディープリンクで起動された場合は、次のようにします。

// SDK 初期化後に Pending ディープリンクを確認
await AdStage.initialize({ apiKey: 'your-api-key' });
 
// 先にリスナーを設定
AdStage.deepLink.setListener((data) => {
  console.log('ディープリンク:', data);
  handleDeepLink(data);
});
 
// Pending ディープリンクの確認と処理
AdStage.deepLink.checkPendingDeepLink();

4. 実践例:React Navigation との連携

import React, { useEffect } from 'react';
import { NavigationContainer, useNavigation } from '@react-navigation/native';
import { AdStage } from '@adstage/react-native-sdk';
 
function App() {
  const navigationRef = React.useRef(null);
  
  useEffect(() => {
    const initSDK = async () => {
      await AdStage.initialize({ apiKey: 'your-api-key' });
      
      // ディープリンクリスナーの設定
      AdStage.deepLink.setListener((data) => {
        const { parameters } = data;
        
        // React Navigation で画面遷移
        if (navigationRef.current) {
          if (parameters?.screen) {
            navigationRef.current.navigate(parameters.screen, parameters);
          }
        }
      });
      
      // Cold start ディープリンクの確認
      AdStage.deepLink.checkPendingDeepLink();
    };
    
    initSDK();
  }, []);
  
  return (
    <NavigationContainer ref={navigationRef}>
      {/* ナビゲーションスタック */}
    </NavigationContainer>
  );
}

ディープリンクの作成

基本のディープリンク作成

import { AdStage } from '@adstage/react-native-sdk';
 
const createDeepLink = async () => {
  try {
    const result = await AdStage.deepLink.create({
      name: '夏のプロモーションリンク',
      description: '2025 年夏のセールイベント',
      
      // アトリビューションパラメータ
      channel: 'instagram',
      subChannel: 'social',
      campaign: 'summer_sale_2025',
      
      // リダイレクト設定
      redirectConfig: {
        type: 'APP', // 'STORE' | 'APP' | 'WEB'
        android: {
          packageName: 'com.yourapp.android',
          appScheme: 'yourapp://promo',
          webUrl: 'https://yourapp.com/promo',
        },
        ios: {
          appStoreId: '1234567890',
          appScheme: 'yourapp://promo',
          webUrl: 'https://yourapp.com/promo',
        },
        desktop: {
          webUrl: 'https://yourapp.com/promo',
        },
      },
      
      // カスタムパラメータ
      parameters: {
        promo_code: 'SUMMER25',
        discount: '20',
        screen: 'PromoDetail',
      },
    });
    
    console.log('✅ ディープリンク作成成功');
    console.log('  - Short URL:', result.shortUrl);
    console.log('  - Short Path:', result.shortPath);
    console.log('  - Link ID:', result.linkId);
    
    // リンクを共有
    shareDeepLink(result.shortUrl);
    
  } catch (error) {
    console.error('❌ ディープリンク作成失敗:', error);
  }
};

CreateDeepLinkRequest のパラメータ

パラメータ型必須説明
namestring✅ディープリンク名
descriptionstring-ディープリンクの説明
shortPathstring-Short Path のカスタム指定
channelstring-チャネル
subChannelstring-サブチャネル
campaignstring-キャンペーン
adGroupstring-広告グループ
creativestring-広告クリエイティブ
contentstring-コンテンツ
keywordstring-キーワード
redirectConfigRedirectConfig-リダイレクト設定
parametersobject-カスタムパラメータ

RedirectConfig の構造

interface RedirectConfig {
  type: 'STORE' | 'APP' | 'WEB';   // リダイレクトタイプ
  android?: PlatformConfig;          // Android プラットフォームの設定
  ios?: PlatformConfig;              // iOS プラットフォームの設定
  desktop?: { webUrl?: string };     // デスクトップの設定
}
 
interface PlatformConfig {
  storeUrl?: string;     // アプリストアの URL
  appScheme?: string;    // アプリのカスタムスキーム
  webUrl?: string;       // ウェブのフォールバック URL
  packageName?: string;  // パッケージ名(Android) / バンドル ID(iOS)
  appStoreId?: string;   // App Store ID (iOS)
}
タイプアプリインストール済みアプリ未インストール
STOREストアへ移動ストアへ移動
APPアプリを起動(リアルタイムディープリンク)ストアへ移動 → インストール後にディファードディープリンク
WEBウェブ URL へ移動ウェブ URL へ移動

ユーティリティ関数

Short Path の抽出

// URL から Short Path を抽出
const shortPath = AdStage.deepLink.extractShortPath('https://adstage.net/ABCDEF');
console.log(shortPath); // "ABCDEF"

Android Intent の手動処理

import { Linking } from 'react-native';
 
// Android でアプリがすでに実行中のときに新しい Intent を処理
Linking.addEventListener('url', ({ url }) => {
  // ネイティブで自動処理されますが、必要に応じて手動で呼び出す
  AdStage.deepLink.handleIntent();
});

トラブルシューティング

iOS の問題

ディープリンクを受信できない

  1. Info.plist に URL Scheme が正しく設定されているか確認
  2. AppDelegate.mm にディープリンク処理メソッドが追加されているか確認
  3. Universal Links の場合、Associated Domains が設定されているか確認

ATT 権限のポップアップが表示されない

  • Info.plist に NSUserTrackingUsageDescription キーがあるか確認

Android の問題

ディープリンクが重複して受信される

  • android:launchMode="singleTask" の設定を確認

ディープリンクを受信できない

  1. AndroidManifest.xml の Intent Filter を確認
  2. android:exported="true" の設定を確認
  3. App Links の場合、Digital Asset Links ファイルを確認

共通の問題

ディファードディープリンクが動作しない

  1. SDK の初期化が完了した後にリスナーを設定したか確認
  2. checkPendingDeepLink() を呼び出しているか確認
  3. ネットワークの接続状態を確認

パラメータが渡されない

  • ディープリンク作成時に parameters オブジェクトへ正しく値を設定したか確認

目次