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

# Identifying Users

> Link analytics events to specific users so you can see what individual people do in your app — not just anonymous numbers.

## What is user identification?

By default, every event tracked by Analytiq is anonymous — you can see *that* a button was clicked, but not *who* clicked it.

`identify()` links all future events to a specific user. After you call it, every `track()` event is automatically tagged with that user's ID — so on the dashboard you can filter events by user, see a single user's journey, and understand your users individually.

***

## When to call identify()

Call `identify()` in exactly one place: **right after login or signup succeeds**.

```
User clicks Login button
  - Your API call succeeds
  - Call identify(user) here
  - User is redirected to dashboard
```

***

## Basic usage

```js theme={null}
import { identify } from 'analytiq'

// Pass any unique ID — usually user.id from your database
identify('user_abc123')
```

You can use:

* A database UUID or integer ID: `identify('550e8400-e29b-41d4-a716-446655440000')`
* An email address: `identify('john@example.com')` (only if emails are unique)
* Any unique string your system uses

***

## After signup

<Tabs>
  <Tab title="React / Next.js">
    If you used the `analytics.jsx` "One-File Setup" from the Quickstart, **you don't need to call identify manually.**

    When your user signs up successfully, your app's authentication state changes.
    The `useEffect` inside your `analytics.jsx` file detects the new user and calls `identify()` for you automatically.

    ```jsx components/Signup.jsx theme={null}
    import { track } from '../analytics.jsx'    // Import from your hub, not the package!

    async function handleSignup(email, password) {
      try {
        const response = await api.post('/auth/register', { email, password })
        
        // 1. Update your app's user state (triggers your analytics.jsx hook)
        setUser(response.data.user)

        // 2. Track the signup event manually
        track('signup_completed', { method: 'email' })
        navigate('/dashboard')

      } catch (error) {
        track('signup_failed', { reason: error.message })
      }
    }
    ```
  </Tab>

  <Tab title="Vue / Vanilla JS">
    ```js theme={null}
    import { track, identify } from 'analytiq'

    async function handleSignup(email, password) {
      const response = await api.post('/auth/register', { email, password })
      const user = response.data.user

      identify(user)
      track('signup_completed', { method: 'email' })

      router.push('/dashboard')
    }
    ```
  </Tab>
</Tabs>

***

## After login

<Tabs>
  <Tab title="React / Next.js">
    Just like signup, **you don't need to call identify manually.**

    When the login succeeds and you update your user state, the `useEffect` in your `analytics.jsx` file automatically fires `identify()`.

    ```jsx components/Login.jsx theme={null}
    import { track } from '../analytics.jsx'

    async function handleLogin(email, password) {
      const response = await api.post('/auth/login', { email, password })

      // Just update your auth state — your analytics.jsx handles identify!
      setUser(response.data.user)
      track('login_success')
      navigate('/dashboard')
    }
    ```
  </Tab>

  <Tab title="Vue / Vanilla JS">
    ```js theme={null}
    import { identify } from 'analytiq'

    async function handleLogin(email, password) {
      const response = await api.post('/auth/login', { email, password })
      identify(response.data.user)
      router.push('/dashboard')
    }
    ```
  </Tab>
</Tabs>

***

## When the user is already logged in (page refresh)

If your app keeps users logged in, you need to re-identify them when the app loads after a page refresh — otherwise events after a refresh won't be linked to their identity.

<Tabs>
  <Tab title="React / Next.js">
    **This is handled automatically.** When your app loads, your `useAuth` hook automatically fetches the user from local storage or cookies. Because that variable updates, the `useEffect` inside `analytics.jsx` runs again and successfully calls `identify()` automatically.
  </Tab>

  <Tab title="Vue / Vanilla JS (manual)">
    Call `identify()` when the app loads and the user is already logged in:

    ```js src/main.js theme={null}
    import { init, identify } from 'analytiq'

    init(import.meta.env.VITE_ANALYTIQ_KEY)

    // Re-identify if user is already logged in
    const savedUser = JSON.parse(localStorage.getItem('user') || 'null')
    if (savedUser) {
      identify(savedUser)  // SDK extracts id, _id, uid, or email automatically
    }
    ```
  </Tab>
</Tabs>

***

## Resetting on logout

When a user logs out, their identity must be cleared so the next person using the device doesn't inherit it.

<Tabs>
  <Tab title="React / Next.js">
    **This is handled automatically.** When you clear your user state, your auth hook becomes empty. The `useEffect` inside `analytics.jsx` detects this and automatically calls `reset()`.

    You do not need to call `reset()` manually inside your Logout button if you have the `analytics.jsx` file installed perfectly.
  </Tab>

  <Tab title="Vue / Vanilla JS">
    Call `reset()` manually right when the user logs out.

    ```jsx components/Header.jsx theme={null}
    import { reset } from 'analytiq'

    function handleLogout() {
      reset()              // always call this first
      navigate('/login')  // then redirect
    }
    ```
  </Tab>
</Tabs>

***

## How identity flows through events

After `identify()` is called, all subsequent `track()` calls are automatically linked:

```
identify('user_abc')
track('page_view', { page: 'Dashboard' })     // linked to user_abc
track('upgrade_clicked', { plan: 'pro' })     // linked to user_abc
track('purchase', { amount: 49 })             // linked to user_abc
reset()
track('page_view', { page: 'Landing' })       // anonymous again
```

***

## What NOT to do

| Don't                                       | Why                                                         |
| ------------------------------------------- | ----------------------------------------------------------- |
| `identify(user.email)` if emails can change | User gets new email, resulting in their history being split |
| `identify(user.name)`                       | Names aren't always unique                                  |
| Call `identify()` before login succeeds     | You might identify the wrong user                           |
| Skip `reset()` on logout                    | Next user inherits previous user's identity                 |

***

## Anonymous events before identify()

Any events tracked before `identify()` is called are stored anonymously. Once you call `identify()`, future events are linked — but past anonymous events remain anonymous. This is expected behavior.

***

## Tracking anonymous visitors (no login required)

If your app or website has users who **never log in** (a marketing landing page, a blog, a documentation site), `identify()` is never called naturally — and all events will have `userId = null`, meaning they won't appear in your Unique Users, DAU, or MAU counts.

The fix is to generate a **stable visitor ID** using `localStorage`. This creates a unique ID the first time someone visits, stores it in their browser, and reuses it on every future visit — all without requiring any login.

<Tabs>
  <Tab title="React / Next.js">
    Add this to your `analytics.jsx` provider file, **before** or **alongside** the `useAuth` identify logic:

    ```jsx src/analytics.jsx theme={null}
    import { Analytiq, identify, reset, track } from 'analytiq/react'
    import { useEffect } from 'react'
    import { useAuth } from './context/AuthContext'

    // Generate a stable anonymous visitor ID
    function getVisitorId() {
      let id = localStorage.getItem('_visitor_id')
      if (!id) {
        id = crypto.randomUUID()
        localStorage.setItem('_visitor_id', id)
      }
      return id
    }

    export function AnalyticsProvider({ children }) {
      const { user } = useAuth()

      useEffect(() => {
        if (user) {
          identify(user)          // Logged-in user: use their real identity
        } else {
          identify(getVisitorId()) // Anonymous visitor: use stable browser ID
        }
      }, [user])

      return (
        <>
          <Analytiq apiKey={import.meta.env.VITE_ANALYTIQ_KEY} />
          {children}
        </>
      )
    }

    export { track }
    ```
  </Tab>

  <Tab title="Vue 3">
    Add this to your `src/main.js`, right after `init()`:

    ```js src/main.js theme={null}
    import { init, identify } from 'analytiq'

    init(import.meta.env.VITE_ANALYTIQ_KEY)

    // Identify every visitor — logged in or not
    function getVisitorId() {
      let id = localStorage.getItem('_visitor_id')
      if (!id) {
        id = crypto.randomUUID()
        localStorage.setItem('_visitor_id', id)
      }
      return id
    }

    identify(getVisitorId())

    // Later, after login, override with the real user:
    // identify(user)
    ```
  </Tab>

  <Tab title="Vanilla HTML / JS">
    Add this to your main `<script>` block right after `analytiq.init()`:

    ```html index.html theme={null}
    <script>
      analytiq.init('pk_live_YOUR_KEY_HERE')

      // Identify every visitor — logged in or not
      let visitorId = localStorage.getItem('_visitor_id')
      if (!visitorId) {
        visitorId = crypto.randomUUID()
        localStorage.setItem('_visitor_id', visitorId)
      }
      analytiq.identify(visitorId)
    </script>
    ```
  </Tab>
</Tabs>

<Note>
  **How this works:** `crypto.randomUUID()` generates a unique ID (like `"f47ac10b-58cc-4372-a567-0e02b2c3d479"`) the very first time someone visits. It is saved in `localStorage` so future visits by the same person reuse the same ID — giving you accurate repeat visitor counts.
</Note>

<Warning>
  This visitor ID is **device and browser specific**. If the same person visits from Chrome and Safari, they will appear as two different visitors. This is expected for anonymous tracking — it is the same behavior used by most analytics platforms for unauthenticated users.
</Warning>

| Scenario                    | What happens                                                                        |
| --------------------------- | ----------------------------------------------------------------------------------- |
| First visit, no login       | New visitor ID generated → DAU and Unique Users count this visitor                  |
| Return visit, no login      | Same visitor ID reused → recognized as the same visitor                             |
| User logs in after browsing | `identify(user)` overrides the visitor ID → events now linked to their real account |
| User logs out               | Back to visitor ID → browsing continues tracked anonymously                         |
