WhollySoftware
Back to blogMobile

Deep Linking and Universal Links: Getting Attribution Right

Wholly Software TeamOctober 2, 20256 min read
Deep Linking and Universal Links: Getting Attribution Right

A retail client ran a paid campaign that drove strong click-through but showed a suspicious 40% gap between reported clicks and attributed app opens. The root cause was deferred deep linking — users without the app installed were tapping a link, going through the App Store, and landing on the app's home screen instead of the specific product page the ad promised, because we hadn't implemented deferred linking for the not-yet-installed case at all, only for users who already had the app.

We rebuilt the flow using Universal Links on iOS and App Links on Android for the direct case, backed by a deferred deep linking service (we've used Branch and, for privacy-conscious clients, a self-hosted solution based on matching install timestamps and IP/user-agent fingerprints server-side) for the install-then-open case. The critical detail most teams miss is that Universal Links only work reliably if the apple-app-site-association file is served correctly with the right content type and no redirects — we've debugged more broken deep links caused by a misconfigured CDN serving that file with a redirect than by actual app code bugs.

Android's App Links have a parallel gotcha: the assetlinks.json file needs to match the exact signing certificate of the release build, and a debug-signed test build will silently fail verification against a production assetlinks.json, which caused two full days of confused debugging on one project before we realized the QA team was testing against the wrong build variant.

Attribution accuracy also depends on handling the cold-start vs. warm-start cases differently. A cold start needs to parse the link, hold onto the destination, wait for the app's dependency graph and auth state to initialize, and then navigate — doing this too early causes crashes when a screen tries to render before its ViewModel has real data. We built a small pending-navigation queue that holds the target route until the app reports it's ready to navigate, rather than trying to time it with delays.

After the rebuild, the client's attributed conversion numbers matched their ad platform's reported clicks within about 3%, which was close enough to trust the data again for budget decisions. The broader lesson: deep linking bugs don't look like crashes, they look like marketing spend that appears to underperform, so they often get misdiagnosed as a campaign problem rather than an engineering one.

Deep LinkingAttributioniOSAndroid
Deep Linking and Universal Links: Getting Attribution Right — Wholly Software