Analytics SDK for Clamp, agentic analytics your coding agent can read, query, and act on. Track pageviews, custom events, and server-side actions. No cookies, no personal data collected, no consent banner required.
npm install @clamp-sh/analyticsimport { init, track, getAnonymousId } from "@clamp-sh/analytics"
init("proj_xxx")
// Custom events
track("signup", { plan: "pro" })
// Get visitor ID (for linking server-side events)
const anonId = getAnonymousId()After init(), pageviews are tracked automatically, including SPA navigations.
import { Analytics } from "@clamp-sh/analytics/react"
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Analytics projectId="proj_xxx" />
</body>
</html>
)
}Add to your root layout. Pageviews are tracked automatically. Use track() from @clamp-sh/analytics anywhere in your app for custom events.
import { init, track } from "@clamp-sh/analytics/server"
init({ projectId: "proj_xxx", apiKey: "sk_proj_..." })
await track("account_created", {
anonymousId: "anon_abc123",
properties: { plan: "pro" },
})Server events require an API key (found in your project settings).
<script src="https://cdn.jsdelivr.net/npm/@clamp-sh/analytics@0.2.0/dist/cdn.global.js"></script>
<script>
clamp.init("proj_xxx")
</script>Track any action with track(name, properties). Properties are flat string key-value pairs.
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" })On the server:
import { track } from "@clamp-sh/analytics/server"
await track("subscription_created", {
anonymousId: "anon_abc123",
properties: { plan: "pro", interval: "monthly" },
})Pageviews are tracked automatically. Everything else goes through track().
Define your event map once and get autocomplete and type checking across your app. Zero runtime cost.
type Events = {
signup: { plan: string; source: string }
purchase: { amount: string; currency: string }
feature_used: { name: string }
invite_sent: { role: string }
}
init<Events>("proj_xxx")
track("signup", { plan: "pro", source: "homepage" }) // autocomplete
track("signup", { wrong: "field" }) // type error
track("unknown_event") // type errorWorks the same way with the server SDK:
import { init, track } from "@clamp-sh/analytics/server"
init<Events>({ projectId: "proj_xxx", apiKey: "sk_proj_..." })
await track("purchase", {
properties: { amount: "49", currency: "usd" },
})Event properties are flat string → string maps. Nested objects, arrays, and non-string values are rejected.
| Constraint | Limit |
|---|---|
| Max keys | 20 |
| Key length | 128 chars |
| Value length | 512 chars |
| Payload size | 64 KB |
Log every tracked event, pageview, and flush to the browser console.
init("proj_xxx", { debug: true })Or with React:
<Analytics projectId="proj_xxx" debug />Console output looks like:
[clamp] Initialized { projectId: "proj_xxx", endpoint: "https://api.clamp.sh", ... }
[clamp] track: pageview {}
[clamp] track: signup { plan: "pro" }
[clamp] flush: 2 event(s)
Disable before deploying to production.
track("signup", { plan: "pro", source: "pricing_page" })track("feature_used", { name: "csv_export" })<button onClick={() => track("cta_clicked", { label: "Get started", page: "/pricing" })}>
Get started
</button>Pass the anonymous ID from the browser to your API, then include it in server-side events to connect the two.
// Browser: send anonymous ID with your API call
const anonId = getAnonymousId()
await fetch("/api/checkout", {
method: "POST",
body: JSON.stringify({ plan: "pro", anonId }),
})// Server: include it in the event
await track("checkout_completed", {
anonymousId: req.body.anonId,
properties: { plan: "pro", amount: "49" },
})function ContactForm() {
const handleSubmit = (e: FormEvent) => {
e.preventDefault()
track("form_submitted", { form: "contact", page: location.pathname })
}
return <form onSubmit={handleSubmit}>...</form>
}// app/layout.tsx
import { Analytics } from "@clamp-sh/analytics/react"
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Analytics projectId="proj_xxx" />
</body>
</html>
)
}
// app/pricing/page.tsx (client component)
"use client"
import { track } from "@clamp-sh/analytics"
export default function Pricing() {
return (
<button onClick={() => track("plan_selected", { plan: "growth" })}>
Choose Growth
</button>
)
}// app/actions.ts
"use server"
import { track } from "@clamp-sh/analytics/server"
export async function createTeam(name: string, anonId: string) {
const team = await db.teams.create({ name })
await track("team_created", {
anonymousId: anonId,
properties: { team_id: team.id },
})
return team
}import express from "express"
import { init, track } from "@clamp-sh/analytics/server"
init({ projectId: "proj_xxx", apiKey: "sk_proj_..." })
const app = express()
app.post("/api/subscribe", async (req, res) => {
await track("subscription_started", {
anonymousId: req.body.anonId,
properties: { plan: req.body.plan },
})
res.json({ ok: true })
})MIT