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_idfrom the_gacookie, but the www→api proxy is a server-to-server hop that strips it. Theclient_id+session_idare 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
purchasewithvalue: 0, so fully-comped memberships still count. -
role_idnormalized on read: the BigQueryv_eventsview coalesces the int/string × user-property/event-param shapes to a single STRING (GA4 coerces the numeric strings web/api send toint, while the app keepsstring). -
PR: #765
-
Follows: TUN-801