API Reference

The public collection endpoints the tracker uses. You can call them directly from any language.

Base URL & CORS

The production API lives at https://app.produl.tech. The current tracker posts to /r, /b, and /f. The older /api/collect, /api/ping, and /api/vitals paths remain available for compatibility. All three endpoints accept cross-origin requests — Access-Control-Allow-Origin: * is returned on every response.

All request bodies are application/json. All responses are 204 No Content on success. No response body is returned, even for successful writes.

Authentication

The public collection endpoints are unauthenticated and identified by public site API key — the tracker POSTs from the browser without any secret. The site API key (field k) is what attributes the event to your site.

For server-side tracking, include an X-Produl-Server-Key header with a secret key generated from your dashboard. Server-authenticated requests get a higher rate limit. See Server-Side Tracking.

Rate limits

Request typeLimit
Client (browser) requests200 / minute / IP
Server-authenticated requests2,000 / minute / IP

Requests over the limit return 429 Too Many Requests.

POST /r

POST/r

Send a pageview or custom event. Alias of /api/collect.

Body

FieldTypeRequiredDescription
kstringyesSite ID
t"pv" | "ev"yesType: pageview or event
ustringyesFull URL of the page
pstringyesPath, including query string when present
vistringyesVisitor ID
skstringyesSession key
tistringnoPage title
rstringnoReferrer URL
dnumbernoDuration on previous page (ms)
sdnumbernoScroll depth (0–100)
swnumbernoScreen width (px)
shnumbernoScreen height (px)
lstringnoBrowser language
nstringif t=evEvent name
probjectnoEvent properties (JSON)

Pageview example

json
{
  "k":  "site_abc123",
  "t":  "pv",
  "u":  "https://example.com/pricing?utm_source=newsletter",
  "p":  "/pricing?utm_source=newsletter",
  "vi": "v8abcd1lmno2",
  "sk": "sess_xyz789",
  "ti": "Pricing — Example",
  "r":  "https://google.com/",
  "sw": 1920,
  "sh": 1080,
  "l":  "en-US"
}

Event example

json
{
  "k":  "site_abc123",
  "t":  "ev",
  "u":  "https://example.com/pricing?utm_source=newsletter",
  "p":  "/pricing?utm_source=newsletter",
  "vi": "v8abcd1lmno2",
  "sk": "sess_xyz789",
  "n":  "cta_click",
  "pr": { "location": "hero", "variant": "blue" }
}

Response codes

StatusMeaning
204 No ContentAccepted. (Also returned silently for invalid payloads, bot UAs, and over-limit sites.)
429 Too Many RequestsRate limit exceeded.

Why 204 on invalid payloads?

The endpoint is called from every page on every site — returning an error body would risk cascading exceptions in user code. Invalid payloads are silently dropped.

POST /b

POST/b

Keep the active-visitor counter fresh and backfill time-on-page + scroll depth. Alias of /api/ping.

Body

FieldTypeRequiredDescription
kstringyesSite ID
skstringyesSession key
vistringyesVisitor ID
pstringyesCurrent path
dnumbernoPage duration (ms), sent on visibility change
sdnumbernoScroll depth (0–100)

Behavior

The tracker sends /b on a 30-second heartbeat and again on visibilitychange. This keeps the live-visitor counter fresh — any visitor whose last ping is older than 3 minutes is treated as inactive.

POST /f

POST/f

Submit Core Web Vitals measurements captured in the browser. Alias of /api/vitals.

Body

FieldTypeRequiredDescription
kstringyesSite ID
skstringyesSession key
vistringyesVisitor ID
pstringyesPath
lcpnumbernoLargest Contentful Paint (ms)
fcpnumbernoFirst Contentful Paint (ms)
clsnumbernoCumulative Layout Shift
inpnumbernoInteraction to Next Paint (ms)
ttfbnumbernoTime to First Byte (ms)
fidnumbernoFirst Input Delay (ms) — deprecated in favor of INP

Example

json
{
  "k":    "site_abc123",
  "sk":   "sess_xyz789",
  "vi":   "v8abcd1lmno2",
  "p":    "/pricing",
  "lcp":  2350,
  "fcp":  1200,
  "cls":  0.07,
  "inp":  180,
  "ttfb": 420
}

Errors

With the exception of rate-limit violations, these endpoints return 204regardless of the outcome — this keeps third-party analytics from interfering with your site's normal operation. To debug an event that doesn't arrive:

  • Check the browser network tab — the request should show as a 204
  • Verify your site API key matches a site in the dashboard
  • For script installs, confirm window.ma.track('debug_event') creates a successful /r request
  • Check FAQ & Troubleshooting for common issues (ad blockers, CSP)