Designing iOS Measurement Around App Tracking Transparency
How to handle Apple's App Tracking Transparency when users deny IDFA access, with a Swift example and SKAdNetwork fallback guidance.
08 Sept 2026, 02:22 UTC

The problem: your IDFA just became optional
If your iOS app relies on the Identifier for Advertisers (IDFA) for attribution or audience segmentation, Apple's App Tracking Transparency (ATT) framework changes the default from "track unless opted out" to "do not track unless explicitly permitted." On iOS 14.5 and later, the system shows a dialog asking the user whether your app may track them across apps and websites. If they tap Don't Allow, or if they never respond, ASIdentifierManager.shared().advertisingIdentifier returns a string of zeros. Your ad network SDKs and attribution pipelines can no longer tie installs or events to a specific device.
The useful takeaway is not to find a way around the dialog. It is to design your measurement stack so that a denied or undetermined authorization status does not break reporting.
When and how to request tracking permission
ATT is provided by the AppTrackingTransparency framework. The entry point is ATTrackingManager.requestTrackingAuthorization(completionHandler:). It presents the system alert once per app install and returns one of four statuses: authorized, denied, restricted, or notDetermined.
You must add a purpose string to your app's Info.plist under the key NSUserTrackingUsageDescription. Without it, the system may reject the build or fail to show the alert.
Worked example: request permission and read the result
Add this to your Xcode project target. The code below runs on a physical device with iOS 14.5 or later; the simulator does not display the real system alert and usually returns notDetermined.
import AppTrackingTransparency
import AdSupport
func requestTrackingPermission() {
ATTrackingManager.requestTrackingAuthorization { status in
switch status {
case .authorized:
let idfa = ASIdentifierManager.shared().advertisingIdentifier
print("IDFA available: \(idfa.uuidString)")
case .denied, .restricted, .notDetermined:
print("Tracking not authorized. IDFA will be all zeros.")
@unknown default:
print("Unknown authorization status")
}
}
}
Call this from a clear UI moment—such as an onboarding screen—rather than immediately in application(_:didFinishLaunchingWithOptions:), so users understand why you are asking. Required permissions: none beyond linking the framework and adding the usage description. Risk: the dialog can only appear once per install. If the user dismisses it without choosing, or denies it, you cannot prompt again without a reinstall.
Measurement when IDFA is unavailable
When the status is anything other than authorized, plan for these alternatives:
- First-party data: Log in or account-based identifiers you control, with user consent under your own privacy policy.
- Contextual signals: Use app content, device type, and locale rather than cross-app behavior.
- SKAdNetwork: Apple's privacy-preserving attribution framework. It reports campaign conversions as aggregated, delayed, and anonymized postbacks rather than device-level events.
You can verify behavior on a physical device by logging ATTrackingManager.trackingAuthorizationStatus at launch and comparing it to the value of advertisingIdentifier. If the string is 00000000-0000-0000-0000-000000000000, tracking is limited.
Trade-offs and limitations
- One-shot dialog: You cannot re-prompt after denial. Poor copy or bad timing permanently lowers opt-in rates for that install.
- Simulator gaps: Automated UI tests and CI cannot reliably reproduce the real alert. Validate on hardware.
- No fingerprinting workaround: Attempting to fingerprint devices to replace IDFA violates Apple's App Store Review guidelines and does not provide reliable cross-app measurement.
What to check before your next release
- Add
NSUserTrackingUsageDescriptiontoInfo.plistwith a specific, user-facing reason. - Call
requestTrackingAuthorizationat a deliberate UI point, not blindly at launch. - Log authorization status and IDFA on a physical iOS 14.5+ device for both Allow and Don't Allow.
- Confirm your attribution provider has a SKAdNetwork or aggregated fallback for denied users.
ATT forces a privacy-first measurement model. Treat the permission dialog as a product decision, not just an API call, and build your analytics so that zeroed-out IDFA is an expected state, not an error.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.