Preserve the Referrer
Carry the original visitor source across the interstitial so Google Analytics still sees where traffic came from.
Overview
When an uncertain visitor passes through the interstitial challenge, the browser reloads into your protected page. That reload erases the original referrer, so analytics on the page attributes the visit to your own site instead of the real source (Google, a newsletter, a partner link).
Centinel preserves the original source in a session-scoped value named _centinel_ref, kept in the browser's sessionStorage. This page explains why the loss happens and how to feed the saved value into Google Analytics.
Why the referrer is lost
The interstitial is a real page load. To send the visitor on to your content, it calls location.reload(). A reload (like a redirect) does not carry the previous page's referrer forward: after it, both document.referrer and the Referer request header become the interstitial's own URL. The visit looks like a self-referral from your own domain.
JavaScript cannot fix this on its own. document.referrer is read-only, and Referer is a forbidden header that scripts may not set on a top-level navigation. The only document that still holds the true upstream referrer is the interstitial itself, before it reloads.
The _centinel_ref value
While it is still running, the interstitial captures the upstream referrer and writes it to sessionStorage so it survives the reload. sessionStorage is scoped to the tab and origin, so the value is there when your page loads but never travels to your server the way a cookie would.
Prop
Type
Two things to know about the value:
- Origin only. The entry holds the referrer's origin (
https://www.google.com), never the full path or query. That is all an analytics tool needs for source attribution, and it stays free of personal data regardless of the referring site'sReferrer-Policy. - Cross-origin only. It is written only when the visitor arrived from a different origin. A same-origin visit (or a retry of the interstitial itself) leaves nothing behind, so it never overwrites a good value with your own URL.
The value is absent when there was no cross-origin referrer. Always treat it as optional: if it is missing, fall back to the browser's normal behavior.
Read the value
Read _centinel_ref from sessionStorage. Remove it right after reading: the referrer belongs to this one page view, and clearing it stops the origin from being reused on later navigations in the same tab.
function centinelReferrer() {
const ref = sessionStorage.getItem('_centinel_ref');
if (ref) sessionStorage.removeItem('_centinel_ref');
return ref || undefined;
}It returns the original origin (for example https://www.google.com), or undefined when nothing was stored.
Send it to Google Analytics
Google Analytics 4 reads document.referrer to derive source and medium. Because the reload has already overwritten that, pass the saved origin to gtag explicitly with the page_referrer parameter. Set it in the config call so it applies to the automatic first page view.
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
function centinelReferrer() {
const ref = sessionStorage.getItem('_centinel_ref');
if (ref) sessionStorage.removeItem('_centinel_ref');
return ref || undefined;
}
const ref = centinelReferrer();
gtag('config', 'G-XXXXXXX', ref ? { page_referrer: ref } : {});
</script>When the value is missing, the snippet configures GA with no override and the page behaves as usual. Replace G-XXXXXXX with your own measurement ID.
Other analytics tools
The pattern is the same for any tool: read _centinel_ref before the tool records its first page view, then hand the value to whatever referrer or source field that tool exposes. That might be a referrer option in the tracker's init call or a custom property on the first event. The value lives in sessionStorage, so it stays in the browser and is never sent to your server.
The read snippet above works with any of them today. We'll add concrete setups for specific tools here as we write them.