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

# Visitor Identification

> How DATALYR identifies and tracks visitors across sessions

DATALYR automatically identifies visitors to build complete customer journeys, even across multiple sessions and devices.

## How Visitor Identification Works

Every visitor gets a unique anonymous ID that persists across sessions. When users log in or provide their email, DATALYR links their anonymous ID to their user ID for cross-device tracking.

### Anonymous ID

**What it is:**
A unique identifier automatically generated for every visitor (`anon_abc123...`).

**How it's stored:**

* Primary: Root domain cookie (`__dl_visitor_id`)
* Backup: localStorage (`dl_anonymous_id`)

**Persistence:**

* Lasts 1 year by default
* Works across subdomains (e.g., [www.example.com](http://www.example.com) and app.example.com)
* Survives browser restarts
* Does NOT survive browser data clearing

**Generation:**

```javascript theme={null}
// Automatically generated on first visit
anon_f47ac10b-58cc-4372-a567-0e02b2c3d479
```

### User ID

**What it is:**
Your internal identifier for logged-in users (user\_123, email address, database ID, etc.).

**How it's set:**

```javascript theme={null}
// Web
datalyr.identify('user_123', {
  email: 'user@example.com',
  name: 'John Doe',
  plan: 'pro'
});

// iOS
await DatalyrSDK.shared.identify("user_123", properties: [
    "email": "user@example.com"
])

// React Native
await Datalyr.identify('user_123', {
  email: 'user@example.com'
});
```

**Persistence:**

* Stored in localStorage (`dl_user_id`)
* Survives page reloads and browser restarts
* Cleared on logout (call `datalyr.reset()`)

### Distinct ID

**What it is:**
The primary identifier DATALYR uses for each visitor.

**Logic:**

```
Distinct ID = User ID (if logged in) || Anonymous ID
```

**Example Flow:**

```
Visit 1: anonymous_id = anon_abc123
         distinct_id = anon_abc123

User logs in:
         anonymous_id = anon_abc123 (unchanged)
         user_id = user_456
         distinct_id = user_456

Visit 2 (same browser):
         anonymous_id = anon_abc123
         user_id = user_456
         distinct_id = user_456
```

## Cross-Subdomain Tracking

DATALYR automatically tracks visitors across subdomains using root domain cookies.

### How It Works

When a visitor first arrives at **[www.example.com](http://www.example.com)**:

1. DATALYR generates `anon_abc123`
2. Sets cookie on root domain (`.example.com`)
3. Cookie is accessible on all subdomains

When the same visitor goes to **app.example.com**:

1. DATALYR reads cookie from root domain
2. Uses same `anon_abc123` ID
3. Journey continues seamlessly

### Supported Domains

**Standard TLDs:**

* `.com`, `.net`, `.org` → Cookie set on `.example.com`

**Country-Specific TLDs:**

* `.co.uk`, `.com.au`, `.co.nz` → Cookie set on `.example.co.uk`

**Localhost:**

* `localhost` → Cookie set on `localhost`

**IP Addresses:**

* `192.168.1.1` → Cookie set on exact IP

## Cross-Device Tracking

Link visitors across devices using user identification.

### Example Journey

**Device 1 (Mobile):**

```
Day 1, 10:00 AM - Mobile phone
- Clicks Meta ad (fbclid captured)
- anonymous_id: anon_mobile_123
- Browses products
- Does NOT purchase
```

**Device 2 (Desktop):**

```
Day 1, 8:00 PM - Desktop computer
- Types URL directly (direct traffic)
- anonymous_id: anon_desktop_456
- Logs in as user_789
- Completes purchase
```

**Without Identify:**

* Purchase attributed to "direct" (wrong!)
* Ad spend wasted

**With Identify:**

```javascript theme={null}
// User logs in on mobile
datalyr.identify('user_789');
// anonymous_id: anon_mobile_123 → user_id: user_789

// User logs in on desktop
datalyr.identify('user_789');
// anonymous_id: anon_desktop_456 → user_id: user_789

// Purchase attributed correctly to Meta ad!
```

DATALYR links both devices to `user_789` and attributes the purchase to the original Facebook ad.

## Session Tracking

Sessions track continuous user activity with 30-minute timeout.

### Session ID

**Format:**

```
sess_1727634645123_a1b2c3d4
```

**Components:**

* `sess_`: Prefix
* `1727634645123`: Timestamp (milliseconds)
* `a1b2c3d4`: Random identifier

**Storage:**

* Stored in localStorage (`dl_session_data`)
* Includes start time, last activity, page count, event count

### Session Lifecycle

**New Session Starts When:**

* First visit to site
* 30 minutes of inactivity
* Browser is closed and reopened (after timeout)

**Session Continues When:**

* User navigates between pages
* User is active (clicks, scrolls, etc.)
* Time since last activity is less than 30 minutes

**Session Ends When:**

* 30 minutes of inactivity
* User closes browser (eventually)
* `datalyr.reset()` is called

### Session Data

Each session stores:

```json theme={null}
{
  "id": "sess_1727634645123_a1b2c3d4",
  "startTime": 1727634645123,
  "lastActivity": 1727638245123,
  "pageCount": 5,
  "eventCount": 23
}
```

## Identity Resolution

DATALYR automatically links anonymous IDs to user IDs when you call `identify()`.

### How It Works

1. **Pre-Login:**
   ```
   anonymous_id: anon_abc123
   user_id: null
   distinct_id: anon_abc123
   ```

2. **User Identifies (Login/Signup):**
   ```javascript theme={null}
   datalyr.identify('user_456');
   ```

3. **Post-Login:**
   ```
   anonymous_id: anon_abc123 (unchanged)
   user_id: user_456
   distinct_id: user_456
   ```

4. **Identity Link Event Sent:**
   ```json theme={null}
   {
     "event_name": "$identify",
     "anonymous_id": "anon_abc123",
     "user_id": "user_456",
     "previous_id": null,
     "identified_at": "2025-09-29T10:30:45.123Z"
   }
   ```

5. **All Past Events Linked:**
   * DATALYR retroactively links all `anon_abc123` events to `user_456`
   * Complete journey from anonymous → identified
   * Attribution preserved across identification

## Cookie Storage

### Primary Cookie

**Name:** `__dl_visitor_id`

**Value:** Anonymous ID (`anon_...`)

**Attributes:**

* Domain: Root domain (e.g., `.example.com`)
* Path: `/`
* Max-Age: 31536000 (1 year)
* SameSite: `Lax`
* Secure: Yes (on HTTPS sites)

**Example:**

```
__dl_visitor_id=anon_f47ac10b-58cc-4372-a567-0e02b2c3d479; domain=.example.com; path=/; max-age=31536000; SameSite=Lax; Secure
```

### localStorage Backup

DATALYR also stores IDs in localStorage as a backup:

**Keys:**

* `dl_anonymous_id`: Anonymous ID
* `dl_user_id`: User ID (after identify)
* `dl_session_data`: Current session info

**Why Both Cookie and localStorage?**

* Cookie: Works across subdomains
* localStorage: Survives when cookies are blocked or deleted
* Fallback strategy ensures tracking continues

## Privacy and Compliance

### Opt-Out

Users can opt out of tracking:

```javascript theme={null}
// User opts out
datalyr.optOut();
```

This sets a cookie:

```
__dl_opt_out=true
```

All tracking stops. To opt back in:

```javascript theme={null}
datalyr.optIn();
```

### Do Not Track

DATALYR respects browser Do Not Track (DNT) settings by default:

**Respected Signals:**

* `navigator.doNotTrack === '1'`
* `navigator.globalPrivacyControl === true`
* `window.globalPrivacyControl === true`

To disable DNT respect:

```javascript theme={null}
datalyr.init({
  workspaceId: 'ws_123',
  respectDoNotTrack: false // Don't respect DNT
});
```

### GDPR Compliance

Clear user data on request:

```javascript theme={null}
// Remove user ID (keeps anonymous_id for analytics)
datalyr.reset();

// OR fully opt out
datalyr.optOut();
```

## Troubleshooting

**Visitor ID changes on every page load?**

Check that:

* Cookies are enabled in browser
* Third-party cookie blockers are disabled
* You're not in incognito/private mode
* Cookie domain is set correctly

**Cross-subdomain tracking not working?**

Verify:

* Both subdomains are on same root domain
* Cookie is set on root domain (check with DevTools)
* No cookie blockers interfering

**User ID not persisting?**

Check:

* `identify()` was called with a non-empty userId
* localStorage is available (not disabled)
* `reset()` wasn't called unintentionally

**Anonymous ID lost after browser restart?**

This means:

* Cookies were cleared by user
* Cookie didn't save properly (check domain)
* localStorage also cleared

## Next Steps

<CardGroup cols={2}>
  <Card title="Identity Calls" icon="user-plus" href="/understanding-data/identity-calls">
    Learn how to identify users
  </Card>

  <Card title="Events Overview" icon="bolt" href="/understanding-data/events-overview">
    Understand event tracking
  </Card>

  <Card title="Cross-Domain Tracking" icon="link" href="/understanding-data/cross-domain-tracking">
    Track across multiple domains
  </Card>

  <Card title="Attribution Models" icon="chart-network" href="/understanding-data/attribution-models">
    How attribution works
  </Card>
</CardGroup>

## Need Help?

Questions about visitor identification? Check our [troubleshooting guide](/troubleshooting/tracking-not-working) or contact support.
