Identify people
Every visitor starts anonymous. Call identify when someone signs in and their past and future events, on this device and others, come together as one person.
Updated
Anonymous until identified
On a visitor’s first page load the tracker creates a random ID for the browser (per_…) and keeps it in local storage, along with a session ID. Every event carries both. ClickClacks never sets a cookie and never guesses who someone is from their IP address or device, so an anonymous visitor stays anonymous until you say who they are.
Call identify at sign-in
// After sign-in, with the stable ID your own system uses for this user
window.clickclacks('identify', 'user_4821', {
plan: 'pro',
company: 'Acme',
signed_up_at: '2026-09-01',
})- The ID is a string of 1 to 128 characters. Use your own stable user ID, such as a database primary key, not an email address that might change.
- It records an
$identifyevent carrying the ID asdistinct_id, plus any traits you pass. - The ID is saved in the browser, so every later event from that browser carries it as
$distinct_id, across reloads, until you callreset. - Everything the browser did before, while anonymous, belongs to the same person.
$identifyevents are free: they don’t count toward your monthly events.
Calling it again with the same ID is harmless, so it’s fine to call on every page load while someone is signed in. That also covers people who were already signed in before you added ClickClacks.
// For example, where your app learns who is signed in
async function onSignedIn(user: { id: string, plan: string }) {
window.clickclacks?.('identify', user.id, { plan: user.plan })
}
// And on each page load while they stay signed in ($identify events are free)
if (currentUser) {
window.clickclacks?.('identify', currentUser.id)
}Traits
The object you pass to identify describes the person: plan, company, role. A person’s traits are read from their newest $identify, so sending a new value replaces the old one.
- The same rules as event properties apply: a plain object, 2 KB of JSON at most. Over that, only the ID is sent.
- Keep personal data to what you need. An email or name is fine as a trait if your team needs it in People; a password or payment detail never is.
- Properties on ordinary events describe the event, not the person. Use traits for “who they are now”.
Across devices
identify is also the cross-device call; there’s no separate linking command. The first browser to identify with an ID owns it. When a different browser later identifies with the same ID (a phone after a laptop, say), ClickClacks links it to that person, and its anonymous history comes along.
A browser that already belongs to one ID isn’t moved to another. That’s why reset on sign-out matters: it gives the next person on a shared computer a fresh browser ID instead of the last user’s. If two records for one person were never joined, you can merge them by hand: open one in People and choose Merge with… from the profile’s menu. Merges can be undone.
Across domains
Browsers keep local storage separate for every hostname, so the ID you set on acme.com isn’t visible on app.acme.com. Two things join them:
- Links between listed domains carry the anonymous ID and session, so a visitor who clicks from your site into your app arrives as the same person. Domains and identity explains how.
- Calling
identifyon each domain where the person is signed in. The identified ID itself doesn’t travel with the link.
With your backend
Server events join the same people when they use the same ID. Send the ID you pass to identify in the browser as distinct_id from your server, and the events land on that person’s timeline. If the server sees an ID before any browser has identified with it, ClickClacks creates the person, and the browser joins them at its first identify. Identity from the server has the details, including attaching a server event to a specific browser.
Reset on sign-out
async function signOut() {
await fetch('/api/sign-out', { method: 'POST' })
window.clickclacks?.('reset')
}reset forgets the identified ID, drops any events not sent yet, and starts a new anonymous ID and session. Tracking carries on, as a new visitor. It’s also available as window.clickclacks.reset().
To stop tracking someone altogether, reset is the wrong tool: opt them out instead.
Next steps
- Domains and identity: one person from your marketing site into your app.
- Identity from the server: identify and track from your backend.
- Consent and opt-out: when someone says no.