Flutter | Deep Linking With AppsFlyer Legacy OneLink (Guilde for Payload Behavior)

Published on November 17, 2025 5 min read

Flutter | Deep Linking With AppsFlyer Legacy OneLink (Guide for Payload Behavior)

Deep linking with AppsFlyer in Flutter can be confusing — especially when using the legacy OneLink structure.
Documentation often mixes legacy vs. new mode behaviors, and the real-world payload inside Flutter does not always match the expected parameters.

This article explains:

  • How legacy OneLink actually behaves in Flutter
  • Which parameters arrive in onDeepLinking
  • Why af_sub1…af_sub5 never show up
  • Correct use of deep_link_value and deep_link_subX
  • Why only one SDK callback (onDeepLinking) should be used for handling deep links
  • How domain verification works on Android
  • How to verify your hosts using ADB
  • Which assetlinks.json values must be added from Google Play Console
  • Fully working long OneLink example for referral or campaign flows

a. Legacy OneLink Payload Behavior in Flutter

AppsFlyer’s documentation states that OneLink parameters (such as af_sub1) will be included in the payload. However, based on multiple real device tests using the legacy OneLink format, the behavior is different.

Do NOT write any parsing logic for af_sub* when using legacy OneLink.
Use only deep_link_value and deep_link_subX

A working long OneLink URL should look like this:

https://yourbrand.onelink.me/AbCd
?pid=invite
&c=referral_campaign
&deep_link_value=ABC123// referral value
&deep_link_sub1=bonus10// optional data or campaign name (whatever you want)

AppsFlyer Flutter SDK provides three main callbacks:

onDeepLinking: Use for direct & deferred deep linking, contains deep link params in payload.

onInstallConversionData: Use if you need data for attribution only

onAppOpenAttribution: Use if you need legacy re-open attribution

Only onDeepLinking contains the actual deep link parameters in Flutter.
The other two callbacks contain measurement & attribution data only — not the deep link parameters data.

Sample setup for handling deep_link_value and deep_link_sub1 parameter:

class AppsflyerUtil {
const AppsflyerUtil._();

static AppsflyerSdk? _appsflyerSdk;
static String? inviteCode;

static Future<void> init() async {
final options = AppsFlyerOptions(
afDevKey: AF_DEV_KEY,
appId: APP_ID,
showDebug: kDebugMode,
appInviteOneLink: null,
disableAdvertisingIdentifier: false,
disableCollectASA: false,
manualStart: true,
);

_appsflyerSdk = AppsflyerSdk(options);

_appsflyerSdk!
.initSdk(
registerConversionDataCallback: false,
registerOnAppOpenAttributionCallback: false,
registerOnDeepLinkingCallback: true,
)
.then((_) {
_setupCallbacks();

_appsflyerSdk!.startSDK(
onSuccess: () {
debugPrint("Appsflyer INIT Success");
},
onError: (errorCode, errorMessage) {
debugPrint(errorMessage);
},
);
});
}

static void _setupCallbacks() {
_appsflyerSdk!.onDeepLinking(
(deepLinkResult) {
debugPrint("onDeepLinking: ${deepLinkResult.toJson()}");
String? campaignName;

//* ONELINK DEEPLINK
if (deepLinkResult.deepLink?.deepLinkValue != null) {
inviteCode = deepLinkResult.deepLink?.deepLinkValue;

if (deepLinkResult.deepLink?.clickEvent["deep_link_sub1"] != null) {
campaignName =
deepLinkResult.deepLink?.clickEvent["deep_link_sub1"];
}
}
}
},
);
}
}

b. Android Domain Verification (Digital Asset Links)

For Android deep links to open in your app reliably:

  • Your host must be added to the Flutter intent filters
  • Your host must appear under Supported Links in Android device your_app settings
  • AND your host must be verified

Firstly you must add your onelink domains in your AndroidManifest.xml like this:

<meta-data android:name="flutter_deeplinking_enabled" android:value="false" />

<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="your_domain.onelink.me" />
</intent-filter>
Make sure do flutter_deeplinking_enabled to false for handling Appsflyer plugin can correctly handle deep linking instead of Flutter framework itself.

then check your app domains using this adb prompt:

adb shell pm get-app-links YOUR.PACKAGE.NAME
Host: yourdomain.com
Status: verified

If the host shows unverified, deep links may open in the browser instead of your app.

Solving host verification problem: Google Play Console → Your App → Setup → Deep Links → App Links Verification

Google provides a block like:

{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "your.package.name",
"sha256_cert_fingerprints": [
"AB:CD:EF:...."
// Google provides another fingerprint value too here especially, we
// need that also. Dont forget copy too it.
]
}
}

Copy this block exactly and place it inside:

https://yourdomain.com/.well-known/assetlinks.json

After uploading:

  • Wait a few minutes
  • Run the ADB command again
  • Host becomes verified instantly

c: Apple Side Verifications

For iOS ensure your domains are added in:

Info.plist:

key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:your_domain.onelink.me</string>
</array>
When you make changes to the Apple asset file (your branded domain’s apple site association file or auto generated onelink file), the cache time on the Apple server side must expire for the changes to be reflected, so the changes you make are not immediately reflected on the Apple side. So If you make changes in Appsflyer onelink management panel you must wait for your changes reflect to apple files.

Legacy OneLink behaves differently in Flutter than the documentation suggests, especially regarding which parameters are delivered and which callbacks actually matter. In practice, only onDeepLinking provides real deep-link payloads, while the other callbacks contain attribution data only. Relying exclusively on deep_link_value and deep_link_subX ensures consistent behavior across both direct and deferred flows.

Correct domain verification is equally important: Android App Links require proper assetlinks.json setup and matching SHA-256 fingerprints, while iOS may delay updates due to Apple’s caching of association files. Once these pieces are correctly configured, Flutter deep linking with AppsFlyer becomes stable, predictable, and production-ready.

Thanks for reading, i hope it will be useful for the problems you are experiencing 👏. Happy sunday gardaşım (means bro in Turkish :).

Flutter | Deep Linking With AppsFlyer Legacy OneLink (Guilde for Payload Behavior)

Category: mobile-app-developmentTags: mobile-app-development, appsflyer, android-app-development, flutter, deeplink