Skip to main content
Identity management allows you to track users across different sessions, devices, and platforms by associating multiple identifiers (aliases) with a single user profile.

Single Identity

Multiple Identities

IDFA Provider

Overview

In the iOS SDK, you can set aliases using the setIdentities(aliases:) method. The SDK uses a singleton pattern via Permutive.shared.

Key Concepts

Setting Identity

For apps with a single identifier type:
do {
    let alias = Alias(tag: "internal_id", identity: userId)
    try Permutive.shared.setIdentities(aliases: [alias])
} catch {
    print("Failed to set identity: \(error)")
}

Security Best Practices

Always hash personally identifiable information like email addresses before sending to Permutive.
import CryptoKit

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

// Usage
let emailHash = hashEmail("user@example.com")
let alias = Alias(tag: "email_sha256", identity: emailHash)
try? Permutive.shared.setIdentities(aliases: [alias])

Standard Tag Names

Identifier TypeRecommended TagNotes
SHA-256 hashed emailemail_sha256Most common
Internal user IDinternal_id or user_idYour system’s ID
Vendor identifieridfvUIDevice.identifierForVendor
Customer IDcustomer_idE-commerce systems
Subscriber IDsubscriber_idSubscription services

Reserved Tags

Some alias tags are reserved by the SDK and cannot be used:
  • appnexus
  • amp
  • gigya
  • sailthru
  • aaid
Aliases with these tags will be ignored.

IDFA Identity

Permutive recommends against using IDFA due to Apple’s App Tracking Transparency requirements. Consider using identifierForVendor or hashed email addresses instead.
If you do need IDFA, use the dedicated setIdentityForIDFA method:
import AdSupport
import AppTrackingTransparency
import Permutive_iOS

func setIDFAIdentity() {
    if #available(iOS 14, *) {
        ATTrackingManager.requestTrackingAuthorization { status in
            guard status == .authorized else { return }

            let idfa = ASIdentifierManager.shared().advertisingIdentifier
            do {
                try Permutive.shared.setIdentityForIDFA(idfa)
            } catch {
                // IDFA may be all zeros (tracking denied)
                print("Failed to set IDFA: \(error)")
            }
        }
    }
}

IDFA Provider Guide

Complete IDFA integration documentation

Retrieving User ID

Get the current Permutive user ID:
let userId = Permutive.shared.currentUserId
print("Permutive User ID: \(userId)")

Tracking User ID Changes

Use TriggerAction to react when the user ID changes:
var userIdTrigger: TriggerAction?

func watchUserIdChanges() {
    userIdTrigger = Permutive.shared.triggerProvider?.actionUpdateForUserIdentity { userId in
        print("User ID changed to: \(userId)")
    }
}

// Release when done
deinit {
    userIdTrigger = nil
}

Common Patterns

func onLoginSuccess(userId: String, email: String) {
    let emailHash = hashEmail(email)

    do {
        let aliases = [
            Alias(tag: "email_sha256", identity: emailHash),
            Alias(tag: "internal_id", identity: userId, priority: 1)
        ]
        try Permutive.shared.setIdentities(aliases: aliases)
    } catch {
        print("Failed to set identity: \(error)")
    }
}
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])
}
class UserManager {
    // User starts as guest (anonymous)
    func onAppLaunch() {
        // SDK automatically creates anonymous ID
        // Optionally set vendor identifier
        setVendorIdentity()
    }

    // User logs in or signs up
    func onUserAuthenticated(userId: String, email: String) {
        let emailHash = hashEmail(email)

        // Permutive merges guest data with authenticated profile
        try? Permutive.shared.setIdentities(aliases: [
            Alias(tag: "email_sha256", identity: emailHash),
            Alias(tag: "internal_id", identity: userId, priority: 1)
        ])
    }
}

Expiry

Aliases can expire automatically, useful for GDPR compliance, session identifiers, and temporary access tokens.
// Never expire (default)
Alias(tag: "email_sha256", identity: emailHash)

// Expire in 30 days
let thirtyDaysFromNow = Date().addingTimeInterval(86400 * 30)
Alias(tag: "session_id", identity: sessionId, expiry: thirtyDaysFromNow)

// Expire at distant future (effectively never)
Alias(tag: "permanent_id", identity: id, expiry: Date.distantFuture)

tvOS Considerations

tvOS Note: Identity management works identically on tvOS. However, IDFA and App Tracking Transparency are not available on tvOS. Use identifierForVendor or hashed email as primary identifiers.

Troubleshooting

Problem: Setting identity doesn’t merge user data across devices.Solutions:
  • Check network connectivity
  • Verify the alias has been used in other sessions/devices
  • Enable debug logging: options.logModes = LogMode.all
  • Look for identity-related logs in the console
Problem: Same user appears as two different users.Solution: Use consistent alias tags and values. When a user logs in on multiple devices, use the same alias (e.g., hashed email).
Problem: Alias with certain tags is ignored.Solution: Avoid reserved tags: appnexus, amp, gigya, sailthru, aaid. Use custom tags instead.

Best Practices

  • Hash PII (especially email addresses) before setting as identity
  • Use meaningful tag names that describe the identifier type
  • Set priorities based on reliability and persistence
  • Use expiry dates for temporary or less reliable identifiers
  • Set identity as early as possible in the user journey
  • Use identifierForVendor as a fallback identifier

IDFA Provider

Apple advertising identifier integration

Cohorts & Activations

Understanding user segments

Triggers Provider

React to cohort changes

Issues

Solutions to common issues