Skip to content

Consent-based GTM setup for generating and persisting a long-lived, secure user ID cookie — ITP/ETP-compliant, GA4-ready, and fully privacy-aware.

License

Notifications You must be signed in to change notification settings

mediafaktur/gtm-custom-user-id-cookie

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GTM Custom User ID Cookie (CUIC)

Consent-based, long-lived first-party ID cookie for privacy-friendly user tracking in restrictive environments.

Overview

Custom User ID Cookie (CUIC) is a solution specifically designed for tracking setups built on Google Tag Manager (GTM). It enables the generation and persistence of a random user ID across sessions via a secure, first-party HTTP-only cookie. The ID is generated client-side in GTM (based on user consent, if applicable) and made available immediately — even before the cookie is set — for GA4 tracking and other downstream integrations.

CUIC is fully compatible with ITP/ETP restrictions and enables stable cross-session identification in Safari and Firefox. It supports the use of user_id in both client- and server-side tracking architectures.

All configuration of key behaviors — such as cookie name, expiration, refresh policy, and visibility — is managed directly in GTM. No changes to the PHP files are required during setup, maintenance, or testing.

Key Features

  • Persistent first-party, secure, HTTP-only cookie (SameSite=Lax)
  • ID available on first pageview – usable before the cookie is stored
  • Fully consent-controllable via GTM
  • Compatible with Safari/Firefox ITP/ETP restrictions
  • HTTP-only cookie value accessible via GTM data layer
  • Entire behavior (refresh, name, expiration) controlled via GTM
  • Optional fallback via if XHR is blocked
  • Ideal for GA4 user_id and server-side tracking setups

What Problem Does CUIC Solve?

🔍 Problem ✅ CUIC Solution
1st-party, long-lived cookie required, but:
only valid if set server-side with secure, same-origin conditions
CUIC sets the cookie server-side on the main domain using PHP — not via JavaScript
Consent is required before setting any ID, including via server CUIC integrates seamlessly with GTM consent triggers, ensuring privacy compliance
GA4 and server must use the same ID immediately, even before the cookie exists CUIC uses a central variable (jsUserIdResolve) to generate or reuse the ID and send it simultaneously to GA4 and the cookie handler
On subsequent pageviews, the HttpOnly cookie is not accessible via JS, and the ID must still be available in GTM CUIC exposes the cookie value via a PHP dataLayer snippet (cuic_datalayer-snippet.php), making the ID available before GTM loads
Multiple entry points / pageviews must not generate multiple IDs CUIC ensures consistent logic in both GTM and PHP: existing values are always reused if present (in dataLayer or cookies)
Safari and Firefox block or shorten JS-set cookies CUIC fully complies with Safari/Firefox ITP: 1st party, secure, SameSite=Lax, server-set, HttpOnly
XHR requests may fail due to ad blockers or ITP CUIC includes an automatic fallback using an image GET request if the main XHR fails

Architecture & Data Flow

The diagram below illustrates the CUIC cookie lifecycle across first and subsequent pageviews:

CUIC Architecture & Data Flow

Components

  • cuic_controller.html
    GTM Custom HTML tag that sends the ID to the server-side cookie handler – includes XHR logic with fallback image request
    Triggers cookie creation/update after consent; configurable via GTM variables

  • cuic_cookie-handler.php
    Server-side handler that sets the cookie via POST or GET – supports dynamic config via GTM
    Used by the controller tag to persist the ID as a secure, SameSite, HTTP-only cookie

  • cuic_datalayer-snippet.php
    PHP snippet which exposes the cookie value to the dataLayer via PHP in non-cached environments – required when using HttpOnly cookies
    Ensures ID is available on first pageload

  • cuic_datalayer-snippet_cached.php
    JavaScript-based alternative for use on fully cached pages (e.g. WordPress with page caching)
    Loaded via <script src="/...">; executes server-side, delivers JS response

  • jsUserIdResolve.js
    Central GTM variable that checks for an existing value in the dataLayer (from cookie snippet or previous tag push) or creates a new ID on first pageview
    Ensures consistent value at all times

Installation Guide

  1. Deploy the server scripts to your main domain (same origin as your GTM container):

    • /cuic_cookie-handler.php
      → receives the Custom User ID and sets the tkncstm cookie (via POST or GET)

    • /cuic_datalayer-snippet.php
      → for non-cached environments
      → inject directly into the HTML <head> via PHP, before the GTM container
      → ensures the Custom User ID is available synchronously at page render time
      or alternatively:
    • /cuic_datalayer-snippet_cached.php
      → for cached or static environments (e.g. full-page caching, CDNs)
      → embed via <script src="/cuic_datalayer-snippet_cached.php"> in the <head>
      → returns a dynamic JavaScript response with the dataLayer push, bypassing HTML caching
  2. Create GTM variables:

    • Add jsUserIdResolve.js as a Custom JavaScript Variable
    • Name it jsUserIdResolved or similar
  3. Add the GTM tag:

    • Use cuic_controller.html as a Custom HTML Tag
    • Adjust path to /cuic_cookie-handler.php if needed
    • Reference the jsUserIdResolved variable in the tag
    • Trigger only after valid consent
  4. Make the ID available to GA4:

    • Use {{jsUserIdResolved}} as user_id in your GA4 Config and Events
  5. Customize behavior via GTM:

    • All cookie parameters (name, refresh, maxAge, httpOnly) are configurable via inline variables in the tag
    • No PHP edits required

Consent & Privacy

  • CUIC should only run after user consent (fully controlled via GTM)
  • No personally identifiable information (PII) is stored
  • No fingerprinting, no localStorage
  • Fully compliant with ITP, ETP, GDPR, and ePrivacy standards

Use Case: Testing Multiple Cookie Variants

CUIC makes it easy to test different cookie configurations (e.g. name, expiration, visibility, refresh behavior) without modifying any server-side code. Just duplicate the GTM tag (cuic_controller.html) and adjust the inline config:

  • cn: cookie name (e.g. tkncstm_test)
  • refresh: 1 = extend on every visit, 0 = set once
  • httpOnly: 1 = HTTP-only (default), 0 = JS-readable
  • maxAge: cookie lifetime in seconds (e.g. 3600 for 1 hour)

You can run multiple variants in parallel using different GTM tags and triggers — all handled by the same cuic_cookie-handler.php on the server.

License

MIT – see LICENSE

Author

/ MEDIAFAKTUR – Marketing Performance Precision, https://mediafaktur.marketing
Florian Pankarter, fp@mediafaktur.marketing