Makuhari Development Corporation
6 min read, 1079 words, last updated: 2025/3/4
TwitterLinkedInFacebookEmail

Complete Guide to Implementing App Tracking Transparency (ATT) in iOS Apps

Apple's App Tracking Transparency (ATT) framework has fundamentally changed how iOS apps handle user tracking and advertising identifiers. Since iOS 14.5, apps must explicitly request user permission before accessing the Identifier for Advertisers (IDFA) or tracking users across apps and websites.

In this comprehensive tutorial, you'll learn how to properly implement ATT in your iOS app, handle different iOS versions, and navigate App Store submission requirements.

Prerequisites

Before implementing ATT in your app, ensure you have:

  • Xcode 12 or later
  • An iOS project targeting iOS 14.0 or later
  • Basic understanding of Swift and iOS development
  • Understanding of your app's tracking and advertising requirements

Understanding App Tracking Transparency

ATT requires apps to request explicit user consent before:

  • Accessing the device's advertising identifier (IDFA)
  • Tracking users across apps or websites owned by other companies
  • Sharing user data with data brokers

Step 1: Configure Info.plist

First, add the tracking usage description to your Info.plist file. This message explains to users why your app needs tracking permission.

<key>NSUserTrackingUsageDescription</key>
<string>This app uses your advertising ID to provide personalized ads and improve your experience.</string>

Important: Without this key, your app will likely be rejected during App Store review if it accesses IDFA.

Step 2: Import Required Frameworks

Import the necessary frameworks in your Swift files:

import AppTrackingTransparency
import AdSupport

Step 3: Request Tracking Authorization

Here's the core implementation for requesting ATT permission:

func requestTrackingPermission() {
    if #available(iOS 14, *) {
        ATTrackingManager.requestTrackingAuthorization { status in
            DispatchQueue.main.async {
                switch status {
                case .authorized:
                    // User granted permission
                    let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString
                    print("Tracking authorized. IDFA: \(idfa)")
                    // Initialize ad SDKs or analytics here
                    self.initializeAdServices()
                    
                case .denied:
                    print("User denied tracking permission")
                    // Handle denied state - use alternative attribution methods
                    self.handleTrackingDenied()
                    
                case .restricted:
                    print("Tracking permission restricted")
                    // Device or parental controls prevent tracking
                    self.handleTrackingRestricted()
                    
                case .notDetermined:
                    print("Tracking permission not determined")
                    // User dismissed the prompt without making a choice
                    
                @unknown default:
                    print("Unknown tracking authorization status")
                }
            }
        }
    } else {
        // iOS 13 and below - ATT not required
        handleLegacyIOSTracking()
    }
}

Step 4: Handle iOS 13 and Below

For devices running iOS versions prior to 14, ATT is not available, but you can still access IDFA directly:

func handleLegacyIOSTracking() {
    if ASIdentifierManager.shared().isAdvertisingTrackingEnabled {
        let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString
        print("Legacy iOS IDFA: \(idfa)")
        initializeAdServices()
    } else {
        print("User disabled ad tracking in settings")
        handleTrackingDenied()
    }
}

Step 5: Check Authorization Status

You can check the current tracking authorization status at any time:

func checkTrackingStatus() {
    if #available(iOS 14, *) {
        let status = ATTrackingManager.trackingAuthorizationStatus
        switch status {
        case .authorized:
            print("Tracking is authorized")
            return true
        case .denied, .restricted, .notDetermined:
            print("Tracking is not authorized")
            return false
        @unknown default:
            return false
        }
    } else {
        // For iOS 13 and below
        return ASIdentifierManager.shared().isAdvertisingTrackingEnabled
    }
}

Step 6: Handle Different Scenarios

When Permission is Granted

func initializeAdServices() {
    // Initialize your ad SDKs here
    // Example for Google AdMob:
    // GADMobileAds.sharedInstance().start(completionHandler: nil)
    
    // Example for Facebook SDK:
    // Settings.shared.isAdvertiserTrackingEnabled = true
}

When Permission is Denied

func handleTrackingDenied() {
    // Use alternative attribution methods
    // 1. SKAdNetwork for Apple's attribution framework
    // 2. First-party data (user accounts, in-app behavior)
    // 3. Device fingerprinting (where legally permitted)
    // 4. Identifier for Vendor (IDFV) for same-publisher apps
    
    let idfv = UIDevice.current.identifierForVendor?.uuidString
    print("Using IDFV instead: \(idfv ?? "unavailable")")
}

Step 7: Complete Implementation Example

Here's a complete implementation that you can use in your app:

import UIKit
import AppTrackingTransparency
import AdSupport
 
class TrackingManager {
    static let shared = TrackingManager()
    
    private init() {}
    
    func requestPermissionIfNeeded() {
        if #available(iOS 14, *) {
            switch ATTrackingManager.trackingAuthorizationStatus {
            case .notDetermined:
                requestTrackingPermission()
            case .authorized:
                initializeAdServices()
            default:
                handleTrackingDenied()
            }
        } else {
            handleLegacyIOSTracking()
        }
    }
    
    private func requestTrackingPermission() {
        ATTrackingManager.requestTrackingAuthorization { status in
            DispatchQueue.main.async {
                switch status {
                case .authorized:
                    self.initializeAdServices()
                case .denied, .restricted:
                    self.handleTrackingDenied()
                case .notDetermined:
                    // User dismissed without choosing
                    break
                @unknown default:
                    break
                }
            }
        }
    }
    
    private func initializeAdServices() {
        let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString
        print("IDFA available: \(idfa)")
        // Initialize your ad SDKs here
    }
    
    private func handleTrackingDenied() {
        print("Using alternative tracking methods")
        // Implement fallback strategies
    }
    
    private func handleLegacyIOSTracking() {
        if ASIdentifierManager.shared().isAdvertisingTrackingEnabled {
            initializeAdServices()
        } else {
            handleTrackingDenied()
        }
    }
}
 
// Usage in AppDelegate or ViewController
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Request permission when appropriate
        TrackingManager.shared.requestPermissionIfNeeded()
    }
}

App Store Submission Considerations

If Your App Uses IDFA

  • You must implement ATT
  • You must include NSUserTrackingUsageDescription in Info.plist
  • Apple's automated scanning will detect IDFA usage

If Your App Doesn't Use IDFA

  • You don't need to implement ATT
  • Don't include tracking-related code or frameworks
  • Ensure third-party SDKs don't access IDFA

WebView and Cookies

Regarding your question about WebView and cookies: WebView content with cookies is generally separate from IDFA requirements. However:

  • If your WebView content uses JavaScript to access device identifiers or cross-site tracking
  • If you're sharing user data from WebView content with third parties for tracking purposes
  • If you're using WebView in combination with native tracking

Then you might still need ATT implementation. The key factor is whether you're doing cross-app/cross-site tracking, not just the presence of cookies.

Best Practices and Tips

  1. Timing Matters: Request permission at a natural point in your user journey, not immediately at app launch

  2. Provide Context: Explain the benefits to users before showing the ATT prompt

  3. Handle All Cases: Always have fallback strategies for when tracking is denied

  4. Test Thoroughly: Test on different iOS versions and authorization states

  5. SDK Integration: Ensure third-party SDKs are ATT-compliant and initialized after permission is granted

Summary

Implementing App Tracking Transparency involves several key steps:

  1. Configure Info.plist with usage description
  2. Import required frameworks (AppTrackingTransparency, AdSupport)
  3. Request authorization using ATTrackingManager
  4. Handle different authorization states appropriately
  5. Support legacy iOS versions (iOS 13 and below)
  6. Implement fallback strategies for denied permissions

Remember that ATT is about user privacy and transparency. By implementing it correctly, you're not only complying with Apple's requirements but also building trust with your users by giving them control over their data.

The key to successful ATT implementation is providing clear value propositions to users and having robust fallback strategies that don't compromise your app's core functionality when tracking is denied.

Makuhari Development Corporation
法人番号: 6040001134259
サイトマップ
ご利用にあたって
個人情報保護方針
個人情報取扱に関する同意事項
お問い合わせ
Copyright© Makuhari Development Corporation. All Rights Reserved.