> ## 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>

## Important: IDFA Recommendation

<Warning>
  **Permutive recommends against using IDFA** for identity. Apple's App Tracking Transparency (ATT) requirements significantly limit IDFA availability and utility. Consider using `identifierForVendor` or hashed email addresses instead.
</Warning>

## Why Not IDFA?

1. **Low opt-in rates:** Most users deny tracking permission
2. **Extra implementation:** Requires ATT framework integration
3. **App Store compliance:** Must justify IDFA usage in App Store Connect
4. **Limited utility:** Only available when user explicitly permits
5. **Not available on tvOS:** ATT is not supported on tvOS

## 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 **not available on tvOS**. Use `identifierForVendor` or hashed email as primary identifiers on tvOS.
</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 use IDFA on tvOS (not 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>
