client_id
client_id is the field GA4 uses to stitch sessions, events, and devices into a single browser-level identity. It looks like 1843720384.1714291234 — two integers, a dot, written into the _ga first-party cookie on first pageview, read on every subsequent hit, and sent with every event payload to Google's collector. It is the join key that turns a stream of events into a "user".
How GA4 generates it
On first hit, the GA4 tag (gtag.js or GTM) generates a random 32-bit integer, concatenates a UNIX timestamp, and writes the result to a cookie named _ga with a 2-year max-age. Every later event reads that cookie and attaches the value as client_id on the request. Inside BigQuery export, the column is user_pseudo_id — same string, different name. The mapping is 1:1.
What the join lets GA4 do
Three things, all of which depend on a stable identifier persisting across sessions:
- Returning vs new users. "Was this device seen in the last 30 days?" is a
client_idlookup against a recency table. - Multi-touch attribution. Walking the touchpoint chain — paid-search Monday, organic Wednesday, direct conversion Friday — requires a single
client_idon all three sessions. - Audience Builder cohorts. "Users who viewed the pricing page twice in 14 days" is a count of distinct
client_idrows that match a predicate.
How cookieless tools do not do this
Plausible, Fathom, Umami, and Matomo-in-cookieless-mode all rotate identity at midnight UTC. The hash that identifies a visitor on Monday is not the hash that identifies them on Tuesday — by construction, the daily salt is fresh. There is no equivalent of client_id. There is no equivalent of _ga. The join is gone.
| Tool | Stable cross-day identity | What replaces it |
|---|---|---|
| GA4 | client_id (2-year cookie) | — |
| Plausible | none | per-day visitor hash |
| Fathom | none | per-day visitor hash |
| Matomo cookied mode | _pk_id cookie | configurable max-age |
| Matomo cookieless | none | per-visit fingerprint |
What you lose on migration
Returning-visitor percentages collapse to a daily approximation. Multi-touch attribution disappears entirely — last-click via UTM is what remains. Audience cohorts dependent on multi-day windows cannot be reconstructed; you can rebuild last-7-day cohorts from server-side data if you have a user_id of your own (logged-in users), but anonymous-traffic cohorts are gone.