Unity
Overview
Project Setup
Unity Project Setup
Android Platform Setup
iOS Platform Setup
Creating Deep Links
Troubleshooting
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
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"
}
}
These are automatically included when the package is installed:
Newtonsoft.Json : JSON serialization
Native plugins : iOS/Android bridge
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 }" );
}
);
}
}
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 >
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)
<!-- 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 }" );
}
}
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)
↓
사용자 콜백 호출
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:
Check AndroidManifest.xml
Verify the android:launchMode="singleTask" setting
Verify the Intent Filter is correct
Check adb logcat
adb logcat | grep -i adstage
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:
Check Info.plist
CFBundleURLTypes setting
Associated Domains setting
Universal Links verification
# Apple App Site Association 파일 확인
curl https://go.myapp.com/.well-known/apple-app-site-association
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:
Add the permission to AndroidManifest.xml :
< uses-permission android:name = "com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE" />
Configure Install Referrer in the Play Console
Cause: Using launchMode="standard"
Solution:
<!-- AndroidManifest.xml -->
android:launchMode="singleTask"
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 >
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
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.
Contact:
© 2025 NBase. All rights reserved.