App Tracking Transparency (iOS 14.5+)

Starting with iOS 14.5 (April 2021) and the App Tracking Transparency (ATT) framework, Apple requires that your app provides transparency on the data that it uses and on the third parties that will track the user in your app.

Tracking and the use of the IDFA are subject to permission being obtained from the user. "Tracking refers to the act of linking user or device data collected from your app with user or device data collected from other companies’ apps, websites, or offline properties for targeted advertising or advertising measurement purposes. Tracking also refers to sharing user or device data with data brokers." (from Apple's guidelines).

ATT tracking permission

At the moment, the Didomi SDK does not ask for the user permission for tracking in the ATT framework and it is the responsibility of the app to do so and to decide how the Didomi CMP and the ATT permission should coexist.

Your app must follow Apple's guidelines for disclosing the data collected by your app and asking for the user's permission for tracking. Permission for tracking on iOS can be asked by calling the ATTrackingManager.requestTrackingAuthorization function in your app.

When and how to ask for the ATT permission?

According to Apple's guidelines, you must display the ATT tracking permission alert before trying to use the IDFA from the iOS device. If permission is not asked or if the user denies permission, the IDFA will not be available to your app and embedded third-party SDKs. Third-party SDKs might not be able to function properly in that case.

To be fully compliant with both Apple and GDPR requirements, you must ask for the user permission through ATT AND ask for user consent through the CMP. Apple's ATT is not compliant with the IAB TCF or with GDPR requirements at the moment so that it cannot be used as the only consent-collection mechanism and must be used in conjunction with the Didomi CMP.

We recommend two options to combine the CMP and ATT:

ImplementationPros/Cons

Ask permission via ATT then collect consent from the CMP if and only if the user has given permission via ATT

This implementation allows the users to only be asked once if they do not give consent in ATT. It still requires users to be asked twice (ATT then CMP) for users who give consent but there is no way around this at the moment.

The main drawback of this solution is that a user who does not give consent to ATT is assumed to also not give consent to the CMP even though ATT and the CMP deal with different purposes and vendors. Your app would be extrapolating user choices from ATT (tracking via IDFA) to all other purposes. Whether that is acceptable or not is an app-specific choice.

In our experience, this implementation is the one that is the most accepted by Apple. This is our recommended implementation.

Collect consent from the CMP then ask permission via ATT

The main advantage of this implementation is that it allows the user to make different choices between the ATT tracking and other CMP purposes and vendors. It still requires users to be asked twice (CMP then ATT) but there is no way around this at the moment.

The ATT permission can also be collected at a later point in the user experience but your third-party vendors might not be able to operate if the IDFA is not available until the user has given permission.

Apple guidelines

Apple also provides some guidelines on how the ATT permission should be integrated. The public guidelines lack specificity and we have seen Apple reject apps for various reasons. We recommend being careful about the following points:

  • Do not show the CMP after a user denies an ATT permission request. Apple considers that the CMP is asking the user to reconsider their decision in the ATT permission request. Similarly, avoid showing any message asking the user to reconsider their decision even if it is not the Didomi CMP.

  • If you show the ATT permission request after the CMP, always show the ATT permission irrespective of the user choice in the CMP. Apple consider the CMP as "custom messaging before the ATT alert" in that case and ATT must always be displayed. (See "Displaying Custom Messaging Before the Alert" on https://developer.apple.com/design/human-interface-guidelines/ios/app-architecture/accessing-user-data/)

  • If you show the ATT permission request after the CMP, do not allow the CMP to be closed without the user agreeing or disagreeing. If the CMP is allowed to be closed, this would delay the permission request which Apple does not accept after showing a custom message before the alert.

Please read our section on integrating the CMP notice and ATT permission for code samples.

Can I use only ATT or only the Didomi CMP?

To the user, the CMP notice and the iOS ATT permissions alert might look like the app asking for the same permission twice with a slightly different UI. This is confusing and disappointing.

However, that is not true from a legal perspective:

  • ATT is Apple's specific solution to collecting the user permission for Apple's definition of tracking: "Tracking refers to the act of linking user or device data collected from your app with user or device data collected from other companies’ apps, websites, or offline properties for targeted advertising or advertising measurement purposes. Tracking also refers to sharing user or device data with data brokers." (from https://developer.apple.com/app-store/user-privacy-and-data-use/)

  • The Didomi CMP covers the legal definition of collecting consent and helps with IAB TCF compliance as well.

Unfortunately, at the moment, these two definitions are not aligned. ATT's permission is not detailed enough to be considered legal under GDPR or compliant with the IAB TCF. As a result, the ATT's permission cannot be used alone without a CMP. For apps to be compliant with GDPR and Apple's guidelines, the app developers are forced to use disappointing combinations of consent notices / ATT permission which leads to increased user confusion and poor user experience.

Didomi is in discussions with Apple, the IAB, and European DPAs to try to find common grounds in the long term.

Does the Didomi SDK use the IDFA and require ATT permission?

Since version 1.48.2 (https://developers.didomi.io/cmp/mobile-sdk/ios/versions#1-48-2-april-2021) of our SDK, the Didomi SDK does not use the IDFA in any way and does not require the ATT permission. We recommend updating to that SDK version as soon as possible.

Didomi uses its own random user ID that is specific to every app that the SDK is embedded in. This ID is not used for any user tracking and is only used for the purpose of consent management.

If an older version of the SDK is used on an iOS version that requires ATT then:

  • Consent will still be collected as usual and will be TCF compliant

  • Analytics in the Didomi Console will be correctly reported

  • Individual proof of consent will not be available as some users will not have an individual user ID

How does the ATT permission (or the lack thereof) impact third-party SDKs?

This depends on third-party SDKs. Third-party SDKs that rely on the IDFA (advertising or analytics SDKs, for instance), will require the IDFA and might stop working if the user denies consent in the ATT prompt.

Check with your third-party SDK providers how they behave in that case and what they expect from the app.

Is ATT permission compliant with GDPR/CCPA/IAB TCF/CNIL/AEPD/BfDI/...?

ATT is an Apple-specific solution to collecting user consent to "tracking" with its own definition of what constitutes tracking and, more importantly, how consent should be collected and what valid consent is.

On its own, ATT is not compliant with the IAB TCF specifications and is unlikely to be considered a compliant way of collecting consent for data processing under GDPR or CCPA. It cannot be used as a replacement to a CMP for GDPR, CCPA, or IAB TCF compliance at the moment.

The two are independent.

If the user rejects ATT, the behavior of apps and third-party SDKs that rely on IDFA will be impacted. The impact depends on what those apps and third-party SDKs are doing and needs to be assessed directly by the app developer with the SDK providers.

Why did Apple reject my app because of how I am asking for ATT permission?

We have seen Apple accept and reject apps for all combinations of ATT and CMP. We have also seen Apple accept and reject two apps with the same ATT/CMP configuration, or reject then accept a given app without any modifications.

It is hard to give definitive answers and guidelines at the moment as there is some unpredictability in Apple's validation process. It is likely that Apple is still fine-tuning its guidelines and acceptance criteria as ATT is a recent feature.

We have listed recommendations and guidelines from the Apple validation processes that our clients have been through in When and how to ask for the ATT permission?. Following the guidelines will strongly avoiding rejection.

We will keep updating this page with more recommendations on how to integrate ATT and CMP consent notices.

Feel free to reach out to our Support team at support@didomi.io to discuss your specific app if needed.

Integrate the CMP notice and ATT permission

This sample shows how to:

The CMP consent notice will always be displayed and the ATT permission will not show if the user denies consent to all purposes in the Didomi consent notice. The ATT status will remain notDetermined.

import UIKit
import AdSupport
import AppTrackingTransparency

class ViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        let didomiEventListener = EventListener()
        didomiEventListener.onConsentChanged = { event in
            // The consent status of the user has changed
            if #available(iOS 14, *) {
                if ATTrackingManager.trackingAuthorizationStatus == .notDetermined && !Didomi.shared.getEnabledPurposes().isEmpty {
                    // Show the ATT permission request if the user has not made an ATT choice before AND the user gave consent to at least one purpose in the Didomi CMP
                    ATTrackingManager.requestTrackingAuthorization { status in }
                }
            }
        }
        Didomi.shared.addEventListener(listener: didomiEventListener)
        
        // Show the Didomi notice
        Didomi.shared.setupUI(containerController: self)
    }
}

Show the ATT permission then the CMP notice if the user accepts the ATT permission

This sample shows how to:

The ATT permission request will always be displayed if it is not restricted. The Didomi consent notice will only be displayed if the user accepts the ATT permission OR the ATT permission cannot be displayed for any reason (restricted or iOS < 14).

import UIKit
import AdSupport
import AppTrackingTransparency

class ViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        if #available(iOS 14, *) {
            ATTrackingManager.requestTrackingAuthorization { status in
                switch status {
                    case .authorized:
                        // Show the Didomi CMP notice to collect consent from the user
                        Didomi.shared.setupUI(containerController: self)
                    case .denied:
                        // The user denied ATT permission, deny user consent for all purposes/vendors in the Didomi CMP as well
                        Didomi.shared.setUserDisagreeToAll()
                    case .restricted:
                        // ATT is restricted on the device so the user was not asked for a choice (https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/restricted)
                        // Show the Didomi CMP notice to collect consent from the user
                        Didomi.shared.setupUI(containerController: self)
                    case .notDetermined:
                        // This is not supposed to happen
                        // Show the Didomi CMP notice to collect consent from the user
                        Didomi.shared.setupUI(containerController: self)
                }
            }
        } else {
            // Show the Didomi CMP notice to collect consent from the user as iOS < 14 (no ATT available)
            Didomi.shared.setupUI(containerController: self)
        }
    }
}

Last updated