Reference
API reference
Every endpoint the analytics script talks to, and how to call them yourself from a server or a custom integration.
Authentication
There are two keys per project:
- Public key: a UUID. Safe to embed in client HTML. Used for
/trackand/experiments/active. - Secret key: generate and rotate from Settings. Required for
/server-events. Never ship to the browser.
Rotating a secret key
Old keys keep working for 24 hours after rotation, so you have a window to redeploy.Endpoints
| Method | Path | Auth | Purpose |
|---|---|---|---|
| GET | /api/analytics/script.js?projectId=… | Public | Serve tracking script. |
| POST | /api/analytics/track | Public | Submit batched client events. |
| POST | /api/analytics/server-events | Secret | Submit a single server event with idempotency. |
| GET | /api/analytics/experiments/active | Public | Fetch experiments for the script. |
Track event payload
POST /api/analytics/track accepts a batch of events. Events are deduped server-side on (visitorId, timestamp, eventType, pathname).
interface TrackRequest {
projectId: string; // your public key
events: TrackEvent[];
}
interface TrackEvent {
eventType: "pageview" | "scroll" | "engagement" | "conversion"
| "experiment_impression" | string;
eventName?: string; // e.g. "signup", "purchase"
eventData?: Record<string, unknown>;
pathname: string;
fullUrl: string;
referrer?: string;
sessionId: string;
visitorId: string;
timestamp: number; // epoch ms
utm?: {
source?: string;
medium?: string;
campaign?: string;
term?: string;
content?: string;
};
}Server event payload
POST /api/analytics/server-events accepts one event at a time. Authenticate with your project's secret key in the Authorization header. Pass experimentId + variantId when you want the conversion attributed to an A/B experiment variant.
interface ServerEventRequest {
eventType: string; // e.g. "conversion"
eventName: string; // e.g. "signup", "purchase"
timestamp?: string; // ISO 8601 — defaults to ingestion time
idempotencyKey?: string; // stable key for retry dedup (Stripe event ID, etc.)
visitor?: {
id?: string; // any stable anonymous ID (user ID, gmp_vid, hashed email)
ip?: string;
userAgent?: string;
};
page?: string; // pathname to attribute the event to
properties?: Record<string, unknown>;
// Optional: attribute this conversion to an A/B experiment variant.
// Grab both from window.grademypage.getExperimentAssignments() on the
// browser and forward them through your backend to this endpoint.
experimentId?: string;
variantId?: string;
}Active experiments response
GET /api/analytics/experiments/active?projectId=… returns every running experiment. Responses are cached at the edge for 60s with a 30s stale-while-revalidate window.
interface ActiveExperimentsResponse {
experiments: Experiment[];
}
interface Experiment {
id: string;
name: string;
type: "copy" | "css" | "layout";
targetUrl: string;
urlMatchType: "all" | "exact" | "contains" | "starts_with";
trafficPercentage: number; // 0-100
variants: Variant[];
}
interface Variant {
id: string;
name: string;
isControl: boolean;
weight: number;
changes: VariantChange[];
}
interface VariantChange {
selector: string;
changeType: "text" | "html" | "style" | "class" | "css";
property?: string;
value: string;
}