Privacy-First Measurement: Server-Side Tagging, Consent Mode and Conversion APIs · GA4 and server-side tagging · lesson 5 of 14 · 8 min
GA4 with consent: modeling, settings and the Measurement Protocol
What GA4 does when consent is denied
With Consent Mode in advanced implementation, when analytics_storage is denied GA4 receives cookieless pings: no _ga cookie is read or written, and each ping cannot be tied to a returning user. With basic implementation, GA4 receives nothing from users who deny.
GA4 can fill part of the gap with behavioral modeling: machine learning estimates the behavior of unconsented users based on similar consented users. Modeled data appears when the property's reporting identity is set to Blended and eligibility thresholds are met (Google's documentation specifies minimum daily volumes of denied-consent events and consented users over a period — check the current thresholds in the GA4 help center). Modeling requires advanced implementation because it learns from the cookieless pings.
Reporting identity choices
| Reporting identity | Uses | When to choose | |---|---|---| | Blended | User-ID, device ID and modeling | Default for most; enables behavioral modeling | | Observed | User-ID and device ID only | When you want only observed data | | Device-based | Device ID only | Simple comparisons; ignores User-ID |
Switching reporting identity does not change collected data; it changes how reports are computed, so you can compare.
Consent settings in GA4 Admin
Under Admin > Data collection and modification > Data collection (and the consent settings view), GA4 shows whether ad_user_data and ad_personalization signals are being received for EEA traffic. If they are not, Google signals-based features, audiences for ads, and some conversion exports to Google Ads may be limited.
Other GA4 privacy controls to review:
- Data retention (2 or 14 months for event-level data in standard properties).
- Granular location and device data collection (can be disabled per region).
- Google signals (cross-device features; respects ad_personalization).
- IP handling: GA4 does not log or store IP addresses for EU users, per Google's statements; still assess your own setup.
- Data deletion requests for removing specific data.
- Redacting PII from page URLs (GA4 offers data redaction for email addresses and query parameters in web data streams).
Server-to-server events: the Measurement Protocol
The GA4 Measurement Protocol lets your server send events to GA4 — for example, a purchase confirmed by the payment provider, a subscription renewal, or an offline sale. It complements, not replaces, the tag.
Key rules:
- Each request needs a
measurement_idand anapi_secret(created in the data stream settings — keep it secret, server-side only). - Include the
client_idfrom the user's_gacookie (captured at checkout) to join the event to the web session; includeuser_idif you use it. - Pass consent: the
consentobject withad_user_dataandad_personalizationreflecting the user's choices. - Use the validation server (
/debug/mp/collect) during development.
import os, requests
MEASUREMENT_ID = os.environ["GA4_MEASUREMENT_ID"]
API_SECRET = os.environ["GA4_API_SECRET"]
def send_purchase(client_id: str, order: dict, consent_ads: bool, debug: bool = False):
url = "https://www.google-analytics.com/" + ("debug/mp/collect" if debug else "mp/collect")
payload = {
"client_id": client_id,
"consent": {
"ad_user_data": "GRANTED" if consent_ads else "DENIED",
"ad_personalization": "GRANTED" if consent_ads else "DENIED",
},
"events": [{
"name": "purchase",
"params": {
"transaction_id": order["id"],
"currency": order["currency"],
"value": order["value"],
"items": [{"item_id": i["sku"], "price": i["price"], "quantity": i["qty"]} for i in order["items"]],
},
}],
}
r = requests.post(url, params={"measurement_id": MEASUREMENT_ID, "api_secret": API_SECRET},
json=payload, timeout=10)
r.raise_for_status()
return r.json() if debug else r.status_code
Only send Measurement Protocol events for users whose consent choices allow analytics for that purpose; store the consent state alongside the order.
Deduplication in GA4
GA4 deduplicates purchase events with the same transaction_id for the same property in many cases, but do not rely on it blindly: decide whether the browser or the server is the source of truth for each event, and avoid sending the same purchase from both unless you have tested how GA4 handles it.
Worked example: a Lahore subscription app
A meal-kit subscription in Lahore sees renewals happen server-side (card charges), which GA4 never saw. They send renewal events through the Measurement Protocol with the stored client_id and consent state, build a GA4 exploration of first-order to renewal paths, and export to BigQuery for cohort analysis.
Pitfalls
- Exposing the API secret in client-side code.
- Sending Measurement Protocol events without a valid
client_id, creating orphan users. - Forgetting consent parameters in server events.
- Reading modeled numbers as observed facts.
How to measure success
Consent settings show signals received; modeled data active where eligible; server events joining sessions (low share of "(not set)" sources); BigQuery export reconciling with backend orders within a known tolerance.
Video lecture: GA4 with consent: modeling, settings and the Measurement Protocol
Lecture coming soon · 14 chapters · about 8 minutes. Read the full transcript below.
- GA4 with consent
- Why it matters
- Denied consent in GA4
- Behavioral modeling
- Reporting identity
- Simple example: Dubai travel agency (illustrative)
- GA4 admin checks
- Measurement Protocol
- Build and validate
- Duplicates and an example
- Mistakes + try this now
- Quick self-check
- Watch me do it: server renewal event (illustrative)
- Recap and next step
Lecture transcript
GA4 with consent
Here's a question worth asking about your GA4 data: when someone says no to analytics, what does GA4 actually see? The answer depends on choices you may not know you made. In this lecture you'll learn how GA4 behaves under consent, how behavioral modeling fills gaps, which privacy settings to review, and how to send server-confirmed events with the Measurement Protocol while respecting consent.
Why it matters
Why does this matter? Because GA4 is often the number leadership looks at, and if nobody understands how consent shapes it, people make decisions on numbers they misread. Here's an analogy. Think of a weather station that only measures when the sun is out, and estimates the rainy days from patterns. That's useful, as long as everyone knows which days were measured and which were estimated. GA4 under consent is similar. Some users are observed, some are modeled, and some aren't there at all. Knowing which is which is the difference between insight and illusion.
Denied consent in GA4
With advanced Consent Mode, when analytics storage is denied, GA4 still receives pings, but they're cookieless. No analytics cookie is read or written, so each ping can't be linked to a returning user. With basic mode, GA4 receives nothing at all from people who decline. That difference matters because GA4's behavioral modeling learns from those cookieless pings. No pings, no advertiser-specific modeling.
Behavioral modeling
Behavioral modeling uses machine learning to estimate what unconsented users did, based on similar consented users. You'll see modeled data when your reporting identity is set to Blended and your property meets Google's eligibility thresholds, which require minimum daily volumes of both denied and consented traffic over a period. Check the current numbers in the help center. And remember, modeled numbers are estimates, not observations.
Reporting identity
Reporting identity has three options. Blended uses User-ID, device ID and modeling. Observed uses only User-ID and device ID. Device-based uses only the device. Switching doesn't change the data you collected, only how reports are computed, so you can flip between them to see how much of a number is modeled. That's a great way to explain gaps to stakeholders.
Simple example: Dubai travel agency (illustrative)
Here's a simple worked example. A Dubai travel agency sees two numbers for last week's users. With reporting identity set to Blended, GA4 shows twelve thousand users. Switch to Observed, and it shows nine thousand six hundred. The difference, about two thousand four hundred, is modeled from cookieless pings of visitors who declined analytics. Neither number is wrong. When they present results, they say: we observed nine thousand six hundred users, and GA4 estimates about twelve thousand in total. That one sentence prevents a lot of confusion, especially when comparing with periods before Consent Mode was set up. The numbers are illustrative.
GA4 admin checks
Next, check the consent settings in GA4's admin, under data collection. It shows whether ad user data and ad personalization signals are arriving for European traffic. If they're missing, audiences for ads and some features linked to Google Ads will be limited. While you're there, review data retention, granular location and device collection, Google signals, and data redaction, which can strip email addresses and chosen query parameters from page URLs.
Measurement Protocol
Now the Measurement Protocol. It lets your server send events to GA4, like a purchase confirmed by the payment provider, a subscription renewal or an offline sale. It complements the tag. Each request needs your measurement ID and an API secret, which must stay on the server. Include the client ID captured from the user's analytics cookie at checkout, so the event joins the right session. And pass consent, ad user data and ad personalization, reflecting what the user chose.
Build and validate
The lesson includes a Python function that sends a purchase, with a debug switch that uses the validation server during development. Use it before going live, because the validation server tells you if your payload is malformed, whereas the live endpoint silently accepts almost anything. Store the client ID and consent state with every order in your database, so server events always carry the right context.
Duplicates and an example
A word on duplicates. GA4 often deduplicates purchases with the same transaction ID, but don't rely on it blindly. Decide which source is the truth for each event, the browser or the server, and avoid sending the same purchase from both unless you've tested the result. Here's an illustrative example: a Lahore meal-kit subscription never saw renewals in GA4, because they happened when cards were charged. Sending renewal events server-side, with stored client IDs and consent, finally let them analyze first order to renewal paths.
Mistakes + try this now
Common GA4 consent mistakes. Putting the Measurement Protocol secret in front-end code. Sending server events without a client ID, which creates orphan users. Forgetting the consent object in server events. Comparing modeled and observed numbers across periods without saying so. And never checking data redaction, so email addresses end up in page URLs. Try this now: in GA4 admin, open the data collection settings and write down three things: your data retention period, whether consent signals are being received, and whether URL query parameter redaction is on. Fix anything that surprises you.
Quick self-check
Quick self-check. Your GA4 users dropped fifteen percent the week you launched a new consent banner, while orders in your backend stayed flat. Did traffic fall? Pause. Almost certainly not. More people declined analytics, so GA4 observes fewer of them. If you're on advanced Consent Mode with Blended identity, modeling may fill some of the gap once you're eligible. The right response is to annotate the change in GA4, compare with backend orders, and avoid reading the drop as lost demand.
Watch me do it: server renewal event (illustrative)
Watch me do it. Let's send a server-confirmed renewal event for an illustrative Dubai gym subscription using the Measurement Protocol. First, at signup, our site stores the GA4 client ID from the underscore g a cookie on the customer record, along with the consent choices from the CMP. Second, a month later the payment provider's webhook tells our server that the renewal succeeded for customer one two three. Third, the server looks up the stored client ID and consent. Analytics consent was granted; advertising consent was not. Fourth, I build the payload: client ID, the event name subscription renewal, value and currency in dirhams, and the consent object with ad user data and ad personalization both denied. Fifth, I send it to the debug endpoint first. The validation response lists no messages, so the format is right. Sixth, I switch to the live endpoint, then check GA4's real-time report, where the renewal appears. Finally, I build an exploration: first purchase to renewal, by acquisition channel. For the first time, the gym can see which channels bring members who stay, not just members who join.
Recap and next step
Recap. With advanced Consent Mode, GA4 gets cookieless pings and can model under Blended identity if you're eligible. Check consent signals and privacy settings in admin. Use the Measurement Protocol for server-confirmed events, keep the secret on the server, and send client ID and consent. Your next step: in a test property, send a purchase through the validation server with consent parameters, and document how you'll store client ID and consent with each order.
Key takeaways
- With advanced Consent Mode, GA4 receives cookieless pings when analytics is denied and can model behavior under Blended reporting identity (if thresholds are met).
- Check GA4 consent settings for ad_user_data and ad_personalization signals.
- Review retention, granular data, Google signals and PII redaction settings.
- Use the Measurement Protocol for server-confirmed events, with client_id, consent and a secret kept server-side.
- Decide a single source of truth per event to avoid duplicates.
Try it
In a GA4 test property, send a purchase via the Measurement Protocol validation server with consent parameters, then document how you'll store client_id and consent state with each order.