Tracking

What Clamp captures on its own, and what you can add. Pageviews, sessions, and engagement for free. Custom events and Money on Pro.

What’s captured automatically

Every pageview is enriched on our servers with the dimensions below. No extra code, no extra config, all available on the free plan and filterable in every chart, funnel, and MCP query.

CategoryFields
Pageurl, pathname, referrer, referrer_host
Attributionutm_source, utm_medium, utm_campaign, utm_content, utm_term, channel (direct, organic_search, organic_social, paid, email, referral)
Devicedevice_type (desktop, mobile, tablet, bot), browser, browser_version, os, os_version, screen_width, screen_height, language
Geocountry, region, city (from IP, IP itself is never stored)
SessionPer-tab session ID, bounce rate, engagement_seconds (visible time only), rotates after 30 min idle
Identityanonymous_id (no cookies, daily-rotating fingerprint)

The SDK fires on initial load, history.pushState, replaceState, popstate, and bfcache restore, so SPAs work without extra setup. localhost and 127.0.0.1 are skipped by default so dev traffic never lands in your charts.

See Engagement for how visible time and bounce rate are measured.

Custom events Pro

Custom events require a Pro or Growth plan. On the free plan, track() calls are accepted by the SDK but dropped at ingest. Pageviews, sessions, and engagement keep working for everyone. See pricing.

Track any action with track(name, properties?). Properties are a flat map of strings to strings (or Money values — see below).

app.ts
import { track } from "@clamp-sh/analytics"

track("signup", { plan: "pro", source: "pricing_page" })
track("feature_used", { name: "csv_export" })
track("invite_sent", { role: "editor", team: "acme" })

Calls made before init() are queued and flushed after init runs. See Properties for naming rules and limits.

Typed events

Declare your event map once and get autocomplete and type checking on every track() call. Zero runtime cost.

analytics.ts
import { init, track } from "@clamp-sh/analytics"

type Events = {
  signup: { plan: string; source: string }
  purchase: { amount: string; currency: string }
  feature_used: { name: string }
}

init<Events>("proj_xxx")

track("signup", { plan: "pro", source: "homepage" })   // ✓ autocomplete
track("signup", { wrong: "field" })                     // ✗ type error
track("unknown_event")                                  // ✗ type error

Money properties

Any property whose value is a Money object becomes a queryable revenue field. Attach total, mrr, tax, anything, and get_revenue aggregates them over any cohort.

Browser
import { track } from "@clamp-sh/analytics"

track("checkout_completed", {
  plan: "pro",
  total: { amount: 348.00, currency: "USD" },
})

See Revenue for the full pattern: refunds, mixed currencies, and server-side tracking for authoritative numbers.

Property limits

ConstraintLimit
Max keys per event20
Key length128 chars
Value length512 chars
Payload size64 KB

Properties are flat. Nested objects (other than Money), arrays, and non-string values are rejected at ingest.