BlogTutorial

SKAN 4.0 Implementation: A Step-by-Step Developer Guide

SKAdNetwork 4.0 introduces significant improvements over previous versions, including multiple conversion windows, hierarchical conversion values, and source app identification. This guide walks you through implementing SKAN 4.0 in your iOS app.

📋 Prerequisites

  • Xcode 14.1 or later
  • iOS 16.1+ deployment target
  • Apple Developer account
  • Understanding of basic iOS development

What's New in SKAN 4.0

Multiple Conversion Windows

SKAN 4.0 introduces three conversion windows instead of one:

Hierarchical Conversion Values

The new hierarchical system provides different levels of data granularity based on crowd anonymity thresholds:

Source App ID

When privacy thresholds are met, you can now receive the source app that displayed the ad, enabling better publisher-level optimization.

Step 1: Update Your Info.plist

Add the SKAdNetwork identifiers for your ad networks:

<key>SKAdNetworkItems</key> <array> <dict> <key>SKAdNetworkIdentifier</key> <string>cstr6suwn9.skadnetwork</string> </dict> <!-- Add more network identifiers --> </array>

Step 2: Register for Attribution

Call the registration method when your app launches:

import StoreKit func registerForAttribution() { if #available(iOS 16.1, *) { SKAdNetwork.updatePostbackConversionValue(0) } else if #available(iOS 15.4, *) { SKAdNetwork.updatePostbackConversionValue(0) { error in if let error = error { print("Error: \(error)") } } } }

Step 3: Update Conversion Values

For SKAN 4.0, use the new method with coarse value support:

import StoreKit @available(iOS 16.1, *) func updateConversionValue( fineValue: Int, coarseValue: SKAdNetwork.CoarseConversionValue, lockWindow: Bool ) { SKAdNetwork.updatePostbackConversionValue( fineValue, coarseValue: coarseValue, lockWindow: lockWindow ) { error in if let error = error { print("SKAN update error: \(error)") } } }

Step 4: Design Your Conversion Value Schema

With 64 possible fine-grained values (0-63), you need a strategic approach to value assignment. Common patterns include:

Revenue-Based Schema

Event-Based Schema

💡 Pro Tip

Always design your schema to be backward-compatible. Start with your most important metrics and add complexity as you gain confidence in the system.

Step 5: Handle Coarse Values

When privacy thresholds aren't met, you'll receive coarse values instead of fine values. Plan your schema accordingly:

enum ConversionTier { case low // Non-monetizing user case medium // Small purchaser case high // Whale user } func getCoarseValue(revenue: Double) -> SKAdNetwork.CoarseConversionValue { if #available(iOS 16.1, *) { switch revenue { case 0: return .low case 0.01...9.99: return .medium default: return .high } } return .low }

Step 6: Lock Conversion Windows

You can lock a conversion window early if the user has completed all relevant events:

// Lock window when user makes significant purchase func onSignificantPurchase() { if #available(iOS 16.1, *) { updateConversionValue( fineValue: 63, // Max value coarseValue: .high, lockWindow: true // Lock this window ) } }

Step 7: Server-Side Postback Handling

Configure your server to receive and process SKAN postbacks. The new postback format includes:

Testing Your Implementation

Using Xcode

  1. Enable StoreKit Testing in your scheme
  2. Use the SKAdNetwork testing profile
  3. Monitor console for SKAN-related logs

Using TestFlight

Deploy to TestFlight and use real ad networks' test modes to validate end-to-end attribution.

"SKAN 4.0 testing requires patience. The conversion windows and postback delays mean you'll need several days to fully validate your implementation."

Common Pitfalls

SKAN 4.0 represents a significant improvement in privacy-preserving attribution. While it requires upfront investment in implementation, the enhanced measurement capabilities make it worthwhile for serious iOS marketers.

SKAdNetwork iOS Tutorial Development Attribution