Sending the Source and Landing Page to a CRM
UTM parameters only tell part of the attribution story. The moment a visitor arrives without a UTM — direct traffic, organic search, an untagged referral link — your CRM has no idea where they came from or what page they landed on. This recipe closes that gap with two additional GTM variables and a single session-start cookie write.
This builds directly on two earlier posts. UTM values are covered in "Using GTM to pass your UTMs into your CRM", and the anonymous browser client ID — sourced from a 1st-party cookie variable built on the _ga cookie — is covered in "Anonymous Browser Client Id and Session Id." Although only the last two nodes of the _ga value are technically the client ID, there's no harm in keeping the entire cookie value when passing it to the CRM.
The Missing Piece: Source and Landing Page
UTMs and the client ID are not the complete picture. Two additional facts still need to reach the CRM: 1) the source of traffic, in the absence of a utm_source, and 2) the landing page the visitor actually arrived on. Fortunately, both are a small matter to capture.
The GTM Variables Behind This Recipe
The original implementation relies on five GTM variables working together — two built-in variables that read the browser at the moment of arrival, and three 1st-Party Cookie variables that read back what gets written to cookies at session start. Between them, they cover every value referenced by the scripts further down this post.
| Variable | Type | Purpose |
|---|---|---|
{{Referrer}} | Built-in Variable (Referrer) | The full referring URL the browser reports for this visit, used to test whether the visitor arrived from an external domain. |
{{Page URL}} | Built-in Variable (Page URL) | The full URL of the current page at the moment of session start, written verbatim as the landing page. |
{{Site Landing Has Run Before Cookie}} | 1st-Party Cookie | Reads the siteLandingHasRunBefore cookie. Used as the "undefined" guard so the landing/referrer write only fires once per session. |
{{Site Referral Source Cookie}} | 1st-Party Cookie | Reads the siteReferralSource cookie back out once it has been set, for use in the hidden form field. |
{{Site Landing Page Cookie}} | 1st-Party Cookie | Reads the siteLandingPage cookie back out once it has been set, for use in the hidden form field. |
The two built-in variables (Referrer and Page URL) require no configuration beyond enabling them in GTM's Variables menu under "Configure Built-In Variables." The three 1st-Party Cookie variables each need only a single configuration field: the cookie name (siteLandingHasRunBefore, siteReferralSource, and siteLandingPage respectively), matching the cookie names set by the tag in the next section.
Writing the Referrer and Landing Page to a Session Cookie
With the variables in place, a single tag does the actual work. It runs once per session, at session start, and only writes the referrer and landing page to a 1st-party session cookie if the referrer's domain differs from the site's own domain — there's no value in recording the site as its own referral source.
<script type="text/javascript">
/* Get Domain */
function getDomainName() {
var hostName = window.location.hostname.toLowerCase();
return hostName.substring(hostName.lastIndexOf(".", hostName.lastIndexOf(".") - 1) + 1);
}
/* Set Cookie */
function setCookie(cookieName, cookieValue) {
var theDomain = getDomainName();
document.cookie = cookieName + "=" + cookieValue + "; path=/; SameSite=None; Secure; domain=." + theDomain + ";";
}
if (!({{Site Landing Has Run Before Cookie}})) {
setCookie("siteLandingHasRunBefore", true);
}
var theDomain = getDomainName();
setCookie("siteLandingPage", {{Page URL}});
if ({{Referrer}}.search(/[0-9A-Za-z]+/) >= 0) {
if (!({{Referrer}}.toLowerCase().search(theDomain) >= 0)) {
var arrayReferrer = {{Referrer}}.toLowerCase().replace("https://", "").replace("http://", "").split("/");
setCookie("siteReferralSource", arrayReferrer[0]);
}
}
</script>
A few details worth calling out in this script:
- The "has run before" guard —
{{Site Landing Has Run Before Cookie}}— ensures the landing page write happens once per session rather than re-stamping it on every pageview, which would overwrite the true entry page with whatever page the visitor happens to be on later. - The landing page is written unconditionally on first run, but the referral source is conditional: it only writes if the referrer string contains real characters (i.e., isn't blank — which it would be for direct traffic) and if the referrer's domain doesn't match the site's own domain (i.e., isn't an internal navigation being mistaken for a referral).
- The referrer is reduced to just its hostname via
.split("/")[0]after stripping the protocol, so the cookie stores something likegoogle.comrather than a full search results URL.
The trigger for this tag should be the same session-start trigger used elsewhere in your container — typically a custom event fired once per session, or a "first pageview" condition built on the same "has run before" pattern shown above.
Reading the Cookies Back for the Form
Once the cookies exist, two 1st-Party Cookie variables — {{Site Referral Source Cookie}} and {{Site Landing Page Cookie}} — read them back at any later point in the session, including several pages later when the lead form finally appears.
Sending the Values Into the CRM Form
The last step mirrors the pattern used for UTMs and the client ID: write the cookie-sourced values directly into hidden fields on the form using a Custom HTML tag, triggered on whichever page the form actually appears on.
document.querySelector('input[data-sc-field-name="referralSource"]').value = {{Site Referral Source Cookie}};
document.querySelector('input[data-sc-field-name="landingPage"]').value = {{Site Landing Page Cookie}};
As with every hidden-field example in this series, the selectors above are illustrative — align data-sc-field-name with whatever attribute your own form implementation actually uses, and if the form is an off-site link or an iframe, pass these values as URL query parameters using the same decoration technique covered in "Using GTM to pass your UTMs into your CRM."
What You Now Have in the CRM
- The campaign's UTM values, when present
- The anonymous
_gaclient ID, for joining the lead back to BigQuery or GA4 event data - The actual referral source domain, for the traffic that arrived without a UTM
- The exact landing page the visitor entered on, regardless of how many pages they viewed before reaching the form
Put together, this is a meaningfully more complete attribution record than UTMs alone could ever provide — and it costs nothing more than two built-in variables, three cookie variables, and one small session-start tag.
This post is a Blogger rewrite of an earlier piece originally published on Weebly. The original post illustrated the GTM variable configuration with screenshots; the table above describes those same variables based on the variable names referenced directly in the scripts.
Comments
Post a Comment