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

# Identity: identify() and reset()

> How identify() ties events to a user, what traits ride along on every event, and how sessions and reset() fit together.

Until you say otherwise, events are anonymous and carry only a generated session ID. Once you know who the user is, call `identify()` and every event after that carries their user ID and traits. The session's earlier anonymous events are linked to that user at query time too, so a funnel counts the whole journey as one person. The identity is saved in `localStorage` and restored by `init()`, which means a returning visitor is still identified until you call `reset()` on logout.

## Identifying a user

```ts theme={null}
Wendung.identify(userId: string, traits: Record<string, unknown> = {})
```

* **`userId`**: a string that uniquely identifies the user in your system. Use a stable, non-PII identifier like a database ID or UUID.
* **`traits`**: an optional `Record<string, unknown>` of attributes that describe the user. Traits are sent with every event after this call.

Each call replaces the identity wholesale. Traits are never merged: calling `identify('user_42', {})` wipes previously set traits, so pass the complete trait set every time. Traits are deep-cloned at call time, so mutating the object afterwards has no effect.

```ts theme={null}
Wendung.identify('user_42', {
  email: 'alice@example.com',
  name: 'Alice Nguyen',
  plan: 'pro',
  source: 'google_ads',
})
```

<Warning>
  Traits are included in **every event payload**, not just at the moment you call `identify()`. Avoid putting sensitive PII (passwords, card numbers, government IDs) in traits.
</Warning>

## The identity object shape

The identity is stored internally as an `Identity` type and embedded in each request payload:

```ts theme={null}
type Identity = {
  userId: string | null
  traits?: Record<string, unknown>
}
```

Before `identify()` is called, `userId` is `null` and `traits` is an empty object `{}`. After calling `identify()`, both fields reflect the values you provided.

## When to call identify()

Call `identify()` as soon as the user's identity becomes known to your app:

<Steps>
  <Step title="After login">
    The user just authenticated. You now have a stable user ID to associate with future events.

    ```ts theme={null}
    async function handleLogin(credentials) {
      const user = await authService.login(credentials)
      Wendung.identify(user.id, { email: user.email, plan: user.plan })
    }
    ```
  </Step>

  <Step title="After signup">
    A new account was just created. Identifying immediately links the first events (onboarding steps, feature tours) to the new user.

    ```ts theme={null}
    async function handleSignup(form) {
      const user = await authService.signup(form)
      Wendung.identify(user.id, { email: user.email, source: form.referral })
    }
    ```
  </Step>

  <Step title="On page load when the session is already authenticated">
    `init()` restores the saved identity, so a returning visitor is already identified. Re-identifying after you check your auth session is still worth it. It keeps traits fresh and covers users whose browser storage was cleared.

    ```ts theme={null}
    Wendung.init({ apiKey: '...' })

    const session = await getSession()
    if (session?.user) {
      Wendung.identify(session.user.id, { plan: session.user.plan })
    }
    ```
  </Step>
</Steps>

## Sessions

Identity and session are separate. The **session ID** is a UUID generated for you and kept in `sessionStorage` under `@wendung/sdk/session/v1`, so it survives reloads in the same tab. Every event carries it; you never manage it yourself.

A session ends, and a new ID starts, after 30 minutes without activity, after 24 hours in total, when you call `reset()`, or when `identify()` names a different user than the current one (an account switch without a logout). The first `identify()` in an anonymous session keeps the session. That is what makes the earlier anonymous events attributable to the user.

## Resetting identity on logout

Call `reset()` when the user logs out. It does five things:

1. Flushes any pending events. They are delivered with the identity they were tracked under, never dropped.
2. Clears the `userId` (sets it back to `null`)
3. Clears all traits (resets to `{}`)
4. Removes the persisted identity from `localStorage`
5. Generates a new session ID

```ts theme={null}
async function handleLogout() {
  await authService.logout()
  Wendung.reset()
}
```

After `reset()`, any new events you track are anonymous until you call `identify()` again. They carry the new session ID but no user.

<AccordionGroup>
  <Accordion title="What happens to events tracked before identify()?">
    They are sent with `userId: null` and linked at query time to the first user identified in that session. Funnels, user stats, and journeys count the anonymous prefix and the identified tail as one person, with nothing for you to stitch. Events in sessions where nobody ever identifies stay anonymous.
  </Accordion>

  <Accordion title="Can I call identify() multiple times?">
    Yes. Each call replaces the current `userId` and `traits` entirely. Re-identifying the same user (for example after a plan upgrade) keeps the session; identifying a different user starts a new session so the two users' events stay separate. Include all traits on every call.
  </Accordion>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.