The Measurement Protocol is GA4’s server-side ingestion API. It lets your backend, mobile app, or IoT device send events directly to Google Analytics over HTTPS β no browser, no gtag, no cookies. For ecommerce sites, it’s the safety net that captures revenue when payment gateways redirect users away, when ad blockers strip the client tag, or when the order is confirmed asynchronously hours after checkout. This guide covers the GA4 Measurement Protocol endpoint, api_secret authentication, payload format, validation, and the trade-offs versus client-side data layer tracking.
What Is the Measurement Protocol?
The GA4 Measurement Protocol is a REST endpoint that accepts JSON event payloads from any HTTPS-capable system. Instead of the user’s browser sending a hit, your server constructs the payload and posts it to https://www.google-analytics.com/mp/collect. The same GA4 events you send via gtag β purchase, sign_up, add_to_cart β are accepted, and they appear in identical reports and BigQuery exports.
The Measurement Protocol is not a separate product. It’s the server-side door into the same GA4 property your data stream already feeds. That means the events join the same sessions, the same audiences, and the same conversion reports β provided you pass a stable client_id.
When to Use Measurement Protocol vs Client-Side gtag
Measurement Protocol is rarely a wholesale replacement for gtag. It’s a complement β a server-side track that handles edge cases the browser can’t.
| Aspect | gtag / dataLayer (client) | Measurement Protocol (server) |
|---|---|---|
| Setup effort | Low β paste tag or use GTM | Higher β build payload, manage api_secret |
| Auto-collected fields | page, UA, screen, UTM, client_id | None β you must supply each one |
| Sessions | Auto-stitched via _ga cookie | Manual β pass client_id + session_id |
| Ad blockers | Often blocked | Bypassed entirely |
| Async / offline events | Impossible | Native β backend jobs, refunds, renewals |
| PII risk | Browser-bounded | Higher β discipline required |
| Best for | Pageviews, user-driven events | Revenue, post-payment, mobile, IoT |
The standard pattern in production e-commerce: client-side gtag captures everything up to and including add_payment_info, and Measurement Protocol fires the purchase event from the order-management backend after payment is confirmed. That combination survives ad blockers, payment redirects, and refresh-spam on the thank-you page.
GA4 Measurement Protocol Endpoint and Parameters
There are two endpoints β production and debug:
- Production:
POST https://www.google-analytics.com/mp/collectβ events are recorded. - Debug:
POST https://www.google-analytics.com/debug/mp/collectβ payload is validated, response describes errors, nothing is recorded.
Both endpoints require two query-string parameters:
measurement_idβ your GA4 data stream ID, formattedG-XXXXXXX. Find it in Admin β Data Streams β Web β Measurement ID.api_secretβ a token generated specifically for Measurement Protocol use.
The body is JSON and accepts up to 25 events per request, sharing a single client_id (or app_instance_id for mobile streams).
Authentication: api_secret and measurement_id
The api_secret is generated inside GA4, not in Google Cloud. To create one:
- Open GA4 β Admin β Data Streams β select your web stream.
- Scroll to Measurement Protocol API secrets β click Create.
- Name the secret (e.g., “server-orders-prod”), click Create, copy the
secret_value.
Treat the secret like a password. Store it in your server’s environment variables or a secrets manager β never expose it in client-side JavaScript, mobile app binaries, or git history. If a secret leaks, revoke it from the same GA4 screen and issue a new one. A single property can hold multiple secrets, which is useful for separating staging, production, and per-system tokens.
Sending Events: Payload Anatomy
A minimal purchase event looks like this:
curl -X POST \
"https://www.google-analytics.com/mp/collect?measurement_id=G-XXXXXXX&api_secret=abc123xyz" \
-H "Content-Type: application/json" \
-d '{
"client_id": "1234567.890",
"events": [{
"name": "purchase",
"params": {
"transaction_id": "T12345",
"value": 99.99,
"currency": "USD",
"items": [{
"item_id": "SKU123",
"item_name": "Wireless Headphones",
"price": 99.99,
"quantity": 1
}]
}
}]
}'
A few rules that quietly break payloads in production:
client_idmust be stable. If you generate a fresh ID per request, every event becomes a new user and sessions never stitch. Reuse the_gacookie value (everything afterGA1.1.) when the user originated from the web.valueis a number, not a string. Send99.99, not"99.99". Strings silently aggregate to zero in revenue reports.- Event and parameter names follow GA4 schema. Use the same names you’d use in gtag, including reserved ones like purchase event, add to cart,
begin_checkout. - Pass campaign context manually. The MP endpoint does not auto-attach UTM, referrer, or user agent β capture them at the edge and send them as event params.
Common Use Cases
Where Measurement Protocol earns its place in the stack:
- Server-side e-commerce. Fire
purchasefrom the order-confirmed webhook. Survives payment redirects (Stripe, PayPal), ad blockers, and thank-you-page refreshes that duplicate transactions client-side. - Mobile app event repair. When the Firebase SDK can’t send (no network, app killed), queue events server-side and replay them via MP using the
app_instance_id. - Async confirmations. Subscription renewals, refunds, manually approved orders β events that happen minutes or days after the original session. Send them with the original
client_idto attribute correctly. - IoT and kiosk devices. Smart TVs, point-of-sale terminals, and connected products send events directly to GA4 β no browser available.
- Backfilling missing data. Replay yesterday’s missed conversions from your order database when a tag deployment broke client-side tracking.
Limitations and Quotas
Measurement Protocol is generous but not unlimited. The constraints that matter in production:
- Payload size: 130 kB per request, 25 events maximum, 25 parameters per event, 100 user properties total.
- Time skew: Events older than 72 hours are silently dropped unless you provide a
timestamp_microsparam explicitly. For historical backfills, set the timestamp; otherwise GA4 stamps “now.” - No cross-domain stitching: The MP endpoint doesn’t have access to the user’s browser, so it can’t propagate
_gaacross domains automatically. Capture and pass the cookie value yourself. - No automatic page metadata: Page title, location, and referrer must be set manually as event params if you want them in reports.
- Real-time delay: MP events appear in DebugView within seconds, but Realtime reports may lag 1-2 minutes.
- PII enforcement: Sending email addresses, phone numbers, or names violates Google’s terms β hash before sending if you must use them as user_id.
Validation: The /debug Endpoint
Before pointing your code at production, validate every payload variant against the debug endpoint:
curl -X POST \
"https://www.google-analytics.com/debug/mp/collect?measurement_id=G-XXXXXXX&api_secret=abc123xyz" \
-H "Content-Type: application/json" \
-d '{ "client_id": "1234567.890", "events": [...] }'
The response is a JSON object with a validationMessages array. An empty array means the payload would be accepted. Common errors flagged by the debug endpoint:
VALUE_INVALIDβ usuallyvaluesent as a string, orcurrencynot in ISO 4217 format.NAME_INVALIDβ event names containing dashes, spaces, or starting with a number.NAME_RESERVEDβ using GA4-reserved event names likeapp_removein non-app contexts.UNKNOWN_PARAMβ typos in standard params (e.g.,tx_idinstead oftransaction_id).
Once validated, switch the URL from /debug/mp/collect to /mp/collect, leave authentication unchanged, and confirm the live event in GA4 β Admin β DebugView. For deeper diagnostics, the official Measurement Protocol reference documents every accepted parameter.
Frequently Asked Questions
What is the Measurement Protocol in GA4?
The Measurement Protocol is GA4’s server-side API for sending events. Your backend posts JSON payloads to https://www.google-analytics.com/mp/collect, authenticated with a measurement_id and api_secret. Events appear in the same reports as client-side hits.
How do I send events to GA4 server-side?
Generate an api_secret in GA4 Admin β Data Streams β Measurement Protocol API secrets. Then POST a JSON body containing client_id and an events array to the MP endpoint. Use the /debug/mp/collect endpoint first to validate the payload format.
What’s the difference between gtag and Measurement Protocol?
gtag runs in the browser and auto-collects page, UTM, user agent, and the client_id cookie. Measurement Protocol runs on your server and supplies nothing automatically β you provide every field. Use gtag for browser interactions; use MP for server-confirmed events like purchases, subscriptions, and offline conversions.
Is the Measurement Protocol free?
Yes β Measurement Protocol is part of GA4 and has no per-event cost. The standard GA4 quotas apply (10 million events per month per property in the free tier), but there’s no separate API billing.
What is the api_secret and where do I get it?
The api_secret is a token that authenticates Measurement Protocol requests for a specific data stream. Create one in GA4 β Admin β Data Streams β select stream β Measurement Protocol API secrets β Create. Store it in environment variables β never in client code.
Do server-side events join the same GA4 sessions as web events?
Only if you pass the same client_id. Capture the _ga cookie value during the web session, store it with the order, and reuse it when sending the server-side event. Without that, the server event becomes an isolated user with no session attribution.
Can I send events older than 72 hours via Measurement Protocol?
Yes, but only by setting the timestamp_micros parameter explicitly. Without it, GA4 timestamps the event at receipt and silently drops anything older than 72 hours. The hard ceiling is 72 hours back from “now” for any event regardless of timestamp.
Related Terms
- GA4 events β the underlying schema MP uses
- Data layer β client-side counterpart
- Data stream β where measurement_id and api_secret live
- Purchase event β the canonical MP use case
- Add to cart β earlier funnel event
- Conversion β what server-side delivery protects
- Cookies β what Measurement Protocol bypasses
- Cookieless analytics strategies β broader context