← Back to Field Notes & Guides
June 22, 2026 • 9 min read

Configuring SKAdNetwork & AdAttributionKit Without Fingerprinting Fallbacks

How to structure privacy-preserving conversion value schemas under Apple's SKAdNetwork 4.0 and AdAttributionKit frameworks.

By Chalit Kittisuk, Senior Mobile Telemetry Practice
Configuring SKAdNetwork & AdAttributionKit Without Fingerprinting Fallbacks

When Apple introduced App Tracking Transparency (ATT), many ad networks attempted to circumvent user opt-outs by employing probabilistic fingerprinting (such as IP addresses combined with User-Agent and locale headers). However, App Store review guidelines strictly prohibit probabilistic device matching regardless of user consent.

The official, privacy-preserving attribution standard on iOS is Apple’s SKAdNetwork (and the expanded AdAttributionKit framework in iOS 17.4+).


Designing a Coarse Conversion Value Matrix

SKAdNetwork 4.0 provides three distinct conversion windows, returning both fine-grained (6-bit values from 0 to 63) and coarse-grained values (low, medium, high) depending on the crowd anonymity tier achieved by the campaign.

To maximize measurement fidelity without transmitting personal data:

Conversion Window 1 (0–2 Days post-install):

  • Coarse Value ‘Low’: Completed tutorial or initial onboarding screen.
  • Coarse Value ‘Medium’: Completed profile setup and engaged with primary feature.
  • Coarse Value ‘High’: Completed in-app purchase or account verification.

Conversion Window 2 (3–7 Days post-install):

  • Uses exclusively coarse values (low for dormant sessions, high for repeat daily engagement) to prevent campaign operators from isolating individual user session histories.

Code-Level Implementation in Swift

To update the conversion value securely without logging extraneous metadata:

import StoreKit

final class TelemetryAttributionService {
    static let shared = TelemetryAttributionService()
    
    func recordMilestone(tier: AppMilestone) {
        Task {
            do {
                if #available(iOS 16.1, *) {
                    try await SKAdNetwork.updatePostbackConversionValue(
                        tier.fineValue,
                        coarseValue: tier.coarseValue,
                        lockPostback: false
                    )
                }
            } catch {
                // Handle attribution failure gracefully without unconsented telemetry fallback
                print("SKAdNetwork postback update failed: \(error.localizedDescription)")
            }
        }
    }
}

By relying strictly on on-device StoreKit postbacks, your application maintains complete visibility into acquisition channel performance while eliminating all server-side tracking infrastructure.

Have questions regarding this telemetry pattern?

We assist mobile development teams in conducting code reviews and restructuring live event pipelines.

Consult with an Auditor