Developer Docs

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

1

User clicks your branded short link on web or social

2

ylnk saves a fingerprinted context (clickId + device info) server-side

3

User is directed to the App Store or Play Store to install your app

4

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. 1 Go to Dynamic Links Apps and click Create App
  2. 2 Fill in your Android package name + SHA-256 fingerprints (for AssetLinks) and/or iOS Bundle ID + Team ID (for AASA)
  3. 3 Note the App Config ID — you'll need this in your SDK integration
  4. 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.

Gradle dependency:implementation("com.android.installreferrer:installreferrer:2.2")
kotlin
// 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:).

swift
// 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

POST/v2/deeplink/query

Called at every cold app launch. Returns the deferred deep link context if a match is found. No auth token required — public endpoint.

Query params

ParamRequiredNotes
appConfigIdYesFrom your app config
clickIdNoAndroid 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

Ready to set up?

Create your app config and get pre-filled code snippets in the dashboard.