What do the fields inside the _ga and _gid cookies actually mean, and why would one be empty?
Quick answer
The _ga cookie's value follows the pattern GA1.2.1234567890.1690000000: GA1 is a fixed version prefix, the next number (usually 1 or 2) indicates how many domain levels the cookie is scoped to, and the final two numbers are the random client identifier and the Unix timestamp of the client's first visit - the same two numbers you'd extract for a Measurement Protocol client_id. _gid holds a similar but session-oriented client identifier and expires after 24 hours by design. Either cookie showing empty or absent almost always means it was blocked by browser privacy settings, cleared before the page finished loading, or never written because analytics consent hadn't been granted yet.
Why This Happens
These cookies are written by GA4's JavaScript library the first time it runs successfully on a domain, using document.cookie. If anything prevents that JavaScript from executing fully - an ad blocker, a strict browser privacy mode (Safari's ITP, Firefox's Enhanced Tracking Protection), or a consent banner that hasn't yet granted analytics_storage - the cookie is either never written, or is written and then immediately cleared by the browser's own anti-tracking logic.
It's also possible to see a cookie present but with an unexpected shape: if your site recently migrated domains, changed its cookie domain scope setting, or moved between subdomains without cross-domain configuration, a new _ga cookie can be issued with a fresh client ID and timestamp, effectively starting a new identity for a returning visitor, which shows up as odd-looking 'first visit' timestamps that don't match a person's actual first-ever visit.
Fix It
Check whether analytics_storage consent is actually being granted
If using Consent Mode, confirm the gtag('consent', 'update', { analytics_storage: 'granted' }) call actually fires when a visitor accepts, and fires before (or is correctly re-applied after) the GA4 tag attempts to set its cookies.
Test with browser privacy features temporarily disabled
Load the site in a browser with tracking protection features off (or in a browser known to be more permissive, like Chrome in a non-Incognito profile) to isolate whether the missing cookie is a browser-side block rather than a site-side bug.
Confirm your cookie domain configuration matches your actual domain structure
In GA4's tag settings (or GTM's GA4 Configuration tag), the 'Fields to set' / cookie domain setting should match how your site actually uses subdomains - an overly narrow or overly broad domain setting can cause the cookie to be rejected or scoped incorrectly.
Don't try to read or write these cookies manually in your own code
Treat _ga/_gid as GA4-owned and read-only for your own scripts (useful for extracting a client_id, per the Measurement Protocol page) - writing to them directly can conflict with GA4's own cookie-refresh logic and produce inconsistent client identities.
How To Verify It Worked
In the browser's DevTools > Application > Cookies panel, load the page fresh (after clearing cookies for the domain) and confirm both _ga and _gid appear within a second or two of the GA4 tag executing, with values matching the GA1.N.number.number pattern described above.
If a cookie is still missing after confirming consent is granted, open the Network tab and check whether the GA4 collect request itself is being sent at all (filter for collect) - if the request never fires, the problem is upstream of cookies entirely (the tag isn't loading); if it fires but no cookie appears, that points specifically to browser-level cookie blocking.
Still Not Fixed?
We audit and fix GA4 implementations for a living - if this doesn't resolve it, the next step is usually a full event-by-event audit.
Talk to a GA4 Consultant