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
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 optionalRecord<string, unknown>of attributes that describe the user. Traits are sent with every event after this call.
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.
The identity object shape
The identity is stored internally as anIdentity type and embedded in each request payload:
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()
Callidentify() as soon as the user’s identity becomes known to your app:
1
After login
The user just authenticated. You now have a stable user ID to associate with future events.
2
After signup
A new account was just created. Identifying immediately links the first events (onboarding steps, feature tours) to the new user.
3
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.Sessions
Identity and session are separate. The session ID is a UUID generated for you and kept insessionStorage 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
Callreset() when the user logs out. It does five things:
- Flushes any pending events. They are delivered with the identity they were tracked under, never dropped.
- Clears the
userId(sets it back tonull) - Clears all traits (resets to
{}) - Removes the persisted identity from
localStorage - Generates a new session ID
reset(), any new events you track are anonymous until you call identify() again. They carry the new session ID but no user.
What happens to events tracked before identify()?
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.Can I call identify() multiple times?
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.