Skip to main content
Documentation
SDKsiOS

iOS Deferred Deep Links

Preserve a link's destination through an App Store install, then route the user on first launch, with the WarpLink iOS SDK.

Deferred deep links let you route users to specific content even when they don't have your app installed. The user clicks a link, installs from the App Store, and on first launch the SDK matches them back to the original link.

How It Works

  1. User taps a WarpLink URL in Safari
  2. WarpLink's redirect page records the click. The server derives the IP and stores it with the normalized language and timezone. Clicks that share a match key are kept as a list, newest first, up to 10, so a second click never overwrites the first
  3. User is redirected to the App Store
  4. User installs and opens the app
  5. SDK detects first launch. The completion marker is written only after the check completes, so a failed attempt retries on the next launch. It lives in a backup-excluded file inside the app container, so it goes away with the app and does not come back from an iCloud or iTunes restore.
  6. SDK collects device signals (preferred language, timezone name and offset, IDFV)
  7. SDK sends signals to the attribution API. The server derives the IP from the request and computes the match key
  8. Server matches against stored click data and returns the deep link

Automatic Check

The deferred check fires automatically from configure(). The result arrives in your onLink callback, where isDeferred is true:

If the device has no network on launch, the SDK retries the check on the next launch by itself.

Manual Check (Advanced)

To run the check yourself, set autoDeferredCheck: false in WarpLinkOptions and call checkDeferredDeepLink early in your first-launch flow:

Confidence-Based Routing

Confidence Scores

Probabilistic scores depend on the match key variant. enriched_tz hashes the IANA timezone name and is what an SDK that collects a zone name sends. enriched hashes the minute offset instead and stays as the fallback for older SDKs. basic drops the timezone entirely.

ScenarioConfidenceMatch Type
IDFV repeat check, same install asking again (not a reinstall)The stored install's own scoreThe stored install's own type
enriched_tz match key, < 1 hour0.85probabilistic
enriched_tz match key, < 3 hours0.65probabilistic
enriched_tz match key, < 6 hours0.50probabilistic
enriched_tz match key, < 24 hours0.30probabilistic

The offset variant scores 0.80 / 0.60 / 0.45 / 0.25 across the same bands, and basic scores 0.70 / 0.50 / 0.35 / 0.20. Two further signals adjust the score: more than one distinct link in the match key bucket applies x0.6, and a shared click IP applies x0.6 for carrier-grade NAT or a private address, x0.9 for a household IPv4 address, and x1.0 for IPv6. Past 24 hours there is no match at all.

Recommendation: Route to specific content when matchConfidence > 0.5. Show generic onboarding below 0.5. Route a probabilistic match to content or a sign-in screen, and keep sign-in on your own authentication.

Match Window

The match window controls how far back the server looks for matching clicks. It is set per link on the server, not in the SDK. Configure it in the dashboard when you create or edit a link. The default is 6 hours and the maximum is 24 hours.

The window is deliberately short so the match key bucket stays tight and matches stay precise. Links created before the current limits may still carry a longer stored value, but the server caps every window at 24 hours when it reads them.

This governs probabilistic matching only. An IDFV repeat check is not affected by the window, because it returns an install the device already has.

Caching Behavior

  • The SDK checks for a deferred deep link only on first launch
  • Once the check completes, a completion marker is recorded so it does not run again for this install
  • Subsequent launches return without another network request
  • An attempt that produced no usable answer (offline, or a match the SDK cannot route to a destination) is not recorded as complete, so it retries on the next launch
  • A reinstall is a new install, so it gets a new check. See App Reinstall

Edge Cases

Offline First Launch

If the device has no connectivity on first launch, checkDeferredDeepLink fails with .networkError. The attempt is not consumed, so the SDK retries the check on the next launch.

If connectivity is critical for first-launch, check for network availability before calling checkDeferredDeepLink.

App Reinstall

A reinstall is a new install and is attributed again. The SDK keeps two markers with two different jobs:

  • Completion marker: a backup-excluded file in the app container. It says the check already ran for this install. Deleting the app deletes it, and an iCloud or iTunes restore does not bring it back, so a reinstall starts clean.
  • Device-seen marker: a Keychain item. It says the device was attributed at some point, and it outlives an app delete. It gates nothing. Its only job is to set is_reinstall: true on the attribution request, so the install is recorded as a reinstall rather than a first install

Both installs count. The dashboard shows installs and reinstalls together as one installs number.

Routing-only mode

If the app is in routing-only mode, the server skips the probabilistic match. Deep links still open the app. No SDK change is needed.

Clicks that share a match key are kept as a list, newest first, up to 10. The most recent click your app can claim is the one matched, and the others stay available for the other devices that share the address. When more than one click is claimable, the confidence score is multiplied by 0.6 to report that ambiguity.

Testing

Deleting the app is enough to retest. The completion marker goes with it, so the next install runs the check again:

  1. Delete the app from the test device
  2. Open the test link in Safari. You'll be redirected to the App Store (or fallback URL)
  3. Install the app via Xcode or TestFlight
  4. Launch the app. checkDeferredDeepLink should return the matched deep link

The request from step 4 carries is_reinstall: true, because the Keychain marker from the earlier install is still on the device. To test the first-install path instead, erase the device: on a simulator use Device > Erase All Content and Settings (or xcrun simctl erase), which clears the Keychain along with everything else, and on a physical device use one that has never run the app.