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

# User Identity

> Link attribution and purchases to user accounts

## Overview

By default, SpendOwl uses an anonymous device ID to track attribution and purchases. When you set a user ID, all events are associated with that user, enabling:

* User-level ROAS analysis
* Cohort tracking across devices
* Accurate LTV calculation

## Setting User ID

Call `setUserId()` after the user logs in or registers:

```swift theme={null}
// After successful authentication
SpendOwl.setUserId(user.id)
```

<Tabs>
  <Tab title="SwiftUI">
    ```swift theme={null}
    struct LoginView: View {
        @StateObject private var viewModel = LoginViewModel()

        var body: some View {
            // ... login UI
        }
    }

    class LoginViewModel: ObservableObject {
        func login(email: String, password: String) async throws {
            let user = try await AuthService.login(email: email, password: password)

            // Set SpendOwl user ID
            SpendOwl.setUserId(user.id)

            // Continue with login flow
        }
    }
    ```
  </Tab>

  <Tab title="UIKit">
    ```swift theme={null}
    class LoginViewController: UIViewController {
        func login(email: String, password: String) {
            Task {
                do {
                    let user = try await AuthService.login(email: email, password: password)

                    // Set SpendOwl user ID
                    SpendOwl.setUserId(user.id)

                    // Navigate to main app
                    navigateToHome()
                } catch {
                    showError(error)
                }
            }
        }
    }
    ```
  </Tab>
</Tabs>

## Clearing User ID

Call `clearUserId()` when the user logs out:

```swift theme={null}
func logout() {
    // Clear SpendOwl user ID
    SpendOwl.clearUserId()

    // Clear other user data
    AuthService.logout()
}
```

## Best Practices

<AccordionGroup>
  <Accordion title="Use Stable Identifiers">
    Use your internal database ID or UUID, not email addresses or usernames which can change.

    ```swift theme={null}
    // Good
    SpendOwl.setUserId(user.id)  // "usr_abc123"

    // Avoid
    SpendOwl.setUserId(user.email)  // Can change
    ```
  </Accordion>

  <Accordion title="Set Early, Clear on Logout">
    Set the user ID as soon as authentication succeeds. Clear it immediately on logout.

    ```swift theme={null}
    // Set on any successful auth
    func onAuthSuccess(user: User) {
        SpendOwl.setUserId(user.id)
    }

    // Clear on any logout path
    func onLogout() {
        SpendOwl.clearUserId()
    }
    ```
  </Accordion>

  <Accordion title="Handle Session Restoration">
    Set the user ID when restoring a session from keychain/token:

    ```swift theme={null}
    func restoreSession() async {
        guard let user = try? await AuthService.restoreSession() else {
            return
        }
        SpendOwl.setUserId(user.id)
    }
    ```
  </Accordion>
</AccordionGroup>

## Anonymous ID Behavior

When no user ID is set, SpendOwl uses an anonymous ID:

* Generated on first launch
* Stored securely in Keychain
* Persists across app reinstalls (if Keychain is preserved)
* Replaced by user ID when `setUserId()` is called

```mermaid theme={null}
flowchart LR
    A[App Launch] --> B{User logged in?}
    B -->|Yes| C[Use user ID]
    B -->|No| D[Use anonymous ID]
    D --> E[User logs in]
    E --> C
    C --> F[User logs out]
    F --> D
```

## User ID in Attribution

The user ID is included with attribution data:

```swift theme={null}
// Get attribution with user context
SpendOwl.setUserId("user-123")
let attribution = try await SpendOwl.attribution()
// Attribution is now linked to "user-123"
```

## User ID in Purchases

Purchases are automatically tagged with the current user ID:

```swift theme={null}
SpendOwl.setUserId("user-123")

// Any StoreKit 2 purchase is now linked to "user-123"
let result = try await product.purchase()
```

<Note>
  If the user ID changes during a purchase, the ID at transaction time is used.
</Note>

## Multiple Accounts

If your app supports multiple accounts:

```swift theme={null}
func switchAccount(to user: User) {
    // Clear previous user
    SpendOwl.clearUserId()

    // Set new user
    SpendOwl.setUserId(user.id)
}
```

## Privacy Considerations

* User IDs are transmitted securely over HTTPS
* IDs are hashed before storage in SpendOwl's database
* You can request user data deletion through the dashboard

## Next Steps

<CardGroup cols={2}>
  <Card title="Purchase Tracking" icon="shopping-cart" href="/sdk/purchase-tracking">
    Learn about automatic purchase tracking
  </Card>

  <Card title="Privacy" icon="shield" href="/resources/privacy">
    Privacy manifest and compliance
  </Card>
</CardGroup>
