Product analytics · 3 min read · Updated 2026-09-21

Visitors, sessions, and identify

Three ids doing three different jobs. Get them straight and every number downstream makes sense.

Every argument about whether an analytics number is right eventually turns out to be an argument about identity. “We had 4,000 users last week” — users, or browsers? Over what window? Before or after they logged in? Talaria uses three ids, and once you know what each one does, the numbers stop being mysterious.

The three ids

  • anonymousId — the visitor. A random id created the first time the SDK runs, stored first-party, and kept until something resets it. This is a browser or a device, not a person.
  • sessionId — the visit. A random id for one continuous stretch of activity. One visitor produces many sessions over time.
  • userId — the person. Only present after you call identify. This is your id from your database.

One visitor, three sessions, one person

storefront

production
  • Mon 09:02$pageviews_9d2…4eanonymous

    First visit. Visitor id created and stored first-party.

  • Mon 09:05add_to_carts_9d2…4eanonymous

    Same session — under 30 minutes since the last event.

  • Mon 11:40$pageviews_1b4…a8anonymous

    New session. Same visitor: the idle window expired.

  • Mon 11:42$identifys_1b4…a8user_123

    Signs in. Every later event carries the user id.

  • Tue 08:15$pageviews_66f…02user_123

    New UTC day, new session — still one unique person.

One visitor across two days: three sessions, an identify in the middle, and still a single unique person.

When a session rotates

A session ends and a new one begins on two triggers, whichever comes first:

  • 30 minutes without an event from that visitor.
  • A change of UTC calendar date, so a session never straddles midnight UTC.

The clock is touched on every capture, track, and pageview, so an active person keeps one session no matter how long they stay. Nothing expires mid-checkout.

What identify actually does

Calling identify does two things. It sends an $identify event with whatever traits you pass, and it sets the current user on the SDK — so every later analytics event, error, and span carries that user id too.

Typescript
// After your own sign-in completes:
Talaria.analytics.identify('user_123', { plan: 'team' });

// Everything after this point carries userId = 'user_123'
Talaria.analytics.track('project_created', { template: 'blank' });

It does not rewrite history. Events sent before the identify keep only the anonymous id. That is normal and usually fine — see the uniques rule below.

How uniques are counted

One rule, applied per event: use the user_id if the event has one, otherwise use the anonymous_id. Then count the distinct values over the window.

Two consequences worth internalising:

  • A person who browses anonymously and then signs in within the same window can count twice — once as a browser, once as a person. Identifying earlier narrows the gap.
  • The same person on a laptop and a phone counts once if they signed in on both, and twice if they did not.

Identity applies forward from the call, so earlier anonymous events keep their anonymous id. Call identify as early as your auth flow allows when exact de-anonymised counts matter.

Reset, and when to call it

Call reset on sign-out. It issues a brand-new anonymous id, starts a new session, and clears the user — so the next person on a shared machine is not counted as the last one.

Typescript
Talaria.analytics.reset();

On the server

Browsers and Flutter apps persist identity for you: the browser uses first-party localStorage, Flutter uses shared preferences. Server runtimes cannot, because one process handles everyone.

So in PHP, Node, and server-side Dart you pass the identity on each call — usually the anonymous id forwarded from the browser on your own API request. If you pass neither a user id nor an anonymous id, the event is skipped rather than being attributed to the wrong person.

Php
$talaria->analytics->track('order_completed', ['total' => 129.0], [
    'anonymousId' => $browserAnonymousId,
    'sessionId' => $browserSessionId,
]);

The ids live in first-party storage, not cookies. What that means for consent is covered in Privacy and consent.

Related guides

  • Product analytics · 4 min

    What product analytics actually is

    Error tracking tells you what broke. Product analytics tells you what people were trying to do — and how many of them gave up.

  • Product analytics · 3 min

    Events and properties

    Four kinds of call, one envelope, and a property bag you control. Naming is the only hard part.

  • Product analytics · 4 min

    Privacy and consent

    Analytics is the part of observability most likely to end up in a privacy review. Here is exactly what Talaria stores, and what it refuses to.

Turn analytics on

Enable analytics on a project, opt in from an official SDK, and your first funnel is minutes away.