Visitors
A visitor is the persistent identity of a browser/device, independent of whether you've called identify(). It survives reloads, tab closures, and "log out" flows.
Visitor ID
A random ID minted the first time the SDK runs, stored in localStorage under a namespaced key:
localStorage["galacha:visitor_id"] = "v_01HK8Z2M7F..."On every subsequent page load, the SDK reads it back, so the same browser always reports the same visitor ID.
Read it at runtime:
const { visitorId } = useGalacha();
// => "v_01HK8Z2M7F3Y4Q9R3B7KJX5PM2"Anonymous by default
You do not need to call identify() for a session to be recorded. The SDK captures every visitor, even if they never log in. Anonymous sessions appear in the dashboard with no user label.
<GalachaProvider projectKey="..." />
// Visitor recording starts immediately. No identify needed.When the user eventually logs in, call identify() (or use useIdentify()) and the current session gets tagged with that identity. Past anonymous sessions under the same visitor ID stay linked.
When a visitor ID changes
| Event | New visitor ID? |
|---|---|
| Page reload | No |
| Close + reopen tab | No |
| Close + reopen browser | No |
| Private/incognito window | Yes (separate localStorage) |
| Different device | Yes |
| User clears browser storage | Yes |
You call stop() then reload | No (visitor ID persists) |
| Logout | No (visitor ID is not user identity) |
Visitor vs User
Two different concepts:
| Visitor | User | |
|---|---|---|
| Scope | Browser/device | Your auth system |
| Set by | SDK automatically | You, via identify() |
| Changes when | Storage clears | You call identify() with a different ID |
| Persistent? | Yes (localStorage) | Yes (linked to visitor) |
A single visitor can be associated with multiple users over time (shared computer). The dashboard lets you filter by either.
Multi-domain / cross-subdomain
localStorage is per-origin. If your app spans multiple origins (app.example.com and billing.example.com), you'll get different visitor IDs for each. There's no cross-origin linking in the public SDK yet.
Workaround: call identify() with the same user ID on both. The dashboard then groups by user, not visitor.