Skip to main content
Documentation
Concepts

Deferred Deep Links

How deferred deep links preserve their destination and context through an app install, routing new users to the right place after first launch.

Deferred deep links solve the "click before install" problem. When a user clicks a link but doesn't have the app installed, deferred deep linking preserves the link context through the install flow so the user lands on the right content after installing. This page is the technical reference for how WarpLink matches the install and scores the match. For the short version, with the iOS and Android differences side by side, see the deferred deep linking overview.

The Problem

Without deferred deep links:

  1. User clicks a product share link
  2. App isn't installed: user goes to the App Store
  3. User installs and opens the app
  4. User lands on the home screen with no context

The link context is lost during the install step.

The Solution

With WarpLink deferred deep links:

  1. Click: User taps a WarpLink URL
  2. Signal capture: WarpLink's redirect records the click from a mobile browser. The server derives the IP and stores it with the normalized language and the timezone
  3. Store redirect: User goes to the App Store or Play Store. A Play Store URL gets an install referrer that names the link
  4. Install: User installs the app
  5. First launch detection: The SDK detects first launch and records a completion marker once the check finishes. The marker is gone after an uninstall and never returns from a backup, on iOS and on Android alike, so a reinstall runs the check again
  6. Signal collection: The SDK collects device signals (preferred language, IANA timezone name and offset, platform-specific IDs)
  7. Attribution request: The SDK sends signals to the WarpLink attribution API, which derives the IP from the request
  8. Match: The server matches install-time signals against click-time signals and returns the original link data

The user now opens the app and lands directly on the shared product.

How Matching Works

The server walks a cascade and stops at the first rung that matches: the Play Install Referrer, then the device ID, then the probabilistic match.

Tier 1: Deterministic (Android)

  • Play Install Referrer: WarpLink adds referrer=utm_source=warplink&utm_content={link_id} to every play.google.com destination. The Play Store passes it through the install, and the SDK reads it on first launch, so the server is told which link produced the install

A deterministic match always has confidence 1.0, and only a deterministic match sets matchGuaranteed to true on the result. Use that flag, like a confidence threshold, to route the user to the right destination. Keep sign-in on your own authentication.

Repeat checks: the device ID (iOS)

  • IDFV: the Identifier for Vendor answers the same install asking again, for example when an earlier check was cut off before its answer arrived. It returns the install the device already has, with that install's own match type and confidence, so it never turns a probabilistic match into a guaranteed one. A reinstall the SDK reports as one is deliberately not answered from this rung: it falls through to the probabilistic tier below and is recorded there as a new install

On iOS, a first install is matched probabilistically, and the result carries matchGuaranteed: false.

Tier 2: Probabilistic (Match Key)

This tier runs unless the app is in routing-only mode. In that mode the server stores no match key payload for the app's clicks and the app reaches a deferred deep link only through the Play Install Referrer.

The match restores the link a user tapped on the first open after install. It uses no advertising ID, does not track users across other companies' apps or websites, and the match key is hashed. Each tap can be matched only within the app's match window, and pending entries are deleted automatically within 48 hours. A matched install keeps the hashed key for your plan's data retention period. The raw IP address is not stored.

When the referrer isn't available (every first install on iOS, sideloaded Android builds, devices without the Play Store, destinations that are not a Play Store URL), the server compares click-time and launch-time signals to compute a probabilistic match. Current SDKs send the raw language and timezone, and the server computes the hash with the request IP on both sides:

Time Since Clickenriched_tzenrichedbasic
< 1 hour0.850.800.70
< 3 hours0.650.600.50
< 6 hours0.500.450.35
< 24 hours0.300.250.20

Matches run up to 24 hours after the click.

enriched_tz is the variant current SDKs send. It hashes the IANA timezone name, for example America/Toronto, which carries far more entropy than the minute offset (roughly 340 zones against 38 offsets) and does not shift at a daylight-saving boundary, so a click and install pair that straddles the change still matches. enriched hashes the offset and is the fallback for SDKs that send no zone name. basic covers signals that carry neither.

Two multipliers then reduce the score. A bucket that held more than one distinct link scores at 0.6 of the band. A click from a carrier-grade NAT or private address also scores at 0.6, a household IPv4 address at 0.9, and an IPv6 address at 1.0.

Match Window

The match window controls how far back the server looks for matching clicks. It is set per link on the server, in the dashboard, not in the SDK.

The default is 6 hours, set per link, up to 24 hours.

The 24-hour window covers the installs that convert: installs overwhelmingly happen soon after the click.

This governs the probabilistic tier only. The referrer and device ID rungs read stored install records instead, so a short window costs them nothing. Links created earlier may still carry a larger configured value, and the server reads it as 24 hours.

How the deferred payload is stored

When a click comes from a mobile browser, WarpLink stores a short payload for it: the link, the destination, the deep link URL for that device's operating system, and the click time. The payload is keyed to the hashed match key and held for the length of the match window, then is deleted automatically within 48 hours.

Each key holds a list of recent clicks. The list is newest first, capped at ten clicks per key. A match claims the newest click in the list that no install has claimed yet, and a claimed click is never handed to a second install, so two installs from one bucket get two different clicks.

When the bucket held more than one distinct link, the confidence score is multiplied by 0.6. Use the confidence score to choose the destination for each match.

The attribution API reads this payload when the SDK requests a match.

The Play Install Referrer is present when the Play Store performs the install. A sideloaded APK or a restored emulator image uses the probabilistic tier. On iOS every first install takes the probabilistic tier. The IDFV is scoped to your Apple team, which is stable across TestFlight and App Store installs, but a simulator install and a device install won't necessarily behave the same way on a repeat check if you're comparing against different provisioning.

For manual testing, use the probabilistic tier as described under How Matching Works. For the most reliable manual result, click and install on the same network within the shortest confidence band (under an hour).

In our October 2026 test, a network change between the tap and the first launch was the main cause of a miss: 30 correct in 90 runs, against 30 in 30 on the same network. The full results are on Attribution accuracy.

Caching

The SDK runs the attribution check on first launch and records a durable completion marker once it finishes:

  • First launch: collects signals, sends the attribution request, records the completion marker
  • Subsequent launches: return without another network request
  • An attempt that produced no usable answer (no connectivity, or a match the SDK cannot route to a destination) is not recorded as complete, so the SDK retries the check on the next launch
  • A reinstall is a new install and gets a new check. The completion marker belongs to one install, so deleting the app clears it. A second, device-level marker does outlive the delete, and its only job is to set is_reinstall on the request. See Reinstalls