Your app decides what happens with the data. Despia resolves the link natively and hands you the payload. It never navigates the WebView to a URL built from the link, so there is no 404 risk and no routing you are forced into. What you do with the metadata, redirect, fetch, or render in place, is entirely your app logic.
Installation
- Bundle
- CDN
How it works
You attach the context you care about to a OneLink when you create it (which product, which creator, which invite code). AppsFlyer stores that click server-side. When the app opens, the SDK resolves it and Despia callswindow.onAppsFlyerDeepLink(payload) with that data. On a fresh install this is the deferred case: the click was stored before the app existed on the device, and it is delivered on first launch. Despia keeps registered OneLink domains out of the WebView entirely, so the user never sees a redirect page and your app never has to parse a link.
Deferred deep linking works even if the user installs days after clicking. AppsFlyer stores the click with a configurable lookback window (default 7 days) and delivers it on the first launch inside that window.
What arrives in the app
The callback receives a plain object: the data you put on the link, delivered intact. A typical creator campaign for a specific product looks like this:deep_link_value tells you what kind of destination this is, for example "product", "collection", "creator", "episode", or "offer". It is just a string you chose when you built the link. The deep_link_sub1 through deep_link_sub10 params carry the specifics, the product ID, the creator or affiliate code, the invite code, the episode ID. Along with deep_link_value, these ten sub params are the fields AppsFlyer guarantees on a deferred first-launch resolution, so put anything a fresh install must receive into them. You can also add your own named params like page_id or episode_id, and they arrive as top-level keys on the callback, but read the reliability note below before relying on them for deferred installs.
On a deferred install both native paths can fire, so your handler may be called more than once. Keep it idempotent. The session-flag dedupe shown under Cold-start fallback covers this.
Use the data
You get the object, you do whatever your app needs. There is no required pattern. The three most common: Redirect to a page that loads its own content from the params:deep_link_value to a route is one clean way to do the same thing, but it is an option, not a requirement:
Register the callback early
Definewindow.onAppsFlyerDeepLink as early as possible, ideally in an inline script in your document <head>, before your app bundle loads. Despia queues deep links that arrive before the page is ready and replays them roughly 300 ms after the page registers, so the handler must already exist by then. Assign it bare, outside any user agent gate, since setting a property on window is harmless when the app runs outside Despia.
When the callback fires
| Scenario | What happens |
|---|---|
| Fresh install (deferred) | On first launch the stored click resolves and the callback fires. deep_link_value and deep_link_sub1 through deep_link_sub10 are guaranteed; custom named params arrive when the conversion-data fallback matches the click. This is the case deep linking exists for. |
| App installed, link tapped | The link opens the app, AppsFlyer resolves it, and the callback fires with the click payload. Attribution updates to install_type: "re-engagement". |
| Paid install without deep_link_value | The callback still fires on first launch for non-organic installs, so you can personalize onboarding from media_source or campaign even when the ad carried no routing value. |
| Organic install, no link | The callback does not fire. despia.appsFlyerReferrer is "organic". |
On iOS, deferred resolution happens after the App Tracking Transparency prompt is answered (the SDK waits up to 60 seconds for it), so on a fresh install the callback can arrive well after your first page render. Keep the handler installed, do not treat it as launch-time-only.
Cold-start fallback
The last resolved deep link also persists inside the injected attribution object. If your page reloads after the callback already fired, read it from there and de-duplicate with your own one-shot flag:Payload reference
The kind of destination, chosen by you when creating the OneLink, e.g.
"product", "creator", "episode", "offer". Keep values short and URL-safe.The specific content ID to load, e.g. a product ID, episode ID, or profile ID. A custom param, but a special-cased one: Despia also lifts
page_id to a top-level normalized field on despia.appsFlyerAttribution (both platforms). Other custom keys only appear under despia.appsFlyerAttribution.raw. On the callback payload every key is top-level regardless.Ten general-purpose values from the OneLink, commonly a creator code, affiliate code, or invite code. Along with
deep_link_value, these are the only fields AppsFlyer guarantees on a deferred first-launch resolution, so use them for anything a fresh install must receive. deep_link_sub1 also doubles as the appsFlyerReferrer fallback when deep_link_value is absent, so set both together.Any parameter you add to the OneLink (
episode_id, season, ref, …) arrives as a top-level key on the callback payload, and under despia.appsFlyerAttribution.raw on the attribution object. Reliable on direct opens and re-engagements. On a deferred install they come through the conversion-data fallback rather than the guaranteed UDL payload, so move must-have IDs into deep_link_sub1 through deep_link_sub10.The attributed network and campaign for this click.
true when the payload comes from a deferred deep link on first launch."Organic" or "Non-organic" (first-launch conversion payloads only).Creator and Affiliate Links
Give each creator their own OneLink with a unique code indeep_link_sub1 and the content they are promoting in page_id. When a user installs through that link, the code arrives on first launch, so you know exactly which creator drove the install and can credit them, apply their discount, and open the product they were promoting.
af_sub1 in your AppsFlyer dashboard to see installs, events, and revenue per creator.
Create the OneLink
Create a OneLink URL
In your AppsFlyer dashboard, go to Engage > OneLink Management and create a link. Attach a
deep_link_value and put the IDs a fresh install must receive into deep_link_sub1 through deep_link_sub10. page_id and other named params work too, but are only guaranteed on direct opens and re-engagements, see the reliability note above.Register the OneLink domain with your app
Your OneLink domain (e.g.
yourapp.onelink.me) must be registered in your Despia app build so the OS opens the app directly and Despia keeps the URL out of the WebView. Links from unregistered domains behave like ordinary web links.Use the link in ads or hand it to creators
Paste the OneLink into your TikTok or Meta ad creative, or give it to a content creator as their affiliate link.
Frequently Asked Questions
What is the actual point of deferred deep linking?
What is the actual point of deferred deep linking?
To carry the context of a click into the app on first launch even though the user did not have the app when they clicked. They tap your ad or a creator link, install from the store, open the app, and the product, creator, invite, or episode they came for is available immediately. Without it, every install lands on a generic home screen and the campaign context is lost.
Do I have to use a router?
Do I have to use a router?
No. You receive a plain object and do whatever you want with it, redirect, run a backend call and render the result, apply a code, or open a screen in place. A router is just one convenient way to dispatch on
deep_link_value if your app already has one.What if deep_link_value is null?
What if deep_link_value is null?
The user did not come from a deep link campaign. Read
media_source and campaign from the payload if you still want to personalize a paid install, otherwise show your default page.Can I pass my own custom parameters?
Can I pass my own custom parameters?
Yes. Named params (
episode_id, ref, …) arrive as top-level keys on the callback payload and under despia.appsFlyerAttribution.raw. One caveat for deferred installs: AppsFlyer’s Unified Deep Linking payload only guarantees deep_link_value and deep_link_sub1 through deep_link_sub10 for a brand-new user. Custom keys still tend to arrive because Despia also forwards the conversion-data payload on first launch, but that is a fallback, so put anything a fresh install must have into deep_link_sub1 through deep_link_sub10.Resources
NPM Package
despia-native