A client learned which user it belongs to. Written only when you say so.
| Field | Value |
|---|---|
| Name | identify |
| Severity | 9 (INFO) |
| Written by | Every SDK, on user(). Not the browser tag. |
When you call user() with an id. The entry exists so the id lands on a row immediately instead of waiting for the next thing that happens to be recorded, and from then on user.id rides on everything the client sends.
Naming a different person also replaces the session id, because a sign-in is a boundary and one session spanning two accounts belongs to neither. Naming the same person again does nothing at all, so a router may call it on every route change.
Calling it with null writes nothing. There is no entry meaning somebody stopped being somebody: the client simply goes back to anonymous, keeping any device.id, because that belongs to the machine rather than to whoever signed in.
The browser tag does not write this entry. Its user() sets user.id for the rest of the page and nothing else, and the id is never written to storage: it is your data about a signed-in person, and persisting it would put a second identifier on a visitor's disk that nobody answered a consent banner about.
| Attribute | Type | What it holds |
|---|---|---|
| user.id | string | Exactly the string you passed, clamped to the length limit. It rides on this entry and on every later one. |
Every entry also carries the resource its client sends once per batch: session.id, user.id once you have called user(), and the rest of the list on the overview. Anything you pass yourself lands in the same map, and your key wins on a collision.
Nothing is inferred, derived, looked up or merged. A user id is only ever the string you handed over. There is no probabilistic matching, no IP or fingerprint heuristic, and no cross-surface resolution anywhere in this product.
Two sources in one project are not linked to each other. The same person on your site and in your app is two uniques, and that is the correct answer. If you want them joined, call user() with the same id on both: your data, your decision, not something we reconstruct from behaviour.
Naming somebody does not rewrite history. Entries already written keep whatever identity they had; nothing is back-filled, and nothing records what the id was before.
A widget is a filter, a group by, an aggregate, a time bucket and a limit. These are those five parts written out, and every one of them is something you can build yourself.
| Question | The query |
|---|---|
| How many people signed in | Name is identify . count of uniques . bucket by week |
| Sign-ins over time | Name is identify . count of entries . bucket by day |
| Whether one account is active | user.id is acct_8812 . count of entries . bucket by day |