Skip to Content

Server-side GA4 purchase now joins the buyer’s web session

Shipped 2026-07-06

Verifying the live BigQuery export a few days after the Q3 analytics cutover showed every server-side purchase event using a synthetic fallback client_id (<member_id>.0) instead of the real GA client — so purchases never joined the member’s web session (attribution defaulted to direct/none) and session_id was never set. User-ID stitching still worked; session/source attribution of revenue did not.

  • Root cause: the api read the GA client_id from the _ga cookie, but the www→api proxy is a server-to-server hop that strips it. The client_id + session_id are now captured client-side (gtag('get', …)) and passed to the api as query params, then persisted in the Stripe PaymentIntent metadata.

  • The 100%-off coupon path (which fires no webhook) now emits the same purchase with value: 0, so fully-comped memberships still count.

  • role_id normalized on read: the BigQuery v_events view coalesces the int/string × user-property/event-param shapes to a single STRING (GA4 coerces the numeric strings web/api send to int, while the app keeps string).

  • PR: #765 

  • Follows: TUN-801 

Last updated on