StageUp
Mobile SDKDeep Link

Unity

AdStage DeepLink Integration Guide (Unity)

Table of Contents

  1. Overview
  2. Project Setup
  3. Unity Project Setup
  4. Android Platform Setup
  5. iOS Platform Setup
  6. Creating Deep Links
  7. Troubleshooting

Overview

The AdStage DeepLink SDK for Unity provides the following features:

  • Real-time deep links: Immediate handling via URL Scheme and App Link/Universal Links
  • Deferred deep links: Automatic restoration on the first launch after app installation
  • Dynamic deep link creation: Trackable link generation through the server API
  • Attribution tracking: Marketing analytics based on UTM parameters
  • Cross-platform: Identical API for Android/iOS
  • URL Scheme: myapp://promo/summer
  • Android App Links: https://go.myapp.com/abc123
  • iOS Universal Links: https://go.myapp.com/abc123
  • Deferred deep links: When the app is not installed, restored on store → install → app launch

Project Setup

1. Package Installation

Installation via Package Manager:

Window → Package Manager → + → Add package from git URL
https://github.com/nbase-io/NBase-SDK-Unity.git?path=/AdStageSDK-Package

Or edit manifest.json directly:

{
  "dependencies": {
    "com.nbase.adstage": "https://github.com/nbase-io/NBase-SDK-Unity.git?path=/AdStageSDK-Package#3.0.0"
  }
}

2. Required Dependencies

These are automatically included when the package is installed:

  • Newtonsoft.Json: JSON serialization
  • Native plugins: iOS/Android bridge

Unity Project Setup

1. SDK Initialization

using AdStageSDK;
using UnityEngine;
 
public class AdStageInitializer : MonoBehaviour
{
    void Start()
    {
        // AdStage 초기화
        AdStage.Initialize(
            apiKey: "your-api-key-here"
        );
        
        // 딥링크 리스너 등록
        SetupDeepLinkListener();
        
        Debug.Log("✅ AdStage SDK 초기화 완료");
    }
    
    private void SetupDeepLinkListener()
    {
        AdStage.SetDeepLinkListener(
            onDeepLink: (data) => {
                Debug.Log($"✅ 딥링크 수신: {data.shortPath}");
                if (data.parameters != null && data.parameters.Count > 0)
                {
                    foreach (var param in data.parameters)
                    {
                        Debug.Log($"  - {param.Key}: {param.Value}");
                    }
                }
            },
            onError: (error) => {
                Debug.LogError($"❌ 딥링크 실패: {error}");
            }
        );
    }
}

Android Platform Setup

1. AndroidManifest.xml Setup

Create Assets/Plugins/Android/AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    
    <application
        android:allowBackup="true"
        android:icon="@drawable/app_icon"
        android:label="@string/app_name">
        
        <activity
            android:name="com.unity3d.player.UnityPlayerActivity"
            android:theme="@style/UnityThemeSelector"
            android:screenOrientation="fullSensor"
            android:launchMode="singleTask"
            android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density"
            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>
        </activity>
        
    </application>
</manifest>

2. launchMode Important Notes

android:launchMode="singleTask"
  • singleTask: Reuses the existing Activity (recommended)
  • ⚠️ singleTop: Reuses only when at the top of the stack
  • standard: Creates a new instance every time (causes duplicate deep links)

iOS Platform Setup

1. Info.plist Setup in Xcode

<!-- URL Scheme 설정 -->
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLName</key>
        <string>com.example.myapp</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>your_ios_scheme</string>
        </array>
    </dict>
</array>

public async void CreateDetailedDeepLink()
{
    try
    {
         var builder = new DeepLinkBuilder("Unity Test Link")
             .SetDescription("Unity SDK 테스트")
             .SetCampaign("unity_test")
             .SetChannel("app_channel")
             .SetRedirectType(RedirectType.APP)
             .SetAndroidConfig("your.package.name","your_aos_scheme", "https://yourdomain.com")
             .SetIOSConfig("your.appstoreid", "your_ios_scheme", "https://yourdomain.com")
             .SetWebConfig("https://yourdomain.com")
             .AddParameter("user_id", "value")
             .AddParameter("test", "true");
        
         AdStage.CreateDeeplink(
             builder: builder,
             onSuccess: (shortUrl) =>
             {
                 InAppLog("✅ 딥링크 생성 성공!");
                 InAppLog($"  URL: {shortUrl}");
             },
             onError: (error) =>
             {
                 InAppLog($"❌ 딥링크 생성 실패: {error}");
             }
         );
        
    }
    catch (System.Exception e)
    {
        Debug.LogError($"❌ 에러: {e.Message}");
    }
}

RedirectType Explanation

public enum RedirectType
{
    STORE,  // 스토어로 이동
    
    APP,    // 앱 미설치 시 → 스토어로 이동
            // 앱 설치 시 → 앱 실행 (실시간 딥링크)
    
    WEB     // 항상 웹 URL로 이동
            // 앱 설치 여부 무관
}

Android Deep Link Flow:

사용자가 딥링크 클릭 (myapp://abc123)

Android System이 Intent 생성

UnityPlayerActivity 시작/재개

AdStageLifecyclePlugin.onActivityCreated/Resumed()

AdStageUnityWrapper.handleIntent(intent)

AdStage.handleIntent(context, intent)

DeeplinkHandler.handleIntent()
  ├─ URI 추출: myapp://abc123
  ├─ shortPath 파싱: abc123
  ├─ API 호출: GET /deeplinks/abc123
  └─ DeeplinkListener.onDeeplinkReceived()

UnitySendMessage("AdStageCallbackReceiver", "OnDeepLinkReceived", json)

AdStageCallbackReceiver.OnDeepLinkReceived(json)

사용자 콜백 호출

iOS Deep Link Flow:

사용자가 딥링크 클릭 (myapp://abc123)

iOS System이 URL 전달

AdStageUnityAppController.application:openURL: 또는
AdStageUnityAppController.application:continueUserActivity:

AdStageUnityBridge.AdStageIOS_HandleDeepLink(url)

AdStageManager.shared.handleDeepLink(url)

DeepLinkManager.handleDeepLink()
  ├─ URL 파싱
  ├─ API 호출
  └─ DeepLinkDelegate.onDeepLinkReceived()

UnitySendMessage("AdStageCallbackReceiver", "OnDeepLinkReceived", json)

AdStageCallbackReceiver.OnDeepLinkReceived(json)

사용자 콜백 호출

Troubleshooting

This is expected behavior! The AdStage SDK only works on mobile platforms (Android/iOS). In the Editor, calling AdStage.Initialize() causes IsInitialized() to return false, and deep link callbacks are received only on real devices.

How to check:

#if UNITY_EDITOR
Debug.Log("📊 [Editor Mode] 딥링크는 실제 기기에서만 동작합니다");
#endif

How to test: Install an actual Android/iOS build on a device, then verify deep link reception using the Intent / URL Scheme tests (items 2 and 3) in the troubleshooting section below.

Checklist:

  1. Check AndroidManifest.xml

    • Verify the android:launchMode="singleTask" setting
    • Verify the Intent Filter is correct
  2. Check adb logcat

adb logcat | grep -i adstage
  1. Intent test
# URL Scheme 테스트
adb shell am start -W -a android.intent.action.VIEW -d "myapp://promo/summer" com.example.myapp
 
# HTTPS App Link 테스트
adb shell am start -W -a android.intent.action.VIEW -d "https://go.myapp.com/abc123" com.example.myapp

Checklist:

  1. Check Info.plist

    • CFBundleURLTypes setting
    • Associated Domains setting
  2. Universal Links verification

# Apple App Site Association 파일 확인
curl https://go.myapp.com/.well-known/apple-app-site-association
  1. Check the Xcode Console
    • Check error messages
    • Check deep link reception logs

Android:

# Install Referrer 확인
adb shell dumpsys package com.example.myapp | grep -i referrer

Solution:

  1. Add the permission to AndroidManifest.xml:
<uses-permission android:name="com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE" />
  1. Configure Install Referrer in the Play Console

Cause: Using launchMode="standard"

Solution:

<!-- AndroidManifest.xml -->
android:launchMode="singleTask"

6. Unity 2021+ IL2CPP Build Error

Problem:

TypeLoadException: Could not load type 'AdStageSDK.DeepLinkData'

Solution: Create a link.xml file

Assets/link.xml:

<linker>
    <assembly fullname="AdStageSDK" preserve="all"/>
    <assembly fullname="AdStageSDK.Models" preserve="all"/>
    <assembly fullname="Newtonsoft.Json" preserve="all"/>
</linker>

7. JSON Serialization Error

Problem:

JsonSerializationException: Error converting value

Solution:

// Parameters는 Dictionary<string, object> 사용
var parameters = new Dictionary<string, object>
{
    { "key1", "value1" },
    { "key2", 123 },  // int도 가능
    { "key3", true }  // bool도 가능
};

How to check:

# Digital Asset Links 검증
curl https://go.myapp.com/.well-known/assetlinks.json

Checklist:

  • ✅ Use HTTPS
  • ✅ Content-Type: application/json
  • ✅ Verify the SHA256 fingerprint is correct
  • ✅ Package name matches

FAQ

Q: Can I test deep links in the Unity Editor?
A: No. The SDK only works on mobile platforms, so deep link testing must be done on a real Android/iOS device.

Q: Can I use the same deep link URL on Android and iOS?
A: Yes, both URL Scheme and HTTPS links can be used identically.

Q: How do deferred deep links work?
A: App installation → first launch → Install Referrer lookup → restoration of the stored deep link → callback invocation

Q: Is there a limit on the number of deep link parameters?
A: There is no server limit, but consider the URL length limit (~2000 characters).

Q: Do deep links work offline?
A: Real-time deep links require a network. Deferred deep links are cached and can be restored even offline.

Q: Does it work in Unity WebGL?
A: WebGL cannot use native plugins, so it is not supported. In a web environment, parse the URL parameters directly.


Support

Contact:


© 2025 NBase. All rights reserved.

Table of Contents