Mobile Attribution Without IDFA
Since iOS 14.5 (April 2021), an app can only read the IDFA — the Identifier for Advertisers — after the user taps Allow on the App Tracking Transparency prompt. Most users don't. For everyone else the identifier comes back as zeros, and any attribution built on matching the IDFA at click time to the IDFA at install time simply stops working.
This guide covers what still works: the deterministic paths Apple and Google actively support, probabilistic matching for your own links, and the aggregate frameworks built for paid advertising — and how LinkForty fits in.
Android is on the same road. Google Play requires apps to honor the "delete advertising ID" setting, at which point the advertising ID reads as zeros too. Everything below applies to both platforms; iOS is simply where it happened first.
What ATT actually changed
Before: the IDFA was readable by any app without asking. An attribution provider recorded it on the ad click, read it again on first app open, matched the two, and attributed the install. Deterministic, and it worked across companies — an ad network could follow a user from a game into a shopping app.
After: reading the IDFA requires the ATT prompt:
"YourApp would like permission to track you across apps and websites owned by other companies."
The prompt describes exactly the thing users least want, so the typical answer is Ask App Not to Track. Once that happens the IDFA is 00000000-0000-0000-0000-000000000000 for that app, and Apple's guidelines forbid working around the answer by other means.
The important nuance: ATT governs tracking across companies. Understanding how someone got from your link to your app is a different problem, and it has answers that need no prompt.
Four things that still work
1. Universal Links and App Links — deterministic, when the app is installed
If the app is already installed, an https:// link on a domain the app has claimed opens the app directly. The OS hands the app the full URL; nothing is inferred. This is 100% attribution with zero privacy cost, and it should be the first thing you set up.
LinkForty serves the association files (apple-app-site-association, assetlinks.json) on your LinkForty domain and custom domains; the app claims the host in its entitlements or manifest. See Universal Links vs App Links.
2. Probabilistic matching — for the install that follows a click
When the app is not installed, the link sends the user to the store. When the app opens for the first time, the question is: was this the person who clicked a link a little while ago?
LinkForty answers it by comparing what the link server saw at click time with what the SDK reports on first open — network address, user agent, timezone, language, screen size, platform and OS version — inside an attribution window (7 days by default) and above a confidence threshold. A match delivers the link's deep-link path to the app (this is deferred deep linking) and records the install against the link.
What this is and is not:
- It is first-party: your link, your app, your data. No identifier is shared with anyone else and nothing is matched across other companies' apps.
- It is probabilistic: a match is a confident inference, not a proof. Two devices on the same office Wi-Fi with the same model and settings can look alike; a long gap between click and open, a VPN or a network change lowers confidence. LinkForty declines to attribute below its threshold rather than guess.
- It uses no restricted APIs. Apple's required-reason API rules exist because signals like boot time or free disk space were being used to build cross-app fingerprints; the SDK doesn't read them.
Apple's App Store guidelines prohibit using device signals to identify a user across apps and websites owned by other companies — the thing ATT asks about — regardless of whether the user tapped Allow. Matching a click on your own link to the first open of your own app is not that, and it is how deferred deep linking has worked on iOS for a decade. Keep it there: don't feed these signals into an ad network, a data broker, or a cross-app profile.
3. SKAdNetwork 4 and AdAttributionKit — for paid advertising
For installs driven by ads on networks you don't control, Apple provides an attribution channel that needs no identifier at all. The ad network registers the impression or click; after the install, Apple sends the network a postback saying that a campaign produced a conversion — with no device or user information attached.
SKAdNetwork 4 (iOS 16.1+) is the current version most networks run: up to three postbacks over 35 days, a fine conversion value (0–63) in the first postback when enough installs make the crowd anonymous, coarse values (low / medium / high) otherwise, and hierarchical source identifiers so you can encode more about the campaign when volume allows.
AdAttributionKit (iOS 17.4+) is its successor: the same privacy model, extended to alternative app marketplaces in the EU and, from iOS 18, to re-engagement attribution. It interoperates with SKAdNetwork 4 during the transition, so a network reading one can read the other.
Neither gives you per-user data, real-time results, or a deep link. They tell the ad platform which campaign worked; you still need something in the app to know which link opened it.
4. The IDFA itself — if you have a real reason to ask
Some apps have a genuine case for the prompt (a personalized ad experience the user benefits from, for instance). If you ask and the user allows, the IDFA is deterministic and can supplement everything above for that user. For most apps the prompt costs more in first impressions than it returns, and everything in this guide works without it.
Putting them together
The approach that works in practice layers the four, most certain first:
- App installed? Universal Link / App Link opens it — deterministic.
- Fresh install after a click? Probabilistic match delivers the deep link and attributes the install.
- Paid campaign? SKAdNetwork / AdAttributionKit tells the ad network which campaign converted.
- User granted ATT? The IDFA confirms what the other layers inferred.
LinkForty handles 1 and 2 — links, association files, the click record, the match, the deferred deep link, and the dashboard that reports installs per link and per campaign. 3 lives between your ad networks and Apple; 4 is your product decision.
Setting it up with LinkForty
The full walkthrough for each platform is on the SDK pages; this is the shape of it.
1. Install the SDK — React Native, Expo, iOS, Android or Flutter.
2. Initialize at launch with your app token (Workspace Settings → App Token):
// React Native
import LinkForty from '@linkforty/mobile-sdk-react-native';
LinkForty.init({
baseUrl: 'https://api.linkforty.com',
appToken: process.env.LINKFORTY_APP_TOKEN,
debug: __DEV__,
});
// iOS
import LinkFortySDK
let config = LinkFortyConfig(
baseURL: URL(string: "https://api.linkforty.com")!,
appToken: appToken
)
try await LinkForty.shared.initialize(config: config)
// Android
import com.linkforty.sdk.LinkForty
import com.linkforty.sdk.LinkFortyConfig
val config = LinkFortyConfig(
baseURL = "https://api.linkforty.com",
appToken = appToken
)
LinkForty.initialize(this, config)
3. Handle the deferred deep link — the callback fires once on first launch, with the link's data if a click matched and null for an organic install:
LinkForty.onDeferredDeepLink((data) => {
if (!data) return; // organic install: behave normally
navigation.navigate(data.deepLinkPath); // or route on data.customParameters
});
4. Handle direct deep links the same way with onDeepLink, so a link tapped after the install lands on the same screen.
5. Claim your link host so links open the app: applinks:acme.toapp.me in the iOS Associated Domains capability and an autoVerify intent filter for the same host on Android. The SDK pages show each platform's steps, and SDK Health Check confirms the SDK is reporting.
6. Track what happens next — trackEvent('signup'), trackRevenue(amount, 'USD') — so the install becomes a funnel. See Events.
No ATT prompt appears at any point.
What to expect from probabilistic matching
Accuracy is a property of conditions, not of the technique. Rough guide:
| Situation | Match quality |
|---|---|
| Same network, opened within minutes of the click | High — the signals line up exactly |
| Same network, within a day or two | High — network addresses are fairly stable |
| Network changed between click and open (home → mobile data) | Reduced — the address no longer matches, other signals must carry it |
| Shared network with many similar devices (office, campus) | Reduced — more devices look alike; LinkForty prefers a missed match to a wrong one |
| Days between click and open | Declining — addresses and settings drift; the window ends at 7 days by default |
| VPN or carrier-grade NAT | Reduced — many users share an address |
Two practical consequences:
- Keep the window short. The 7-day default is a ceiling for most consumer apps; a day or two suits time-limited campaigns. Configure it with
attributionWindowHoursat initialization (see Attribution Windows). - Read campaign-level numbers, not individual journeys. Across hundreds of installs, missed matches and the occasional wrong one wash out; the relative performance of channels is reliable even when a single attribution isn't.
Privacy
Be honest about what this is. Network address, user agent and device settings are personal data under GDPR (an IP address is, per the Court of Justice's Breyer judgment), even though none of them identifies a person by name. That doesn't make attribution unlawful; it means it needs a basis and a disclosure like anything else you process.
- Basis. Most apps rely on legitimate interest (GDPR Art. 6(1)(f)): understanding which of your own links drove installs of your own app, with a short retention and no sharing, is a limited, expected use. If you also feed the data into advertising profiles, that reasoning no longer holds — don't.
- Retention. The signals only matter inside the attribution window. LinkForty keeps click analytics for your workspace's plan retention period; set your own policy accordingly.
- Rights. Access, deletion and objection apply. On the device,
LinkForty.clearData()wipes the install ID and attribution data so the next launch is treated as new; server-side records go through your normal data-request process. - Disclosure. Say it in your privacy policy. A template:
## Install attribution
When you open our app for the first time after following one of our links, we
compare the network address, device type, language, timezone and screen size the
link recorded with those the app reports, to understand which of our links or
campaigns led to the install and to open the content the link pointed to.
We do this only for our own links and our own app; nothing is shared with
advertising networks or matched across other companies' apps. The signals are
retained for [your retention period] and are not used to build a profile of you.
Legal basis: legitimate interest (GDPR Art. 6(1)(f)). You can object to this
processing or request deletion at [contact].
Summary
- ATT ended cross-company tracking by identifier; it did not end knowing how someone reached your app.
- Universal Links / App Links are deterministic when the app is installed — set them up first.
- Probabilistic matching attributes the install that follows a click and delivers the deferred deep link — first-party, no prompt, short window, honest about confidence.
- SKAdNetwork 4 / AdAttributionKit tell ad networks which paid campaigns converted, in aggregate.
- Ask for the IDFA only when you have a reason the user would agree with.
LinkForty gives you the first two out of the box: Quick Start · SDK Integration · Deferred Deep Linking.