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

js
// 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 $identify event carrying the ID as distinct_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 call reset.
  • Everything the browser did before, while anonymous, belongs to the same person.
  • $identify events 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.

auth.ts
// 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 identify on 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

auth.ts
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