Collect
Browser and server-side collection
One event, two paths. The browser asks Google directly. The server receives a first-party copy and forwards it only when a Measurement Protocol secret is set.
Browser
gtag on this page
gtag('event', 'server_side_test') asks gtag.js to POST to google-analytics.com/g/collect. That host is on common blocker lists. Intelligent Tracking Prevention also caps cookies set from JavaScript, so the client id on that hit can expire in about seven days.
Server
First-party copy
The same button POSTs to /api/server-collect. The body is only the consent flag. The server builds a numeric client id from the first-party visitor cookie and, when GA4_MP_API_SECRET is set, forwards one event to the Measurement Protocol. Otherwise it stores a row. A list that blocks Google does not see this request.
Send the test event
The server does not recover a hit the browser never made. It recovers the event because this page sends a second copy to our origin. The secret stays on the server. The log stores the event name, the transport, and the status.
Measurement Protocol: Checking…
What each path drops
| Condition | Browser gtag | Server copy |
|---|---|---|
| Consent off | No hit. Consent Mode stays denied. | Refused. Nothing is stored. |
| Ad blocker on Google hosts | The collect request is dropped. | The first-party POST still arrives. |
| ITP cookie cap | The JavaScript client id can expire in days. | The httpOnly visitor cookie lasts 400 days and is hashed into the Measurement Protocol client id. |
| Secret unset | Unchanged. The browser still talks to Google if it can. | The event is a database row, not a Google hit. |
Recent server rows
No server copies yet.
Recommended next
Why these picksReading path transitions…