# Identify users and groups (/docs/getting-started/identify)

Before login, the browser SDK tracks each visitor under a random anonymous id. `identify` tells Datahop who they are. Everything they did before (the ad they clicked, the pricing page, the cart they built) then belongs to that user, on every device they use.

## Identify on login [#identify-on-login]

Call `identify` right after sign-up and login, and on page load when the user is already signed in:

```ts title="after login"
if (user?.id) {
  datahop.identify(user.id, { email: user.email, name: user.name, plan: user.plan })
}
```

- Use a **stable id from your database**, not an email address. People change their email, so put it in a property.
- Use the **same id everywhere**: browser, backend and mobile web.
- Calling it on every page load is fine.

## Reset on logout [#reset-on-logout]

```ts title="on logout"
datahop.reset()
```

This starts a fresh anonymous visitor. Without it, the next person on a shared computer would be tracked as the previous user.

<Callout type="info" title="Two users are never merged">
  Datahop never combines two people who have both been identified. If a shared laptop or a bug calls `identify` with the wrong id, two existing customers won't get glued together. Datahop also ignores placeholder ids such as `"undefined"`, `"null"`, `"anonymous"` and `"0"`.
</Callout>

## Person properties [#person-properties]

Properties describe the person: `email`, `plan`, `company_size`, `lifetime_orders`. Pass them to `identify`, or update them later:

```ts
datahop.identify(user.id, { plan: 'pro' }, { signup_source: 'google' })
//                         ↑ always overwritten  ↑ only set the first time
datahop.setPersonProperties({ plan: 'business' })
```

Filters and breakdowns on a person property use the person's **current** value. If someone upgraded to `pro` yesterday, all their past events count as `pro`. To analyse "what plan were they on when they did this", also put `plan` on the event.

## Backend events [#backend-events]

Use your user id directly:

```ts title="billing-webhook.ts"
datahop.capture({ distinctId: user.id, event: 'subscription_renewed', properties: { amount: 29 } })
```

If your server creates the account, send the browser's anonymous id with the sign-up request and identify on the server, so the visits before sign-up are linked too:

```ts title="browser"
await fetch('/api/signup', { method: 'POST', body: JSON.stringify({ ...form, anonId: datahop.getDistinctId() }) })
```

```ts title="server"
datahop.identify({ distinctId: user.id, anonDistinctId: body.anonId, properties: { email: user.email } })
```

## Groups: companies, workspaces, teams [#groups-companies-workspaces-teams]

In B2B products the customer is an account, not a person. Groups let you count active companies, measure activation per account and roll features out to whole teams.

```ts title="browser, after identify"
datahop.group('company', org.id, { name: org.name, plan: org.plan, seats: org.seats })
```

Every later event from this browser is attached to that company, until `resetGroups()` or `reset()`. Call `group` again with a new key when the user switches account. You can use several group types at once, for example `company` and `workspace`.

On the server, pass groups per event and keep group properties up to date:

```ts title="server"
datahop.capture({ distinctId: user.id, event: 'report_exported', groups: { company: 'acme' } })
datahop.groupIdentify({ groupType: 'company', groupKey: 'acme', properties: { plan: 'business', seats: 55 } })
```

<Callout type="warn" title="Up to five group types per project">
  Pick group types deliberately. One or two (`company`, maybe `workspace`) is usually enough. Once five exist, a sixth type isn't tracked.
</Callout>

## Check that it works [#check-that-it-works]

Open **People → Persons** and search for the user's email or id. An identified person has an **identified** badge, and their timeline includes their anonymous visits from before sign-up. Each group type gets its own page under **People**, for example **Companies**.
