Back in June 2020, during WWDC20, Apple announced that starting from iOS 14, developers will have to get permission from users before tracking them. In other words, apps won’t be able to access the device’s IDFA (Identifier for Advertisers) unless it is authorized.
In September 2020, Apple delayed this change so that developers and publishers have more time to adapt to this new privacy change.
Earlier this month (April 2021), Apple made a public announcement, asking all developers to get ready for AppTrackingTransparency, indicating that Apple will fully enforce the tracking authorization in their upcoming iOS public release (iOS 14.5).
As a developer, our job is to ensure that our apps can run without any problem when the public release hits. If your app is using IDFA and would like to learn how to make your apps AppTrackingTransparency compliant, read on.
Understanding IDFA
Before we dive into the code, let’s have a quick look at what IDFA is all about.
First of all, make sure you don’t mix up IDFA and IDFV(Identifier for Vendor), Apple is only enforcing authorization on IDFA. In other words, If your app only uses IDFV, no changes are required.
IDFA is an alphanumeric string that is unique to each device, it is mainly used for ads targeting, frequency capping, advertising fraud detection, campaign measurement, etc. Here’s an example of what an IDFA can look like:
CE3BB49C-0F44-4DB9-9F6D-B2025A8A4FF7
An IDFA has the following behaviors:
- Each device will have its own unique IDFA.
- It is a device-level identifier, meaning apps by different vendors installed in the same device will have the same IDFA.
- Deleting an app will not reset/change the IDFA (because it is a device-level identifier).
- Disabling and re-enabling app tracking of a device will reset its IDFA.
Pro tip:
In iOS 14, you can disable app tracking by going to Settings > Privacy > Tracking > Turn off “Allow Apps to Request to Track” > Ask Apps to Stop Tracking.
Asking Permission to Track
Prior to iOS 14.5, you can easily obtain the IDFA without restriction using the following code:
let idfa = ASIdentifierManager.shared().advertisingIdentifier
Meanwhile in iOS 14.5, the IDFA will be zeroed out if you try to access it without the user’s permission.
Zeroed out IDFA:
00000000-0000-0000-0000-000000000000
In order to get the user permission, you must first add the NSUserTrackingUsageDescription
key to info.plist
. The value of the key is a usage-description string that tells the user why the app is requesting permission to track the user or the device.
With that in place, you can now use the AppTrackingTransparency
framework to display a system-permission alert request:
import AdSupport
import AppTrackingTransparency
ATTrackingManager.requestTrackingAuthorization { status in
DispatchQueue.main.async {
switch status {
case .authorized:
// Authorized
let idfa = ASIdentifierManager.shared().advertisingIdentifier
self.label.text = idfa.uuidString
case .denied,
.notDetermined,
.restricted:
break
@unknown default:
break
}
}
}
In the code above, there are 3 things that you need to be aware of:
- The
requestTrackingAuthorization(completionHandler:)
function will display the system-permission alert only when the app’s tracking authorization status is.notDetermined
. Once the authorization status is set, calling the function will just trigger the completion handler without showing the alert. - The system-permission alert will not be displayed if “Allow Apps to Request to Track” is turned off in the system privacy settings.
- The completion handler is not being triggered on the main thread. Thus dispatch to the main thread is required if you are updating UI in the completion handler.
Note:
At the time of writing, there is a bug in the iOS simulator where the IDFA is always zeroed out. Therefore make sure to test your code on a real device to avoid any unexpected behavior.
Lastly, you can also use the code below to determine the app’s current tracking authorization status:
let status = ATTrackingManager.trackingAuthorizationStatus
Handling Access Denied
Now that you know how to request for app tracking permission, what if the user denied your access to the IDFA?
One way of handling this is to provide a shortcut to Settings so that the user can easily change the tracking permission. Here’s how:
func gotoAppPrivacySettings() {
guard let url = URL(string: UIApplication.openSettingsURLString),
UIApplication.shared.canOpenURL(url) else {
assertionFailure("Not able to open App privacy settings")
return
}
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
Another way of handling is to not use IDFA at all. But this method is only applicable when you are using IDFA purely for campaign measurement. What do I mean by that?
Apple has a class that validates advertisement-driven app installations — SKAdNetwork. It is an ad network API that helps advertisers measure the success of ad campaigns while maintaining user privacy. You can find out more in this article.
Wrapping Up
Once again, Apple has tightened up the privacy control in their product ecosystem. I really like this change and it once again shows that Apple really cares about their user’s privacy.
As a developer, it is our duty to ensure that our apps always comply with the Apple privacy policy, so that our users can feel safe and secure when using our apps.
If you enjoy reading this article, feel free to check out my other iOS development related articles. You can also follow me on Twitter, and subscribe to my monthly newsletter.
Thanks for reading. 👨🏻💻
👋🏻 Hey!
While you’re still here, why not check out some of my favorite Mac tools on Setapp? They will definitely help improve your day-to-day productivity. Additionally, doing so will also help support my work.
- ✨ Bartender: Superpower your menu bar and take full control over your menu bar items.
- ✨ CleanShot X: The best screen capture app I’ve ever used.
- ✨ PixelSnap: Measure on-screen elements with ease and precision.
- ✨ iStat Menus: Track CPU, GPU, sensors, and more, all in one convenient tool.