How to retrieve iPhone IDFA from API?

96k views Asked by At

I would like to get the device IDFA. How to get this info from iOS official API ?

13

There are 13 answers

0
Jakir Hossain On

Here is a complete SwiftUI program.

import SwiftUI
import AdSupport
import AppTrackingTransparency

struct ContentView: View {
    @State var idfa: UUID!
    var body: some View {
        VStack {
            
            Button("Get IDFA"){
                idfa =  ASIdentifierManager.shared().advertisingIdentifier
                print(idfa!)
                
            }
            if let idfa{
                Text("\(idfa)")
            }
        }
        .padding()
        .onReceive(NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)) { _ in
            ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in })
        }
    }
}

#Preview {
    ContentView()
}

You have to update your Info.plist and add Tracking Usage Description: enter image description here

<key>NSUserTrackingUsageDescription</key>
<string>This identifier will be used to deliver personalized ads to you.</string>
0
Jochen Holzer On

A nicer approach to get the IDFA or nil if tracking is disabled via iOS Setting is using a (private) extension:

import AdSupport

class YourClass {

    func printIDFA() {
        print(ASIdentifierManager.shared().advertisingIdentifierIfPresent)
    }
}

private extension ASIdentifierManager {

    /// IDFA or nil if ad tracking is disabled via iOS system settings
    var advertisingIdentifierIfPresent: String? {
        if isAdvertisingTrackingEnabled {
            return advertisingIdentifier.uuidString
        }

        return nil 
    }        
}
0
CodaFi On

ASIdentifierManager is the official way to garner the Advertising Identification Number from a device running iOS 6+. You can use -[[ASIdentifierManager sharedManager] advertisingIdentifier]; to get it.

0
yoAlex5 On

Identifier for Advertising(IDFA)

isAdvertisingTrackingEnabled -> trackingAuthorizationStatus

From iOS v14 Apple deprecated isAdvertisingTrackingEnabled and moved the logic into AppTrackingTransparency Framework. Now user has to grand a permission to read idfa(in the same way as Location permission)

User can control it via:

#iOS 13
#AdSupport
#ASIdentifierManager.shared().isAdvertisingTrackingEnabled
Settings -> Privacy -> Advertising -> Limit Ad Tracking
#iOS 14
#AppTrackingTransparency
#ATTrackingManager.trackingAuthorizationStatus

#a global flag
Settings -> Privacy -> Tracking -> `Allow Apps to Request to Track` 
#or select an app from list to control every app separately 

#a local flag
Settings -> <app_name> -> Allow Tracking 

Implementation

import AppTrackingTransparency
import AdSupport
func getIDFA() -> String? {
    // Check whether advertising tracking is enabled
    if #available(iOS 14, *) {
        if ATTrackingManager.trackingAuthorizationStatus != ATTrackingManager.AuthorizationStatus.authorized  {
            return nil
        }
    } else {
        if ASIdentifierManager.shared().isAdvertisingTrackingEnabled == false {
            return nil
        }
    }

    return ASIdentifierManager.shared().advertisingIdentifier.uuidString
}
0
Oscar Falmer On

Swift 3 & 4

var IDFA = String()
if ASIdentifierManager.shared().isAdvertisingTrackingEnabled {
            IDFA = ASIdentifierManager.shared().advertisingIdentifier
}
1
Jeehut On

Here's a commented helper class in Swift that will give you a nil object for the identifier if the user has turned advertisement tracking off:

import AdSupport

class IDFA {
    // MARK: - Stored Type Properties
    static let shared = IDFA()

    // MARK: - Computed Instance Properties
    /// Returns `true` if the user has turned off advertisement tracking, else `false`.
    var limited: Bool {
        return !ASIdentifierManager.shared().isAdvertisingTrackingEnabled
    }

    /// Returns the identifier if the user has turned advertisement tracking on, else `nil`.
    var identifier: String? {
        guard !limited else { return nil }
        return ASIdentifierManager.shared().advertisingIdentifier.uuidString
    }
}

Just add it to your project (for example in a file named IDFA.swift) and link the AdSupport.framework in your target via the "Linked Frameworks and Libraries" section in the General settings tab.

Then you can use it like this:

if let identifier = IDFA.shared.identifier {
    // use the identifier
} else {
    // put any fallback logic in here
}
0
yonivav On

Please pay attention that in iOS 14, ASIdentifierManager.shared().isAdvertisingTrackingEnabled is deprecated. please use ATTrackingManager.trackingAuthorizationStatus == .authorized instead.

import AdSupport
import AppTrackingTransparency

extension ASIdentifierManager {
    //NOTE: if the user has enabled Limit Ad Tracking, this IDFA will be all zeros on a physical device
    static var identifierForAdvertising: String {

        // Check whether advertising tracking is enabled
        if #available(iOS 14, *) {
            guard ATTrackingManager.trackingAuthorizationStatus == .authorized else {
                return ""
            }
        } else {
            guard ASIdentifierManager.shared().isAdvertisingTrackingEnabled else {
                return ""
            }
        }
            
        // Get and return IDFA
        return ASIdentifierManager.shared().advertisingIdentifier.uuidString
    }
}
0
black_pearl On

Swift 5 with encapsulation:

import AdSupport

struct ID{
    static var advertising: String? {
         // Firstly, Check whether advertising tracking is enabled
         guard ASIdentifierManager.shared().isAdvertisingTrackingEnabled else {
              return nil
         }
         // Then, Get and return IDFA
         return ASIdentifierManager.shared().advertisingIdentifier.uuidString
     }
}
0
Amr Hossam On

Get IDFA in Swift:

    import AdSupport

    ...

    let myIDFA: String?
    // Check if Advertising Tracking is Enabled
    if ASIdentifierManager.sharedManager().advertisingTrackingEnabled {
        // Set the IDFA
        myIDFA = ASIdentifierManager.sharedManager().advertisingIdentifier.UUIDString
    } else {
        myIDFA = nil
    }
1
Rafał Sroka On

You first have to check if user user has decided to opt out from ad tracking. Only if he allowed it you can use the IDFA.

You can check it by calling isAdvertisingTrackingEnabled method of ASIdentifierManager.

isAdvertisingTrackingEnabled

Check the value of this property before performing any advertising tracking. If the value is NO, use the advertising identifier only for the following purposes: frequency capping, conversion events, estimating the number of unique users, security and fraud detection, and debugging.

The following code snippet shows how to obtain a string value of IDFA.

ObjC

@import AdSupport;

- (NSString *)identifierForAdvertising {
    // Check whether advertising tracking is enabled
    if([[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]) {
        NSUUID *identifier = [[ASIdentifierManager sharedManager] advertisingIdentifier];
        return [identifier UUIDString];
    }

    // Get and return IDFA
    return nil;
}

Swift

import AdSupport

func identifierForAdvertising() -> String? {
    // Check whether advertising tracking is enabled
    guard ASIdentifierManager.shared().isAdvertisingTrackingEnabled else {
        return nil
    }

    // Get and return IDFA
    return ASIdentifierManager.shared().advertisingIdentifier.uuidString
}
0
Vlad On

Beginning in iOS 10, when a user enables “Limit Ad Tracking,” the OS will send along the advertising identifier with a new value of “00000000-0000-0000-0000-000000000000.”

As per this article: https://fpf.org/2016/08/02/ios-10-feature-stronger-limit-ad-tracking/

0
worthbak On

Just to extend Amro's Swift answer, here's similar code wrapped in a method:

import AdSupport

...

func provideIdentifierForAdvertisingIfAvailable() -> String? {
    if ASIdentifierManager.sharedManager().advertisingTrackingEnabled {
      return ASIdentifierManager.sharedManager().advertisingIdentifier?.UUIDString ?? nil
    } else {
      return nil
    }
  }
6
Zachary Drake On

First, you have to ask permission from the user to use their IDFA:

#import <AppTrackingTransparency/AppTrackingTransparency.h> 

[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
 // Tracking authorization completed. Start loading ads here. 
 }];

This permission flow will only run once, the first time it is called, even if you re-start the app and/or call it again. If you want to answer differently, you'll have to delete the app off the device or simulator completely and reinstall it. Note that iOS simulators return blanked IDFAs (all zeroes) no matter what the answer to the permission flow. See https://developer.apple.com/documentation/apptrackingtransparency for details, including how to customize the message shown to users when asking to track them. Note that many advertising SDKs have their own consent flow calls that you can use.

To actually get the IDFA once you have permission:

#import <AdSupport/ASIdentifierManager.h> 

If you would like to get it as an NSString, use:

[[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString]

So your code might look like this:

NSString *idfaString = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
NSLog (@"IDFA: %@", idfaString);