client_id

By Lucas Brandao · São Paulo · verified 2026-05-04 · edit on GitHub

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:

  1. Returning vs new users. "Was this device seen in the last 30 days?" is a client_id lookup against a recency table.
  2. Multi-touch attribution. Walking the touchpoint chain — paid-search Monday, organic Wednesday, direct conversion Friday — requires a single client_id on all three sessions.
  3. Audience Builder cohorts. "Users who viewed the pricing page twice in 14 days" is a count of distinct client_id rows 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.

ToolStable cross-day identityWhat replaces it
GA4client_id (2-year cookie)
Plausiblenoneper-day visitor hash
Fathomnoneper-day visitor hash
Matomo cookied mode_pk_id cookieconfigurable max-age
Matomo cookielessnoneper-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.

Gotcha

If your team genuinely depends on multi-touch attribution, the migration target is not a cookieless tool — it is Matomo with cookies enabled, plus a consent banner. That preserves the join. The trade-off is the cookie banner you came to GA4 to escape. There is no free version of this trick.
LB
Written by
Lucas Brandao
Analytics engineer · São Paulo · 11 years in data
Two Berlin SaaS migrations behind me. I write migrateanalytics.com as a public utility — no product, no affiliate, no consulting. All measurements are reproducible; raw data lives on GitHub.
v1 · 2026-05-04 · first publication. · edit on GitHub →