SKAdNetwork (SKAN) is Apple's framework for privacy-preserving attribution on iOS. Instead of tracking individual users, it aggregates conversion data at the network level and delivers postbacks with intentional delay and noise. For developers and marketers accustomed to deterministic attribution, it requires a significant mental shift.
This guide covers everything from the basic postback flow to the specific changes introduced in SKAN 5.0, with concrete implementation guidance throughout.
Why SKAdNetwork Exists
Before App Tracking Transparency (ATT), mobile attribution on iOS relied on the IDFA (Identifier for Advertisers), a device-level identifier that ad networks used to match clicks to installs with high precision. When Apple launched ATT in iOS 14.5, it required explicit user opt-in for any cross-app tracking. Opt-in rates settled at roughly 20-30% across most app categories, gutting the deterministic attribution infrastructure that had grown up around the IDFA. For more on how ATT intersects with deferred linking, see deferred linking and ATT.
SKAdNetwork is Apple's answer. It lets ad networks claim attribution credit for installs without any device-level identifier leaving the device. The tradeoff is that the data is aggregated, delayed, and subject to privacy thresholds that can suppress postbacks entirely.
Understanding this tradeoff is essential before implementing anything. SKAdNetwork gives you campaign-level signal, not user-level signal.
The Basic SKAN Flow
At a high level, SKAN works as follows:
- An ad network shows an ad using a signed SKAdNetwork impression
- The user taps the ad and installs the app
- The app registers the install with
SKAdNetwork.registerAppForAdNetworkAttribution()(or via an MMP SDK) - The app updates a conversion value to encode post-install behavior
- After a timer expires, the device sends a postback directly to the ad network's endpoint
- The ad network receives the postback and reports aggregated data back to you
The device sends the postback, not your server. This is fundamental. You do not receive individual postbacks with user-level data. The data goes to the ad network, which then reports aggregated results in their dashboard or via their API.
Conversion Values: Fine-Grained and Coarse
Conversion values are how you encode post-install behavior into the privacy-preserving SKAN signal.
In SKAN 3 and earlier: A single 6-bit fine-grained conversion value (0-63) was available. You had to pack all the behavioral signal you wanted into 64 possible states.
In SKAN 4.0 and later: Apple introduced a tiered postback system with multiple windows and coarse conversion values.
Fine-Grained Conversion Values (0-63)
These are only available in the first postback window (0-2 days post-install). They give you 64 possible states. Common encoding strategies include:
- Milestone-based: Each value represents a specific in-app event (value 1 = tutorial complete, value 5 = first purchase, etc.)
- Bitmask encoding: Use individual bits to represent multiple binary states (bit 0 = registration, bit 1 = first session, bit 2 = purchase, etc.)
- Revenue bucketing: Map revenue ranges to values (0 = no revenue, 1-10 = $0-$1, 11-20 = $1-$5, etc.)
The choice depends on which signals matter most for your business. For gaming apps, progression milestones are often most predictive. For commerce apps, revenue bucketing tends to be more actionable.
Coarse Conversion Values
SKAN 4.0 introduced coarse conversion values with only three states: low, medium, and high. These are used in the second and third postback windows (postback 2: 3-7 days, postback 3: 8-35 days after install).
Coarse values allow signal from later in the user journey but at much lower resolution. You can map them to behavioral tiers: low for users who opened the app but did not engage, medium for users who completed onboarding, high for users who converted or made a purchase.
The Conversion Value Timer
Conversion values work against a timer. When your app calls updatePostbackConversionValue(_:completionHandler:), it resets the timer. Once the timer expires without a new update, the device locks the conversion value and schedules the postback.
In SKAN 3 and earlier, the timer was 24 hours. Each call to update the conversion value restarted the 24-hour clock. You could theoretically update for days, but in practice you needed to stop updating to let the postback fire.
In SKAN 4.0+, Apple moved to defined windows:
- Window 1: 0-2 days (fine-grained + coarse)
- Window 2: 3-7 days (coarse only)
- Window 3: 8-35 days (coarse only)
Each window has its own postback. You do not need to "let the timer expire" in the same way. The windows are fixed.
Postback Delay and Crowd Anonymity
SKAdNetwork adds a random delay to postbacks before sending them. In SKAN 3, the delay was 24-48 hours after the timer expired. In SKAN 4.0+, delays are per window but still randomized.
More importantly, postbacks are subject to crowd anonymity thresholds. If a campaign does not generate enough installs to meet Apple's minimum threshold, Apple will not send a postback at all. The threshold is not publicly documented but is estimated to be in the range of tens to hundreds of installs per campaign-conversion value combination.
This creates a real problem for smaller campaigns. If you are running many granular campaigns with low install volumes per campaign, a significant portion of your postbacks will simply not arrive.
The practical implication: SKAN works best for high-volume campaigns. For lower-volume campaigns, you will have gaps in your attribution data. Plan for this when setting expectations with stakeholders.
What Changed in SKAN 5.0
Apple announced SKAN 5.0 improvements alongside iOS 18. The most significant changes:
Attributed app installs from web clicks: SKAN 5.0 extends the framework to support web-to-app attribution. Clicks on Safari-browsed pages can now trigger SKAN attribution, closing a gap that previously required fingerprinting or probabilistic matching.
Improved postback rates for small campaigns: Apple has indicated changes to how crowd anonymity thresholds work, with the goal of making postbacks available for more campaigns without compromising user privacy. For the Android equivalent of these privacy-preserving approaches, see Privacy Sandbox for Android attribution. The exact mechanics are not fully public, but this should reduce the "missing postback" problem for smaller volume campaigns.
SKAdNetwork 5.0 signing requirement: Ad networks need to update their impression signing to use the SKAN 5.0 signature format. Check with each ad network you work with about their SKAN 5.0 support timeline.
App install validation: SKAN 5.0 includes additional install validation signals that make it harder for ad networks to claim fraudulent installs. This is good for advertisers.
For the authoritative source on SKAN 5.0 specifics, see Apple's SKAdNetwork documentation and the WWDC sessions on privacy-preserving attribution.
Implementation Guide
App-Side Registration
Your app needs to call the registration API when the app is first opened after an ad-driven install:
// In your AppDelegate or scene lifecycle
import StoreKit
SKAdNetwork.updatePostbackConversionValue(
0, // Initial conversion value
coarseValue: .low,
lockWindow: false
) { error in
if let error = error {
print("SKAN registration error: \(error)")
}
}
If you are using Tolinku's iOS SDK, the SDK handles registration automatically when you initialize it. See the Tolinku attribution docs for SDK-specific instructions.
Updating Conversion Values
Conversion value updates should happen as users complete in-app actions:
// After a purchase, for example
SKAdNetwork.updatePostbackConversionValue(
revenueBucket(for: purchaseAmount), // Your encoding logic
coarseValue: .high,
lockWindow: false
) { error in
if let error = error {
print("SKAN update error: \(error)")
}
}
The key rule: only update in the upward direction within each window. Once a conversion value is set, you can set it to a higher value but Apple recommends not decreasing it, as this can confuse the attribution model.
Receiving Postbacks (for Ad Networks)
If you are building ad network functionality or want to receive SKAN postbacks directly, your endpoint needs to handle Apple's postback format:
{
"version": "4.0",
"ad-network-id": "your-network.skadnetwork",
"campaign-id": 42,
"transaction-id": "abc123",
"app-id": 1234567890,
"attribution-signature": "...",
"redownload": false,
"source-app-id": 9876543210,
"fidelity-type": 1,
"conversion-value": 20,
"coarse-conversion-value": "medium",
"did-win": true
}
Validate the signature using Apple's public key before trusting the postback content. The Apple CryptoKit documentation has implementation guidance.
Practical Conversion Value Strategy
The biggest mistake teams make with SKAN is trying to encode too much information into 6 bits. Here is a more pragmatic approach:
Step 1: Identify your most predictive early signals. Look at your existing attribution data. Which in-app events in the first 48 hours best predict long-term value? For most apps, this is a short list: session depth, completion of a key onboarding step, and first purchase or subscription trigger.
Step 2: Prioritize one primary dimension. You cannot reliably encode both revenue and engagement milestones into 64 states in a way that is actionable. Pick the dimension that matters most for your ad platform optimization.
Step 3: Use coarse values for later windows. Map your coarse values to your retention or monetization tiers. This gives you a directional signal about cohort quality at Day 7 and Day 30.
Step 4: Test and iterate. SKAN conversion value schemas are not permanent. You can update them as you learn more about which signals are most predictive.
Common Pitfalls
Not calling the registration API: If your app does not call registerAppForAdNetworkAttribution() or the equivalent update API on first open, no postback will fire regardless of which ad drove the install.
Updating conversion values from the wrong thread: The update API must be called from the main thread on iOS.
Expecting postbacks to arrive quickly: Plan for delays of several days before postback data appears in your reporting. Build your dashboards to account for this lag.
Ignoring the crowd anonymity threshold: If you are running many small campaigns, restructure them into fewer, larger campaigns to ensure postbacks fire.
Connecting SKAN Data to Your Attribution Workflow
SKAN data supplements rather than replaces your broader attribution data. For the users who opted into ATT, you have deterministic data. For users who did not, you have SKAN signal. Most MMPs and attribution platforms including Tolinku combine both signals to give you the most complete picture possible.
For a broader look at how SKAN fits into your overall mobile attribution setup, see the mobile attribution developer guide and the Tolinku analytics feature page. You may also find our attribution windows guide helpful for understanding how time-based matching affects your data.
Further Reading
Get deep linking tips in your inbox
One email per week. No spam.