APIs
Events API
Send pageviews and custom events from your server, mobile app or anywhere else over HTTP.
The tracking script uses this same API. You can call it directly to record events from places the script can't run — a back end, a mobile app, a CLI or an email-open pixel service.
Endpoint
POST https://plainwebanalytics.com/api/event
Content-Type: application/json
User-Agent: <the visitor's user-agent>
X-Forwarded-For: <the visitor's IP address>
No API key is needed: events are matched to a site by its domain. text/plain and application/json bodies are both accepted, and CORS is open to all origins.
Headers matter. PlainAnalytics counts unique visitors from the IP address and user-agent (see the data policy). When calling from a server, forward the original visitor's User-Agent and put their IP address first in X-Forwarded-For; otherwise every event will look like it came from your server. Requests with an empty user-agent, or a user-agent that looks like a bot, are dropped.
Body
| Field | Required | Description |
|---|---|---|
name |
yes | Event name, up to 120 characters. Use pageview for pageviews. |
url |
yes | Absolute URL of the page the event happened on, up to 2,000 characters. |
domain |
yes | The site's domain as configured in PlainAnalytics. A comma-separated list records the event for several sites. |
referrer |
no | The referring URL. |
props |
no | Up to 30 custom properties; scalar values only. |
revenue |
no | { "amount": 49.99, "currency": "GBP" } for revenue goals. |
interactive |
no | false for events that shouldn't affect bounce rate. Default true. |
The short keys used by the script (n, u, d, r, p, $, i) are accepted too.
Example
curl -i -X POST https://plainwebanalytics.com/api/event \
-H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0 Safari/537.36' \
-H 'X-Forwarded-For: 203.0.113.7' \
-H 'Content-Type: application/json' \
--data '{"name":"Signup","url":"https://example.com/register","domain":"example.com","props":{"plan":"pro"}}'
Responses
| Status | Meaning |
|---|---|
202 ok |
Accepted. Events that are deliberately dropped (bots, unknown domains, shields) also return 202, so the API can't be used to probe your settings. |
400 |
Validation failed. The body is {"errors": {"field": ["message"]}}. |
413 |
Body larger than 64 KB. |
Debugging
Add the header X-Debug-Request: true and the response includes, for each domain, whether the event was accepted or dropped and the reason — for example an unknown domain, a bot user-agent or a shield rule.
Something unclear or missing? Tell us.