AppsFlyer
Record app installs, sessions, and in-app events for attribution and ROI measurement.
The AppsFlyer Native Plugin records app installs, updates, and sessions automatically so you can attribute installs, measure campaign performance, and evaluate user quality. Send custom in-app events through the Median JavaScript Bridge.
The plugin integrates the AppsFlyer SDK in your app and exposes a small JavaScript API for setting a customer user ID, logging custom events, and receiving conversion and deep link data. You configure your app in the AppsFlyer dashboard and in Median App Studio, then use the bridge for custom logic.
iOS 14.5+ App Tracking Transparency Requirement
Requesting user consent through the App Tracking Transparency (ATT) framework is required for iOS 14.5+. See Apple App Tracking Transparency in the Median docs and AppsFlyer – Enabling ATT support for implementation details.
Why use AppsFlyer?
- Attribution and ROI: Attribute installs to campaigns and measure return on ad spend.
- Automatic event tracking: Installs, updates, and sessions are recorded without extra code.
- Custom in-app events: Log business events (e.g. signup, purchase) via the JavaScript Bridge.
- Conversion and deep link data: Receive install attribution and deep link payloads in your web app via callbacks.
Key Terms
Dev Key: A unique key per app in the AppsFlyer dashboard. You use the Android and Apple dev keys in Median App Studio to link your Median app to AppsFlyer.
Conversion data: Data returned by AppsFlyer for an install (e.g. first launch, install time, attribution status). The SDK invokes your callback when the app is launched or brought to the foreground (e.g. after a deep link).
af_status: A string in the conversion data object indicating whether the install is Organic or Non-organic. Use it to branch logic (e.g. show different onboarding for paid vs organic users).
Organic vs non-organic: Organic = install not attributed to a campaign; non-organic = attributed to a marketing source.
Prerequisites
- A Median.co app with JavaScript Bridge enabled
- An AppsFlyer account and app(s) created for iOS and Android
- Apple App ID (from App Store Connect – App Information) or your app’s App Store URL
- Android package name (from Median App Identifiers) or your app’s Play Store URL
- For iOS 14.5+: ATT implemented and, if desired, ATT prompt delay configured in the plugin
Developer DemoDisplay our demo page in your app to test during development https://median.dev/appsflyer/
When to use this plugin
AppsFlyer is essential for apps that need to:
| Use Case | Example |
|---|---|
| Campaign attribution | Attribute installs and re-engagement to paid campaigns (e.g. Facebook, Google) |
| Install and session tracking | Measure installs, updates, and sessions automatically without extra code |
| Custom in-app events | Log signups, purchases, or feature usage for analytics and optimization |
| Conversion data | Know whether an install is organic or non-organic and use it in your app logic |
| Deep link handling | React to deferred or direct deep links (e.g. open a specific screen from a push or ad) |
| ROI measurement | Evaluate user quality and campaign performance in the AppsFlyer dashboard |
What you'll do
- Create apps in AppsFlyer: Complete AppsFlyer configuration and obtain dev keys for Android and Apple.
- Enable the plugin: Go to Plugin setup and enter Android Dev Key, Apple Dev Key, and Apple App ID (and optional ATT delay).
- Use the bridge: Implement
median.appsflyer.setCustomerUserId,median.appsflyer.logEvent, and the global conversion / deep link callbacks in JavaScript bridge functions. - Test on devices: Follow Testing Checklist; the SDK is not fully validated in the simulator.
Implementation Guide
AppsFlyer configuration
Before enabling the plugin in Median, create and configure your app in the AppsFlyer dashboard using your Apple App ID and Android package name (see Prerequisites). Add one app for iOS and one for Android; once each is created, you’ll receive a dev key for that platform.
| Key | Example value | Source |
|---|---|---|
| Apple App ID | 123456789 | App Store Connect – App Information |
| Android package name | co.median.android.dnxqyl | Median App Studio – App Identifiers |
Once the app is created and added to your dashboard, you will receive a dev key for that platform.

AppsFlyer - Dev Key
You may need to configure additional options in AppsFlyer (e.g. re-engagement attribution, uninstall measurement). See AppsFlyer App Settings and the AppsFlyer Help Center.
App Studio configuration
Enable the Plugin
- Open Native Plugins: In Median App Studio, open your app and go to Native Plugins.
- Open AppsFlyer: Select AppsFlyer and go to Settings.
- Enter credentials: Set Android Dev Key, Apple Dev Key, and Apple App ID from your AppsFlyer setup. Optionally set the ATT prompt delay (iOS).
Configuration options
| Setting | Description | Default | Recommended |
|---|---|---|---|
| Android Dev Key | AppsFlyer dev key for your Android app | — | From AppsFlyer dashboard |
| Apple Dev Key | AppsFlyer dev key for your iOS app | — | From AppsFlyer dashboard |
| Apple App ID | Apple App ID (numeric) for your iOS app | — | From App Store Connect |
| ATT prompt delay (optional) | Delay in seconds before showing the ATT prompt on iOS | — | Per your product/legal requirements |

Median AppsFlyer Plugin Configuration
Note
The configuration above is a sample for the developer demo. AppsFlyer is highly customizable. For production, we recommend consulting AppsFlyer or your marketing team to tailor settings (attribution, uninstall measurement, etc.) to your needs. See the AppsFlyer Help Center.
After the plugin is configured, use the JavaScript Bridge functions below to set a customer user ID, log custom events, and handle conversion or deep link data via callbacks.
JavaScript Bridge Functions
Associate a User
Associates your own customer user ID with AppsFlyer so you can cross-reference it with AppsFlyer’s device IDs and your backend.
↔️Median JavaScript Bridge
try { const { success } = await median.appsflyer.setCustomerUserId("user123"); console.log(success ? "User ID set successfully" : "Failed to set user ID"); } catch (err) { console.error(err.code, err.message); }
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Your unique customer or user |
Log a Custom In-App Event
Logs a custom in-app event with an optional object of values. Use it for signups, purchases, or any business event you want to measure in AppsFlyer.
↔️Median JavaScript Bridge
try { const { success } = await median.appsflyer.logEvent("purchase", { value: 99.99, currency: "USD" }); console.log(success ? "Event logged successfully" : "Failed to log event"); } catch (err) { console.error(err.code, err.message); }
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
eventName | string | Yes | Event name (e.g. 'purchase', 'signup') |
eventValues | object | No | Key-value pairs to attach to the event (e.g. { amount: 9.99, currency: 'USD' }) |
Conversion data and deep link callbacks
The plugin does not expose a single “get conversion data” function. Instead, the app invokes global callback functions you define when conversion or deep link data is available (on app launch or when brought to the foreground, e.g. via a deep link). Data is cached after the first call and will be the same on later invocations.
Legacy conversion (install) data
Define this function so the app can pass conversion data for the install:
↔️Median JavaScript Bridge
function median_appsflyer_cd_success(conversionDataMap) {
// conversionDataMap.af_status is "Organic" or "Non-organic"
console.log('Install attribution:', conversionDataMap);
}New conversion data
function median_appsflyer_cd(data) {
console.log('Conversion data:', data);
}UDL (Unified Deep Linking) / deep link result
For deep link payloads (e.g. deeplinkValue, campaign, mediaSource):
function median_appsflyer_deeplink_result(data) {
console.log('Deep link data:', data);
if (data.deeplinkValue) {
// Navigate or handle deep link
}
}Sample response – conversion data
{
"is_first_launch": false,
"in-stall_time": "2026-02-11 10:32:16.951",
"af_message": "organic install",
"af_status": "Organic"
}Sample response – deep link
{
"afSub1": "",
"afSub2": "",
"afSub3": "",
"afSub4": "",
"afSub5": "",
"campaign": "",
"campaignId": "",
"clickEvent": {},
"clickHTTPReferrer": "",
"deeplinkValue": "",
"isDeferred": true,
"matchType": "",
"mediaSource": ""
}Testing Checklist
Use this checklist to confirm AppsFlyer is working in your app:
Basic Functionality
- Plugin is enabled and configured in Native Plugins > AppsFlyer > Settings
-
median.appsflyer.setCustomerUserId(id)runs without errors -
median.appsflyer.logEvent(name, values)runs without errors - Conversion callback (
median_appsflyer_cd_successormedian_appsflyer_cd) is called on launch or when returning to the app
Platform Testing
- Behavior verified on a real Android device (not only simulator)
- Behavior verified on a real iOS device (not only simulator)
- On iOS 14.5+, ATT prompt appears when configured and consent affects behavior as expected
Configuration Testing
- Android Dev Key, Apple Dev Key, and Apple App ID match the AppsFlyer dashboard
- Global callback function names match exactly (
median_appsflyer_cd_success,median_appsflyer_cd,median_appsflyer_deeplink_result)
User Experience
- No JavaScript errors in the console from the plugin or callbacks
- Callbacks do not block the UI; navigation or UI updates remain responsive
Troubleshooting
AppsFlyer functions are undefined or not working
Ensure the JavaScript Bridge is enabled in your Median app and that you are calling median.appsflyer after the app and bridge are ready (e.g. after deviceready or when your main app script runs). Confirm the AppsFlyer plugin is enabled under Native Plugins in App Studio.
Conversion callback is never called
Conversion data is provided when the app is launched or brought to the foreground. Ensure you define the global function names exactly: median_appsflyer_cd_success (legacy), median_appsflyer_cd (new), or median_appsflyer_deeplink_result (UDL). The SDK may take a moment to return data; avoid removing or redefining these callbacks during the first launch.
ATT prompt does not appear on iOS
Confirm App Tracking Transparency is implemented in your app and that you have configured the ATT prompt (and optional delay) as required. The simulator may not show the system ATT dialog; test on a real device.
Events or installs do not show in the AppsFlyer dashboard
Verify Android Dev Key, Apple Dev Key, and Apple App ID in Native Plugins > AppsFlyer > Settings match the app in your AppsFlyer dashboard. Ensure you are testing on a real device; the SDK does not fully work in the simulator. Allow some time for data to appear in the dashboard.
Wrong or missing conversion data
Conversion data is cached after the first callback. For a fresh install, the first launch may have limited data until attribution is resolved. Check AppsFlyer’s documentation on timing and testing.
Deep link callback not firing
Confirm your deep link URL scheme and link format are configured correctly in AppsFlyer and that the app is opened via that link (not only from the home screen). Use AppsFlyer’s deep link validator and test on a real device.ent!
Still having trouble?For SDK-level errors or attribution behavior, refer to AppsFlyer SDK documentation.
Updated 10 days ago