Matching Architecture
This page explains how Detour matches an app's first open to a link click.
Matching modes
-
Deterministic (preferred) — when an exact
clickIdis present (Android install referrer), the server performs a simple lookup and returns the link if the click exists and is unmatched. Deterministic matching is exact and fast. -
Probabilistic (fallback) — when
clickIdis not available (typical on iOS), Detour computes a similarity score between the device fingerprint sent by the SDK and recent unmatched click beacons.
Probabilistic fingerprint fields
platform,model,manufacturer,systemVersion— device identity signals.screenWidth,screenHeight,scale— display metrics.locale- language/region.timezone— timezone string.userAgent— raw user agent for more granular device signature.timestamp— when the fingerprint was captured (used for time-window filtering).pastedLink(optional) — the clipboard content if the user had a link copied prior to first open. Platform checks equality of token generated by server which was added as search param and url string.
Scoring
The server scores each candidate click using separate scoring functions. The weights used by Detour today:
| Signal | Weight |
|---|---|
| IP exact | 500 |
| User agent match | 300 |
| Timezone | 200 |
| Screen match | 200 |
| Clipboard/paste match | 300 |
| Language match | 100 |
The server computes a total score as the sum of each applicable signal's weight. The current acceptance THRESHOLD is 800. Only the highest scoring candidate above the threshold is accepted.
Why these weights? weights prioritize signals that are harder to spoof or coincidental (IP, user-agent/device signature, clipboard) and treat softer signals (language) as weaker evidence.
Time window
- Clicks outside the configured time window are ignored. The default window in the matching logic is 15 minutes between click timestamp and fingerprint timestamp. This reduces false positives and focuses on near-in-time installs.
Example scoring scenarios
- Strong deterministic evidence: same IP (500) + clipboard exact match (300) = 800 → accepted.
- Weak signals: timezone + language + screen match = 200 + 100 + 200 = 500 → below threshold → rejected.
- User-agent + IP: 300 + 500 = 800 → accepted.
Matching algorithm (high-level pseudocode)
for each unmatched click in recentClicks:
if |click.timestamp - fingerprint.timestamp| > windowMs: continue
score = scoreIP(click, fingerprint)
+ scoreUserAgent(click, fingerprint)
+ scoreTimezone(click, fingerprint)
+ scoreScreen(click, fingerprint)
+ scorePastedLink(click, fingerprint)
+ scoreLanguage(click, fingerprint)
if score > bestScore:
best = { click, score }
if best.score >= THRESHOLD:
return best.click
else:
return null
Post-match: mark the click as matched
When a match is accepted, the system updates the click row and marks it matched to prevent duplicate attribution for subsequent installs.
False positives & safety
The high threshold and conservative weights minimize false positives. Still, probabilistic matching may fail on noisy networks, VPN use, or where users share similar devices in a local population. It is not recommended to redirect users to pages or screens that contain sensitive data.