Core Concepts
Shared vocabulary used across the dashboard, SDKs, and API. Read this once — every other doc page builds on these ideas.
Organization and project
Pug is multi-tenant. Your data always lives inside a project; projects belong to an organization.
Organization ← billing & member boundary
├── Members (roles)
└── Project ← data boundary
├── API keys (SDK + shared)
├── Events
├── Profiles
└── Dashboards| Concept | What it is | Scope |
|---|---|---|
| Organization | Team workspace with members and billing | All projects in the org |
| Project | Isolated analytics environment | Events, profiles, dashboards |
| API key | Credential for SDK or server integrations | Single project |
Every dashboard URL is prefixed with the active project: /p/:projectId/…. SDK requests include the project ID in the x-project-id header.
Event pipeline
When your app calls track(), the event travels through an async pipeline before it appears in analytics.
SDK (browser/app)
│ track('purchase', { revenue: 29.99 })
▼
EventsService.BatchCreate ← Connect RPC, API key auth
│
▼
NATS (message queue)
│
▼
Event workers ← geo, user agent, bot score enrichment
│
▼
ClickHouse ← analytics storage
│
▼
Dashboard & InsightsService ← queries, charts, KPIsTiming: 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 — see Profiles below.
Events
An event is a named occurrence with properties and a timestamp.
track('button_clicked', { label: 'Sign up', page: '/pricing' })- Event name — any string; well-known events have typed schemas
- Properties — arbitrary key-value pairs (strings, numbers, booleans)
- Auto-properties — SDK and server attach fields prefixed with
$(e.g.$url,$geo.country). See Auto-properties - Timestamp — defaults to client time; override for offline replay
Events are immutable once stored. Corrections require a new event or profile trait update.
Profiles
A profile represents a user — anonymous or identified.
Anonymous → identified flow
- Visitor lands on your site. SDK creates an anonymous profile tied to a device/session.
- Events accumulate against that anonymous ID.
- User signs in. You call
identify('user-123', { email: '…' }). - Prior anonymous events merge into the identified profile.
// Before sign-in — events are anonymous
track('page_view')
track('add_to_cart', { product_id: 'sku-123' })
// After sign-in — merges anonymous history
identify('user-123', { email: 'user@example.com', plan: 'pro' })
track('purchase', { revenue: 29.99, currency: 'USD' })Alias
Alias merges two profile IDs — useful when a user had separate anonymous sessions before and after signup, or when migrating from another system:
anonymous-id-abc ──alias──▶ user-123
pre-migration-id ──alias──▶ user-123Alias is server-side via ProfilesSDKService. See Profiles API.
Storage model
- Writes — async via NATS profile workers (identify, trait upsert, alias)
- Reads — ClickHouse (event-derived traits and history) + Postgres (soft-delete state)
- Expect a few seconds of lag between
identify()and profile appearing in search
Sessions
A session groups events within a single visit. SDKs manage session IDs automatically:
- New session on first event after timeout (default 30 minutes of inactivity)
- Session extended on each event within the window
- Web SDK syncs session ID across browser tabs via
localStorage
Force a new session without clearing identity: rotate(). Clear identity and session: reset().
Insights
An insight is a query specification — not a saved chart, but the definition of one:
| Field | Example |
|---|---|
| Events | page_view, purchase |
| Time range | Last 7 days |
| Granularity | Day |
| Aggregation | Unique users |
| Breakdown | $geo.country |
| Filters | plan = 'pro' |
The same insight model powers:
- Overview KPI tiles
- Insights ad-hoc queries
- Dashboard tiles
- InsightsService API queries
Example mental model — “daily unique purchasers by country”:
Events: purchase
Range: last 30 days
Granularity: day
Aggregation: unique users
Breakdown: $geo.countryDashboards
A dashboard is a saved grid of tiles. Each tile is either:
- Insight tile — bound to an insight query spec (line chart, KPI, funnel, etc.)
- Markdown tile — free-form notes, links, or runbook text
Dashboards are project-scoped. Tile changes use a full-reconcile upsert — the saved payload is the complete desired state.
Authentication modes
Pug has three auth boundaries. Pick the one that matches your integration:
| Mode | Used by | Access |
|---|---|---|
| JWT | Dashboard users | Read/write project data via UI |
| SDK API key | Client SDKs | Write events, identify |
| Shared key / JWT | Server integrations | Insights, profile reads |
Browser SDK ──▶ SDK API key ──▶ EventsService, ProfilesSDKService
Dashboard ──▶ JWT ──▶ DashboardsService, ProjectsService, OrgsService
Your server ──▶ Shared key ──▶ InsightsService, ProfilesServiceSee Authentication for headers and examples.
Further reading
- Authentication — headers, key types, Connect RPC setup
- Well-known events — typed event schemas
- Glossary — quick term lookup