Skip to Content
DocsQuickstartCore Concepts

Core Concepts

Shared vocabulary used across the SDKs, the API, and the dashboard. Read this once — every other page builds on these ideas.

Organization and project

Pug is multi-tenant. Your data always lives inside a project; projects belong to an organization. You only deal with these for billing and access — the things you actually instrument are events and profiles.

Organizationbilling & member boundary
Members (roles)
Projectdata boundary
API keys (public + private)
Events
Profiles
ConceptWhat it isScope
OrganizationTeam workspace with members and billingAll projects in the org
ProjectIsolated analytics environmentEvents, profiles, insights
Public key (pub_…)Client credential for SDKsSingle project
Private key (prv_…)Secret credential for your serversSingle project

The dashboard URL is prefixed with the active project: /p/<projectId>/….

Event pipeline

When your app calls track(), the event travels through an async pipeline before it appears in analytics.

SDK (browser / app)track('purchase', { productId: 'sku_123', amount: 29.99, currency: 'USD' })
sdk.events.v1.EventsService/BatchCreate
Connect RPC · x-api-key auth
NATS (JetStream queue)
Workers
geo · user-agent · bot-score enrichment
ClickHouse
analytics storage
Dashboard & shared.insights.v1
queries · charts · KPIs

Timing: ingestion is near-real-time. Events typically appear in Live within seconds and in Insights queries within the same minute. Profile writes are fully async, processed by profile workers.

Events

An event is a named occurrence with properties and a timestamp.

track('button_clicked', { label: 'Sign up', page: '/pricing' })
  • Event name (kind) — any string; well-known events have typed schemas. Names starting with pug. are reserved.
  • Custom properties — your key/value pairs (string, number, boolean, timestamp).
  • Auto-properties — fields prefixed with $ that the SDK and server attach automatically (e.g. $url, $browser, $country). $-prefixed keys are reserved — see Auto-properties.
  • Timestamp — defaults to send time; override per event for offline replay.

Events are immutable once stored. Corrections mean a new event or a profile-trait update.

Profiles

A profile represents a user — anonymous or identified.

Anonymous → identified

  1. A visitor arrives. The SDK creates an anonymous ID (anon-…) tied to the device.
  2. Events accumulate against that anonymous ID.
  3. The user signs in. You call identify('user-123', { email: '…' }).
  4. On that first identify, the SDK sends the anonymous ID alongside your external ID so the backend can merge the prior anonymous activity into the identified profile.
// Before sign-in — anonymous track('page_view') track('add_to_cart', { productId: 'sku_123' }) // After sign-in — merges anonymous history into the identified profile await identify('user-123', { email: '[email protected]', plan: 'pro' }) track('purchase', { productId: 'sku_123', amount: 29.99, currency: 'USD' })

Three ID terms recur across the SDKs and API:

IDWhat it isWhen used
Anonymous ID (anon-…)Device ID the SDK generatesBefore sign-in
External IDYour stable user ID, passed to identify()After sign-in
Distinct IDThe umbrella value stored on every eventAnonymous ID until identified, then external ID

Storage and timing

  • Writes (identify, trait updates, merges) are processed asynchronously by profile workers via NATS.
  • Expect a few seconds between an identify() call and the profile appearing in dashboard search.
  • Use a stable external ID (your database user ID), not something that changes like an email.

Sessions

A session groups events within a single visit. SDKs manage session IDs automatically:

  • A new session starts on the first event after the idle timeout (default 30 minutes of inactivity).
  • The session extends on each event inside the window, up to a max duration (default 24 hours).
  • The Web SDK syncs the session ID across browser tabs via localStorage.

Force a new session without clearing identity with rotate(). Clear identity and start fresh with reset().

Insights

An insight is a query specification — the definition of an analytics question, not a saved chart:

FieldExample
Eventspage_view, purchase
Time rangeLast 7 days
GranularityDay
AggregationUnique users
Breakdown$country
Filtersplan = 'pro'

The same insight model powers the dashboard’s charts and the shared.insights.v1.InsightsService API, which you can query from your own backend with a private key. Insight types include trends, funnels, retention, segmentation, user flow, and session metrics.

Authentication modes

Pug has three auth boundaries: the public key (pub_…) authenticates client SDKs, the private key (prv_…) authenticates your server, and a JWT authenticates the dashboard. See Authentication for the full matrix of headers, scopes, and examples.

Further reading

Last updated on