// context projectglobal

Identity & Sessions

Every web event includes three identifiers:

  • visitor_id — a stable UUID that persists across visits (~1 year). Identifies a browser, not a person.
  • session_id — a UUID that resets after 30 minutes of inactivity. Used for funnels, “sessions per visitor” metrics.
  • user_id — your application’s user ID, attached only when you call Loguro.identify(...). Lets you join analytics back to your auth database.

Visitor ID

Generated on first event of a fresh browser. Stored in localStorage by default under the key loguro_v. Survives:

  • Tab close, browser restart
  • Going to a different domain and coming back (same origin = same key)
  • App reinstall (no — localStorage is cleared)

Does not survive:

  • Different browser
  • Private / incognito window
  • User clears site data
  • Loguro.reset() call

Storage strategies

data-analytics-id-storage="localStorage"    <!-- default -->
data-analytics-id-storage="cookie"          <!-- cross-subdomain -->
data-analytics-id-storage="memory"          <!-- per-tab, never persists -->

localStorage (default)

Per-origin storage. Simple, fast, doesn’t show up in browser cookie listings (less consent-banner pressure). Use this unless you specifically need cross-subdomain.

cookie

Use when you have multiple subdomains (www.acme.com + app.acme.com) and want a single visitor identity across them:

data-analytics-id-storage="cookie"
data-analytics-domain=".acme.com"

The leading . makes the cookie valid across all subdomains. Cookie attributes: Path=/, SameSite=Lax, 1-year expiry.

memory

A fresh visitor_id per tab load. Useful for sites with strict privacy requirements where any persistence is unacceptable (or for testing). Reduces visitor analytics to mostly useless — only session-level data makes sense.

Session ID

A new session starts on the first event of a fresh browser. Each subsequent event refreshes lastSeen. After 30 minutes without any event, the next one starts a new session.

This means:

  • Typical user (active browsing): 1 session per visit
  • User who tabs away for an hour and comes back: 2 sessions
  • User who reads a long article without clicks or scroll events: session might expire mid-read

If you want to count “engaged time” in long articles, send a heartbeat event every 5 minutes:

setInterval(() => {
  window.Loguro.track('article_heartbeat', { article_id: '...' });
}, 5 * 60 * 1000);

User ID

Optional. Set it whenever you have one — typically right after login:

window.Loguro.identify('user_42');

From that point forward, every event includes user_id: "user_42". Past events are not retroactively updated — they remain anonymous (only visitor_id + session_id). This is intentional: events live in immutable Parquet storage.

With traits

window.Loguro.identify('user_42', {
  plan: 'pro',
  signed_up_at: '2025-11-10',
  team_id: 'team_acme'
});

If traits are provided, a custom event called identify is fired with those traits. Useful for tracking plan changes, role updates, etc.

Persistence

By default user_id is in-memory only — set fresh on every page load. This is the safe default: if your user logs out by closing the tab, the next visitor on the same browser doesn’t inherit the previous identity.

Opt into persistence:

data-analytics-persist-user="true"

Now user_id survives reloads. Useful for SPAs that don’t reload between auth boundaries, but make sure you call Loguro.reset() on logout.

Logout flow

function logout() {
  // Your auth cleanup
  await api.logout();
  localStorage.removeItem('auth_token');

  // Reset analytics identity
  window.Loguro.reset();

  // Optional: redirect
  window.location.href = '/';
}

Loguro.reset() wipes:

  • visitor_id (generates a new one on next event)
  • session_id
  • user_id
  • Cookie identity (if id-storage="cookie")

The next pageview belongs to a brand-new visitor with no link to the previous one.

When identify() should be called

ScenarioCall identify() here
User logs inRight after successful auth
User signs upAfter account creation, before redirect to onboarding
App initializes with existing session (cached auth token)On every page load if you already know who they are
User upgrades planCall identify() again with updated traits
User logs outCall Loguro.reset(), not identify(null)

Wire shape — full

A custom event after identify() looks like:

{
  "event_type": "custom",
  "custom_event_name": "subscription_upgraded",
  "url": "https://app.acme.com/billing",
  "path": "/billing",
  "visitor_id": "01HZ7XK4N8...",
  "session_id": "01HZ7XK4P2...",
  "user_id": "user_42",
  "custom_props": { "new_plan": "pro", "old_plan": "starter" },
  "timestamp": "2026-05-14T10:00:00.000Z"
}

Privacy notes

  • IP and User-Agent are never sent in the body — they’re extracted server-side from request headers. The server uses them for geo + device parsing, then discards them.
  • We do not fingerprint. No canvas, no audio, no WebGL, no installed fonts.
  • visitor_id is a UUID, not derived from any user signal. Random per browser.

See Privacy & Consent for GDPR, DNT, cookie-consent flows.

Next

// related

See also