> ## Documentation Index
> Fetch the complete documentation index at: https://docs.permutive.com/llms.txt
> Use this file to discover all available pages before exploring further.

# IDFA Provider

> Apple advertising identifier integration and privacy considerations

This guide covers using the Identifier for Advertisers (IDFA) with the Permutive SDK, including App Tracking Transparency requirements and privacy best practices.

<CardGroup cols={2}>
  <Card title="ATT Framework" href="#app-tracking-transparency" icon="shield-check" />

  <Card title="Alternatives" href="#recommended-alternatives" icon="lightbulb" />
</CardGroup>

## Should you collect IDFA?

<Note>
  IDFA is opt-in only, it's gated behind Apple's App Tracking Transparency (ATT) prompt, so it's never available for 100% of your users. When a user consents, the IDFA can be collected as an additional, stable identifier for that user.
</Note>

<Note>
  **Config-driven auto-collection is available from v2.6.0.** If your workspace has it enabled, the SDK can automatically collect the IDFA (and IDFV / IP) as aliases, no manual `setIdentityForIDFA` code required. The manual approach below is still supported. See the [v2.6 Migration Guide](/sdks/mobile/ios/guides/migration/v2-6) for setup and the privacy/App Store implications.
</Note>

## Why opting in can be worth it

1. **Consent rates are rising, not collapsing.** The industry-wide ATT opt-in rate reached roughly **35% by Q2 2025**, up from \~34% in 2023 and \~34.5% in 2024, a steady upward trend as prompt design and onboarding flows have matured.
2. **A stable, consented identifier.** For users who consent, the IDFA stays consistent for that user, giving a reliable signal to resolve their identity accurately.
3. **A standard iOS identifier.** IDFA uses Apple's own identifier format, so it fits into your existing identity setup without custom handling.
4. **Complements your other identifiers.** IDFA adds to the identity you already collect (hashed email, IDFV) rather than replacing it, helping build a more complete picture of the consenting share of your audience.

## What to weigh before opting in

1. **Coverage is partial.** Even at healthy opt-in rates, a meaningful share of users will decline, so IDFA should never be your only identifier. Pair it with hashed email and IDFV (see [Recommended Alternatives](#recommended-alternatives)).
2. **Extra implementation.** Requires integrating the ATT framework and requesting permission at the right moment.
3. **App Store compliance.** You must justify IDFA usage and declare it accurately in App Store Connect.

## Recommended Alternatives

### 1. Identifier for Vendor (IDFV)

A consistent identifier across your apps from the same vendor:

```swift theme={"dark"}
import UIKit
import Permutive_iOS

func setVendorIdentity() {
    guard let idfv = UIDevice.current.identifierForVendor?.uuidString else {
        return
    }

    let alias = Alias(tag: "idfv", identity: idfv, priority: 2)
    try? Permutive.shared.setIdentities(aliases: [alias])
}
```

**Benefits:**

* No user permission required
* Consistent across app installs (until uninstall)
* Available on both iOS and tvOS
* No App Store justification needed

### 2. Hashed Email Address

The most reliable cross-device identifier:

```swift theme={"dark"}
import CryptoKit
import Permutive_iOS

func setEmailIdentity(email: String) {
    let normalized = email.trimmingCharacters(in: .whitespaces).lowercased()
    let data = Data(normalized.utf8)
    let hash = SHA256.hash(data: data)
    let emailHash = hash.compactMap { String(format: "%02x", $0) }.joined()

    let alias = Alias(tag: "email_sha256", identity: emailHash, priority: 0)
    try? Permutive.shared.setIdentities(aliases: [alias])
}
```

**Benefits:**

* Works across devices and platforms
* Highest priority for identity resolution
* No Apple framework dependencies
* User provided and expected

### 3. Internal User ID

Your system's user identifier:

```swift theme={"dark"}
func setUserIdentity(userId: String) {
    let alias = Alias(tag: "internal_id", identity: userId, priority: 1)
    try? Permutive.shared.setIdentities(aliases: [alias])
}
```

## App Tracking Transparency

If you still need IDFA, follow these steps:

### 1. Add Usage Description

Add to your `Info.plist`:

```xml theme={"dark"}
<key>NSUserTrackingUsageDescription</key>
<string>We use this identifier to personalize your ad experience.</string>
```

### 2. Request Permission

<CodeGroup>
  ```swift Swift theme={"dark"}
  import AppTrackingTransparency
  import AdSupport
  import Permutive_iOS

  class TrackingPermissionManager {

      func requestTrackingPermission() {
          // Only available on iOS 14+
          if #available(iOS 14, *) {
              ATTrackingManager.requestTrackingAuthorization { status in
                  switch status {
                  case .authorized:
                      self.setIDFAIdentity()
                  case .denied:
                      print("User denied tracking")
                  case .restricted:
                      print("Tracking restricted")
                  case .notDetermined:
                      print("Not determined")
                  @unknown default:
                      break
                  }
              }
          } else {
              // iOS 13 and earlier - no ATT required
              setIDFAIdentity()
          }
      }

      private func setIDFAIdentity() {
          let idfa = ASIdentifierManager.shared().advertisingIdentifier

          // Check if IDFA is valid (not all zeros)
          guard idfa != UUID(uuidString: "00000000-0000-0000-0000-000000000000") else {
              print("IDFA not available (tracking denied or restricted)")
              return
          }

          do {
              try Permutive.shared.setIdentityForIDFA(idfa)
              print("IDFA set successfully")
          } catch {
              print("Failed to set IDFA: \(error)")
          }
      }
  }
  ```

  ```objectivec Objective-C theme={"dark"}
  #import <AppTrackingTransparency/AppTrackingTransparency.h>
  #import <AdSupport/AdSupport.h>
  @import Permutive_iOS;

  @implementation TrackingPermissionManager

  - (void)requestTrackingPermission {
      if (@available(iOS 14, *)) {
          [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
              if (status == ATTrackingManagerAuthorizationStatusAuthorized) {
                  [self setIDFAIdentity];
              } else {
                  NSLog(@"Tracking not authorized: %ld", (long)status);
              }
          }];
      } else {
          // iOS 13 and earlier
          [self setIDFAIdentity];
      }
  }

  - (void)setIDFAIdentity {
      NSUUID *idfa = [[ASIdentifierManager sharedManager] advertisingIdentifier];

      // Check if IDFA is valid
      NSUUID *zeroUUID = [[NSUUID alloc] initWithUUIDString:@"00000000-0000-0000-0000-000000000000"];
      if ([idfa isEqual:zeroUUID]) {
          NSLog(@"IDFA not available");
          return;
      }

      NSError *error = nil;
      [Permutive.shared setIdentityForIDFA:idfa error:&error];

      if (error) {
          NSLog(@"Failed to set IDFA: %@", error);
      } else {
          NSLog(@"IDFA set successfully");
      }
  }

  @end
  ```
</CodeGroup>

### 3. Check Status Before Requesting

```swift theme={"dark"}
func checkAndRequestTracking() {
    if #available(iOS 14, *) {
        let status = ATTrackingManager.trackingAuthorizationStatus

        switch status {
        case .notDetermined:
            // Can request permission
            requestTrackingPermission()

        case .authorized:
            // Already authorized
            setIDFAIdentity()

        case .denied, .restricted:
            // Cannot use IDFA
            useAlternativeIdentity()

        @unknown default:
            break
        }
    }
}
```

### 4. When to Request

<Warning>
  Don't request tracking permission immediately on app launch. Wait for an appropriate moment when the user understands the value.
</Warning>

```swift theme={"dark"}
// Good: Request after user has engaged with the app
func onFirstContentView() {
    // User has started using the app
    requestTrackingPermission()
}

// Good: Request when user is about to see ads
func onPrepareToPresentAds() {
    requestTrackingPermission()
}

// Bad: Requesting immediately on launch
func applicationDidFinishLaunching() {
    // Don't do this - user hasn't understood the app yet
    // requestTrackingPermission()
}
```

## Using setIdentityForIDFA

The SDK provides a dedicated method for IDFA:

```swift theme={"dark"}
do {
    try Permutive.shared.setIdentityForIDFA(idfa)
} catch {
    // IDFA was invalid (all zeros) or otherwise unusable
    print("setIdentityForIDFA failed: \(error)")
}
```

This method:

* Sets an alias with the reserved tag `"idfa"`
* Validates the IDFA is not all zeros
* Throws an error if IDFA is invalid

## Apple Privacy Information

When submitting to the App Store, you must declare data collection. For apps using Permutive:

### Without IDFA

If you're NOT using IDFA, Permutive's SDK data collection is:

* **Identifiers:** Device ID (vendor identifier if used)
* **Usage Data:** Product interaction
* **Purpose:** Analytics, advertising

### With IDFA

If you ARE using IDFA, also declare:

* **Identifiers:** Device ID (IDFA)
* **Purpose:** Third-party advertising, tracking

For complete privacy information, see Apple's [App Store data collection policies](https://developer.apple.com/app-store/app-privacy-details/).

## tvOS Considerations

<Info>
  **tvOS Note:** App Tracking Transparency and IDFA are available on tvOS from version 14.5 onwards.
</Info>

```swift theme={"dark"}
#if os(tvOS)
// tvOS - use vendor identifier
if let idfv = UIDevice.current.identifierForVendor?.uuidString {
    let alias = Alias(tag: "idfv", identity: idfv, priority: 2)
    try? Permutive.shared.setIdentities(aliases: [alias])
}
#else
// iOS - can request IDFA if needed
requestTrackingPermission()
#endif
```

## Best Practices

<Tabs>
  <Tab title="Do">
    * Use `identifierForVendor` as a reliable alternative
    * Use hashed email for cross-device identity
    * Request ATT permission at an appropriate time
    * Explain the value to users before requesting
    * Handle all authorization statuses gracefully
    * Have fallback identifiers when IDFA unavailable
  </Tab>

  <Tab title="Don't">
    * Don't rely solely on IDFA for identity
    * Don't request permission immediately on launch
    * Don't assume IDFA is available
    * Don't forget to update App Store privacy declarations
  </Tab>
</Tabs>

## Troubleshooting

<AccordionGroup>
  <Accordion title="setIdentityForIDFA throws error">
    **Problem:** IDFA call fails with error.

    **Cause:** IDFA is all zeros (tracking denied/restricted).

    **Solution:** Check authorization status first and use alternative identifiers:

    ```swift theme={"dark"}
    if ATTrackingManager.trackingAuthorizationStatus == .authorized {
        try Permutive.shared.setIdentityForIDFA(idfa)
    } else {
        setAlternativeIdentity()
    }
    ```
  </Accordion>

  <Accordion title="ATT prompt not appearing">
    **Problem:** `requestTrackingAuthorization` doesn't show prompt.

    **Possible Causes:**

    * Missing `NSUserTrackingUsageDescription` in Info.plist
    * User already responded (check status first)
    * Running on iOS 13 or earlier
    * Running on simulator (may behave differently)
  </Accordion>

  <Accordion title="App rejected for IDFA usage">
    **Problem:** App Store rejects app for tracking without permission.

    **Solution:** Ensure you:

    * Request ATT permission before accessing IDFA
    * Have clear `NSUserTrackingUsageDescription`
    * Accurately declare data usage in App Store Connect
  </Accordion>
</AccordionGroup>

## Related Documentation

<CardGroup cols={2}>
  <Card title="Identity Management" icon="user" href="/sdks/mobile/ios/core-concepts/identity-management">
    All identity options
  </Card>

  <Card title="Initialization" icon="gear" href="/sdks/mobile/ios/getting-started/initialization">
    SDK setup and consent
  </Card>

  <Card title="Google Ad Manager" icon="google" href="/sdks/mobile/ios/integrations/google-ad-manager">
    Ad targeting
  </Card>

  <Card title="Issues" icon="triangle-exclamation" href="/sdks/mobile/ios/troubleshooting/common-errors">
    Common problems
  </Card>
</CardGroup>
