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

# Users & Identity

> How anonymous visitors become identified users and how identity merging works.

Understanding how the system tracks users is fundamental to getting value from your event data. This guide explains anonymous visitors, identified users, and the "magic" that connects them into one complete customer journey.

***

## The Two Types of Users

Every person who interacts with your product exists in one of two states in Zixflow: **anonymous** or **identified**. Understanding these states is crucial because they determine what you can do with your data—from personalization to multi-channel messaging to conversion tracking.

Think of it like this: an anonymous user is someone browsing your store with a shopping basket (we can see what they're doing), while an identified user is someone with a loyalty card (we know who they are and can engage with them directly).

***

### **What is an Anonymous User?**

An anonymous user is someone using your product **before** you know who they are. They haven't signed up, logged in, or given you their email address. You don't know their name, contact information, or anything personally identifiable about them.

**But here's the powerful part:** Even though you don't know *who* they are, you can still track *what* they do.

#### How Anonymous Tracking Works

When someone first visits your website or opens your mobile app, the Zixflow SDK automatically generates a unique identifier called an `anonymousId`. This is a random string (UUID) that looks like `abc-123-def-456`.

**Where this ID is stored:**

* **Web browsers**: First-party cookie (or localStorage as fallback)
* **Mobile apps**: Device keychain (iOS) or SharedPreferences (Android)
* **Server-side**: Your session management system (you generate and pass it)

**Important:** This ID stays the same as long as the user is on the same device/browser. If they clear cookies or switch devices, they get a new `anonymousId`—until they identify themselves, at which point we can connect all their devices.

#### What You Can Do With Anonymous Users

Even without knowing who they are, you can:

* ✅ **Track their behavior**: Every page view, button click, product view
* ✅ **Measure conversion funnels**: See where anonymous visitors drop off
* ✅ **Show personalized content**: "You recently viewed these items"
* ✅ **Retarget with ads**: Connect anonymous IDs to ad platforms
* ✅ **Calculate true conversion rates**: Include pre-signup behavior in your metrics
* ✅ **Send push notifications**: If a device is registered before sign-up, you can send push notifications to it immediately — no sign-up required. The device is also automatically linked to the user's profile when they identify later.

**What you CANNOT do:**

* ❌ Send them emails (you don't have their email)
* ❌ See their activity across different devices (each device has its own anonymousId)
* ❌ Connect their behavior to your CRM or internal systems

#### Real-World Anonymous User Journey

**Example: Sarah discovers your product**

```
Day 1, Monday 2:30 PM:
  - Sarah clicks a LinkedIn ad and lands on your homepage
  - SDK generates: anonymousId = "anon_abc-123-def"
  - Zixflow tracks:
    → Viewed Homepage (anonymousId: anon_abc-123-def)
    → Clicked "Pricing" (anonymousId: anon_abc-123-def)
    → Viewed Pricing Page (anonymousId: anon_abc-123-def)
  
Day 1, Monday 4:00 PM:
  - Sarah returns via a Google search
  - Same browser, same cookie, same anonymousId
  - Zixflow tracks:
    → Viewed Product "Red Sneakers" (anonymousId: anon_abc-123-def)
    → Added to Cart (anonymousId: anon_abc-123-def)
    → Started Checkout (anonymousId: anon_abc-123-def)
    → Abandoned (closed browser)
```

At this point, you have 6 events for anonymous user `anon_abc-123-def`. You can see what they did, when they did it, and that they abandoned their cart—but you can't email them a reminder because you don't know who they are.

***

### **What is an Identified User?**

An identified user is someone you **know**. They've given you their email, created an account, logged in, or otherwise told you who they are. Now you have a way to reach them and can track their behavior across all their devices.

When a user identifies themselves, Zixflow transitions them from anonymous tracking (using `anonymousId`) to identified tracking (using `userId` from your system).

#### How User Identification Works

You tell Zixflow who the user is by calling the `identify()` method, usually triggered by:

* **User signs up**: Creates a new account
* **User logs in**: Existing account authentication
* **Email capture**: Newsletter signup, waitlist, lead form
* **OAuth/SSO**: Google, Facebook, Apple, Microsoft login
* **Guest checkout**: Enters email to complete purchase

**Your code calls:**

```javascript theme={null}
Zixflow.identify({
  userId: "user_12345",  // Your internal user ID
  traits: {
    email: "sarah@example.com",
    name: "Sarah Johnson",
    plan: "free"
  }
});
```

**What happens next:**

1. Zixflow creates or updates a user profile with `userId = "user_12345"`
2. All future events from this user are linked to their profile
3. You can now message them across multiple channels

#### The Magic of userId

The `userId` is **your** identifier for this person—the primary key from your database, their email address, or any other stable, unique identifier in your system. This is how Zixflow connects to the rest of your infrastructure.

#### What You Can Do With Identified Users

Once you know who someone is, the possibilities expand dramatically:

* ✅ **Send multi-channel messages**: Email, push notifications, SMS, in-app messages
* ✅ **Track across all devices**: Same userId on iPhone, iPad, and web browser
* ✅ **Enrich with external data**: Sync with your CRM, customer support, billing systems
* ✅ **Build rich user profiles**: Combine behavior data with demographic and firmographic data
* ✅ **Personalize deeply**: "Hi Sarah, your trial expires in 3 days"
* ✅ **Calculate customer lifetime value**: Aggregate all purchases, subscriptions, and activities
* ✅ **Attribute marketing campaigns**: Know which campaign brought them in originally

#### Real-World Identified User Journey

**Example: Sarah creates an account**

```
Day 2, Tuesday 10:00 AM:
  - Sarah returns to your site (still has cookie with anonymousId: anon_abc-123-def)
  - She's impressed and decides to sign up
  - Your app calls: identify(userId: "sarah@example.com", traits: {...})
  - ✨ IDENTITY MERGE HAPPENS ✨
  - Zixflow automatically links her 6 anonymous events to her new profile
  
  - Sarah's profile now shows:
    [Anonymous History - Now Merged]
    → Day 1: Viewed Homepage
    → Day 1: Viewed Pricing Page
    → Day 1: Viewed Product "Red Sneakers"
    → Day 1: Added to Cart
    → Day 1: Started Checkout
    → Day 1: Abandoned Cart
    
    [Identified Events - Going Forward]
    → Day 2: Signed Up (userId: sarah@example.com)
    
Future events (all with userId: sarah@example.com):
  → Day 2: Completed Profile
  → Day 3: Made First Purchase
  → Day 5: Opened Mobile App
  → Day 7: Invited Team Member
```

Now you can:

* Email Sarah about her abandoned cart (you have her email)
* Send her push notifications when she installs your app
* Show her personalized recommendations based on her full history
* Calculate her conversion path from first touch (LinkedIn ad) to signup
* Track her across all devices once she logs in on each one

#### The Power of Identification

The transition from anonymous to identified is where Zixflow becomes most powerful. You get:

1. **Complete customer journey**: See everything from their first visit to their latest purchase
2. **True conversion attribution**: Know which marketing channel brought them in (even if they didn't convert immediately)
3. **Cross-device continuity**: Track them seamlessly across phone, tablet, and desktop
4. **Personalization at scale**: Speak to thousands of users as individuals
5. **Predictive capabilities**: Use their full behavioral history to predict churn, upsell opportunities, and lifetime value

***

## Identity Merging: How It Works

Identity merging is what makes pre-signup attribution and funnel analysis possible. When someone signs up or logs in, Zixflow automatically connects all their previous anonymous activity to their identified profile.

### When Merging Happens

**You call identify with both IDs:**

```javascript theme={null}
Zixflow.identify({
  userId: "user_12345",
  anonymousId: "anon_abc-123",  // ← Including both triggers the merge
  traits: { email: "user@example.com" }
});
```

**What Zixflow does automatically:**

1. Finds all events from that anonymous visitor
2. Upgrades the existing anonymous profile in-place — the user's `first_seen_at` and `created_at` timestamps are preserved from when they first arrived, not from when they signed up
3. Links all anonymous events to the identified profile
4. Links all devices registered before sign-up to the user's profile (enables push notifications immediately after identify)
5. Makes everything searchable under their user ID

**Result:** The user's profile now shows their complete journey — everything they did before and after signing up, with accurate first-touch timestamps.

### Profile Timeline Preservation

When a user signs up after browsing anonymously, their profile retains the original timestamps from their first visit:

```
Anonymous browsing starts:  Monday 14:30  ← first_seen_at stays as Monday 14:30
Signs up / calls identify(): Tuesday 10:00 ← NOT overwritten
```

This means your "time to convert" metrics and "first seen" reports accurately reflect when a visitor first engaged, not when they finally created an account.

### Visual Timeline Example

```
Timeline: Anonymous → Identified

Day 1 (Anonymous):
  [anonymousId: abc-123]
  14:30 → Viewed Homepage
  14:35 → Viewed Product "Red Sneakers"  
  14:37 → Added to Cart

Day 2 (Sign Up + Merge):
  10:00 → Signed Up
          ↓
     [You call identify() with both userId + anonymousId]
          ↓
     ✨ MERGE HAPPENS ✨
          ↓
  [userId: sarah@example.com]
  
Final Profile (sarah@example.com):
  Events:
    ✓ Viewed Homepage (Day 1, 14:30)        ← merged from anonymous
    ✓ Viewed Product (Day 1, 14:35)         ← merged from anonymous
    ✓ Added to Cart (Day 1, 14:37)          ← merged from anonymous
    ✓ Signed Up (Day 2, 10:00)              ← identify event
    → Future events linked to sarah@example.com
```

***

## Why Identity Merging Matters

### 1. **Multi-Touch Attribution**

Connect first-touch (anonymous) to conversion (identified):

```
Anonymous phase:
  Day 1: User clicks LinkedIn ad → Lands on homepage
  Day 2: Returns via Google (direct) → Views pricing
  Day 3: Clicks email campaign link → Starts trial

Identified phase:
  Day 3: Signs up → identify() merges history
  
Result: 
  First-touch attribution = LinkedIn ad
  Last-touch attribution = Email campaign
  Full journey = LinkedIn → Direct → Email → Conversion
```

### 2. **Funnel Completion Analysis**

Measure conversion rates including anonymous drop-offs:

```
Signup funnel:
  1. Viewed homepage (1000 anonymous visitors)
  2. Viewed pricing (450 continued)
  3. Started trial form (180 proceeded)
  4. Signed up (120 converted) ← Identity merge happens here
  
Conversion rate: 12% (120/1000)
```

Without merging, you'd only see step 4 (missing 88% of funnel context).

### 3. **Behavioral Enrichment for Activation**

Use pre-signup behavior to optimize onboarding:

```
Pre-signup signals:
  - Viewed "Enterprise Features" page 3x
  - Downloaded pricing PDF
  - Spent 8 minutes on case studies
  
Onboarding personalization:
  - Skip basic intro (they're already educated)
  - Highlight enterprise features in email sequence
  - Assign to enterprise sales rep (high intent)
```

***

## User IDs: What to Use

When calling `identify()`, you need to provide a `userId` — your application's unique identifier for this user.

### Choosing Your User ID

**Option 1: Database Primary Key** (Recommended)

```javascript theme={null}
identify({ userId: "user_12345" })
```

* ✅ Never changes (stable identifier)
* ✅ Unique per user
* ✅ Works even if user changes email
* ❌ Not human-readable in reports

**Option 2: Email Address**

```javascript theme={null}
identify({ userId: "sarah@example.com" })
```

* ✅ Human-readable
* ✅ Unique (in most systems)
* ❌ Can change if user updates email
* ❌ Privacy concerns (visible in logs)

**Option 3: Username**

```javascript theme={null}
identify({ userId: "sarah_johnson" })
```

* ✅ Human-readable
* ❌ Can change
* ❌ Not always unique

### ❌ **What NOT to Use**

**Session IDs** ❌

```javascript theme={null}
identify({ userId: "sess_abc123" })  // Changes every login!
```

* Problem: User gets a new ID every session → Can't track across sessions

**Device IDs** ❌

```javascript theme={null}
identify({ userId: "device_abc123" })  // Different per device!
```

* Problem: Same user on multiple devices → Looks like different people

**Temporary IDs** ❌

```javascript theme={null}
identify({ userId: "temp_123" })  // What if they reset password?
```

* Problem: ID might expire or be reassigned

### Rule of Thumb

Use an identifier that:

1. **Never changes** for the lifetime of the user
2. **Is unique** across all users
3. **Exists in your system** (so you can look up the user)

***

## User Profiles

Once a user is identified, the system maintains a profile with all their data.

### Profile Structure

**Profile information stored:**

```javascript theme={null}
{
  id: "prof_xyz789",                    // System-generated UUID
  workspace_id: "ws_123",               // Your workspace
  user_id: "sarah@example.com",         // Your user ID
  email: "sarah@example.com",           // Email if provided
  anonymous_id: "abc-123-def",          // Original anonymous ID
  
  // Custom attributes (you set these)
  attributes: {
    name: "Sarah Johnson",
    plan: "pro",
    company: "Acme Corp",
    signup_date: "2026-05-04",
    total_purchases: 3,
    lifetime_value: 267.99
  },
  
  // System-generated
  created_at: "2026-05-04T10:00:00Z",   // First seen
  updated_at: "2026-05-04T14:30:00Z",   // Last attribute update
  last_seen_at: "2026-05-04T14:30:00Z"  // Last event received
}
```

### What Profiles Contain

**Core identity fields:**

* `user_id`: Your application's ID for this user
* `email`: Email address (if provided in traits)
* `name`: Name(if provided in traits)
* `phone`: Phone number (if provided in traits)
* `anonymous_id`: Original anonymous ID before identification

**Custom attributes:**

* Anything you pass in `traits` during `identify()`
* Anything you set via `setProfileAttributes()`
* Examples: name, plan, company, preferences, computed values

**System metadata:**

* `created_at`: When we first saw this user
* `updated_at`: When profile was last modified
* `last_seen_at`: Timestamp of most recent event

**Associated data:**

* Events: All events linked to this user\_id
* Devices: All devices registered for push notifications

***

## Multiple Devices Per User

One user can interact with your product across multiple devices. The system automatically links them all to the same profile.

### Scenario: Sarah's Devices

```
User: sarah@example.com

Devices:
  1. iPhone (iOS)
     - Token: apns_abc123...
     - Registered: 2 days ago
     - Last seen: 1 hour ago
     
  2. iPad (iOS)
     - Token: apns_def456...
     - Registered: 5 days ago
     - Last seen: 3 hours ago
     
  3. Chrome Browser (Web)
     - Token: web_ghi789...
     - Registered: 10 days ago
     - Last seen: 30 minutes ago
```

**How it works:**

1. Sarah logs in on iPhone → `identify()` called with her userId
2. Sarah logs in on iPad → Same userId, different device token
3. Sarah logs in on web browser → Same userId, different device token

All devices linked to the same user (`user_id = "sarah@example.com"`).

**Benefits:**

* Send push notifications to ALL her devices (or target specific platforms)
* Track cross-device behavior (started on mobile, finished on desktop)
* Unified view of engagement across devices

***

## Common User Scenarios

### Scenario 1: First-Time Visitor

```
[No cookies, no account]
  ↓
User visits site
  ↓
SDK generates: anonymousId = "anon_123"
  ↓
Events tracked as anonymous:
  - Viewed Homepage
  - Viewed Product
  - Viewed Pricing
```

**System view:** One anonymous user with 3 events.

***

### Scenario 2: Returning Visitor (Not Logged In)

```
[Has cookie with anonymousId = "anon_123"]
  ↓
User returns to site
  ↓
SDK reads anonymousId from cookie
  ↓
Events still tracked as same anonymous user:
  - Viewed Product B
  - Added to Cart
```

**System view:** Same anonymous user (anon\_123) now has 5 total events.

***

### Scenario 3: User Logs In

```
[Anonymous user anon_123 with 5 events]
  ↓
User creates account / logs in
  ↓
App calls: identify(userId: "sarah@example.com", anonymousId: "anon_123")
  ↓
System merges:
  - All 5 anonymous events → linked to sarah@example.com
  - Upgrades the existing anonymous profile in-place (same profile ID, timestamps preserved)
  - Any devices registered before sign-up → linked to sarah@example.com
  - Future events tracked as identified user
```

**System view:** Identified user ([sarah@example.com](mailto:sarah@example.com)) with complete 5-event history. The profile's `first_seen_at` reflects when the anonymous session started, not when sign-up happened.

***

### Scenario 4: User Logs Out

```
[Identified user sarah@example.com]
  ↓
User logs out
  ↓
SDK generates NEW anonymousId = "anon_456"
  ↓
New events tracked as new anonymous user:
  - Viewed Homepage
  - Viewed Different Product
  
[Until they log back in]
```

**System view:**

* Identified profile: [sarah@example.com](mailto:sarah@example.com) (previous history intact)
* New anonymous user: anon\_456 (new browsing session)

**Best practice:** Call `clearIdentify()` on logout to ensure clean separation:

```javascript theme={null}
// When user logs out
Zixflow.clearIdentify();
```

***

### Scenario 5: User Switches Devices

```
Day 1: Sarah on iPhone
  ↓
SDK generates: anonymousId = "anon_iphone_123"
  ↓
Events: Viewed Product, Added to Cart
  ↓
Creates account: identify(userId: "sarah@example.com", anonymousId: "anon_iphone_123")

Day 2: Sarah on Desktop
  ↓
SDK generates NEW: anonymousId = "anon_desktop_456"
  ↓
Events: Viewed Cart
  ↓
Logs in: identify(userId: "sarah@example.com", anonymousId: "anon_desktop_456")
  ↓
System merges desktop anonymous history too!
```

**System view:** One profile ([sarah@example.com](mailto:sarah@example.com)) with events from both devices, all in chronological order.

***

## User Lifecycle States

Beyond anonymous/identified, a user profile can be in one of these server-controlled states:

### User Deleted

When `User Deleted` is triggered:

* Profile is soft-deleted (`is_deleted = true`)
* All linked devices are deactivated (push tokens disabled)
* Existing event history is preserved for analytics

This is triggered server-side — typically via the Track API v1 `DELETE /api/v1/customers/{id}` endpoint or from your backend. Cannot be triggered from the client SDK.

### User Suppressed / Unsuppressed

Suppression blocks all outbound messages for a user across every channel, regardless of their individual opt-out settings:

| State               | Profile flag            | Effect                              |
| ------------------- | ----------------------- | ----------------------------------- |
| `User Suppressed`   | `is_suppressed = true`  | No push, email, SMS, or any channel |
| `User Unsuppressed` | `is_suppressed = false` | Normal message delivery resumes     |

**Use suppression when:** A user requests complete communication silence, or your system detects abuse/fraud.

Suppression is distinct from channel opt-out: channel opt-out is per-channel and user-controlled; suppression is workspace-controlled and blocks everything simultaneously.

***

## Device Registration for Anonymous Users

A common pattern — especially for mobile apps — is that a user registers their device for push notifications **before** they create an account or log in. Zixflow handles this as a first-class use case:

1. **Anonymous device registration**: The SDK fires a `Device Created or Updated` event with the device's push token and the user's `anonymousId`. Zixflow creates an anonymous profile and links the device to it.

2. **Push notifications work immediately**: The anonymous device is fully active. You can send push notifications to it right away — no sign-up required.

3. **User signs up / logs in**: The app calls `identify()` with the `userId` and `anonymousId`.

4. **Automatic device migration**: Zixflow finds all devices registered under that `anonymousId` and links them to the now-identified user profile. Push notifications continue working unchanged.

```
Timeline:
  Monday:  User opens app → device token registered (anonymous_id: anon_123)
           ← Push notifications can be sent to this device immediately
  Tuesday: User signs up → identify(userId: "sarah", anonymousId: "anon_123")
           ← Device migrated to sarah's profile automatically
           ← Push continues working — no re-registration needed
```

This is handled entirely by the backend — your app only needs to call `identify()` at sign-up.

***

**Next:** Learn how to register devices for push notifications → [Devices & Push Notifications](/documentation/events/devices-and-push-notifications)
