Deferred Deep Linking
Open your app to the exact right screen — even when it wasn't installed yet when the link was clicked.
How it works
User clicks your branded short link on web or social
ylnk saves a fingerprinted context (clickId + device info) server-side
User is directed to the App Store or Play Store to install your app
On first launch, your app calls /v2/deeplink/query → ylnk returns the deep link destination
Android uses the Play Install Referrer API — an exact clickId is passed through the Play Store install flow.
iOS uses device fingerprinting (IP + User-Agent + timezone) matched within a 15-minute window — no store attribution available on iOS.
1. Setup in ylnk Dashboard
- 1 Go to Dynamic Links Apps and click Create App
- 2 Fill in your Android package name + SHA-256 fingerprints (for AssetLinks) and/or iOS Bundle ID + Team ID (for AASA)
- 3 Note the App Config ID — you'll need this in your SDK integration
- 4 Click the 📖 Integration Guide button on your app card for pre-filled SDK code
2. Android Integration
Add to your Application.onCreate() or first Activity.
implementation("com.android.installreferrer:installreferrer:2.2")// Call checkDeferredDeepLink() from Application.onCreate()
// Gradle: implementation("com.android.installreferrer:installreferrer:2.2")
private const val APP_CONFIG_ID = "YOUR_APP_CONFIG_ID"
private const val YLNK_QUERY_URL = "https://api.ylnk.cc/v2/deeplink/query"
fun checkDeferredDeepLink(context: Context) {
val referrerClient = InstallReferrerClient.newBuilder(context).build()
referrerClient.startConnection(object : InstallReferrerStateListener {
override fun onInstallReferrerSetupFinished(responseCode: Int) {
var clickId: String? = null
if (responseCode == InstallReferrerClient.InstallReferrerResponse.OK) {
val referrer = referrerClient.installReferrer.installReferrer
clickId = Uri.parse("?$referrer").getQueryParameter("click_id")
}
referrerClient.endConnection()
CoroutineScope(Dispatchers.IO).launch { queryYlnk(context, clickId) }
}
override fun onInstallReferrerServiceDisconnected() {
CoroutineScope(Dispatchers.IO).launch { queryYlnk(context, null) }
}
})
}3. iOS Integration
Add to your AppDelegate.application(_:didFinishLaunchingWithOptions:).
// Call checkDeferredDeepLink() from:
// application(_:didFinishLaunchingWithOptions:)
private let APP_CONFIG_ID = "YOUR_APP_CONFIG_ID"
private let YLNK_QUERY_URL = "https://api.ylnk.cc/v2/deeplink/query"
func checkDeferredDeepLink() {
let timezone = TimeZone.current.identifier
let screen = UIScreen.main.bounds
let scale = UIScreen.main.scale
let resolution = "\(Int(screen.width * scale))x\(Int(screen.height * scale))"
guard let url = URL(string: "\(YLNK_QUERY_URL)?appConfigId=\(APP_CONFIG_ID)"),
let body = try? JSONSerialization.data(withJSONObject: [
"timezone": timezone, "screenResolution": resolution
]) else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = body
URLSession.shared.dataTask(with: request) { data, _, _ in
guard let data = data,
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
let d = json["data"] as? [String: Any], d["found"] as? Bool == true,
let deepLink = d["deepLinkUrl"] as? String,
let url = URL(string: deepLink) else { return }
DispatchQueue.main.async {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}.resume()
}4. API Reference
/v2/deeplink/queryCalled at every cold app launch. Returns the deferred deep link context if a match is found. No auth token required — public endpoint.
Query params
| Param | Required | Notes |
|---|---|---|
| appConfigId | Yes | From your app config |
| clickId | No | Android only — from Install Referrer |
Request body
{
"timezone": "Asia/Dhaka",
"screenResolution": "1080x1920"
}Success response (match found)
{
"status": true,
"data": {
"found": true,
"deepLinkUrl": "yourapp://product/123",
"originalUrl": "https://example.com/product/123",
"utmParams": { "utm_source": "campaign" }
}
}No match response
{
"status": true,
"data": { "found": false }
}5. Testing Checklist
App config created with correct package name / bundle ID
Android SHA-256 fingerprints added for AssetLinks verification
Required for Android App Links (Universal Links equivalent)
iOS Team ID + Bundle ID added for AASA file generation
Your custom domain serves /.well-known/apple-app-site-association automatically
App config linked to your custom domain in Domain Settings
Domains → Configure → App Config dropdown
checkDeferredDeepLink() called on every cold app launch (not warm)
Skip if app is already open — only call on fresh process start
Test Android: clear app data → click link → reinstall → check navigation
clickId via Play Install Referrer is the most reliable Android method
Test iOS: click link → install within 15 min → launch → check navigation
Fingerprint matching works within a 15-minute window