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;    // 應用程式自訂 scheme
  webUrl?: string;       // 網頁備援 URL
  packageName?: string;  // 套件名稱(Android) / Bundle 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 物件中正確設定了值

目錄