Quickstart
One link, two journeys: open it with the app installed (direct App Link), then install the app from a click (deferred match). This picks up after install & initialize — the app config, intent-filter, and SDK initialization are in place.
Create the link
In the OptoLink portal, create a link with the path /promo/flash-24h. Its canonical URL is https://links.yourdomain.com/acme/<shortCode>; share that URL to a device.
Direct open (app installed)
With the app already installed, tap the link in Chrome. Android verifies the autoVerify intent-filter, opens your activity directly, and hands it the Intent. Forward it and collect:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
OptoLink.instance().handleIntent(intent)
scope.launch {
OptoLink.instance().links.collect { data ->
Log.d("OptoLink", "$data")
}
}
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
OptoLink.instance().handleIntent(intent) // warm starts land here
}
Logcat shows the resolved link:
OptoLinkData(linkId=clxk…, path=/promo/flash-24h, params={utm_source=instagram}, matchMethod=DIRECT, confidence=EXACT, isDeferred=false, score=null)
handleIntent is safe to call before initialize finishes; the intent is parked and processed once initialization completes.
Deferred match (install from a click)
On a device without the app:
- Tap the link. The OptoLink redirect page opens and copies a one-time attribution token to the clipboard, then shows the Get it on Google Play button (from your AppConfig
storeUrl). - Install and open the app.
- On first launch,
initializereads the clipboard token, matches it server-side, and emits the link onlinks:
OptoLinkData(linkId=clxk…, path=/promo/flash-24h, params={utm_source=instagram}, matchMethod=CLIPBOARD, confidence=EXACT, isDeferred=true, score=null)
On Android 12+, the first-launch clipboard read shows a system toast ("… pasted from your clipboard"). That toast is the expected output of this test: it confirms the deferred match ran.
The match runs once per install. If the first launch had no network, the opportunity isn't lost: call resolveDeferredLink() later to re-run the match manually; it returns an OptoLinkData? (null = no match) and throws on network failure.
What you have
Both journeys end in the same place: an OptoLinkData on the links stream, with matchMethod telling you how it arrived. From here:
- Every method and shape: API reference
- What throws, what retries: Errors & retries
- Bind the device to a user or report events with
setIdentity/trackEvent— same reference.