Server-side tracking
The measurement no ad blocker can touch, and the one rule that makes it accurate.
Server-side tracking is the only measurement no ad blocker can touch, because it never involves the visitor’s browser. It is also the only way to record things that happen after the user leaves — a payment confirmed by a webhook, a subscription renewed by a cron job.
One HTTP call
There is no library to install. Sending an event is a single POST, authenticated with a write-scoped API key — every language you might use has this built in.
curl -i -X POST https://causalit.fr/api/ev \n -H "Authorization: Bearer $CAUSALIT_WRITE_KEY" \n -H "Content-Type: text/plain" \n --data '{"d":"example.com","n":"purchase","u":"https://example.com/checkout/success","p":{"plan":"pro"},"ip":"203.0.113.7","ua":"Mozilla/5.0 (...)"}'The same call from Node, with nothing beyond the standard library:
await fetch('https://causalit.fr/api/ev', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CAUSALIT_WRITE_KEY}`,
'Content-Type': 'text/plain',
},
body: JSON.stringify({
d: 'example.com',
n: 'purchase',
u: 'https://example.com/checkout/success',
p: { plan: 'pro' },
ip: request.headers['x-forwarded-for'], // the visitor's, not your server's
ua: request.headers['user-agent'],
}),
});Pass the visitor’s IP and user agent
Both are used transiently to compute the same daily fingerprint the browser tag would have produced, and neither is stored. Read them from the request that reached your server. Omit them and every server-side event is attributed to your server — one visitor, all day.
Running the SDK alongside the tag
Sending from both channels is what makes recovered traffic measurable: the uplift is the visitors the server saw and the tag did not. But a pageview counts every row it finds, so the same view sent twice under the name ‘pageview’ is counted twice, and a session whose pageview count is doubled stops looking like a bounce.
When both channels run on the same site, send your server-side views as ‘pageview.server’. It is a reserved name: it stays out of the Events tab and out of every pageview total, while still carrying a real visitor fingerprint — which is all the comparison needs.
Generating a client
The whole contract is published as an OpenAPI 3.1 document, so a typed client in your language is one generator run away — see the API reference for both.
Identified mode
You may attach an already-hashed user id to tie events to a known account. That is pseudonymised personal data of your users, so the legal basis becomes yours: it needs a per-site opt-in here and a line in your privacy policy. Send only irreversible hashes — never an email, never a raw id.