Skip to main content

GA4 anon_* client IDs

info

Server-side Google Analytics 4 Measurement Protocol tracking is a feature only available for users of the Pro version. Get the Pro version here.

If you inspect the Pixel Manager logs you may find server-side GA4 purchase events whose client_id looks like this:

anon_76413.1786483870

instead of the browser's normal GA4 client ID, which looks like this:

171933599.1747821527

This page explains exactly when the Pixel Manager generates an anon_* value, whether it is only a fallback, and what it means for GA4 Measurement Protocol attribution and "(not set)" reporting.

Short answer

Short answer

The Pixel Manager uses an anon_* GA4 client_id only as a fallback, and only for server-side GA4 Measurement Protocol events. Whenever a browser GA4 client_id was captured for the order, that value is used. There is no case in which the Pixel Manager sends anon_* while a usable browser client ID is available.

So an anon_* value is not itself a failure, and it is not the root cause of anything. It is a marker that the browser's GA4 client ID was never captured for that order. That missing identity is what prevents GA4 from joining the server-side purchase to the original browser session, which is what produces "(not set)" attribution.

Which events this affects

anon_* can only ever appear in three payloads, all of them server-side GA4 Measurement Protocol events:

  • purchase
  • full refund
  • partial refund

Browser-side GA4 events are never affected. They always use the real client ID that gtag issued in the browser.

What an anon_* client ID is

The value is built from a random 10 digit number and the current Unix timestamp, after which the first five characters are replaced by the anon_ prefix. The result keeps the general shape of a GA4 client ID:

PropertyBehavior
OriginRandomly generated at the moment the payload is built
Derived from the customer, order, browser, or session?No
Stored anywhere?No. It is never written to order meta, the WooCommerce session, or a cookie
Stable across events?No. A purchase and a later refund on the same order carry different anon_* values
Persistent or deterministic?Neither
Accepted by GA4?Yes. GA4 treats any string as a syntactically valid client_id

Because it is random and never reused, an anon_* value identifies nothing. It exists purely because the GA4 Measurement Protocol requires a client_id field to be present in every payload.

Identifier selection

SituationBrowser GA4 client ID available?client_id sentsession_id sentExpected GA4 attribution
Normal checkout, statistics consent granted, _ga cookie readableYesBrowser client IDYesJoins the original session, normal source, medium, and campaign
_ga cookie missing at checkout (never written, cleared, or blocked)Noanon_*NoNew unattributed user and session, typically "(not set)"
_ga cookie present but malformed (fewer than four dot separated parts)Noanon_*NoSame as above
Statistics consent denied, "always send server-side events" offNot applicableNothing is sent. The purchase event is suppressed entirelyNothingNo GA4 purchase at all, by design
Statistics consent denied, "always send server-side events" onUsually no, because Consent Mode stops gtag from writing _gaanon_*No"(not set)". This is the most common way a store produces anon_* at scale
Checkout only ever observed inside a cross domain payment gateway iframeNoanon_*No"(not set)"
Subscription renewal order (since 1.59.0)Yes, resolved from the parent orderParent order's client IDParent order's stored session IDAttributed to the same user. A session level join is unlikely because the original session is long over
Order created in the WordPress backend and paid by the customer on the front endYes, refreshed from the paying customer's browserBrowser client IDYesNormal attribution
A valid browser client ID exists and was capturedYesAlways the browser client IDYesanon_* is never used in this case

Where the browser client ID comes from

The Pixel Manager reads the GA4 client ID out of the _ga cookie that gtag writes. The cookie looks like GA1.1.171933599.1747821527, and the client ID is the third and fourth part joined together: 171933599.1747821527.

Three details matter for troubleshooting:

  1. The client ID is captured at checkout, not at send time. It is stored in the WooCommerce session and then on the order, and read back from the order when the Measurement Protocol event is dispatched. If the cookie was not readable when the order was created, no client ID is stored, and nothing later can recover it. This is why delayed payments, webhooks, and cron triggered sends cannot repair a missing identity: there is no browser in those contexts.
  2. Identifier capture is skipped inside an iframe. Some payment gateways render the checkout in a cross domain iframe, where reading the parent context would produce wrong data. The Pixel Manager deliberately skips capture there.
  3. A malformed cookie is ignored. If the _ga cookie does not have at least four dot separated parts, it is treated as unusable.

session_id travels with the client ID

The GA4 session ID comes from a separate cookie, _ga_<MEASUREMENT_ID_SUFFIX>. The Pixel Manager only adds session_id to the payload when that cookie was captured, and it adds engagement_time_msec alongside it.

Because gtag writes the _ga and _ga_* cookies together, when the _ga cookie is missing the session cookie is almost always missing too. An anon_* purchase therefore usually carries no session_id either, and it is that combination, an unknown user with no session reference, that makes a session join impossible.

HTTP 204 does not prove attribution

This is the single most important distinction on this page.

warning

An HTTP 204 response means Google accepted the Measurement Protocol request. It says nothing about attribution.

The GA4 Measurement Protocol production endpoint does not return error responses, even when the payload is malformed. A 204 therefore does not confirm any of the following:

  • that the client_id matched an existing GA4 user
  • that the event was joined to the original browser session
  • that source, medium, and campaign were assigned
  • that the event appears in your reports the way you expect

To validate that a payload is well formed, use Google's Measurement Protocol validation endpoint, which does return errors. Even then, a valid payload with an anon_* client ID remains an unattributed one.

What the order flags actually mean

wpm_google_analytics_4_mp_purchase_hit is written immediately after the request is dispatched, without inspecting the response. It means "the Pixel Manager sent this purchase once", and it exists to prevent duplicate hits. It is not a statement about GA4 attribution, or even about GA4 having processed the event.

The Pixel Manager order meta keys are:

  • wpm_google_analytics_4_mp_purchase_hit
  • wpm_google_analytics_4_mp_full_refund_hit
  • wpm_google_analytics_4_mp_partial_refund_hit
  • wooptpm_google_analytics_4_mp_purchase_hit (legacy key, still honored)
note

_ga_tracked is not a Pixel Manager order meta key. It does not exist anywhere in the plugin. If you see it on your orders, it was written by another plugin or by a custom integration, and its meaning is defined by whatever wrote it.

Server-side GA4 purchase events are gated on the statistics consent category, not marketing, because GA4 is an analytics destination. This gate was introduced in 1.62.0.

  • Statistics consent denied, always send off. The purchase event is suppressed completely. Nothing is sent, and you will not see an anon_* hit. Refunds for that order are suppressed too, so GA4 never receives a refund for a purchase it never saw. This is expected behavior and requires no action.
  • Statistics consent denied, always send on. The consent gate is bypassed and the event is sent. But Google Consent Mode sets analytics_storage to denied, so gtag never writes the _ga cookie, so there is no browser client ID to capture, so the hit goes out with anon_* and no session_id. If you have enabled "always send server-side events" and a meaningful share of your visitors deny statistics consent, this is almost certainly where your anon_* hits and your "(not set)" revenue come from.
  • No consent snapshot on the order. Orders created before the consent gate existed, or through an integration that never reported a consent state, are sent by default to preserve legacy behavior. Strict setups can suppress those as well with the pmw_s2s_require_consent_snapshot filter.

The trade-off is deliberate: with always send enabled you keep the revenue figure in GA4 but lose its attribution, and with it disabled you lose the purchase entirely but never send an unattributable one. Neither setting can produce an attributed purchase for a visitor who denied statistics consent, because no identity was ever allowed to exist.

Why "(not set)" happens when everything else looks correct

The reported pattern is: WooCommerce order attribution is stored correctly, the Pixel Manager order flags are set, the Measurement Protocol returns HTTP 204, and GA4 still reports "(not set)" for a share of purchases.

All of those facts are compatible with each other, because they measure different things:

FactWhat it provesWhat it does not prove
WooCommerce attribution shows source=google, medium=cpcWooCommerce observed and stored the referral itselfNothing about GA4. WooCommerce order attribution is an entirely separate system, and GA4 cannot read it
wpm_google_analytics_4_mp_purchase_hit is setThe Pixel Manager dispatched the event onceThat GA4 accepted, processed, or attributed it
Measurement Protocol returned HTTP 204Google accepted the requestThat it was joined to a session or attributed

None of the three tells you whether GA4 could identify the user. Only the client_id and session_id in the payload do that.

Once delivery is confirmed, attribution can still be missing for these reasons:

  1. anon_* client ID and no session ID. No join is possible. GA4 records a new unattributed user, so the purchase lands under "(not set)".
  2. A real client ID but no session ID. GA4 can identify the user but has no session to attach the event to.
  3. A real client ID and session ID, but the session has expired. Server-side events dispatched long after checkout, for example on a bank transfer or invoice paid days later, arrive after the original session is over.
  4. The 72 hour backdating limit. The Pixel Manager sends timestamp_micros so GA4 attributes the purchase to the moment the order was placed, but GA4 only honors a timestamp up to 72 hours before it receives the hit. Anything older is silently clamped.
  5. General GA4 Measurement Protocol limitations, which no plugin side change can remove.

Point 1 is the only one that anon_* itself indicates, and even there the anon_* value is the symptom, not the cause. Fixing "(not set)" means restoring the browser identity at checkout, not changing what the fallback sends.

Diagnosing a specific order

  1. In the Pixel Manager, open Support → Logger, turn on Enable logger, set the log level to Debug, and check Log HTTP requests. See the Logs page for details. HTTP request logging turns itself off automatically after 3 hours.
  2. Reproduce a purchase, or wait for an affected order.
  3. Open the log file at /wp-content/uploads/wc-logs/. The file names are prefixed with pmw-.
  4. Find the json payload: line for the GA4 request and record:
    • the client_id, and whether it starts with anon_
    • whether a session_id is present
    • the event timestamp and the WooCommerce order ID
    • the response code that follows
    • the Pixel Manager version
  5. Then follow the decision tree:
What the log showsWhat it meansWhat to do
client_id starts with anon_, no session_idThe browser identity was never captured for this orderCheck why _ga was absent at checkout: statistics consent state, the "always send server-side events" setting, an iframe checkout, ad blockers, or cleared cookies
client_id looks like 171933599.1747821527The identity was captured correctly. anon_* is not your problemInvestigate session timing, the 72 hour limit, and GA4 processing delay instead
No GA4 request at all, plus a log line about consent suppressionThe consent gate suppressed the eventExpected behavior. No action needed unless you intend to enable always send
The request is logged with an error responseA configuration or connectivity problemCheck the measurement ID, the API secret, and outbound connectivity

Allow for GA4's processing delay before concluding anything from reports. Comparing a purchase in DebugView or a report within minutes of the hit will mislead you.

When to contact support

If the log shows a normal browser client_id and a session_id and attribution is still missing, or if you see anon_* on orders where you can prove the _ga cookie existed at checkout, send a request to [email protected] with:

  • Pixel Manager version, WooCommerce version, and WordPress version
  • the affected order IDs, with timestamps and timezone
  • whether anon_* or a browser GA4 client ID was logged, and whether a session_id was present
  • the relevant log file links, using Copy log file links in the logger panel
  • your consent platform and its configuration, plus the state of the "always send server-side events" setting
  • whether browser-side GA4 requests are visible for the same checkouts
  • a screenshot or export showing the GA4 "(not set)" result
  • whether the issue affects all orders or only a subset, and roughly what share
warning

Do not post full client IDs, customer data, GA4 API secrets, or unredacted log files in public channels such as the WordPress support forum. Use email for those, or share the log file links, which are access controlled.

Frequently asked questions

When does Pixel Manager generate an anon_* GA4 client ID?

Only when it is building a server-side GA4 Measurement Protocol payload (purchase, full refund, or partial refund) and no browser GA4 client ID was captured for that order.

Why does Pixel Manager use an anon_* client ID?

Because the GA4 Measurement Protocol requires a client_id in every payload. Without a placeholder the request would be invalid and the purchase would be lost from GA4 entirely, including its revenue.

Is anon_* only a fallback when the browser's normal GA4 client ID cannot be retrieved?

Yes. It is used only in that case.

Can Pixel Manager use anon_* when the original GA4 client ID is available?

No. If a client ID was captured for the order it is always used. There is no exception, no setting, and no filter that makes the plugin prefer a random value over a real one.

Does an anon_* GA4 client ID cause "(not set)" attribution?

Not on its own, and the distinction matters. anon_* is used because the browser identity was unavailable, and that same absence is what prevents GA4 from joining the purchase to the original session. An anon_* hit will not be attributed, but replacing the fallback with something else would not fix attribution, because there is no identity to send. Treat anon_* as the diagnostic signal, not the defect.

Why do I see "(not set)" in GA4 even though my Measurement Protocol purchase request returned HTTP 204?

Because HTTP 204 only means Google accepted the request. The GA4 Measurement Protocol production endpoint does not return errors even for malformed payloads. Acceptance, storage, session joining, and traffic source attribution are four separate things, and only the first is confirmed by the response code.

Why do _ga_tracked=1 and wpm_google_analytics_4_mp_purchase_hit=1 not guarantee GA4 source, medium, and campaign attribution?

wpm_google_analytics_4_mp_purchase_hit is written right after the request is dispatched, without checking the response, purely to prevent duplicate sends. It records that the Pixel Manager did its job, not that GA4 attributed the result. _ga_tracked is not a Pixel Manager key at all, so whatever it means is defined by the plugin or integration that wrote it.

How can I check whether Pixel Manager used the browser GA4 client ID or an anon_* fallback?

Enable the logger at Debug level with Log HTTP requests turned on, then read the json payload: line for the GA4 request in /wp-content/uploads/wc-logs/pmw-*.log. See Diagnosing a specific order.

Yes, indirectly, because they determine whether the _ga cookie exists to be captured. Note the asymmetry: denying statistics consent normally suppresses the server-side purchase entirely rather than sending an anon_* one. You only get anon_* from a consent restricted visit when "always send server-side events" is enabled. Blocked or cleared storage, and iframe checkouts, produce anon_* without any consent involvement.

What information should I send support when a purchase uses anon_*?

See When to contact support.

Make more money from your ads with high-precision tracking