GA4 Measurement Protocol: server-side events without double counting

The GA4 Measurement Protocol lets your server send events the browser never sees, but it has no deduplication. Here is how to use it safely, with client IDs, sessions and testing.

By Mohammad Ayan · · 3 min read

Google Analytics 4 lets you send events from your server with the Measurement Protocol. It is useful for sales the browser never sees. It is also easy to misuse, because unlike Meta, GA4 does not give you event-level deduplication between browser and server. This guide explains what the Measurement Protocol is for, how it works, and how to avoid counting the same sale twice.

What the Measurement Protocol is

The Measurement Protocol is an HTTP endpoint that accepts GA4 events as JSON. Instead of a browser tag sending the event, your server posts it to Google:

POST https://www.google-analytics.com/mp/collect?measurement_id=G-XXXXXXX&api_secret=YOUR_SECRET

{
  "client_id": "1234567890.1700000000",
  "events": [
    { "name": "purchase", "params": { "transaction_id": "10482", "value": 49.0, "currency": "USD" } }
  ]
}

You create the api_secret in the GA4 data stream settings, under Measurement Protocol API secrets. Keep it on the server only.

The client ID is what ties it together

Every event needs a client_id. To connect a server event to a visitor already tracked in the browser, send the same client ID the browser uses. It is stored in the _ga cookie, and your page or checkout has to capture it and pass it along with the order. If you send an unrelated ID, GA4 records a new, separate user, and the sale will not be attributed to the session that produced it.

To keep the event inside the right session, also pass the session_id. Google's reference says it must be a positive number, and that session attribution needs the request to arrive within 24 hours of the session start. Capture both values in the browser at order time (the gtag('get', …) call returns them) and store them with the order.

There is no deduplication between browser and server

If your browser tag sends purchase and your server also sends purchase for the same order, GA4 can count both. Meta's pixel and Conversions API solve this with a shared event ID. GA4's Measurement Protocol has no equivalent, so the rule is simple: do not send the same event from both places.

Use the browser tag as your main source, and use the server only for events the browser cannot observe:

  • a purchase confirmed after the customer left, such as a cash-on-delivery order marked delivered,
  • an order created outside the website, for example by phone or in a back-office tool,
  • refunds and cancellations,
  • subscription renewals and other recurring charges.

For these events there is no browser copy, so nothing is duplicated.

Sending events from the past

If an event happened earlier, include timestamp_micros so GA4 files it at the right time. Events can be backdated up to 72 hours. With the default relaxed validation, an older timestamp is still accepted but is set to 72 hours ago; with the stricter ENFORCE_RECOMMENDATIONS setting it is rejected. For slow flows, send as soon as the status changes.

Test before you trust it

The Measurement Protocol does not return an HTTP error when an event is malformed, so a request can look successful and still be ignored. Google provides a validation server, https://www.google-analytics.com/debug/mp/collect, which takes the same request but returns a list of validation messages instead of recording anything. Events sent to it never show up in reports. It also does not check your api_secret, so verify that value yourself.

During development, set validation_behavior to ENFORCE_RECOMMENDATIONS for strict checks, and leave it unset in production to reject as little data as possible. After validating, send a real event and confirm it in the Realtime report, or in DebugView by including the debug parameters.

Google also notes the Measurement Protocol is mature and not being deprecated, but recommends its Data Manager API for new server-to-server integrations. Check which fits your setup before building.

Common mistakes

  • Missing or invented client_id, which splits the visitor into a second user.
  • Duplicating browser events, which inflates revenue and conversions.
  • Wrong currency or value type. value must be a number, not a string with a symbol.
  • Exposing the API secret in front-end code. Anyone with it can send fake events to your property.
  • Expecting instant reports. Standard reports can lag; use DebugView to confirm arrival first.

Where this fits

GA4 is one destination among several. If you also send conversions to Meta and TikTok, a single pipeline that sends each event to every platform keeps them consistent. PixelFox does this and treats GA4 as server-side opt-in, so you choose which events leave the server. For Meta's side, read how event deduplication works.

Comments

No comments yet. Questions and corrections are welcome.

Leave a comment

Plain text only. Links may hold a comment for review.

Recover the conversions your pixel misses

PixelFox sends your conversions server-side with matching event ids, so ad platforms see every sale once. Free to start.

Start free