Deferred deep linking allows users who don’t have your app installed to click an Adjust link, install your app from the app store, and then be directed to their intended content when they first open the app.
How it works
This is the basic flow of deferred deep linking:
- The user clicks on an Adjust deep link.
- Adjust’s servers redirect the user to the app store.
- The user installs or reinstalls your app and opens it.
- The Adjust SDK sends an
/attributionrequest to Adjust’s servers. - Adjust’s servers match the click to the install or reinstall and return the deferred deep link in the
/attributionresponse. The Adjust SDK delivers the deferred deep link to your app via the deferred deep link callback. - If applicable, your app displays its initial screens, such as onboarding screens and user login.
- Your app handles the deep link and navigates to the appropriate screen.
Deferred deep link format
When a user clicks an Adjust branded link (brandname.go.link) and the link is deferred, Adjust’s servers convert it to app scheme format (example://), using the app scheme configured in the platform settings in the Adjust dashboard, before passing it to the Adjust SDK.
Setup
Set up a deferred deep link callback
- Create an
AdjustConfigobject. - Set a deferred deep link callback on the
AdjustConfigobject. The Adjust SDK calls this callback after receiving a deferred deep link. - Set the
launchDeferredDeeplinkproperty to control whether the SDK opens the deep link automatically. - Initialize the SDK.
AdjustConfig adjustConfig = new AdjustConfig('{YourAppToken}', AdjustEnvironment.sandbox);adjustConfig.deferredDeeplinkCallback = (String? uri) { /* * TODO: Handle the deep link * (for example, store it or handle it immediately) * * deep link format: * * example://summer-clothes?promo=beach&adj_t=def456 */};
adjustConfig.launchDeferredDeeplink = false; // or true based on your use case (see below)
Adjust.start(adjustConfig);Deep link opening options
The launchDeferredDeeplink property determines what happens after your callback code executes:
Set to false (most common)
Use this approach if you want your app to have complete control over when and how to process the deferred deep link. By setting this to false, the Adjust SDK will not attempt to open the deferred deep link. For example, this approach is appropriate if your app needs to show and move past initial screens (like onboarding or login) before handling the deferred deep link.
Set to true (default)
Use this approach if you want the Adjust SDK to attempt to open the deferred deep link immediately after the callback code runs. For example, this approach is appropriate if your app does not have any initial screens.
When the Adjust SDK receives the deferred deep link, your callback code runs, and then the Adjust SDK opens the deep link URL using native OS methods (application(_:open:options:) on iOS, startActivity(Intent) on Android). The OS then delivers the link to your app_links uriLinkStream listener.
Full code example
This example shows how an app with an onboarding process handles deferred deep links. Here is a summary of the app’s internal flow:
- The user opens the app for the first time.
- The app begins its onboarding process.
- The app’s callback receives the deferred deep link from the Adjust SDK and then checks if onboarding is complete:
- If complete, it handles the deep link immediately.
- If not complete, it stores the deep link.
- Once onboarding finishes, the app checks for and handles any stored deferred deep link.
- The app navigates the user to the deep link screen.
import 'package:adjust_sdk/adjust.dart';import 'package:adjust_sdk/adjust_config.dart';import 'package:flutter/foundation.dart';
String? _pendingDeeplink;
void initAdjust() { // Configure Adjust SDK // Replace {YourAppToken} with your Adjust app token const appToken = '{YourAppToken}'; AdjustConfig? adjustConfig;
// Enable verbose logging for deep link testing if (kDebugMode) { adjustConfig = AdjustConfig(appToken, AdjustEnvironment.sandbox); adjustConfig.logLevel = AdjustLogLevel.verbose; } else { adjustConfig = AdjustConfig(appToken, AdjustEnvironment.production); adjustConfig.logLevel = AdjustLogLevel.suppress; }
// Disable automatic opening so we can handle it manually adjustConfig.launchDeferredDeeplink = false;
// Set up deferred deep link callback adjustConfig.deferredDeeplinkCallback = (String? uri) { if (uri == null) return;
if (hasCompletedOnboarding) { // If onboarding is complete, handle deferred deep link immediately
// deep link format: // // example://summer-clothes?promo=beach&adj_t=def456 // // TODO: Handle the deep link and navigate to the appropriate screen. } else { // Store deferred deep link to handle after onboarding _pendingDeeplink = uri; } };
// Initialize Adjust SDK Adjust.start(adjustConfig);}
// When onboarding completes:void onOnboardingComplete() { if (_pendingDeeplink != null) { // deep link format: // // example://summer-clothes?promo=beach&adj_t=def456 // // TODO: Handle the deep link and navigate to the appropriate screen. _pendingDeeplink = null; }}