Site Landing & Site Referrer Preservation

Site Landing Page & Site Referrer to Cookies in Google Tag Manager — A Complete Recipe Without Custom JavaScript

Persist the user's landing page host, landing page path, and referral source into session or long-lived persistent cookies using only GTM sandboxed Custom Templates. No Custom HTML tags. No new CSP hashes.

Published · Tags: GTM, Google Analytics 4, Cookies, Site Referrer, Landing Page, First-Touch Attribution, User Journey, dataLayer, CSP, GA4

Where did this user first land on your site — and what referred them there? Those two pieces of information are foundational to understanding any user journey. But they only exist at the moment of the first page load. Navigate to a second page, return in a new browser session, or submit a form three days after the original visit, and the browser's native referrer is gone and the landing URL has long since changed. Without a persistence layer, you are flying blind.

This recipe solves that problem cleanly. On the very first Initialisation event — before any other tag fires — it captures the site landing host, landing page path, and referral host, and writes them into browser cookies. Session cookies cover the current visit; persistent cookies with a _1 suffix survive for up to 730 days, recording the user's first ever landing and referral. Both cookie sets flow automatically into every GA4 hit via Shared Event Settings and GA4 User Properties. No Custom HTML tags. No new Content Security Policy SHA-256 hashes required.

⬇ Download the GTM Container JSON from Google Drive

The Core Problem: Landing Context Vanishes After the First Page

A visitor arrives at https://example.com/pricing referred from a partner site at https://partner.example.org/blog/recommended-tools. GA4 records the referral for the session. But the user does not convert. They return three days later by typing the URL directly. GA4 now attributes that second session to direct. The referral source that actually initiated the relationship is invisible.

The same problem applies to your own site's landing pages. Knowing that a user's first ever landing was /pricing versus /blog/use-case-study gives you a completely different picture of their intent and where they are in the funnel — information that is lost the moment they navigate away from that first page.

Cookies are the browser's built-in persistence mechanism for exactly this purpose. This recipe writes the landing and referral context on Initialisation (the very first GTM event) and makes those values available across every subsequent page view, event, and session.

Why this matters beyond utm_source: UTM parameters tell you the campaign-level source a marketer chose to declare. But utm_source is a free-text field — there is nothing enforcing that it contains an actual traffic source. A campaign tagged utm_source=spring-promo tells you nothing about where traffic originated. The site referrer, by contrast, is set by the browser and reflects the actual page the user navigated from. Capturing the referral host independently of UTM tagging gives you a ground-truth signal of traffic origin that is not subject to marketer naming conventions.
Why this matters for user journey analysis: The user's first landing page and first referral source are the starting coordinates of their entire journey on your site. Persisting them in long-lived cookies lets you attach first-touch landing context to any downstream event — form submission, purchase, demo request — regardless of how many sessions have elapsed since that first visit. This enables cohort analysis, funnel analysis by entry point, and lifetime value attribution by acquisition source, none of which are possible if you only have the landing data from the current session.
Why no new CSP hashes are required: The traditional approach to writing cookies in GTM is a Custom HTML tag containing an inline <script> block. Any such script requires its SHA-256 hash to be listed in your Content-Security-Policy header's script-src directive. Every time the script changes — even whitespace — the hash changes and must be redeployed. This recipe uses only GTM sandboxed Custom Templates, which execute inside GTM's own sandbox and require zero additions to your CSP. The cookie-writing logic runs entirely within the GTM runtime — no new hashes, no security team review cycles.

What's Inside the Container

The exported container (site-landing-and-referrer-2-cookies-recipe.json) is organised into three folders, plus the existing Analytics infrastructure and sandboxed Custom Templates.

Folders

FolderContains
Analytics GA4 configuration tag, shared settings variables, environment and stream routing variables, and client ID and timestamp utilities.
Process site landing & site referrer 2 cookies Two tags (session and user/persistent), plus eight Cookie Variable variables reading the landing host, landing path, referral host, and referral path for each track. Fires on Initialisation — the earliest possible GTM event — to capture the landing context before any other tag can fire.
Extend Cookie Life One tag and two supporting variables. Rewrites the persistent cookies on every page visit to refresh their expiry date, ensuring the 730-day window resets on each visit rather than counting from first write.

Tags

TagTypePurpose
Google Analytics Configuration Google Tag (googtag) Standard GA4 configuration tag. Shared Event Settings and User Properties automatically forward landing and referral cookie values on every GA4 hit.
Write site landing & site referrer 2 cookies user Custom Template — Write site landing & site referrer 2 cookies Fires on Initialisation, but only if the landing host and referral host persistent cookies do not already exist (trigger condition: both {{site Referral Host user}} and {{site Landing Host user}} match the empty/null regex). Writes four persistent cookies expiring in 730 days, with the _1 suffix: landHost_1, landPath_1, referHost_1, referPath_1. Because the trigger only fires when the cookies are absent, these values are set exactly once — on the user's first ever visit — and never overwritten.
Write site landing & site referrer 2 cookies session Custom Template — Write site landing & site referrer 2 cookies Fires on Initialisation, but only if the session-level cookies are absent (both {{site Referral Host session}} and {{site Landing Host session}} are empty). Writes four session cookies — landHost, landPath, referHost, referPath — that expire when the browser closes. Refreshed on each new browser session.
Extend Cookie Life Tag Custom Template — Cookie Rewriter Fires on DOM Ready, guarded by the _arrewr sentinel cookie. Rewrites the persistent landing and referral cookies with a refreshed expiry of 720 days from now, without altering their values.

Triggers

TriggerTypeConditionPurpose
Write site landing & site referrer 2 cookies user Initialisation {{site Referral Host user}} AND {{site Landing Host user}} both match ^(undefined|null|0|false|NaN|)$ Fires the persistent-cookie write tag on the very first page load of the user's first ever visit. The Initialisation event type ensures this runs before GA4 configuration and before any other tag fires. The double condition ensures the write only happens once — when both persistent cookies are still absent.
Write site landing & site referrer 2 cookies session Initialisation {{site Referral Host session}} AND {{site Landing Host session}} both match ^(undefined|null|0|false|NaN|)$ Fires the session-cookie write tag on the first page load of each new browser session. Because session cookies expire when the browser closes, the condition will be true at the start of each new session, refreshing the session-level landing context.
Extend Cookie Life Trigger DOM Ready {{Extend Cookie Life Already Ran Cookie Value}} matches ^(undefined|null|0|false|NaN|)$ Fires the Cookie Rewriter tag once per page load. The sentinel cookie _arrewr prevents the tag firing more than once per page even if DOM Ready fires multiple times.

Custom Templates

TemplateAuthorPurpose
Write site landing & site referrer 2 cookies drewspen Reads the current page's host, page path, document referrer host, and document referrer path, and writes them to browser cookies with configurable expiry (session or persistent), a cookie name suffix, root domain scoping, and optional URI decoding. Runs entirely within the GTM sandboxed template runtime — no Custom HTML, no CSP implications.
Cookie Rewriter drewspen Rewrites a specified list of existing cookies with a refreshed expiry date, converting static expiry windows into rolling windows that extend on each visit.
If Else If — Advanced Lookup Table Sublimetrix Powers coalesce and routing logic elsewhere in the container.
Timestamp Sublimetrix Reads Unix timestamps from GA4 session and client cookies for shared event parameters.
Get Root Domain drewspen Extracts the registrable root domain for cookie scoping, ensuring cookies are accessible across subdomains (e.g. www.example.com and app.example.com).

Two Tracks: Session Cookies and Persistent Cookies

The recipe deliberately writes each landing and referral value twice — once as a session cookie and once as a persistent cookie. This gives you two distinct attribution windows with a single implementation: what happened in this session, and what happened on the user's first ever visit.

Session Cookies — Current Visit Context

Session cookies expire automatically when the browser is closed. They record the landing page and referral source for the current visit only. This is ideal for within-session attribution: if a user arrives from a partner site, browses three pages, and completes a download, the session cookie carries the referral host through the entire session — even though document.referrer changes on every page navigation.

Cookie NameTypeContent
landHostSessionHostname of the first page the user landed on this session (e.g. example.com)
landPathSessionPage path of the first landing page this session (e.g. /pricing)
referHostSessionHostname of the referring site at session start (e.g. partner.example.org)
referPathSessionFull referrer path at session start (URI-decoded)

Persistent Cookies — First-Touch Attribution Across Visits

Persistent cookies survive browser restarts and are retained for up to 730 days (2 years) from initial write. The _1 suffix is the distinguishing convention — these cookies hold the values from the user's very first visit. Because the user-level trigger only fires when both cookies are absent, the values are written exactly once and never overwritten by subsequent visits. When the Cookie Rewriter runs on later visits, it refreshes the expiry without touching the values, preserving the original first-touch context.

Cookie NameTypeExpiryContent
landHost_1Persistent730 days (rolling)Hostname of the user's first ever landing page
landPath_1Persistent730 days (rolling)Page path of the user's first ever landing page
referHost_1Persistent730 days (rolling)Hostname of the referring site on the user's first ever visit
referPath_1Persistent730 days (rolling)Full referrer path on the user's first ever visit (URI-decoded)

The Rolling Expiry: How the Cookie Rewriter Works

A persistent cookie written once with a 730-day expiry will expire 730 days after it was first written, regardless of how often the user returns. For most use cases, a rolling expiry is preferable — active users should never lose their first-touch attribution simply because they have not visited in 730 days since acquisition.

The Extend Cookie Life Tag achieves rolling expiry by running the Cookie Rewriter template on every page visit. It reads each of the four persistent landing and referral cookies and rewrites them with the same value but a new expiry date set 720 days from the current time. The first-touch values are preserved; only the expiry date changes.

The Sentinel Guard: Firing Exactly Once Per Page

To avoid the Cookie Rewriter firing multiple times per page load, the recipe uses a sentinel cookie named _arrewr. The Extend Cookie Life Trigger condition checks {{Extend Cookie Life Already Ran Cookie Value}} against the regex ^(undefined|null|0|false|NaN|)$. The tag fires only when the sentinel is absent or empty. The Cookie Rewriter template sets _arrewr on its first run, preventing any subsequent firing within the same page load.

Cookie Variables: Reading the Values Back

Eight Cookie Variable variables are included in the Process site landing & site referrer 2 cookies folder, one for each cookie. These use GTM's built-in First-Party Cookie variable type and require no custom code. The landPath and referPath variables are configured with URI decoding enabled; the host variables are not, as hostnames do not require decoding.

Variable NameCookie ReadDecodeTrack
site Landing Host sessionlandHostNoCurrent session
site Landing Page Path sessionlandPathYesCurrent session
site Referral Host sessionreferHostNoCurrent session
site Referral Page Path sessionreferPathYesCurrent session
site Landing Host userlandHost_1NoFirst touch (persistent)
site Landing Page Path userlandPath_1YesFirst touch (persistent)
site Referral Host userreferHost_1NoFirst touch (persistent)
site Referral Page Path userreferPath_1YesFirst touch (persistent)

How Landing and Referral Data Flow Into Every GA4 Hit

The cookie variable values are wired into the Google Tag Shared Event Settings variable as event-scoped parameters and into the GA4 User Properties block. This means the values are forwarded on every GA4 event sent by the container — page views, scroll events, clicks, form submissions, and conversions alike — without any need to touch individual tag configurations.

Shared Event Settings — Landing and Referral Parameters

GA4 Event ParameterGTM VariableAttribution Track
e_cur_landing_host{{site Landing Host session}}Landing hostname for the current session
e_cur_landing_path{{site Landing Page Path session}}Landing page path for the current session
e_cur_referral_source{{site Referral Host session}}Referral hostname for the current session
e_1st_landing_host{{site Landing Host user}}Landing hostname on user's first ever visit
e_1st_landing_path{{site Landing Page Path user}}Landing page path on user's first ever visit
e_1st_referral_source{{site Referral Host user}}Referral hostname on user's first ever visit

GA4 User Properties — Landing and Referral

In addition to event-scoped parameters, the Shared Event Settings variable also populates GA4 User Properties. User Properties persist at the user level in GA4 and are available in audience definitions, Explorations, and BigQuery exports.

GA4 User PropertyGTM VariableAttribution Track
u_cur_landing_host{{site Landing Host session}}Landing hostname for the current session
u_cur_landing_path{{site Landing Page Path session}}Landing page path for the current session
u_cur_referral_source{{site Referral Page Path session}}Referral page path for the current session
u_1st_landing_host{{site Landing Host user}}Landing hostname on user's first ever visit
u_1st_landing_path{{site Landing Page Path user}}Landing page path on user's first ever visit
u_1st_referral_source{{site Referral Page Path user}}Referral page path on user's first ever visit

Architecture: How a Landing Becomes a Cookie Becomes a GA4 Parameter

  1. User lands on the site for the first time. GTM fires the Initialisation event — the very earliest event in the GTM lifecycle, before page view, before DOM Ready, before any other tag.
  2. Both user-level persistent cookie triggers evaluate. Because landHost_1 and referHost_1 do not yet exist, both Cookie Variable variables return empty strings matching the null regex. The trigger fires.
  3. The user-level write tag runs. The Write site landing & site referrer 2 cookies user tag reads the current page hostname, current page path, document referrer hostname, and document referrer path, and writes them as persistent cookies scoped to the root domain (e.g. .example.com), expiring 730 days from now. These values are permanently set for this user.
  4. The session-level write tag also runs. If the session cookies are also absent (new session), the Write site landing & site referrer 2 cookies session tag writes the same four values as session cookies (no expiry — browser-close expiry).
  5. GTM fires DOM Ready. The Extend Cookie Life Trigger checks the _arrewr sentinel. If absent, the Extend Cookie Life Tag rewrites the four persistent cookies with a new 720-day expiry from now.
  6. Cookie Variable variables are evaluated on every GTM event. The eight cookie variables read the current values from the browser for every subsequent event.
  7. Shared Event Settings deliver values to GA4. The six event parameters (e_cur_* and e_1st_*) and six User Properties (u_cur_* and u_1st_*) are included in every GA4 hit automatically.
  8. Days or weeks later, the user returns directly. Their persistent cookies still hold the original first-touch landing and referral values. The session cookies are absent (browser closed), so the session-level write tag fires again, capturing the new session's landing context. The persistent cookies are extended by the Cookie Rewriter but their values are unchanged.
  9. A conversion event fires. GA4 receives both the current-session landing context and the first-ever landing context on the same event hit, allowing multi-session journey analysis in a single query.

Why Sandboxed Templates Do Not Require New CSP Hashes

GTM's sandboxed Custom Template runtime accesses browser APIs through GTM's own internal permission model — not through Content Security Policy. A template that writes a cookie uses GTM's setCookie sandbox API, which executes within code already authorised by the GTM container's existing CSP allowance (the allowance granted to googletagmanager.com).

In contrast, a Custom HTML tag writes a literal <script> element into the DOM. CSP's script-src directive applies to every inline script element. Unless you have unsafe-inline enabled (which defeats much of CSP's purpose) or a matching SHA-256 hash in your CSP header, the browser blocks execution. Every change to that script — adding a comment, reformatting a line, changing a cookie name — changes the hash and requires a CSP header redeployment and typically a security team review cycle.

With sandboxed templates, your CSP never changes when GTM tag logic changes. The entire landing and referral cookie implementation in this recipe is CSP-transparent.

Real-World Use Cases

Identifying the True Referral Source When utm_source Is Not Reliable

Google's convention is that utm_source should identify the actual traffic source — the platform, publisher, or channel that sent the visitor. In practice, many campaigns use utm_source as a free-text label: utm_source=spring-promo, utm_source=email-footer, utm_source=sales-team. These values describe the campaign intent, not the origin of the traffic.

The referral host cookie, set by the browser from document.referrer, reflects where the user actually navigated from — independent of any UTM tagging. A visit tagged utm_source=spring-promo that shows referHost=email.mailprovider.com tells you it was an email campaign. A visit tagged utm_source=newsletter with referHost=t.co tells you the link was actually shared on X (Twitter). The referral host provides a ground-truth origin signal that complements — and sometimes corrects — the UTM source value.

First-Touch Landing Page Analysis for User Journey Mapping

The user's first ever landing page is one of the most predictive signals of their intent and their position in the funnel. A user whose first landing was /pricing is on a fundamentally different journey from one whose first landing was /blog/what-is-x. But without persistent cookies, you can only know the first landing page if the user converted in the same session — which is rare in B2B and considered-purchase categories.

With landPath_1 persisted for up to two years, you can join any downstream event — a contact form submission, a free trial activation, a purchase — to the user's original entry point. In GA4 Explorations or BigQuery, this enables cohort analysis by first landing page, funnel analysis by acquisition path, and lifetime value modelling by initial intent signal.

B2B Multi-Session Lead Attribution

A prospect clicks a LinkedIn post, lands on /case-studies/enterprise, reads for ten minutes, and leaves. The referral host and landing path are stored in persistent cookies: referHost_1=linkedin.com, landPath_1=/case-studies/enterprise. Two weeks later, they return directly, read the pricing page, and submit a demo request form. Your CRM receives hidden form fields populated from the cookie values — and your sales team knows the lead came from LinkedIn via the enterprise case study page, not from direct traffic.

How to Import

  1. Download the JSON file from the Google Drive link.
  2. In GTM, go to Admin → Import Container.
  3. Upload site-landing-and-referrer-2-cookies-recipe.json.
  4. Choose Merge (not Overwrite) to preserve your existing tags and triggers.
  5. Update Measurement Stream ID Production and Measurement Stream ID Development constant variables to your actual GA4 Measurement IDs.
  6. Verify that {{Root Domain}} resolves correctly for your site — this controls the cookie's domain scope. Check its value in GTM Preview mode on your site before publishing.
  7. In GA4, register the following as custom event-scoped dimensions under Admin → Custom definitions → Custom dimensions: e_cur_landing_host, e_cur_landing_path, e_cur_referral_source, e_1st_landing_host, e_1st_landing_path, e_1st_referral_source.
  8. Register the six User Properties under Admin → Custom definitions → Custom dimensions (selecting User scope): u_cur_landing_host, u_cur_landing_path, u_cur_referral_source, u_1st_landing_host, u_1st_landing_path, u_1st_referral_source.
  9. Open GTM Preview mode on a URL with an external referrer and confirm the cookie variables populate in the Tag Assistant panel under the Initialisation event.
  10. Navigate to a second page and confirm that the session and persistent cookie values persist (the landing host should remain the first page URL, not the current page URL).
  11. Close the browser, reopen, and revisit the site directly. Confirm the session cookies are absent (triggering a new session write) and the _1 persistent cookies still hold the original first-visit values.
Cookie consent: Writing persistent cookies that track user journey and referral attribution may require consent under GDPR, CCPA, or equivalent regulations depending on your jurisdiction and how the data is used. Review with your legal team. The recipe writes cookies on the Initialisation event (the very first GTM event); if you operate a consent-managed site, gate both Write tags behind a consent trigger that only fires after the user has accepted analytics or marketing cookies.

What You Can Do With It

  • Attach first-touch landing page and referral source to CRM lead records via hidden form fields — link pipeline and revenue to the user's original entry point without server-side infrastructure
  • Compare e_cur_referral_source (this session's referrer) against e_1st_referral_source (first-ever referrer) in GA4 Explorations to identify multi-channel journeys and mid-funnel referral sources
  • Segment GA4 audiences by u_1st_landing_path to create intent-based audiences (e.g. users whose first landing was /pricing) for remarketing and personalisation
  • Build BigQuery attribution models joining on e_1st_referral_source to compare first-touch referral attribution against GA4's session-based default attribution
  • Identify referral traffic where utm_source does not match the actual referHost — a powerful quality signal for your UTM hygiene audits
  • Measure cohort differences in conversion rate, session depth, and time-to-convert between users by first landing page — enabling landing page optimisation based on downstream outcome data rather than session-level metrics
  • Use e_1st_landing_path as a dimension in GA4 Explorations funnels to understand which entry points drive users towards high-value conversion paths

The full source — including the container JSON and the drewspen sandboxed Custom Templates — is available on GitHub and via the Google Drive download below. If you extend the implementation with additional cookie naming conventions or add complementary UTM cookie tracks, open a pull request or issue.

⬇ Download GTM Container JSON

Comments

Popular posts from this blog

GTM Browser Viewport Measurement

UTM & URL Query String 2 Cookies