In mobile marketing, the question "which channel brought this user" no longer has a simple answer. Since IDFA was largely disabled on iOS after App Tracking Transparency, Apple moved attribution to aggregated frameworks like SKAdNetwork and AdAttributionKit; on Android, Play Install Referrer and Google's privacy-first measurement experiments are going through a parallel transformation. This guide covers three questions a mobile developer or growth team needs to answer: how SKAdNetwork's mechanics work, when a Mobile Measurement Partner (MMP) is actually needed, and what to watch for when reading aggregated data correctly.
💡 Pro Tip: Before you start designing conversion values, write down which 3-5 in-app events will actually change a marketing decision — filling all 64 values with an "as much data as possible" mindset only speeds up your fall to coarse value on low-volume campaigns.
Table of Contents
- Why Attribution Broke: ATT and After
- Deterministic vs. Aggregated Measurement
- SKAdNetwork Mechanics and Conversion Value Design
- Conversion Value Design Rules
- The Android Side: Play Install Referrer and Privacy Sandbox
- Play Install Referrer API
- The Measurement Side of Privacy Sandbox
- Four Frameworks, Quick Comparison
- MMP Selection Criteria and Decision Table
- The Technical Cost of SDK Integration
- Reading Aggregated Data Correctly
- Practical Reading Rules
- Building Your Own Measurement Layer
- Recommendation by App Type
- FAQ
- How does SKAdNetwork work, what is conversion value?
- What should you look at when choosing an MMP (AppsFlyer, Adjust)?
- How do you measure campaign performance after ATT?
- How does Android's Privacy Sandbox change attribution?
- Update (September 2026)
- Conclusion
- Sources
Why Attribution Broke: ATT and After
With App Tracking Transparency, user-level, deterministic cross-device attribution (click-to-install matching based on IDFA) is no longer possible for users who don't opt in on iOS. The result was the industry splitting into two parallel paths: Apple's own aggregated frameworks (SKAdNetwork, later AdAttributionKit) and MMP layers that keep deterministic data limited to opted-in users and model (probabilistic attribution) the rest.
Deterministic vs. Aggregated Measurement
Deterministic measurement matches a click and an install one-to-one through a shared identifier (IDFA, GAID); it allows user-level LTV calculation but requires consent. Aggregated measurement (like SKAdNetwork), on the other hand, returns no user-level data at all — it only provides a delayed, resolution-reduced (fine→coarse, field-restricted) signal at the campaign/ad-network level. This makes campaign optimization possible but makes user-level cohort analysis impossible.
SKAdNetwork Mechanics and Conversion Value Design
SKAdNetwork is Apple's attribution framework offered inside StoreKit; it tells the ad network which campaign an install came from without sharing any user-level identity. With SKAN 4, two types of conversion value were defined: fine and coarse.
Fine conversion value is a 6-bit integer, meaning it can take 64 possible values from 0 to 63 (Apple Developer, updatePostbackConversionValue). You use these 64 states to encode your app's most critical post-install events (for example onboarding completion, trial start, first purchase) as a bit mask. Coarse conversion value was added with SKAN 4 and has only three levels: low, medium, high. Apple checks whether the volume generated by the app/domain showing the ad, the app being advertised, the country, and the hierarchical source identifier meets a "crowd anonymity" threshold; when the threshold isn't met, it returns coarse value instead of fine value, and the fields carried in the postback are also restricted based on the privacy level (Apple Developer, Receiving postbacks in multiple conversion windows).
1import StoreKit2 3// A simple conversion value update: triggered on first purchase4func reportFirstPurchase() {5 // choose an integer between 0-63 as the fine value field6 let conversionValue = 22 // e.g. bit for "onboarding completed + first purchase"7 8 if #available(iOS 16.1, *) {9 SKAdNetwork.updatePostbackConversionValue(10 conversionValue,11 coarseValue: .medium12 ) { error in13 if let error {14 print("SKAdNetwork update error: \(error)")15 }16 }17 }18}Postback timing was also split into three windows with SKAN 4. By Apple's definition, the first window covers days 0-2 after install, the second window days 3-7, and the third window days 8-35; only the first postback can carry a fine-grained conversion value, the second and third postbacks always return coarse value (Apple Developer, Receiving postbacks in multiple conversion windows). This means it's pointless to try to squeeze a value spread over a long funnel (e.g. a renewal on day 10) into the first postback — that signal already belongs to the third window and will arrive at coarse resolution.
Conversion Value Design Rules
- Time-sensitive bits: Allocate the bulk of your fine value to events expected to happen within 0-2 days, because only that window can get fine resolution.
- Locking (lockWindow): Only the
updatePostbackConversionValue(_:coarseValue:lockWindow:completionHandler:)overload closes the window early and immediately starts postback preparation, so the signal arrives sooner. The random delay duration doesn't change (24-48 hours for the first postback, 24-144 hours for the second/third), only the counter starts from the lock moment — in exchange, you lose whatever data would have accumulated in the remaining window time (Apple Developer, Receiving postbacks in multiple conversion windows; AdAttributionKit-SKAdNetwork interoperability). - Falling back to coarse scenario: Don't build your design on a small-scale campaign based solely on fine value — have a meaningful interpretation plan for coarse (low/medium/high) too.
The Android Side: Play Install Referrer and Privacy Sandbox
While GAID, Android's counterpart to IDFA, is still available on many devices, Google is also pursuing its own aggregated measurement path. There are two separate layers: the Play Install Referrer API you use in production today, and the Privacy Sandbox measurement APIs still in testing.
Play Install Referrer API
The Play Install Referrer API securely returns which referrer information an app was installed with via Google Play. The data it returns: the referrer URL, client- and server-side timestamps of the click, client- and server-side timestamps of the start of install, and the app's version at first install. Referrer information is retained for 90 days and doesn't change unless the app is reinstalled; accessing the API requires the device to have Play Store app version 8.3.73 or higher (Android Developers, Install Referrer API; for the version requirement see Android Developers, Install Referrer API overview).
1import com.android.installreferrer.api.InstallReferrerClient2import com.android.installreferrer.api.InstallReferrerStateListener3import com.android.installreferrer.api.InstallReferrerClient.InstallReferrerResponse4 5fun fetchInstallReferrer(context: Context) {6 val referrerClient = InstallReferrerClient.newBuilder(context).build()7 referrerClient.startConnection(object : InstallReferrerStateListener {8 override fun onInstallReferrerSetupFinished(responseCode: Int) {9 when (responseCode) {10 InstallReferrerResponse.OK -> {11 val response = referrerClient.installReferrer12 val referrerUrl = response.installReferrer13 val clickTimestamp = response.referrerClickTimestampSeconds14 val installTimestamp = response.installBeginTimestampSeconds15 // forward referrerUrl to your attribution server16 referrerClient.endConnection()17 }18 InstallReferrerResponse.FEATURE_NOT_SUPPORTED -> {19 // Play Store version is outdated20 }21 InstallReferrerResponse.SERVICE_UNAVAILABLE -> {22 // connection dropped, retry23 }24 }25 }26 27 override fun onInstallReferrerServiceDisconnected() {28 // reconnection logic29 }30 })31}The Measurement Side of Privacy Sandbox
Under Google's Privacy Sandbox on Android initiative, an Attribution Reporting API was being developed; this API aimed to match source and trigger events on-device and deliver event-level and aggregatable reports to ad tech parties in an aggregated form. As of early 2025, this API was still in Developer Preview/Beta: integration required installing a Privacy Sandbox system image on a supported device or emulator, enabling the API via ADB commands, and comparing raw reports with a debug key (Privacy Sandbox, Attribution Reporting developer guide). In other words, as of when this article was written, it was neither mandatory nor sufficient on its own as a production measurement layer — Play Install Referrer remained the primary source.
Four Frameworks, Quick Comparison
Framework | Platform | Resolution | Timing |
|---|---|---|---|
SKAdNetwork (SKAN 4) | iOS | Fine (0-63) or coarse (low/medium/high) | 3 postback windows: 0-2, 3-7, 8-35 days |
AdAttributionKit | iOS / alternative marketplaces | Works alongside SKAdNetwork, similar postback model | Same postback window model as SKAdNetwork; only a single impression wins per conversion |
Play Install Referrer | Android | Referrer URL + timestamps (user-level) | At install time; data retained for 90 days |
Privacy Sandbox Attribution Reporting | Android | Event-level + aggregatable reports (aggregated) | Beta/testing stage as of when this article was written |
MMP Selection Criteria and Decision Table
A Mobile Measurement Partner combines aggregated frameworks like SKAdNetwork/AdAttributionKit, Play Install Referrer, and deterministic signals from opted-in users into a single reporting layer; it also provides attribution window configuration, postback routing, fraud detection, deep linking, and ready-made integrations with numerous ad networks (AppsFlyer, Fraud Protection product page; RudderStack, what is an MMP). Fraud detection matters especially with multi-channel budgets: a single ad network only sees traffic in its own inventory, so it can't catch a fraud pattern spanning channels — only a measurement layer watching all channels at once can.
- SKAdNetwork/AdAttributionKit postback management: Can it manage the conversion value schema (fine bit mask + coarse mapping) for you and distribute it to ad networks?
- Fraud detection: Does it offer a dedicated module against attack types like install hijacking and click spamming, or just basic filtering?
- Deep linking: Is deferred deep linking (routing to the correct screen after install) part of the SDK, or a separate product?
- Data location and GDPR/local compliance: Which region the raw data is kept in and whether it aligns with your own data retention policy.
- SDK size and init time: How much it affects app cold-start performance.
- API/webhook access: Are there ready connectors to move reported data into your own data warehouse (BigQuery, S3, etc.), or does it only offer a dashboard?
Criterion | Why It Matters | How to Test |
|---|---|---|
Postback schema management | Manually updating the fine/coarse design is error-prone | Compare the conversion value log in a test campaign |
Fraud module coverage | Cross-channel fraud is invisible to a single network | Sandbox test with a known fraudulent traffic source |
Deep link SDK | Correct post-install screen = conversion rate | End-to-end install test with different campaign links |
Data export API | Independent access to your own BI layer | Try a sample export/webhook |
SDK init time | Affects cold-start metrics | Measure with Xcode Instruments / Android Profiler |
The Technical Cost of SDK Integration
Adding an MMP SDK is generally a three-stage job: SDK setup and initialization, implementing the deep link/deferred deep link handler, and validating conversion value/event mapping. The hidden cost is mostly in the third stage — mapping the SDK's own event taxonomy (e.g. "purchase", "subscribe", "tutorial_complete") one-to-one with your own product analytics events requires a separate QA cycle. If you skip this, the "conversion" numbers shown in the dashboard drift away from the event definitions the product team actually uses, and the two teams start arguing over different numbers.
1# iOS: keep SKAdNetwork IDs in sync with the list ad networks share2# check the SKAdNetworkItems array in Info.plist3plutil -extract SKAdNetworkItems xml1 -o - Info.plist | grep -c "SKAdNetworkIdentifier"1{2 "event_mapping": {3 "product_analytics_event": "app_purchase_completed",4 "mmp_event_name": "af_purchase",5 "conversion_value_bit_range": [16, 21],6 "coarse_fallback": "medium"7 }8}Reading Aggregated Data Correctly
Aggregated postback data is distorted by three things: delay, thresholding, and data-tier narrowing. Delay comes from the random duration Apple applies to every postback (24-48 hours for the first, 24-144 hours for the second/third) — that's why a metric like "today's ROAS" can't be produced from SKAdNetwork data, only a delayed window report can. Thresholding means campaigns below the crowd anonymity threshold get coarse instead of fine value; this seriously lowers data resolution on small-budget test campaigns. Data-tier narrowing is Apple restricting the postback fields (source-identifier, conversion-value, coarse-conversion-value, source-app-id, country-code) based on the privacy level — at the lowest tier only the first postback is sent; rather than treating a single campaign's postback count as absolute truth, tracking the trend over time is a more reliable approach (Apple Developer, Receiving postbacks in multiple conversion windows).
Practical Reading Rules
- Trend over absolute number: Watch the weekly moving average, not a single day's postback count.
- Segment by window: Don't mix fine value from the 0-2 day window with coarse value from the 8-35 day window in the same table.
- Treat coarse as a rough indicator: Don't interpret low/medium/high as a precise number; use it only for relative ranking.
Building Your Own Measurement Layer
Some teams prefer to build their own postback receiver servers to reduce MMP cost or data dependency. This requires a server that hosts an endpoint StoreKit will POST SKAdNetwork postbacks to — either the ad network's or an opted-in developer's own — and a layer that maps the conversion value schema to your product events. Doing this increases data ownership but also means building fraud detection, multi-network integration, and deep linking from scratch — so for most mid-sized teams, an MMP plus export to your own data warehouse is a more balanced starting point.
1// A simple SKAdNetwork postback receiver (Node/Express sketch)2app.post("/skadnetwork/postback", (req, res) => {3 const {4 "ad-network-id": adNetworkId,5 "source-identifier": sourceIdentifier,6 "conversion-value": conversionValue,7 "coarse-conversion-value": coarseConversionValue,8 "postback-sequence-index": postbackSequenceIndex,9 "source-app-id": sourceAppId,10 } = req.body;11 12 // 1) verify Apple's signature (separate step, omitted here)13 // 2) the first postback carries fine, second/third only coarse14 const mappedEvent =15 conversionValue !== undefined16 ? decodeConversionValue(conversionValue)17 : decodeCoarseConversionValue(coarseConversionValue);18 19 saveAttributionRecord({20 adNetworkId,21 sourceIdentifier,22 mappedEvent,23 sourceAppId,24 postbackSequenceIndex,25 });26 res.sendStatus(200);27});Recommendation by App Type
- Early stage / single platform (iOS only): Set up SKAdNetwork correctly with the right conversion value schema first, add an MMP only once your fraud detection and deep linking needs become clear.
- Multi-channel, mid-large budget: An MMP is mandatory — postback schema management and cross-channel fraud visibility can't be sustained by hand.
- Android only: Play Install Referrer is your primary source today; keep watching the Privacy Sandbox measurement APIs without making production dependent on them.
- Enterprise / data-ownership priority: Export the MMP's raw data into your own data warehouse, use the dashboard reports only for quick checks.
FAQ
How does SKAdNetwork work, what is conversion value?
SKAdNetwork is Apple's framework that runs through StoreKit and delivers a campaign-level conversion signal to the ad network without sharing any user-level identity. Conversion value is what the app reports via updatePostbackConversionValue; in SKAN 4 it's delivered as fine (a 6-bit integer from 0-63) or, at volumes below the crowd anonymity threshold, as coarse (low/medium/high) (Apple Developer, Receiving postbacks in multiple conversion windows).
What should you look at when choosing an MMP (AppsFlyer, Adjust)?
Postback schema management, fraud detection coverage, deep linking support, data location/compliance, the SDK's impact on app launch, and the ability to export to your own data warehouse are the most decisive criteria; these points are summarized in the decision table above.
How do you measure campaign performance after ATT?
Deterministic data is still available for users who opt in; for those who don't, performance is read through SKAdNetwork/AdAttributionKit postbacks, as delayed, window-based (0-2, 3-7, 8-35 days) aggregated signals. Tracking a weekly trend gives more reliable results than a precise daily ROAS.
How does Android's Privacy Sandbox change attribution?
During the period this article covers (January 2025), Privacy Sandbox's Attribution Reporting API was still in developer beta/testing and had not replaced Play Install Referrer; enabling the API required a special system image and ADB command (Privacy Sandbox developer guide). You can find the current status in the "Update" section below.
Update (September 2026)
On October 17, 2025, Google officially announced it was winding down a large portion of the Privacy Sandbox initiative — including the Attribution Reporting API on Android; the status page moved this API on Android to "Deprecate and remove" status (Privacy Sandbox status page). Ecosystem feedback about their expected value and the technologies' low levels of adoption were cited as the reasons (Privacy Sandbox, plan update announcement). The practical consequence: teams that had built a roadmap dependent on Privacy Sandbox on Android need to move their measurement strategy back to Play Install Referrer and MMPs' own modeling layers. On iOS, both AdAttributionKit and SKAdNetwork remain callable; both frameworks' ad network IDs stay valid, but only one impression wins per conversion — the winner can come from either framework (AdAttributionKit-SKAdNetwork interoperability documentation).
Related posts published later:
- App Store Connect Subscriptions: Offer Codes, Family Sharing, Winback
- App Store Optimization (ASO): Get Your App Discovered
- I Made $1M on the iOS App Store: Real Strategy and Numbers
- Android 15 Developer Guide: Privacy Sandbox, Edge-to-Edge, Foreground Services
- App Store Connect API 2026: TestFlight, Submission, Analytics Automation
- iOS Crash Reporting and Analytics: A Production-Quality Guide
Conclusion
Mobile attribution is no longer one-to-one matching through a single identity — it's the job of gathering and interpreting multiple aggregated signals (SKAdNetwork/AdAttributionKit postbacks, Play Install Referrer, deterministic data from opted-in users). Before moving to an MMP, verify you can set up SKAdNetwork's conversion value schema correctly on your own; this lets you ask more informed questions when choosing an MMP, and it doesn't leave you empty-handed in the early stage when you need to go without one.
GOLDEN TIP
The most valuable insight in this article
This tip holds the article's most important takeaway.
Easter Egg
You found a hidden gem!
There's a hidden detail in this section. Want to uncover it?
Reader Reward
We've gathered the points that are easy to skip while implementing this guide but get expensive later into a single checklist. Check off the items below one by one before you lock your SKAdNetwork schema or sign an MMP contract.
Sources
- SKAdNetwork | Apple Developer Documentation — Official overview of the SKAdNetwork framework.
- updatePostbackConversionValue | Apple Developer Documentation — Primary definition of the fine value's 6-bit / 0-63 range.
- Receiving postbacks in multiple conversion windows | Apple Developer Documentation — The three postback windows and the fine/coarse rule.
- What is Fine Conversion Value? — Singular — Secondary source.
- Receiving postbacks in different conversion windows in SKAN 4.0 — Segwise — Secondary source.
- AdAttributionKit | Apple Developer Documentation — Official overview of AdAttributionKit.
- AdAttributionKit and SKAdNetwork interoperability | Apple Developer Documentation — Parallel callability and the single-winner impression rule.
- Play Install Referrer API | Android Developers — Referrer data and the 90-day retention period.
- Install Referrer API overview | Android Developers — The Play Store 8.3.73+ version requirement.
- Attribution Reporting developer guide | Privacy Sandbox — Testing/beta integration of the Android Attribution Reporting API.
- Privacy Sandbox feature status | Privacy Sandbox — Attribution Reporting's "Deprecate and remove" status on Android.
- Update on plans for Privacy Sandbox technologies | Privacy Sandbox — October 2025 wind-down announcement and rationale.
Tags
iOS Development News
Weekly Swift tips, SwiftUI tricks and iOS best practices. No spam, only valuable content.
We respect your privacy. You can unsubscribe at any time.

