Implement GDPR and ATT for iOS/Swift apps
Asked Answered
T

2

6

My app was rejected by Apple for showing GDPR (Google's UMP) and ATT confusing users. Specifically, if the user is in the EEA, GDPR will show up first. Only then did ATT start showing up. As per Apple's request: "If the user denies permission to track once, do not ask them to allow tracking again within the same permission request flow. There should be no tracking activity until the user grants permission to track". So I need to know the result of the user filling out the GDPR form so that I can decide whether to show ATT or not.

And I still don't have a solution.

This is my Code

func setupAdvertisement() {
    fatalError("This method must be overridden in the subclass")
}

func requestATTAuthorization() {
    if #available(iOS 14.5, *) {
        let trackingAuthorizationStatus = ATTrackingManager.trackingAuthorizationStatus
        if trackingAuthorizationStatus == .notDetermined {
            ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in

            })
        }
    }
}

func showAdvertisement() {
    if #available(iOS 14.5, *) {
        let trackingAuthorizationStatus = ATTrackingManager.trackingAuthorizationStatus
        if trackingAuthorizationStatus == .notDetermined {
            ATTrackingManager.requestTrackingAuthorization(completionHandler: { [weak self] status in
                DispatchQueue.main.async {
                    self?.setupAdvertisement()
                }
            })
        } else {
            DispatchQueue.main.async {
                self.setupAdvertisement()
            }
        }
    } else {
        DispatchQueue.main.async {
            self.setupAdvertisement()
        }
    }
}

@objc func showAdBasedOnConsentStatus() {
    let consentStatus = UMPConsentInformation.sharedInstance.consentStatus

    switch consentStatus {
    case UMPConsentStatus.required:
        loadForm()
    case UMPConsentStatus.obtained:
        showAdvertisement()
    case UMPConsentStatus.notRequired:
        showAdvertisement()
    case UMPConsentStatus.unknown:
        print("Error showAdBasedOnConsentStatus()")
    @unknown default:
        print("Error showAdBasedOnConsentStatus()")
    }
}

func UMPSetup() {
    let parameters = UMPRequestParameters()
    parameters.tagForUnderAgeOfConsent = false


    UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(
        with: parameters,
        completionHandler: { [weak self] error in
            if let error = error {

                print(error)
            } else {
                let formStatus = UMPConsentInformation.sharedInstance.formStatus
                if formStatus == UMPFormStatus.available {
                    self?.loadForm()
                } else {
                    self?.requestATTAuthorization()
                }
            }
        })
}

func loadForm() {
    UMPConsentForm.load(completionHandler: { form, loadError in
        if loadError != nil {

        } else {
            if UMPConsentInformation.sharedInstance.consentStatus == UMPConsentStatus.required {
                form?.present(from: self, completionHandler: { dismissError in
                    if UMPConsentInformation.sharedInstance.consentStatus == UMPConsentStatus.obtained {
                        self.showAdBasedOnConsentStatus()
                    }
                    self.loadForm()
                })
            } else {

            }
        }
    })
}

Typhoon answered 7/7, 2023 at 2:15 Comment(6)
Are you presenting ATT using your own implementation?Mongoose
Hi, I use Apple's built-in ATT.Georganngeorge
My question wasn't clear I'm sorry, I meant: are you showing the IDFA message using the ATT framework in your code, or are you letting UMP deal with the IDFA also in addition to GDPR?Mongoose
Yes, your code uses both the ATT framework and UMP to handle IDFA while also complying with GDPR.Georganngeorge
If you're letting UMP deal with IDFA, you don't need to present it in your code also.Mongoose
The problem is user's almost always deny ATT and almost always approve GDPR...so you're basically screwed with Apple's guidelines.Remuneration
M
2

First of all, you should let UMP deal with the IDFA message, in addition to the GDPR consent form. So that you don't need to present the IDFA message in your code also. Here is explained how to implement it, it's very simple and do not require code, you just need to edit your plist file, link the ATT framework and create the IDFA message on your AdMob profile. I can't really test it to check right now, but I'd assume Google is smart enough to have figured your issue out for you since it's an Apple requirement.

If this is not the case however, there is a great solution by another user that lets you know the user GDPR preferences once set. I tested this recently and it still works. Since it is about the IDFA, I guess you should look at the canShowPersonalizedAds() method.

Mongoose answered 7/7, 2023 at 4:21 Comment(4)
Thanks for your guide. I was able to follow the instructions. But I have 1 question. When GDPR pops up and I refuse to collect the data. ATT no longer shows up. But when I close the app and open it again. The ATT form reappears. Is that unusual? Is it possible that when I close the App and reopen it, the device will recognize that I am not in the EEA region according to the device's factory settings?Georganngeorge
If it solved your issue, feel free to mark my answer as accepted, so it might help others as well. I don’t know about your other question, are you testing it by changing location settings? Anyway, since UMP is built to pass Apple requirements as long as everything is implemented correctly it should be enough to make your app accepted on the App Store.Mongoose
Thank you very much. I solved my problem and got Apple accepted the solution. AppreciateGeorganngeorge
Can you please explain a bit how did you solve your problem?Anemograph
M
1

Our company had similar reason of rejection.

We do not use UMP for IDFA, just for GDPR.

But I think the general idea about the implementation, if you do not use Google's UMP:

  1. Show IDFA prompt manually from code (that Apple's native UIAlert with Allow tracking or Ask App Not to Track)
  2. Upon dismissal of IDFA prompt, present GDPR consent. But only for EU/EEU/UK users, if not EU/EEU/UK user, proceed to next step.
  3. Initialise AdMob SDK.

The targeted ads and privacy madness is somehow solved by the magic in the AdMob SDK.

Since we are on Apple platform, I would go for IDFA first and then GDPR.

⬇️ Here is also proposed "next step" from Apple's rejection email/message: ⬇️

If the user denies permission to track once, do not ask them to allow tracking again within the same permission request flow. There should be no tracking activity until the user grants permission to track.

If you collect data after the user selects "Ask App Not to Track" on the App Tracking Transparency permission request, please revise the GDPR prompt and clarify that you collect data but do not track.

If your app shows the GDPR prompt before showing the App Tracking Transparency permission request, there is no need to modify the wording of the GDPR prompt.

Mcginley answered 15/1, 2024 at 12:56 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.