Key takeaways
- Deferred deep linking carries a link's destination and parameters through a fresh app install, so a brand-new user lands on the right screen the first time they open your app.
- Flutter's standard deep linking cannot do this alone. Plugins like
uni_linksor the app_links package route existing users, but they have no memory across an install. Deferred linking requires an SDK that matches the original click after install. - The flow is: store the click, install, match on first launch, route. This guide implements each step with
flutter_ulink_sdk, including an AutoRoute-friendly handler. - The match uses privacy-safe signals. Android uses the deterministic Play Install Referrer; iOS uses fingerprint matching (IP, user-agent, timestamp) with no IDFA, SKAdNetwork, pasteboard, or ATT prompt, so no tracking permission is required.
- Deferred deep linking is on Ulinkly's paid plans from $9/month; the free tier covers link creation and basic analytics.
Short answer: To implement deferred deep links in Flutter, initialize a deep linking SDK at startup, then on first launch call the SDK's deferred-link method, which matches the user's original pre-install click and returns its parameters. Route the user to the matched destination. Flutter's built-in deep linking cannot preserve context across an install on its own.
What "deferred" actually means in Flutter
A normal deep link works only if the app is already installed. Tap it, the OS opens the app, your router reads the path. If the app is not installed, the link sends the user to the App Store or Play Store, and after they install and open the app, the original context is gone. They land on a generic home screen.
Deferred deep linking closes that gap. The platform records the click, and when the freshly installed app launches for the first time, the SDK matches that click and hands your app the original parameters.
Prerequisites
- iOS Universal Links and Android App Links configured (Associated Domains capability on iOS,
autoVerifyintent filter on Android). See the full Flutter deep linking guide for the native setup. flutter_ulink_sdkadded topubspec.yaml(pin the current published version).
Step 1: Initialize the SDK at startup
import 'package:flutter_ulink_sdk/flutter_ulink_sdk.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final sdk = ULink.instance;
await sdk.initialize(ULinkConfig(apiKey: 'ulk_your_api_key_here'));
runApp(MyApp());
}
Step 2: Listen for resolved links (installed case)
sdk.onUnifiedLink.listen((ULinkResolvedData data) {
// data.slug, data.parameters, data.linkType
router.handle(data);
});
Step 3: Check for a deferred link on first launch
This is the part unique to deferred linking. After init, trigger a deferred-link check. checkDeferredLink() returns Future<void> — it does not return the link directly. When a pre-install click is matched, the result is delivered through the onUnifiedLink stream from Step 2, so the same handler routes it:
// After initialize(). The matched deferred link arrives via the onUnifiedLink listener above.
await sdk.checkDeferredLink();
Step 4: Route with AutoRoute
If you use AutoRoute, translate the resolved data into a route push:
void handle(ULinkResolvedData data) {
switch (data.linkType) {
case 'product':
appRouter.push(ProductRoute(id: data.parameters['id']));
break;
case 'invite':
appRouter.push(InviteRoute(code: data.parameters['code']));
break;
default:
appRouter.push(HomeRoute());
}
}
The SDK also ships a ULinkAutoRouteTransformer if you prefer to plug resolution directly into AutoRoute's deep-link handling; align the exact wiring with the existing Flutter guide.
Step 5: Test the deferred path specifically
The installed-app path is easy to test. The deferred path needs care:
- Uninstall the app completely.
- Tap a Ulinkly link on the device (not the simulator).
- Install from the store build (or a TestFlight / internal-testing build).
- Open the app and confirm it routes to the linked destination with parameters intact.
Simulators and emulators do not reliably reproduce store-install attribution, so use real devices.
A note on privacy and matching
Deferred matching has to work without tracking the user. Ulinkly uses privacy-safe signals: on Android, the deterministic Play Install Referrer; on iOS, fingerprint matching from non-identifying signals (IP, user-agent, timestamp). It does not use IDFA, SKAdNetwork, the pasteboard, or ATT, so there is no tracking-permission prompt and no extra entitlements. Because iOS matching is fingerprint-based, it is probabilistic rather than guaranteed. See the privacy-first attribution guide.
FAQ
Can Flutter do deferred deep linking without an SDK?
No. Flutter's built-in deep linking and packages like app_links route existing users but cannot preserve context across a fresh install. Deferred linking requires an SDK that matches the pre-install click.
How reliable is deferred matching after ATT?
On Android it is deterministic via the Play Install Referrer. On iOS it relies on fingerprint matching (IP, user-agent, timestamp), which is privacy-safe (no IDFA, SKAdNetwork, or ATT prompt) but probabilistic, so a 100% match rate cannot be guaranteed when network or VPN conditions interfere.
Does deferred deep linking work with AutoRoute, go_router, or Navigator 2.0?
Yes. The SDK returns the matched destination and parameters; you map those to whichever routing approach your app uses. This guide shows AutoRoute.
How long does the deferred match stay valid?
Ulinkly holds a deferred click for matching for 24 hours after the click, and each click is matched once. If the user installs and first opens the app within that window, the original context is delivered; after it, the match expires.
Is deferred deep linking free on Ulinkly?
No. Deferred deep linking and install attribution are on Ulinkly's paid plans, starting at $9/month (Starter). The free tier covers link creation, social previews, and basic analytics.
Build the flow
Create a free Ulinkly account and implement the deferred path above. It is the single highest-leverage deep linking feature for new-user onboarding.
