Attribution · definition

iOS attribution without ATT: AdServices, SKAN, AdAttributionKit

FolioKit · July 15, 2026

Short answer: Apple gives you three attribution systems, and they answer different questions. AdServices is deterministic (a definite per-install answer you can join to your own user record) but covers Apple Search Ads only. SKAdNetwork 4 covers other registered ad networks at the campaign level: up to three aggregate postbacks per install, no users, ever. AdAttributionKit is SKAdNetwork's successor — it adds capability while keeping the aggregate privacy model. No combination of the three gives you user-level paid-social attribution without ATT consent. Plan around that instead of against it.

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:

SystemCoversGranularityNeeds 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:

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:

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:

  1. 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.
  2. 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.
Where FolioKit fits: the SDK handles both halves without an MMP — Apple Search Ads attribution via AdServices, deterministic and ATT-free, and SKAdNetwork conversion values mapped from server config so you can retune them without an app update. Aggregate paid-social stays aggregate; we won't pretend otherwise. Details in the SDK docs.

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.

FolioKit is analytics for indie iOS developers — Apple Search Ads attribution and SKAN conversion values built into the SDK, joined to RevenueCat revenue on one user record, no MMP required. The SDK itself requires no ATT prompt; apps with their own retargeting or personalized-ads needs may still choose to show one.

Get early access