Unity SDK

Deep linking

Cold, warm, and deferred deep links — what each one is, how to wire them, and where Reflect helps.

Three flavors

TypeWhat it isExample
ColdApp was NOT running. User taps a link → OS launches the app + delivers the URL.Universal Link from email; intent filter on Android.
WarmApp already running. OS dispatches a new URL.Push notification deep link; iOS scene continueUserActivity.
DeferredUser clicked a link, app wasn’t installed, they were sent to the store, installed, and now we want to honor the original intent.“Promo for spring sale” → install → land on the spring sale screen.

Subscribe to deep-link events

using Reflect;

void Awake() {
    ReflectSDK.OnDeepLink += HandleDeepLink;
}

void OnDestroy() {
    ReflectSDK.OnDeepLink -= HandleDeepLink;
}

void HandleDeepLink(DeepLinkData data) {
    Debug.Log($"[DL] {data.Source} → {data.Url} (path: {data.Path})");
    // Route within your app:
    if (data.Path?.StartsWith("/promo/") == true) {
        Router.GoTo(data.Path);
    }
}

DeepLinkData.Source is one of Cold, Warm, Deferred. The SDK also fires a deep_link_opened event so you can measure deep-link conversion in reports.

Deferred — works out of the box

When you create a tracking link in the admin panel, set Deep link path (e.g. /promo/spring2026). Reflect threads it through:

  • Android: into the Play Install Referrer as dl=....
  • iOS: into the AdServices payload as ct2=....

The SDK reads it on first launch and fires OnDeepLink with Source=Deferred after app_install. Zero extra setup.

Cold + warm — wire from your platform code

Reflect deliberately doesn’t auto-swizzle Activity/AppDelegate methods (it’d conflict with your other SDKs). Call HandleDeepLink from your own handlers:

Android

In your launcher Activity:

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    Uri uri = intent.getData();
    if (uri != null) {
        UnityPlayer.UnitySendMessage("ReflectCallbackReceiver", "OnExternalDeepLink", uri.toString());
    }
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Uri coldUri = getIntent() != null ? getIntent().getData() : null;
    if (coldUri != null) {
        UnityPlayer.UnitySendMessage("ReflectCallbackReceiver", "OnExternalDeepLinkCold", coldUri.toString());
    }
}

iOS

- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
    UnitySendMessage("ReflectCallbackReceiver", "OnExternalDeepLink", url.absoluteString.UTF8String);
    return YES;
}

- (BOOL)application:(UIApplication *)app
            continueUserActivity:(NSUserActivity *)activity
            restorationHandler:(void (^)(NSArray * _Nullable))handler {
    if ([activity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb] && activity.webpageURL) {
        UnitySendMessage("ReflectCallbackReceiver", "OnExternalDeepLink", activity.webpageURL.absoluteString.UTF8String);
        return YES;
    }
    return NO;
}

From C# directly

If you already have your own deep-link handler in C#:

Application.deepLinkActivated += url => {
    // Call us — we'll fire OnDeepLink for your subscribers.
    ReflectSDK.HandleDeepLink(url, isCold: !ReflectSDK.IsInitialized);
};
Why not auto-swizzle?
AppsFlyer / Branch do, and it conflicts often with other SDKs and React Native projects. Reflect’s pattern is one C# line per platform — minimal magic, no conflicts.

Set a deep_link_path on a tracking link

Admin panel → Tracking Links → create / edit a link → Deep link path field. Server appends it to the store URL on every redirect; the SDK delivers it via OnDeepLink with Source=Deferred on first launch.