The confusion here is mostly vocabulary. Three frameworks, three consent stories, three data shapes — and most explainers are written by MMP vendors with a subscription to sell. Here's the map as it stands in 2026, sized for a solo developer rather than a growth team.
The mental model: one deterministic system, two aggregate ones
Sort the three systems by the question they answer and the picture gets simple:
| System | Covers | Granularity | Needs ATT? |
|---|---|---|---|
| AdServices | Apple Search Ads only | Per install: campaign, ad group, keyword IDs, joinable to your user record | No (consent adds click detail) |
| SKAdNetwork 4 | Registered ad networks only | Aggregate: campaign + conversion value, up to three postbacks | No |
| AdAttributionKit | Successor to SKAdNetwork; registered networks, alternative marketplaces, re-engagement | Aggregate, same model, more capability | No |
AdServices exists because Apple owns both sides of a Search Ads install (the ad and the store), so it can attribute deterministically without tracking anyone across companies. Every other network's ads go through the aggregate lane. One caution before you sum anything: the systems don't deduplicate against each other — AdServices and an ad network measuring through AdAttributionKit can both claim the same install or conversion, so treat their numbers as overlapping views, not additive ones.
AdServices: the deterministic Apple Ads path
Your app asks the framework for an attribution token, posts it to Apple's
API, and gets back either attribution: false or the campaign,
ad group, and keyword IDs behind the install. Read false
precisely: it means the install was not attributed to Apple Ads — not that
the user arrived organically. They may have come from a Meta campaign, a
Reddit post, or a friend's recommendation, none of which AdServices can
see. Be precise about "deterministic" too: the payload identifies no user
and no device. What you get is Apple's definite answer for this
install, joinable to your own user record, rather than a modeled
estimate. The standard payload needs no consent; only click-level detail
such as the click timestamp is held back for users who declined ATT.
Attach the result to your user record and "which keyword produced
subscribers" becomes an ordinary query.
Because this is the deterministic half, it deserves its own walkthrough (token retries, payload fields, the ID-to-name mapping), which we've written up separately. The one-sentence version: if Apple Search Ads is your only paid channel, AdServices alone covers the attribution an MMP would otherwise sell you.
SKAdNetwork 4: what the aggregate lane delivers
For Meta, TikTok, Reddit, or any other network (coverage extends only to ad networks registered with Apple, which the major ones are), attribution arrives as postbacks: signed messages from Apple to the ad network (with a copy to you, if you register for it) saying "an install from campaign X reached conversion value Y." No device ID, no user, deliberately delayed. The version-4 specifics that matter:
- Up to three postbacks per install, covering activity windows of roughly days 0–2, 3–7, and 8–35. Whether the later ones arrive depends on conversion activity in each window and on crowd anonymity, and each is sent after a further random delay, so the signal lands days after the behavior.
- Conversion values come in two resolutions. A fine value (0–63) can arrive in the first postback only; the later windows carry at most a coarse low/medium/high. Whatever you want to know about day-30 quality has to compress into three buckets.
- Crowd anonymity decides what you receive. Small campaigns (which, for an indie, is most campaigns) get fields nulled or coarsened. Below the thresholds you may learn only that installs happened.
- Hierarchical source identifiers give up to four digits of campaign structure, but again only when install volume clears the tiers.
Two practical consequences for an indie budget. First, register to
receive your own postback copies — add the
NSAdvertisingAttributionReportEndpoint key to your Info.plist
pointing at an endpoint you control, and Apple sends that endpoint a copy of
each winning postback the ad network receives. Without it, your only view of your own attribution is the
network's dashboard. Second, concentrate spend: crowd
anonymity is per campaign, so five small campaigns can each fall below the
thresholds while one consolidated campaign would have cleared them. Fewer,
bigger campaigns buy you better data, which is backwards from how web
advertisers structure things and worth internalizing early.
The honest summary: SKAdNetwork tells a small advertiser which campaigns produce installs that reach milestones you chose in advance. It does not tell you who, when exactly, or what they did next.
AdAttributionKit: what the successor adds
AdAttributionKit shipped in iOS 17.4, initially so attribution could work on alternative app marketplaces in the EU, and it has been absorbing SKAdNetwork's role since. Calling it a rename undersells it. The successor adds things SKAdNetwork never had: re-engagement attribution (measuring ads that reopen an installed app, from iOS 18, including re-engagement through universal links), custom creatives, developer-defined conversion tags, and a development mode that makes postbacks testable in hours instead of days. It also interoperates with SKAdNetwork campaigns during the migration, so nothing breaks while ad networks move over.
What it preserves is the privacy model: postbacks, conversion windows, crowd anonymity, aggregate only. If you were hoping the successor framework would quietly return user-level data, it doesn't, and Apple's direction of travel makes that a safe long-term assumption. Adopt it because your ad networks will require it and because re-engagement measurement is new capability — not because the granularity changes.
What you cannot know, in writing
Worth stating plainly, because a lot of tooling is marketed as if these were still purchasable:
- Which specific user came from which paid-social ad, without ATT consent. Gone with IDFA consent rates; fingerprinting workarounds violate Apple's rules and get apps rejected.
- Per-user LTV curves by campaign for non-Apple networks. The best you get is conversion-value distributions per campaign.
- Fast feedback. Postback delays plus conversion windows mean paid-social signal is days old by arrival. Budget decisions run on a lag.
- Small-campaign detail. Privacy thresholds bite hardest exactly at indie spend levels.
None of this blocks running ads profitably. It rules out reporting precision you don't have — and at indie scale, most of that precision was noise anyway. The same sample-size honesty we argued for in measuring onboarding against paid conversion applies double behind a privacy threshold.
The one lever you control: what conversion values mean
The volume and timing of what comes back is fixed by Apple; what the conversion values encode is yours to define. The 0–63 fine value and the coarse buckets are that lever, and the common mistake is spending them on vanity milestones (opened the app twice) instead of money-correlated ones (started trial, finished onboarding, reached the value moment). Two rules from doing this on live apps:
- Encode the funnel steps that predict revenue, which you only know if behavior and purchases already join on one user record — the one-ID pattern again. Your own joined data tells you which early actions correlate with paying; the conversion value should encode those.
- Keep the mapping server-side. Conversion-value schemes need iteration, and an app-update round trip per tweak means you'll stop iterating. A config-driven mapping lets you retune what 0–63 means without shipping a build.
FAQ
Do I need an MMP like AppsFlyer or Adjust?
Apple-only spend: no — AdServices covers the attribution question deterministically. An MMP's real scope is broader than postback collection (cost aggregation across networks, fraud detection, deep linking, modeled attribution, reconciling SKAdNetwork data with device-level signals), and it starts earning its fee when you run meaningful spend on several non-Apple networks at once, a scale most indies haven't reached.
Can SKAdNetwork tell me which users came from which campaign?
No, and no setting changes that. Campaign-level counts and conversion values are the entire product, and coverage extends only to registered ad networks. Anything claiming user-level paid-social on iOS without ATT consent is either modeled (estimates) or fingerprinting (against the rules).
Is AdAttributionKit replacing SKAdNetwork?
Yes, gradually, with interoperability during the transition. The privacy model stays aggregate, but the additions are real: re-engagement attribution, universal-link re-engagement, custom creatives, conversion tags, alternative marketplaces, and much better testing. Adopt it when your ad networks ask; expect no user-level data from it.
Should I still show the ATT prompt?
Decision tree, not blanket advice. Apple Search Ads only: skip it — the standard AdServices payload arrives without consent, and one less dialog in onboarding is usually worth more than the gated click detail. Running retargeting, personalized ads, or meaningful multi-network spend: consent can still improve those networks' own targeting and optimization, so decide on their terms.