Server-side GTM cookie and FPID reference
last verified · against GA4 cookie and server-side identification docs as of 2026-07
Reference for server-side GTM FPID cookies: JavaScript Managed versus Server Managed client identification, the _ga, FPID, and FPLC cookies, and migration.
What this is
A lookup for the cookies that carry GA4 identity across a server-side Tag
Manager setup: the JavaScript-set _ga and _ga_<container-id> cookies, the
server-set FPID identifier, and the FPLC cross-domain linker. It records
which cookie each client-identification mode uses, how the two modes are
selected, and the browser lifetime caps that motivate moving identity to the
server.
Cookie inventory
| Cookie | Purpose (per docs) | Set by | Readable by | Default lifetime |
|---|---|---|---|---|
_ga |
“Used to distinguish users.” Stores the GA4 client ID | On-page gtag, via document.cookie |
Browser JavaScript | 2 years (configured) |
_ga_<container-id> |
“Used to persist session state.” | On-page gtag, via document.cookie |
Browser JavaScript | 2 years |
FPID |
First Party Identifier; its value sets the outgoing client_id |
Server container, via Set-Cookie header |
Server only (HttpOnly) |
2 years (practitioner-sourced) |
FPLC |
Cross-domain linker; value hashed from FPID |
Server container / GA4 client | Browser JavaScript (not HttpOnly) |
20 hours |
The support page documents _ga and _ga_<container-id> by name, purpose, and
2-year default. The cookie name FPID, its HttpOnly flag, and its exact
Max-Age are not stated on the official Google pages read here; those specifics
are corroborated by practitioner sources (Simo Ahava, InfoTrust, iDimension) and
are flagged as officially under-documented. The FPID value is a hash that
incorporates a server-side seed, so it cannot be deduced from _ga with
client-side code. Internal cookie value formats are not vendor-documented; treat
any described layout as reverse-engineered.
Client identification modes
The Cookies and client identification setting on the built-in Google
Analytics: GA4 server client selects which cookie supplies the outgoing
client_id.
| Mode | Identifier source | Cookie | Cookie readable by | ITP / JS-cookie truncation |
|---|---|---|---|---|
| JavaScript Managed | Incoming &cid parameter |
_ga |
Browser JavaScript | Subject to browser caps |
| Server Managed | FPID cookie, preferred over incoming &cid |
FPID |
Server only (HttpOnly) |
Not truncated the way a JS-set cookie is |
- JavaScript Managed is the default and the only method that works until the server container’s domain settings are changed.
- Server Managed writes a first-party
FPIDcookie by default and parses the identifier from it, preferring theFPID-derived value over the incoming&cid. - The server client’s mode governs which value the server uses as
client_id, not whether on-page gtag writes_ga/_ga_<container-id>; gtag still manages those client-side cookies regardless of the mode. This interaction is an inference, not officially confirmed. - Durable, HttpOnly
FPIDonly materializes when the server container is served from a same-site first-party subdomain. On the default vendor domain,FPIDloses its first-party durability (domain and transport wiring is covered in the first-party transport reference and not duplicated here).
gtag cookie customization (JavaScript-set cookies)
Options passed to the on-page Google tag that shape the _ga cookies.
| Field | Effect | Notes |
|---|---|---|
cookie_expires |
Cookie lifetime in seconds | 2419200 = 28 days; 0 = session cookie that expires on browser close |
cookie_prefix |
Prepends a prefix, so _ga becomes <prefix>_ga |
Changing the name orphans existing cookies (identity reset) |
cookie_update |
Boolean; default true |
The cited source lists it without describing behavior |
cookie_domain |
Domain the cookie is scoped to | Defaults to the highest possible level (blog.example.com scopes to example.com); localhost uses 'none' |
Cookie expiry can be reconfigured in Analytics settings. GA identity is keyed to
the exact cookie name, so changing cookie_prefix (or otherwise renaming the
cookie) makes returning visitors appear as new users.
Browser cookie-lifetime caps
Browsers cap the lifespan of first-party cookies when a user does not return, independently of GA4’s configured 2-year expiry.
| Browser | Cap on first-party cookie lifespan |
|---|---|
| Chrome | 400 days maximum |
| Safari | 7 days |
The Safari cap applies to JavaScript-set (document.cookie) cookies such as
_ga. A server-set HttpOnly FPID avoids that ITP truncation and improves
returning-user durability. How the 400-day and ITP caps apply to a server-set
HttpOnly cookie in practice, and whether FPID inherits cookie_expires or a
fixed Max-Age, are not confirmed on an official page.
Migration: JavaScript Managed to Server Managed
The Migrate from JavaScript Managed Client ID option retrofits server-managed identification onto a live property without a one-time inflation of new-user counts.
| Population | Behavior |
|---|---|
Existing users (have _ga) |
Keep the _ga client_id until that _ga cookie is deleted or the Client ID is reset, then move to FPID |
| Brand-new users | Get FPID directly |
| During the transition | Both the client-side (_ga) and server-side (FPID) IDs can appear for events, visible in the BigQuery export |
New deployments can enable Server Managed directly. The transition period
resolves as _ga cookies age out; plan identity-dependent analyses (LTV,
cohorts) around the migration window.
Enabling and disabling FPID (the Name field)
| Name field value | Effect |
|---|---|
FPID (or the intended name) |
Client writes FPID via Set-Cookie and reads it to generate the outgoing client_id |
| Blank / empty string | Client neither writes nor reads FPID; identification falls back to the incoming &cid / _ga |
Blanking the Name field is the documented way to intentionally prevent the
server container from setting FPID (for example, to honor a consent state or
keep a pure client-side _ga setup). The full set of server-managed cookie
settings fields (Domain, Path, SameSite, Secure, Max-Age) beyond Name was
not confirmed on any page read here; treat that field list and its defaults as
unverified. SameSite / Secure defaults of the JavaScript-set _ga cookies
were also not confirmable and are flagged as unverified.
Cross-domain identification (FPLC)
Because FPID is HttpOnly and unreadable by the JavaScript cross-domain
linker, the GA4 client sets a companion non-HttpOnly FPLC cookie for
cross-domain stitching.
| Item | Value |
|---|---|
| Cookie | FPLC (cross-domain linker) |
HttpOnly |
No (JavaScript-readable) |
| Value | Hashed from the FPID value |
| Lifetime | 20 hours |
| Requirement | Source and target server containers must share the same GTM account |
If a user stays on a page longer than 20 hours before clicking a cross-domain
link, the linker value is stale and stitching can fail. FPLC is a
session-scoped bridge for cross-domain tracking, not a durable identifier.
Gotchas
- Returning Safari / iOS visitors are counted as new; user and session counts inflate. Cause:
_gais JavaScript-set viadocument.cookieand Safari ITP caps client-script-set first-party cookies to about 7 days, so theclient_idis lost between visits. Fix: switch the GA4 client to Server Managed so the identifier lives in theHttpOnly, server-setFPIDcookie (requires a genuine same-site first-party subdomain — see the first-party transport reference). - Switching an existing site to Server Managed spikes “new users” and duplicates users. Cause: the
FPID-derivedclient_iddiffers from the pre-existing_gaclient_id, so established users are re-identified as new. Fix: enable Migrate from JavaScript Managed Client ID so returning users keep_gauntil it is deleted or reset, then move toFPID; only new users getFPIDimmediately. - Cross-domain tracking stops stitching after enabling FPID / Server Managed. Cause:
FPIDisHttpOnlyand unreadable by the JS linker, and/or theFPLCcookie (20-hour lifetime) is missing or stale, or the two containers are in different GTM accounts. Fix: ensure the non-HttpOnlyFPLCis present, the click is within its 20-hour window, and both server containers belong to the same GTM account. - The same person shows two different
client_idvalues during migration (for example in BigQuery). Cause: expected behavior — the client-side_gaID and the new server-sideFPIDID coexist until the old_gacookie expires or is deleted. Fix: treat as transitional; it resolves as_gacookies age out. Plan identity-dependent analyses around the window. FPIDis never written and identification silently falls back to&cid/_ga. Cause: the Name field in the server-managed cookie settings is an empty / blank string, which disables both writing and readingFPID. Fix: set the Name field toFPID(or the intended name); conversely, blank it deliberately to preventFPIDfor a consent gate.- Setting a
cookie_prefixor renaming GA cookies makes all users appear new. Cause: GA identity is keyed to the exact cookie name; changing the name / prefix orphans existing cookies. Fix: do not change the cookie name / prefix after launch; if you must, expect an identity reset and plan for it. FPIDis set but behaves like a third-party cookie or has a short lifetime. Cause: the server container is served from a non-same-site host (the default vendor domain) rather than a first-party subdomain of the site. Fix: map the server container to a first-party subdomain (covered in the first-party transport reference — not duplicated here).
Quick recipes
Customize the JavaScript-set GA4 cookies from the on-page tag:
// Configure _ga / _ga_<container-id> lifetime and scope.gtag('config', 'G-XXXXXXX', { cookie_expires: 2419200, // seconds; 2419200 = 28 days cookie_domain: 'example.com', // default is the highest possible level cookie_update: true // boolean, default true});Make _ga a session cookie that clears on browser close:
gtag('config', 'G-XXXXXXX', { cookie_expires: 0 // 0 = session cookie, expires on browser close});Read the JavaScript-accessible GA cookies from the browser (note FPID is
absent because it is HttpOnly):
// Split each cookie on its FIRST '=' so base64 values are not mangled.const jar = Object.fromEntries( document.cookie.split('; ').map((c) => { const eq = c.indexOf('='); return [c.slice(0, eq), c.slice(eq + 1)]; }));
console.log('client id cookie:', jar['_ga']); // e.g. _gaconsole.log('session state:', jar['_ga_XXXXXXXXXX']); // _ga_<container-id>console.log('cross-domain linker:', jar['FPLC']); // present, 20h TTLconsole.log('FPID visible to JS:', jar['FPID']); // undefined (HttpOnly)Confirm the server sets FPID via the response header, and that it is
HttpOnly (server-only):
# The server container writes FPID in the Set-Cookie response header.# Dump response headers from a GET (-D -) and discard the body (-o /dev/null).curl -s -o /dev/null -D - "https://metrics.example.com/g/collect?v=2&tid=G-XXXXXXX" \ | grep -i 'set-cookie'# Expect a Set-Cookie: FPID=...; HttpOnly line (FPID is not readable by document.cookie).Avoid an accidental identity reset from renaming cookies:
// A cookie_prefix renames _ga to <prefix>_ga. GA identity is keyed to the// exact cookie name, so changing this AFTER launch orphans existing cookies// and every returning visitor is counted as new. Do not change post-launch.gtag('config', 'G-XXXXXXX', { cookie_prefix: 'shop' // _ga becomes shop_ga (plan for the reset)});Related
- Hub: Server-side tagging guides
- Server-side GTM first-party and transport URL reference
- Server-side GTM clients and tags reference
Sources
Official pages these values were read from (read 2026-07-20):
- [GA4] Cookie usage on websites — Analytics Help (read 2026-07-20)
- Configure and customize cookies — Tag Platform (read 2026-07-20)
- Configuring the GA4 data stream with server-side tagging (read 2026-07-20)
- Send data to server-side Tag Manager (read 2026-07-20)
- Cookies and user identification — GA4 collection (read 2026-07-20)
The FPID cookie name, its HttpOnly flag, the Set-Cookie delivery, the
~2-year lifetime, the FPLC linker (20-hour TTL), the blank-Name-field
behavior, and the migration mechanics are corroborated by practitioner sources
rather than an official Google page, and are flagged above for in-product
verification (read 2026-07-20):
- The FPID cookie for Google Analytics in server-side tagging — Simo Ahava (read 2026-07-20)
- Cross-domain tracking with server-side FPID cookie — Simo Ahava (read 2026-07-20)
- Prevent SGTM from setting the FPID cookie — Simo Ahava (read 2026-07-20)
- Server-side client configuration demystified — InfoTrust (read 2026-07-20)
- Server-side GTM, HTTP cookies and Google Analytics — iDimension (read 2026-07-20)
Changelog
- — Initial version, verified against official documentation.