Implementing iOS privacy prompts correctly in React Native apps
Since iOS 14.5, every app that wants to track a user across devices for advertising purposes must first explicitly ask for consent. Getting the prompt wrong, or showing it at the wrong time, costs analytics and advertising SDKs valuable signal. This article covers how it technically works, practical integration, and the concrete consequences of a denial.
Table of Contents
- 1. What App Tracking Transparency technically is
- 2. The difference between cross-app tracking and on-device tracking
- 3. Practical integration with react-native-tracking-transparency
- 4. Choosing the right moment for the prompt
- 5. A custom pre-prompt screen before the native system dialog
- 6. Consequences of a denial for analytics and advertising SDKs
- 7. Handling all four status values correctly
- 8. App review and the declared app privacy details
- 9. Testing the ATT flow before release
- 10. Summary
- 11. FAQ
1. What App Tracking Transparency technically is
App Tracking Transparency is a framework Apple has mandated since iOS 14.5 that forces every app to show an explicit system prompt before accessing the Identifier for Advertisers, or IDFA. Without that consent, the system returns nothing but a zeroed-out string for IDFA requests, making cross-device tracking for advertising purposes technically impossible.
The prompt itself is rendered exclusively by the operating system, not by the app, so developers cannot change either the text or the layout of the actual system dialog. This lets Apple ensure the wording stays consistent across apps and clearly understandable to users, regardless of which app triggers it.
2. The difference between cross-app tracking and on-device tracking
The ATT prompt explicitly applies only to tracking that links data with other apps or third-party websites, or shares it with data brokers, to build a cross-device user profile. Classic first-party analytics that stays entirely within the app itself and doesn't share data with third parties for advertising purposes does not fall under this consent requirement.
That distinction matters for the implementation, because it determines which SDKs actually need to trigger the prompt. A plain crash-reporting tool without cross-device profiling generally doesn't need ATT consent, while an ad network SDK attributing conversions across app boundaries clearly falls within scope.
3. Practical integration with react-native-tracking-transparency
In React Native, the prompt can be wired up through the react-native-tracking-transparency library, which translates Apple's native ATTrackingManager API into a JavaScript interface. The central requestTrackingPermission call shows the system dialog and returns the chosen status as a promise once the user has made a decision.
The Info.plist entry NSUserTrackingUsageDescription also has to be set, providing the explanatory text shown below the system title in the prompt. Without that entry, the app crashes when the tracking API is called, instead of simply showing the prompt without a description.
import { requestTrackingPermission } from 'react-native-tracking-transparency';
async function requestAttIfNeeded() {
const status = await requestTrackingPermission();
// status: 'authorized' | 'denied' | 'restricted' | 'unavailable'
if (status === 'authorized') {
initializeAdvertisingSdk();
} else {
initializeContextualAdsOnly();
}
return status;
}
4. Choosing the right moment for the prompt
The prompt can only be shown once per app installation; a repeated programmatic call after a decision has already been made does not reopen the system dialog, it simply returns the previously stored status. The timing of the first call therefore has a significant impact on the consent rate and deserves deliberate planning.
A prompt shown immediately on first app launch, before the user has experienced any value from the app, tends to produce noticeably lower consent rates in practice than a prompt shown only after a short explanation screen or the first successful usage experience. Many apps therefore first show their own designed pre-prompt screen explaining the value of tracking before triggering the native system dialog.
5. A custom pre-prompt screen before the native system dialog
A custom pre-prompt screen must not be worded misleadingly and must never suggest that declining in the following system dialog would restrict app functionality, unless that's genuinely the case. Apple checks such wording during app review and consistently rejects manipulative pre-prompt screens.
A more sensible approach is a factual explanation of why personalized content or advertising could offer value to the user, paired with a clear button that only triggers the native prompt after a deliberate user interaction. This approach respects both Apple's guidelines and the user's actual freedom to decide.
6. Consequences of a denial for analytics and advertising SDKs
If the user denies tracking, or the system assigns the restricted status, for example because of enabled screen time restrictions, the IDFA query returns nothing but zeros. Ad networks that rely on the IDFA for retargeting or cross-device attribution can no longer uniquely identify affected users and fall back to aggregated, less precise signals.
Apple's SKAdNetwork framework offers a privacy-preserving alternative for ad attribution that works even without ATT consent, though with significantly delayed, aggregated reports instead of real-time individual data. Analytics SDKs unrelated to advertising, such as pure crash and usage statistics within the app itself, generally remain entirely unaffected by an ATT denial.
7. Handling all four status values correctly
The prompt's return value has four possible states: authorized, denied, restricted, and notDetermined, where notDetermined only occurs before the prompt has been shown for the first time. Apps should handle all four states explicitly in code, rather than mistakenly distinguishing only between a binary yes or no.
The restricted state in particular deserves separate attention, since it gets enforced independently of the user's wishes by device settings such as enabled screen time restrictions for minors. In that case the app must not even attempt to show the prompt, since the system suppresses it automatically and immediately returns the restricted status.
8. App review and the declared app privacy details
Apple explicitly checks during app review whether an app that actually tracks integrates the ATT prompt correctly, and rejects submissions where tracking SDKs are active without prior consent having been obtained. The App Privacy details in App Store Connect must also correctly reflect which data types are actually collected for tracking purposes.
A mismatch between the declared privacy details and the actual SDK behavior in the app, for example an ad SDK collecting tracking data despite missing declaration, regularly leads to review rejections or later complaints, even if the ATT implementation itself is technically correct.
9. Testing the ATT flow before release
Since the prompt only appears once per installation, testing requires either fully uninstalling and reinstalling the app, or resetting tracking permission through the Settings app under Privacy and Security. Simply restarting the app is not enough to trigger the prompt again for another test run.
Before release, it's worth explicitly testing how the app behaves for each of the four possible status values, in particular whether advertising and analytics SDKs actually switch to privacy-preserving alternatives on a denial, instead of continuing to silently make IDFA requests that only return zeros anyway. It's also worth adding an automated UI test that confirms the custom pre-prompt screen reacts correctly for every one of the four states and never attempts to programmatically force the native prompt a second time, which would be technically ineffective anyway.
| Status value | Meaning | IDFA behavior | Practical consequence |
|---|---|---|---|
| notDetermined | User has not yet made a decision | Not available | Prompt can still be shown |
| authorized | User explicitly consented to tracking | Real IDFA available | Advertising and analytics SDKs can operate fully |
| denied | User explicitly denied tracking | Zeroed-out string | Fallback to SKAdNetwork or aggregated signals needed |
| restricted | Enforced by device settings, e.g. screen time | Zeroed-out string, prompt suppressed | App must not attempt to show the prompt |
| unavailable | Device or OS version doesn't support ATT | Not available | App should defensively fall back to a privacy-preserving mode |
Mironsoft
React Native app development and Magento integration
A mobile app for the Magento shop that actually runs smoothly?
We build React Native apps cleanly connected to the Magento REST or GraphQL API, from the first line of code to publishing on the App Store and Google Play.
App Concept
Plan the architecture and feature scope of a Magento-connected app together.
Magento API Integration
Cleanly connect product catalog, cart, and checkout to the shop API.
Store Publishing
Guide the App Store and Google Play release process without pitfalls.
10. Summary
App Tracking Transparency: Key Takeaways
System dialog, not customizable
The ATT prompt is rendered exclusively by the operating system, custom app text and layout are not possible.
Only cross-device tracking is in scope
Pure first-party analytics without sharing data with third parties doesn't need ATT consent.
Timing affects the consent rate
An explanatory pre-prompt screen before the system dialog measurably raises the consent rate compared to an immediate prompt.
Handle four status values explicitly
Besides authorized and denied, restricted and notDetermined must also be correctly handled in code.