* Place inside , BEFORE any analytics scripts on shop. * * Debug: * ?ssl_debug=1 in the URL prints what the script is doing to the console. * --------------------------------------------------------------------------- */ (function () { 'use strict'; // ------------------------------------------------------------------------- // Configuration // ------------------------------------------------------------------------- var BRIDGE_VERSION = '2026.09.28-2'; // keep in step with the header line var APEX_DOMAIN = '.superstratumlabs.com'; var SHOP_HOST = 'shop.superstratumlabs.com'; // The marketing apex ships its own React link decorator (shopLinkAttribution), // which also re-decorates in-place href rewrites this script's observer cannot // see. On the apex this script only CAPTURES origin; it decorates on other // hosts (e.g. calculator.*) that have no bundle. One decorator per host. var APEX_HOST_RE = /^(www\.)?superstratumlabs\.com$/i; var COOKIE_NAME = 'utm_data'; // SESSION-SCOPED, ROLLING. This cookie is not a history store — GA4 and the // BigQuery export own long-term navigation. Its only job is to carry the // CURRENT session's origin across the apex/calculator/shop hops so the last // click survives into Shopify, which cannot resolve it itself. // // 30 minutes of inactivity matches how both GA4 and Shopify define a session, // and the window slides on every page view (see touchCookie), so an active // journey of any length is covered. // // The previous 90-day TTL is what produced the stale-credit bug: with nothing // expiring, buildShopParams fell back to a months-old first touch. Order // #19572 forwarded a 34-day-old Klaviyo campaign onto a visit whose real // referrer was bing.com. A session-length cookie removes that class of error // at the root rather than patching it. var SESSION_MINUTES = 30; var COOKIE_TTL = 60 * SESSION_MINUTES; var DEBUG = /[?&]ssl_debug=1/.test(location.search); var MAX_PATH_LEN = 256; // Hosts whose links we decorate. SHOP ONLY, deliberately. // // Every hop between apex / calculator / shop shares the `.superstratumlabs.com` // cookie, so origin already travels with the visitor on internal hops without // any decoration. Decoration exists for exactly one reason: Shopify reads // attribution from the HTTP request, server-side, before any script runs. So // the ONLY hop that must carry params is the last one into shop. // // This holds for every path shape — apex→calculator→apex→shop, // shop→apex→shop, calculator→shop→apex→shop — because whichever host owns // that final hop (React on apex, this script on calculator) builds the params // from the same shared cookie. // // Decorating internal apex/calculator links would be redundant, would leak // campaign params into shareable URLs, and would feed our own synthesised // params back into capture on the next host. var LINK_TARGETS = ['shop.superstratumlabs.com']; // Tracking params we will capture / forward / restore var UTM_PARAMS = ['utm_source','utm_medium','utm_campaign','utm_term','utm_content','utm_id','utm_source_platform']; var CLICK_IDS = ['gclid','fbclid','ttclid','msclkid','wbraid','gbraid','yclid','irclickid','epik','li_fat_id','rdt_cid','twclid','gad_source','ScCid']; var EXTRA_PARAMS = ['ref','source','aff_id','aff_sub']; var ALL_PARAMS = UTM_PARAMS.concat(CLICK_IDS).concat(EXTRA_PARAMS); // Referrer → source/medium, matched in order. Anything unmatched and external // falls through to { source: , medium: 'referral' }. var REFERRER_RULES = [ { re: /(^|\.)mail\.google\.com$/, source: 'gmail', medium: 'email' }, { re: /(^|\.)google\.[a-z.]+$/, source: 'google', medium: 'organic' }, { re: /(^|\.)bing\.com$/, source: 'bing', medium: 'organic' }, { re: /(^|\.)duckduckgo\.com$/, source: 'duckduckgo', medium: 'organic' }, { re: /(^|\.)search\.yahoo\.[a-z.]+$/,source: 'yahoo', medium: 'organic' }, { re: /(^|\.)ecosia\.org$/, source: 'ecosia', medium: 'organic' }, { re: /(^|\.)search\.brave\.com$/, source: 'brave', medium: 'organic' }, { re: /(^|\.)yandex\.[a-z.]+$/, source: 'yandex', medium: 'organic' }, { re: /(^|\.)baidu\.com$/, source: 'baidu', medium: 'organic' }, { re: /(^|\.)startpage\.com$/, source: 'startpage', medium: 'organic' }, { re: /(^|\.)facebook\.com$/, source: 'facebook', medium: 'social' }, { re: /(^|\.)fb\.(com|me)$/, source: 'facebook', medium: 'social' }, { re: /(^|\.)instagram\.com$/, source: 'instagram', medium: 'social' }, { re: /(^|\.)t\.co$/, source: 'twitter', medium: 'social' }, { re: /(^|\.)(twitter|x)\.com$/, source: 'twitter', medium: 'social' }, { re: /(^|\.)linkedin\.com$/, source: 'linkedin', medium: 'social' }, { re: /(^|\.)lnkd\.in$/, source: 'linkedin', medium: 'social' }, { re: /(^|\.)pinterest\.[a-z.]+$/, source: 'pinterest', medium: 'social' }, { re: /(^|\.)reddit\.com$/, source: 'reddit', medium: 'social' }, { re: /(^|\.)tiktok\.com$/, source: 'tiktok', medium: 'social' }, { re: /(^|\.)youtube\.com$/, source: 'youtube', medium: 'social' }, { re: /(^|\.)threads\.(net|com)$/, source: 'threads', medium: 'social' }, { re: /(^|\.)snapchat\.com$/, source: 'snapchat', medium: 'social' }, { re: /(^|\.)whatsapp\.com$/, source: 'whatsapp', medium: 'social' }, { re: /(^|\.)linktr\.ee$/, source: 'linktree', medium: 'referral'}, { re: /(^|\.)shop\.app$/, source: 'shop_app', medium: 'referral'} ]; // ------------------------------------------------------------------------- // Utilities // ------------------------------------------------------------------------- function log() { if (!DEBUG) return; try { console.log.apply(console, ['[ssl-origin-bridge]'].concat([].slice.call(arguments))); } catch (e) {} } function getCookie(name) { var m = document.cookie.match(new RegExp('(?:^|; )' + name.replace(/([.$?*|{}()[\]\\\/+^])/g, '\\$1') + '=([^;]*)')); return m ? decodeURIComponent(m[1]) : null; } function setCookie(name, value) { document.cookie = name + '=' + encodeURIComponent(value) + '; domain=' + APEX_DOMAIN + '; path=/' + '; max-age=' + COOKIE_TTL + '; SameSite=Lax' + (location.protocol === 'https:' ? '; Secure' : ''); } function parseCookieJSON(name) { var raw = getCookie(name); if (!raw) return {}; try { return JSON.parse(raw); } catch (e) { return {}; } } function parseQuery(search) { var out = {}; var qs = (search || '').replace(/^\?/, ''); if (!qs) return out; qs.split('&').forEach(function (p) { var i = p.indexOf('='); try { if (i < 0) { out[decodeURIComponent(p)] = ''; return; } out[decodeURIComponent(p.slice(0, i))] = decodeURIComponent(p.slice(i + 1)); } catch (e) { /* malformed escape — skip this pair */ } }); return out; } function getQuery() { return parseQuery(location.search); } // FIX 7: the query string of an internal referrer, or {} if none/unparseable. function referrerQuery(ref) { var q = ref.indexOf('?'); if (q < 0) return {}; var end = ref.indexOf('#', q); return parseQuery(ref.slice(q, end < 0 ? undefined : end)); } function isInternalReferrer(ref) { return /^https?:\/\/([a-z0-9-]+\.)?superstratumlabs\.com/i.test(ref || ''); } function onReady(fn) { if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', fn); else fn(); } // FIX 9: drop click-id params (stored as their own keys) from a query string. function stripClickIds(search) { var qs = (search || '').replace(/^\?/, ''); if (!qs) return ''; var kept = qs.split('&').filter(function (t) { var k = t.split('=')[0]; try { k = decodeURIComponent(k); } catch (e) {} return CLICK_IDS.indexOf(k) < 0; }); return kept.length ? '?' + kept.join('&') : ''; } function trimPath(p) { if (!p) return p; return p.length > MAX_PATH_LEN ? p.slice(0, MAX_PATH_LEN) : p; } /** * Classify a referrer into { source, medium }, GA4-style. * Returns direct/none for an empty or unparseable referrer, and null for an * internal referrer (nothing to learn from our own domains). */ function classifyReferrer(ref) { if (!ref) return { source: 'direct', medium: 'none' }; if (isInternalReferrer(ref)) return null; var host; try { host = new URL(ref).hostname.toLowerCase(); } catch (e) { return { source: 'direct', medium: 'none' }; } if (!host) return { source: 'direct', medium: 'none' }; for (var i = 0; i < REFERRER_RULES.length; i++) { if (REFERRER_RULES[i].re.test(host)) { return { source: REFERRER_RULES[i].source, medium: REFERRER_RULES[i].medium }; } } return { source: host.replace(/^www\./, ''), medium: 'referral' }; } function decorateTargets() { var here = (location.hostname || '').toLowerCase(); return LINK_TARGETS.filter(function (h) { return h !== here; }); } // ------------------------------------------------------------------------- // 1. Origin capture (runs on every host) // ------------------------------------------------------------------------- // ------------------------------------------------------------------------- // FIX 6 — a touch is a complete set // ------------------------------------------------------------------------- // A touch is one arrival's tracking params (ALL_PARAMS). First touch lives // under the plain keys, last touch under `last_*`. Each is written, compared // and forwarded whole; a key the chosen touch lacks stays absent. function touchFromQuery(qp) { var t = {}; ALL_PARAMS.forEach(function (k) { if (qp[k]) t[k] = qp[k]; }); return t; } function hasLastTouch(data) { if (data.last_touch_at) return true; return ALL_PARAMS.some(function (k) { return data['last_' + k] != null; }); } // The touch forwarding uses: last touch if one exists, else first touch. // Never a mix of the two. function currentTouch(data) { var prefix = hasLastTouch(data) ? 'last_' : ''; var t = {}; ALL_PARAMS.forEach(function (k) { var v = data[prefix + k]; if (v != null && v !== '') t[k] = String(v); }); return t; } // Every URL param already matches the current touch: this is our own // decoration arriving from the previous host, not a new click. A subset // counts — the apex decorator forwards fewer keys than the bridge stores. function isEchoOf(incoming, touch) { var keys = Object.keys(incoming); return keys.length > 0 && keys.every(function (k) { return touch[k] === incoming[k]; }); } function replaceTouch(data, prefix, touch) { ALL_PARAMS.forEach(function (k) { delete data[prefix + k]; }); Object.keys(touch).forEach(function (k) { data[prefix + k] = touch[k]; }); } // FIX 1: derive source/medium from the referrer when the touch carries no // utm_source of its own. Never overwrites an authored utm_source. function deriveSourceIfMissing(data, ref, externalRef, touchHasParams) { if (data.utm_source) return; if (touchHasParams) { // FIX 11 (BUG-13): the touch has its own campaign/click params. Never pad // it with direct/none or invent a medium; only an external referrer that // names a source may fill utm_source. var d = externalRef ? classifyReferrer(ref) : null; if (d && d.source !== 'direct') { data.utm_source = d.source; data.source_derived = '1'; } return; } var derived = classifyReferrer(externalRef ? ref : ''); if (derived) { data.utm_source = derived.source; if (!data.utm_medium) data.utm_medium = derived.medium; data.source_derived = '1'; } } var firstTouchThisView = false; // FIX 8: set when this page view captured the first touch var touchChangedThisView = false; // journey store: any touch (first/last/upgrade) written this view /** A first touch is provisional only when it was fully synthesised (source/ * medium from the referrer, no params of its own). A campaign whose source * was filled from the referrer (FIX 11) is a real touch. */ function isProvisional(data) { if (data.source_derived !== '1') return false; return !ALL_PARAMS.some(function (k) { return k !== 'utm_source' && k !== 'utm_medium' && data[k]; }); } function newSid() { var a = ''; try { var b = new Uint8Array(9); window.crypto.getRandomValues(b); for (var i = 0; i < b.length; i++) a += ('0' + b[i].toString(16)).slice(-2); } catch (e) { for (var j = 0; j < 18; j++) a += Math.floor(Math.random() * 16).toString(16); } return 's' + a; } function captureOrigin() { var existing = parseCookieJSON(COOKIE_NAME); var qp = getQuery(); var changed = false; var incoming = touchFromQuery(qp); var hasAnyTrackingParam = Object.keys(incoming).length > 0; var ref = document.referrer || ''; var externalRef = !!ref && !isInternalReferrer(ref); if (!existing.captured_at) { // FIRST TOUCH. // Unconditional (FIX 2): previously this required a tracking param or an // external referrer, so true-direct arrivals wrote nothing and their // outbound links went bare — which Shopify then booked as a self-referral. // FIX 7: no cookie + internal referrer = a resumed session (the cookie // lapsed mid-visit), not a direct arrival. If the URL carries nothing, // the previous page's URL may: take its tracking params as the touch. var internalRef = !!ref && !externalRef; var fromRef = false; if (!hasAnyTrackingParam && internalRef) { var recovered = touchFromQuery(referrerQuery(ref)); if (Object.keys(recovered).length) { incoming = recovered; fromRef = true; } } replaceTouch(existing, '', incoming); if (fromRef) { // Whole touch as found; a campaign without utm_source stays without it // rather than being padded with a synthesised direct/none. existing.touch_from_referrer = '1'; } else { deriveSourceIfMissing(existing, ref, externalRef, hasAnyTrackingParam); } if (internalRef) existing.session_resumed = '1'; existing.captured_at = new Date().toISOString(); existing.landing_host = location.hostname; existing.landing_path = trimPath(location.pathname + stripClickIds(location.search)); existing.landing_referrer = ref || null; changed = true; firstTouchThisView = true; log('first-touch captured', existing); } else if (hasAnyTrackingParam && isEchoOf(incoming, currentTouch(existing))) { // ECHO (FIX 6). These params are our own decoration arriving from the // previous host. Treating them as a new click would re-run the upgrade // or last-touch branch and move captured_at / landing_host to the shop. log('forwarded params match the current touch; no change'); } else if (isProvisional(existing) && hasAnyTrackingParam) { // PROVISIONAL UPGRADE. // A derived first-touch (direct / organic / referral, synthesised because // the URL carried no campaign) is provisional: it exists so the visitor // is never invisible, not to claim acquisition. The first REAL campaign // to arrive takes the first-touch slot, which is what the old gate // achieved by refusing to write at all. // old: untagged visit writes nothing -> later ad becomes first-touch // new: untagged visit writes `direct` -> later ad REPLACES it // Same attribution outcome, minus the 26% of orders that were arriving // with no origin at all. // FIX 6: the campaign replaces the provisional touch WHOLE. Previously a // bare ?gclid= kept the derived google/organic and dropped the flag, so // a synthesised source then looked authored. A touch without its own // utm_source is re-derived from the referrer, exactly like a first touch. delete existing.source_derived; delete existing.session_resumed; // FIX 7: the landing moves to this click delete existing.touch_from_referrer; replaceTouch(existing, '', incoming); deriveSourceIfMissing(existing, ref, externalRef, true); if (!existing.first_seen_at) existing.first_seen_at = existing.captured_at; existing.captured_at = new Date().toISOString(); existing.landing_host = location.hostname; existing.landing_path = trimPath(location.pathname + stripClickIds(location.search)); existing.landing_referrer = ref || existing.landing_referrer || null; changed = true; log('provisional first-touch upgraded to campaign', existing.utm_source); } else if (hasAnyTrackingParam) { // LAST TOUCH via explicit campaign params. First-touch keys stay frozen, // so order ssl_utm_* attributes remain comparable across history while // ssl_last_utm_* carries the current campaign. // FIX 6: the new campaign replaces the last-touch slot WHOLE. Merging // per key kept the previous touch's utm_term / utm_id / click ids when // the new one omitted them. (Not an echo — that was ruled out above.) replaceTouch(existing, 'last_', incoming); // An explicit campaign supersedes any previously derived last-touch. delete existing.last_source_derived; existing.last_touch_at = new Date().toISOString(); existing.last_touch_host = location.hostname; changed = true; log('last-touch refreshed (campaign)', existing); } else if (externalRef) { // FIX 3: LAST TOUCH via referrer change. Under the old 90-day TTL this // was what let a month-old email campaign keep winning against a fresh // organic visit. The 30-min scope now retires most of those on its own; // this branch covers the rest — a real origin change inside one session. var d = classifyReferrer(ref); if (d) { var currentSource = existing.last_utm_source != null ? existing.last_utm_source : existing.utm_source; if (d.source !== currentSource) { // FIX 6: whole slot — the previous last touch's campaign and click // ids do not survive onto a referrer-derived touch. replaceTouch(existing, 'last_', { utm_source: d.source, utm_medium: d.medium }); existing.last_source_derived = '1'; existing.last_touch_at = new Date().toISOString(); existing.last_touch_host = location.hostname; changed = true; log('last-touch refreshed (referrer)', d.source, d.medium); } } } touchChangedThisView = changed; if (changed) setCookie(COOKIE_NAME, JSON.stringify(existing)); else if (existing.captured_at) touchCookie(existing); return existing; } /** * Slide the session window. Re-writes the cookie unchanged with a fresh * max-age on every page view, so an active journey never expires mid-flight * while an abandoned one lapses after SESSION_MINUTES of inactivity — * the same rule GA4 and Shopify use to bound a session. */ function touchCookie(data) { try { setCookie(COOKIE_NAME, JSON.stringify(data)); } catch (e) {} } // ------------------------------------------------------------------------- // 2. Link / form decorator (calculator + previews; NOT apex) // ------------------------------------------------------------------------- /** * FIX 5. Is the source we would forward one this script SYNTHESISED as * direct, rather than one the visitor actually arrived with? * * classifyReferrer() returns direct/none for an arrival with no referrer and * no campaign. STORING that is right — it keeps the visitor visible and stops * Shopify inventing a self-referral (FIX 2). FORWARDING it is wrong: GA4's * Direct channel matches source `(direct)` with medium `(none)`/`(not set)`, * so the bare strings `direct`/`none` match no channel rule at all and the * session drops into Unassigned. * * Suppressing is safe because GA4 already resolves these correctly on its * own: over the same 30 days there were ZERO sessions attributed to * superstratumlabs.com, so cross-domain continuity is intact and nothing * falls back to a self-referral on the GA4 side. The ssl_origin_* params * below still travel, and the shop still stamps ssl_* cart attributes, so the * ORDER keeps the origin even though the URL stays clean. What we give up is * Shopify's native report for this slice, which is the lesser report — GA4 * and the BigQuery export are the system of record. * * Only ever suppresses a value this script invented. A real campaign on the * current URL, or a stored campaign from a real click, always wins. */ function isDerivedDirect(data, qp) { if (qp && (qp.utm_source || qp.utm_medium)) return false; // Judge the same touch forwarding will use (FIX 6). if (hasLastTouch(data)) { return data.last_source_derived === '1' && data.last_utm_source === 'direct'; } return data.source_derived === '1' && data.utm_source === 'direct'; } function buildShopParams() { var data = parseCookieJSON(COOKIE_NAME); var qp = getQuery(); var out = {}; var dropDirect = isDerivedDirect(data, qp); // FIX 6: forward ONE touch whole — last touch if there is one, else first // touch. captureOrigin has already folded this page's own params into the // cookie, so the stored touch is the current one. Resolving per key here // is what put a Meta utm_term on a linktree link. var touch = currentTouch(data); UTM_PARAMS.concat(CLICK_IDS).forEach(function (k) { var v = touch[k]; if (!v) return; // Click IDs still travel: a gclid/fbclid is real even when the referrer // was empty, and GA4 resolves those to google/cpc itself. if (dropDirect && (k === 'utm_source' || k === 'utm_medium')) return; out[k] = v; }); if (data.captured_at) out.ssl_origin_at = data.captured_at; if (data.landing_host) out.ssl_origin_host = data.landing_host; if (data.landing_path) out.ssl_origin_path = data.landing_path; return out; } function decorateUrl(urlStr) { var u; try { u = new URL(urlStr, location.href); } catch (e) { return urlStr; } if (decorateTargets().indexOf((u.hostname || '').toLowerCase()) === -1) return urlStr; var params = buildShopParams(); var search = new URLSearchParams(u.search); // FIX 6: a link that authors ANY tracking param carries its own touch. // Adding ours beside it would blend two campaigns, so it gets only the // ssl_origin_* breadcrumbs. var authored = UTM_PARAMS.concat(CLICK_IDS).some(function (k) { return search.has(k); }); Object.keys(params).forEach(function (k) { if (authored && k.indexOf('ssl_') !== 0) return; if (!search.has(k)) search.set(k, params[k]); }); u.search = search.toString(); return u.toString(); } function decorateAnchor(a) { try { var href = a.getAttribute('href'); if (!href || /^(mailto:|tel:|javascript:|#)/i.test(href)) return; if (a.getAttribute('data-ssl-decorated') === '1') return; var newHref = decorateUrl(href); if (newHref !== href) { a.setAttribute('href', newHref); a.setAttribute('data-ssl-decorated', '1'); } } catch (e) {} } function decorateForm(form) { try { var action = form.getAttribute('action'); if (!action) return; if (form.getAttribute('data-ssl-decorated') === '1') return; var u; try { u = new URL(action, location.href); } catch (e) { return; } if (decorateTargets().indexOf((u.hostname || '').toLowerCase()) === -1) return; var params = buildShopParams(); // FIX 6: same rule as decorateUrl — an authored touch is left whole. var authored = UTM_PARAMS.concat(CLICK_IDS).some(function (k) { return !!form.querySelector('input[name="' + k + '"]'); }); Object.keys(params).forEach(function (k) { if (authored && k.indexOf('ssl_') !== 0) return; if (form.querySelector('input[name="' + k + '"]')) return; var input = document.createElement('input'); input.type = 'hidden'; input.name = k; input.value = params[k]; form.appendChild(input); }); form.setAttribute('data-ssl-decorated', '1'); } catch (e) {} } function decorateAll() { var anchors = document.querySelectorAll('a[href]'); for (var i = 0; i < anchors.length; i++) decorateAnchor(anchors[i]); var forms = document.querySelectorAll('form[action]'); for (var j = 0; j < forms.length; j++) decorateForm(forms[j]); log('decorated initial links', anchors.length, 'forms', forms.length); } function watchMutations() { if (!window.MutationObserver) return; var obs = new MutationObserver(function (muts) { muts.forEach(function (m) { if (!m.addedNodes) return; m.addedNodes.forEach(function (n) { if (n.nodeType !== 1) return; if (n.tagName === 'A' && n.hasAttribute('href')) decorateAnchor(n); else if (n.tagName === 'FORM' && n.hasAttribute('action')) decorateForm(n); else if (n.querySelectorAll) { n.querySelectorAll('a[href]').forEach(decorateAnchor); n.querySelectorAll('form[action]').forEach(decorateForm); } }); }); }); obs.observe(document.documentElement, { childList: true, subtree: true }); } function backstopClick() { // Catches programmatic .click() and last-second href swaps. document.addEventListener('click', function (e) { var a = e.target && e.target.closest ? e.target.closest('a[href]') : null; if (a) decorateAnchor(a); }, true); document.addEventListener('submit', function (e) { var f = e.target; if (f && f.tagName === 'FORM') decorateForm(f); }, true); } // ------------------------------------------------------------------------- // 3. Shop-side reconciler // NOTE: this cannot repair Shopify's own attribution — Shopify records // landing_site from the HTTP request, before any script runs. Kept as // best-effort for GTM/dataLayer consumers only. The attribution fix is // decoration on the originating host, above. // ------------------------------------------------------------------------- function reconcileShopUrl() { var data = parseCookieJSON(COOKIE_NAME); if (!data || !Object.keys(data).length) { log('shop reconcile: no cookie data'); return false; } var qp = getQuery(); // FIX 6: a campaign OR a bare click id makes the URL its own touch. Adding // stored params to it blended them: a live ?fbclid= arrival was rewritten // as the stored Klaviyo email campaign. var alreadyTagged = UTM_PARAMS.concat(CLICK_IDS).some(function (k) { return qp[k]; }); if (alreadyTagged) { log('shop reconcile: URL already carries a touch'); return false; } // FIX 8: only where something was lost in transit — an undecorated hop // from the apex/calculator, or the page that just captured the first touch. // Ordinary shop->shop browsing keeps its URLs clean. var ref = document.referrer || ''; var refHost = ''; try { refHost = ref ? new URL(ref).hostname.toLowerCase() : ''; } catch (e) {} var hop = !!refHost && isInternalReferrer(ref) && refHost !== SHOP_HOST; if (!hop && !firstTouchThisView) { log('shop reconcile: not a hop and not a first touch'); return false; } var params = new URLSearchParams(location.search); var added = 0; var dropDirect = isDerivedDirect(data, qp); // FIX 5 — see isDerivedDirect var touch = currentTouch(data); // FIX 6 — one touch, whole UTM_PARAMS.concat(CLICK_IDS).forEach(function (k) { if (dropDirect && (k === 'utm_source' || k === 'utm_medium')) return; var v = touch[k]; if (v && !params.has(k)) { params.set(k, v); added++; } }); if (!added) return false; var newQs = params.toString(); var newUrl = location.pathname + (newQs ? '?' + newQs : '') + location.hash; try { history.replaceState(history.state, '', newUrl); log('shop reconcile: URL rewritten with', added, 'params'); return true; } catch (e) { log('replaceState failed', e); return false; } } function pushDataLayer() { var data = parseCookieJSON(COOKIE_NAME); if (!data || !Object.keys(data).length) return; window.dataLayer = window.dataLayer || []; var payload = { event: 'ssl_origin_ready' }; Object.keys(data).forEach(function (k) { if (k !== 'sid') payload['ssl_' + k] = data[k]; }); window.dataLayer.push(payload); log('dataLayer pushed', payload); } // Cart stamps run one at a time: two POSTs in flight before a `cart` cookie // exists could each create a cart, and the last response would win (review). var stampBusy = false, stampQueued = false, stampNext = null; function stampCartAttributes(consent) { if (stampBusy) { // keep the most informative pending request (a resolved consent beats null) if (!stampQueued || consent !== null) stampNext = consent; stampQueued = true; return; } stampBusy = true; doStamp(consent, function () { stampBusy = false; if (stampQueued) { stampQueued = false; var c = stampNext; stampNext = null; stampCartAttributes(c); } }); } function doStamp(consent, done) { if (!window.fetch) { done(); return; } var data = parseCookieJSON(COOKIE_NAME); if (!data || !Object.keys(data).length) { done(); return; } var pairs = []; var stamped = stampableData(data, consent); Object.keys(stamped).forEach(function (k) { pairs.push( encodeURIComponent('attributes[ssl_' + k + ']') + '=' + encodeURIComponent(String(stamped[k] == null ? '' : stamped[k])) ); }); if (!pairs.length) { done(); return; } // FIX 10: skip when this exact payload is already on this exact cart. var body = pairs.join('&'); var STAMP_KEY = 'ssl_cart_stamp'; var store = null; try { store = window.sessionStorage; store.getItem(STAMP_KEY); } catch (e) { store = null; } var key = body + '|' + (getCookie('cart') || ''); if (store && store.getItem(STAMP_KEY) === key) { log('cart.attributes unchanged — skip'); done(); return; } fetch('/cart/update.js', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' }, body: body, credentials: 'same-origin', keepalive: true }).then(function (r) { log('cart.attributes stamped', r.status); // Record against the cart as it exists AFTER the POST (the first stamp // creates the cart and its cookie), so the next page view can skip. if (store && r && r.ok) { try { store.setItem(STAMP_KEY, body + '|' + (getCookie('cart') || '')); } catch (e) {} } done(); }) .catch(function (e) { log('cart.attributes error', e); done(); }); } // ------------------------------------------------------------------------- // 4. Journey store, phase 2: consent, visitor id, hits // Plan: superstratum_tracking/docs/plans/journey-store.md (D-14..D-16). // Callback + setTimeout style (no Promises) so the test harness can drive // it with a simulated clock. Every step swallows its own errors. // ------------------------------------------------------------------------- var COLLECTOR = 'https://superstratumlabs.com'; var CONSENT_API = 'https://cdn.shopify.com/shopifycloud/consent-tracking-api/v0.2/consent-tracking-api.js'; var CONSENT_WAIT_MS = 3000; // how long to wait for Shopify's API before deciding without it var PRIME_WAIT_MS = 1500; // apex: how long to wait for the proxied consent value var MIRROR_MAX_AGE = 86400; // seconds: refresh ssl_consent at least daily (Safari caps it) var GA_STREAM = '_ga_G9XHLH1WTK'; var CONSENT_KEYS = ['analytics', 'marketing', 'sale_of_data', 'preferences']; var META_CLICK_IDS = ['fbclid']; // T67: click ids whose VALUE identifies a click (gad_source is a campaign flag). var IDENT_CLICK_IDS = CLICK_IDS.filter(function (k) { return k !== 'gad_source'; }); // T68: the shop's Storefront API, asked anonymously for Shopify's consent // for the visitor's region when the calculator has no ssl_consent mirror. var SHOP_SFAPI = 'https://' + SHOP_HOST + '/api/unstable/graphql.json'; // T69: staff pages on the calculator host are not visitor journeys. var NO_HIT_PATHS = /^\/+crm-dashboard(\/|$)/i; var TIME_KEYS = ['captured_at', 'first_seen_at', 'last_touch_at']; // precise times link a session // Cart attributes we stamp (whitelist): touch params, first and last, plus // their metadata. Anything else in utm_data (e.g. a legacy `fbp`) is dropped. var STAMP_META = ['captured_at', 'landing_host', 'landing_path', 'landing_referrer', 'source_derived', 'first_seen_at', 'last_touch_at', 'last_touch_host', 'last_source_derived', 'session_resumed', 'touch_from_referrer']; var resolvedConsent = null; // set once consent is known; used by SPA hits and the listener var hitSent = false; var sidIssuedThisView = false; // a new session's sid is minted once per page view var queuedSpaPaths = []; // apex navigations before consent resolved function ssGet(k) { try { return window.sessionStorage.getItem(k); } catch (e) { return null; } } function ssSet(k, v) { try { window.sessionStorage.setItem(k, v); } catch (e) {} } function deleteDomainCookie(name) { try { document.cookie = name + '=; Max-Age=0; Path=/; Domain=' + APEX_DOMAIN + '; Secure; SameSite=Lax'; } catch (e) {} } /** consent: null = not resolved yet (touch-only stamp, no identity keys); * analytics true = vid/sid values; otherwise '' to CLEAR earlier values * (/cart/update.js merges attributes, so omitting would keep them). */ function stampableData(data, consent) { var out = {}; Object.keys(data).forEach(function (k) { var base = k.indexOf('last_') === 0 ? k.slice(5) : k; if (IDENT_CLICK_IDS.indexOf(base) >= 0) { // T67: click-id values follow consent like the hit log (D-17) and the // calculator drafts (D-18): fbclid needs marketing + sale of data, the // others analytics. Allowed: the value. Explicitly refused: '' clears a // value an earlier stamp wrote (/cart/update.js merges). Unresolved or // unknown (e.g. the API was slow this page): omitted, so an earlier // stamp's value stays. if (!consent) return; var isMeta = META_CLICK_IDS.indexOf(base) >= 0; var okClick = isMeta ? (consent.marketing === true && consent.sale_of_data === true) : consent.analytics === true; var deny = consent.deny || {}; var refused = isMeta ? (deny.marketing || deny.sale_of_data) : deny.analytics; if (okClick) out[k] = data[k]; else if (refused) out[k] = ''; return; } if (ALL_PARAMS.indexOf(base) >= 0 || STAMP_META.indexOf(k) >= 0) out[k] = data[k]; }); if (consent) { var ok = consent.analytics === true; out.sid = ok && data.sid ? data.sid : ''; // ssl_sid out.vid = ok ? (getCookie('ssl_vid') || '') : ''; // ssl_vid } out.bridge_version = BRIDGE_VERSION; // ssl_bridge_version (T10c) return out; } function readMirror() { var m = /^v1\.([01-]{4})\.(\d{9,11})$/.exec(getCookie('ssl_consent') || ''); if (!m) return null; var f = function (ch) { return ch === '1' ? true : ch === '0' ? false : null; }; return { analytics: f(m[1][0]), marketing: f(m[1][1]), sale_of_data: f(m[1][2]), preferences: f(m[1][3]), flags: m[1], ts: +m[2] }; } function shopifyCP() { try { return (window.Shopify && window.Shopify.customerPrivacy) || null; } catch (e) { return null; } } /** Per category: 'yes' → true, 'no' → false (explicit). No decision: the * region default from *Allowed(), unless a banner should be shown (an * opt-in region), in which case it is unknown (null). */ function fromShopify(cp) { try { var raw = cp.currentVisitorConsent() || {}; var banner = false; try { banner = typeof cp.shouldShowBanner === 'function' && !!cp.shouldShowBanner(); } catch (e) {} var pick = function (key, fn) { if (raw[key] === 'yes') return true; if (raw[key] === 'no') return false; if (banner) return null; try { return !!cp[fn](); } catch (e) { return null; } }; return { analytics: pick('analytics', 'analyticsProcessingAllowed'), marketing: pick('marketing', 'marketingAllowed'), sale_of_data: pick('sale_of_data', 'saleOfDataAllowed'), raw: raw }; } catch (e) { return null; } } function loadConsentApi() { try { if (document.getElementById && document.getElementById('ssl-customer-privacy-api')) return; var sc = document.createElement('script'); sc.id = 'ssl-customer-privacy-api'; sc.src = CONSENT_API; sc.async = true; (document.head || document.documentElement).appendChild(sc); } catch (e) {} } /** Apex: fetch the visitor's consent value (_cmp) from the same-origin * Storefront API proxy, in parallel with the script load, cached for the * session. Hydrogen primes the API the same way (cachedConsent = _cmp). */ function fetchCmp(cb) { var cached = ssGet('ssl_cmp'); if (cached) { cb(cached); return; } var done = false; var finish = function (v) { if (!done) { done = true; if (v) ssSet('ssl_cmp', v); cb(v || null); } }; setTimeout(function () { finish(null); }, PRIME_WAIT_MS); try { window.fetch('/api/unstable/graphql.json', { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: 'query ensureCookies { consentManagement { cookies(visitorConsent:{}) { cookieDomain } } }' }) }).then(function (r) { var st = (r && r.headers && r.headers.get('server-timing')) || ''; var m = /\b_cmp;desc="([^"]*)"/.exec(st); finish(m && m[1]); }, function () { finish(null); }); } catch (e) { finish(null); } } /** T68: Shopify's consent for this visitor's REGION, asked anonymously from * the calculator (no proxy there, and the shop's own cookies are blocked by * CORS). trackingConsentCookie is `3.__…`; * letters A/M/P/S = analytics, marketing, preferences, sale of data, upper * case = allowed. The EXPLICIT part (before the dot) is a real signal even * on an anonymous call: a browser's Global Privacy Control makes Shopify * answer `3s.AMP_…` (sale of data refused). So an explicit letter decides * (upper = true, lower = false). Otherwise only an allowed DEFAULT becomes * true: a denied default or a region with a banner stays unknown (null), * never a refusal (D-17). Cached for the session, failures included. * cb({analytics, marketing, sale_of_data} | null). */ function parseRegionConsent(v, bannerOn) { var m = /^3([AMPSamps]*)\.([AMPSamps]*)_/.exec(v || ''); if (!m) return null; var f = function (L) { if (m[1].indexOf(L) >= 0) return true; if (m[1].indexOf(L.toLowerCase()) >= 0) return false; return !bannerOn && m[2].indexOf(L) >= 0 ? true : null; }; return { analytics: f('A'), marketing: f('M'), sale_of_data: f('S') }; } function fetchRegionConsent(cb) { var cached = ssGet('ssl_region_consent'); if (cached) { var p = cached.split('|'); cb(parseRegionConsent(p[0], p[1] === '1')); return; } if (!window.fetch) { cb(null); return; } var done = false; var finish = function (v, bannerOn) { if (done) { // an answer that arrives after the timeout still serves later pages if (v) ssSet('ssl_region_consent', v + '|' + (bannerOn ? '1' : '0')); return; } done = true; // a failure is cached too ('-'), so later pages don't wait again ssSet('ssl_region_consent', (v || '-') + '|' + (bannerOn ? '1' : '0')); cb(v ? parseRegionConsent(v, bannerOn) : null); }; setTimeout(function () { finish(null); }, PRIME_WAIT_MS); try { window.fetch(SHOP_SFAPI, { method: 'POST', credentials: 'omit', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: 'query sslRegionConsent { consentManagement { banner { enabled } cookies(visitorConsent:{}) { trackingConsentCookie } } }' }) }).then(function (r) { if (!r || typeof r.json !== 'function') { finish(null); return; } r.json().then(function (j) { var cm = j && j.data && j.data.consentManagement; var v = cm && cm.cookies && cm.cookies.trackingConsentCookie; finish(typeof v === 'string' ? v : null, !!(cm && cm.banner && cm.banner.enabled)); }, function () { finish(null); }); }, function () { finish(null); }); } catch (e) { finish(null); } } /** * Resolve consent (D-15, D-16). shop: Shopify's decision only. apex: * Shopify's headless decision combined with the ssl_consent mirror. * Calculator: the mirror, plus Shopify's region default when the mirror has * no answer for some category (T68). Per category: any explicit false → denied; else * any true → allowed; else unknown (= not allowed, but not a refusal). */ function resolveConsent(cb) { var done = false, shopVals = null, cmp, cmpReady = mode !== 'apex-capture-only'; function finish() { if (done) return; done = true; var mirror = mode === 'shop' ? null : readMirror(); var c = { deny: {} }; ['analytics', 'marketing', 'sale_of_data'].forEach(function (k) { var vals = [shopVals && shopVals[k], mirror && mirror[k]].filter(function (v) { return v === true || v === false; }); c.deny[k] = vals.indexOf(false) >= 0; c[k] = !c.deny[k] && vals.indexOf(true) >= 0; }); resolvedConsent = c; cb(c, shopVals); } if (mode === 'decorate') { var mir = readMirror(); var complete = mir && mir.analytics !== null && mir.marketing !== null && mir.sale_of_data !== null; if (complete) { finish(); return; } fetchRegionConsent(function (reg) { shopVals = reg; finish(); }); return; } if (mode === 'apex-capture-only') { loadConsentApi(); if (window.fetch) fetchCmp(function (v) { cmp = v; cmpReady = true; }); else cmpReady = true; } if (mode === 'shop') { // The API is present when Shopify's banner or an app loads it; ask for it otherwise. try { if (!shopifyCP() && window.Shopify && typeof window.Shopify.loadFeatures === 'function') { window.Shopify.loadFeatures([{ name: 'consent-tracking-api', version: '0.1' }], function () {}); } } catch (e) {} } var waited = 0; (function poll() { var cp = shopifyCP(); if (cp && cmpReady) { if (cmp) { try { cp.cachedConsent = cmp; } catch (e) {} } shopVals = fromShopify(cp); finish(); return; } if (waited >= CONSENT_WAIT_MS) { finish(); return; } waited += 100; setTimeout(poll, 100); })(); } function post(url, obj, cb) { var done = cb || function () {}; if (!window.fetch) { done(); return; } try { window.fetch(url, { method: 'POST', credentials: 'include', keepalive: true, headers: { 'Content-Type': 'text/plain' }, body: JSON.stringify(obj) }) .then(function () { done(); }, function () { done(); }); } catch (e) { done(); } } /** Shop: copy the visitor's Shopify decision into ssl_consent (D-16). * Reads only; never records a decision in Shopify. No decision → clear it. */ function syncMirror(shop, cb) { var done = cb || function () {}; if (mode !== 'shop' || !shop || !shop.raw) { done(); return; } var map = { yes: '1', no: '0' }; var flags = CONSENT_KEYS.map(function (k) { return map[shop.raw[k]] || '-'; }).join(''); var m = readMirror(); if (flags === '----') { if (m) deleteDomainCookie('ssl_consent'); done(); return; } if (m && m.flags === flags && Math.floor(Date.now() / 1000) - m.ts < MIRROR_MAX_AGE) { done(); return; } var body = {}; CONSENT_KEYS.forEach(function (k, i) { if (flags[i] !== '-') body[k] = flags[i] === '1'; }); // /_t/id checks the mirror (M6), so the id request waits for this update. post(COLLECTOR + '/_t/consent', body, done); } /** Session id (H1): created lazily, only with analytics consent; a new * session (first touch this view) gets a new one; an explicit analytics * refusal removes it. Unknown consent leaves an existing sid alone. */ function ensureSid(consent) { var data = parseCookieJSON(COOKIE_NAME); if (!data || !data.captured_at) return; if (consent.analytics) { if (!data.sid || (firstTouchThisView && !sidIssuedThisView)) { data.sid = newSid(); sidIssuedThisView = true; setCookie(COOKIE_NAME, JSON.stringify(data)); } } else if (consent.deny.analytics && data.sid) { delete data.sid; setCookie(COOKIE_NAME, JSON.stringify(data)); } } /** ssl_vid (D-02): request it when analytics consent allows and it is * missing (or, on the apex, once per session to renew its full lifetime); * remove it on an explicit analytics refusal. */ function ensureVid(consent, cb) { if (!consent.analytics) { if (consent.deny.analytics && getCookie('ssl_vid')) deleteDomainCookie('ssl_vid'); cb(); return; } var need = !getCookie('ssl_vid') || (mode === 'apex-capture-only' && firstTouchThisView); if (!need || !window.fetch) { cb(); return; } var done = false; var finish = function () { if (!done) { done = true; cb(); } }; setTimeout(finish, 1500); try { window.fetch(COLLECTOR + '/_t/id', { credentials: 'include' }).then(finish, finish); } catch (e) { finish(); } } function gaClientId() { var m = /^GA\d\.\d\.(\d+\.\d+)$/.exec(getCookie('_ga') || ''); return m ? m[1] : null; } function gaSessionId() { var v = getCookie(GA_STREAM) || ''; var m = /^GS1\.\d\.(\d+)\./.exec(v) || /^GS2\.\d\.s(\d+)/.exec(v); return m ? m[1] : null; } function pathOnly(p) { return (p || '').split(/[?#]/)[0]; } function originPath(u) { if (!u) return ''; try { var x = new URL(u); return x.origin + x.pathname; } catch (e) { return ''; } } /** Touch state for the hit, filtered like the collector does (M2), and * without the precise capture times unless analytics is allowed (H1). */ function hitTouch(data, consent) { var t = {}; Object.keys(data).forEach(function (k) { if (k === 'sid') return; if (!consent.analytics && TIME_KEYS.indexOf(k) >= 0) return; var base = k.indexOf('last_') === 0 ? k.slice(5) : k; if (CLICK_IDS.indexOf(base) >= 0) { // click-id values only with the matching consent (keys are in click_ids) var ok = META_CLICK_IDS.indexOf(base) >= 0 ? (consent.marketing && consent.sale_of_data) : consent.analytics; if (!ok) return; } if (/landing_path$/.test(k)) t[k] = pathOnly(data[k]); else if (/landing_referrer$/.test(k)) t[k] = originPath(data[k]); else t[k] = data[k]; }); return t; } /** One touch-log row (POST /_t/hit). Identifiers only with consent; * click-id values only with the matching consent (keys always). */ function sendHit(consent, spa) { // spa: the path of a client-side navigation try { if (NO_HIT_PATHS.test(spa ? pathOnly(String(spa)) : location.pathname)) { hitSent = true; return; } // T69 var qp = getQuery(); var data = parseCookieJSON(COOKIE_NAME); var utm = {}, clicks = {}; var meta = consent.marketing && consent.sale_of_data; UTM_PARAMS.forEach(function (k) { if (qp[k]) utm[k] = qp[k]; }); CLICK_IDS.forEach(function (k) { if (!qp[k]) return; var ok = META_CLICK_IDS.indexOf(k) >= 0 ? meta : consent.analytics; clicks[k] = ok ? qp[k] : ''; }); var p = { kind: 'pageview', host: location.hostname, path: spa ? pathOnly(String(spa)) : location.pathname, referrer: spa ? '' : originPath(document.referrer || ''), utm: spa ? {} : utm, click_ids: spa ? {} : clicks, touch: hitTouch(data, consent), new_touch: !spa && touchChangedThisView, session_resumed: !spa && firstTouchThisView && data.session_resumed === '1', bridge_version: BRIDGE_VERSION, consent: { analytics: consent.analytics, marketing: consent.marketing, sale_of_data: consent.sale_of_data } }; var ids = {}; if (consent.analytics) { p.sid = data.sid; ids.ga_client_id = gaClientId(); ids.ga_session_id = gaSessionId(); } if (meta) { ids.fbp = getCookie('_fbp'); ids.fbc = getCookie('_fbc'); } p.ids = ids; var body = JSON.stringify(p); if (body.length > 3800) { delete p.touch; body = JSON.stringify(p); } hitSent = true; var nav = window.navigator; if (nav && nav.sendBeacon && typeof Blob === 'function' && nav.sendBeacon(COLLECTOR + '/_t/hit', new Blob([body], { type: 'text/plain' }))) return; post(COLLECTOR + '/_t/hit', p); } catch (e) { log('hit error', e); } } /** Re-apply identity after a consent change on the shop (H2): mirror, * sid, vid, and a re-stamp that clears or sets ssl_vid / ssl_sid. */ function onConsentChanged() { resolveConsent(function (consent, shop) { syncMirror(shop, function () { ensureSid(consent); ensureVid(consent, function () { stampCartAttributes(consent); }); }); }); } function journeyStart() { // T69: staff pages are not journeys — no hits, no ids, no consent lookups. if (NO_HIT_PATHS.test(location.pathname || '')) return; // Shop, first page of the session: stamp the touch at once so an express // checkout inside the consent wait still carries it (M1). Identity follows. if (mode === 'shop' && !ssGet('ssl_cart_stamp')) { try { stampCartAttributes(null); } catch (e) {} } // Page leaves before consent resolves: send a hit without identifiers (M1). try { window.addEventListener('pagehide', function () { if (!hitSent) sendHit({ analytics: false, marketing: false, sale_of_data: false, deny: {} }); }); } catch (e) {} resolveConsent(function (consent, shop) { try { window.__sslOriginBridge.consent = { analytics: consent.analytics, marketing: consent.marketing, sale_of_data: consent.sale_of_data }; } catch (e) {} syncMirror(shop, function () { ensureSid(consent); ensureVid(consent, function () { if (!hitSent) sendHit(consent); if (mode === 'shop') stampCartAttributes(consent); // apex navigations that happened before consent was known while (queuedSpaPaths.length) sendHit(consent, queuedSpaPaths.shift()); }); }); }); if (mode === 'shop') { try { document.addEventListener('visitorConsentCollected', onConsentChanged); } catch (e) {} } // Apex is a SPA: count client-side navigations as page views (no new touch). if (mode === 'apex-capture-only') { try { var push = history.pushState; var spaHit = function () { var path = location.pathname || '/'; if (resolvedConsent && hitSent) sendHit(resolvedConsent, path); else if (queuedSpaPaths.length < 20) queuedSpaPaths.push(path); }; history.pushState = function () { var r = push.apply(this, arguments); spaHit(); return r; }; window.addEventListener('popstate', spaHit); } catch (e) {} } } // ------------------------------------------------------------------------- // Boot // ------------------------------------------------------------------------- var mode = location.hostname === SHOP_HOST ? 'shop' : (APEX_HOST_RE.test(location.hostname) ? 'apex-capture-only' : 'decorate'); // FIX 4: make the deployed build identifiable from outside. try { window.__sslOriginBridge = { version: BRIDGE_VERSION, host: location.hostname, mode: mode, targets: decorateTargets() }; } catch (e) {} // Always capture first — works on all three hosts. captureOrigin(); if (mode === 'shop') { // Reconcile URL SYNC, before Shopify analytics beacons fire. reconcileShopUrl(); // Push to dataLayer SYNC too (so GTM tags reading dataLayer see it). pushDataLayer(); // Cart attribute stamp now runs after consent is resolved (journeyStart). } else if (mode === 'apex-capture-only') { // Apex: capture only. shopLinkAttribution (React bundle) owns decoration, // because it alone re-decorates React's in-place href rewrites. log('apex host: capture only, React bundle decorates links', BRIDGE_VERSION); } else { // Other hosts (calculator.*, previews) have no bundle — decorate here. onReady(function () { decorateAll(); watchMutations(); backstopClick(); }); } // Journey store (phase 2): consent → ssl_vid → hit (→ cart stamp on the shop). onReady(journeyStart); })();
A woman fogging a living room with a Superstratum Whole Home Detox deodor bomb

Superstratum Labs

Create a healthier home for your family

From products that kill black mold to cleaners that destroy mycotoxins, Superstratum Labs was created to give you the tools and knowledge to create a healthy environment for your family.

Best Sellers

What people buy most

"I've tested more products than I can count. Superstratum is the only one I've found that actually addresses what mold leaves behind — not just the mold itself."

Dave Asprey, Founder of Bulletproof & Producer of MOLDY, The Toxic Mold Movie, Author of Game Changers and Smarter Not Harder

Shop Dave's Kit
Dave Asprey
Beautiful American family home surrounded by trees

Building Related Illness

One in two American homes have conditions that lead to building‑related illness.

Maybe it's the headaches that won't stop. The brain fog you can't explain. The allergies that started after you moved in. Maybe a child keeps getting sick and no one can tell you why.

You're not imagining it. Building Related Illness affects millions of people — but most never connect their symptoms to their home. They bounce between doctors, try every remedy, and never find answers. Because no one ever tells them to look at the building.

You're not alone. And now you know where to look.

Learn About BRI

The Truth No One Tells You

It's Not the Mold That's Making You Sick

It's not the mold itself that creates most building-related illness. It's the mycotoxins water-damage molds produce when they feed on the building materials inside of an airtight modern home.

Once these invisible, odorless toxins become present in your home, they can become the source of ongoing mystery symptoms for years — even after the mold that created them is gone.

Thousands of American families are discovering that these invisible, odorless toxins are the root cause of their family's chronic health conditions.

Isometric house diagram showing water intrusion leading to mold growth and mycotoxin spread
Microscopic view of mold growth

Mold = Biology

A living organism that releases spores to reproduce. Mold is the first breach in a home after water damage — and it can be removed through physical remediation and cleaning.

We work closely with mold remediation companies and give our customers DIY options for small amounts of mold.

Need mold remediation? Connect with a Certified Pro →

Molecular structure of a mycotoxin

Mycotoxins = Chemistry

Chemical biotoxins mold creates in enclosed spaces when it feeds on building materials. Outside, mold is harmless — but inside, the toxins it produces can be deadly.

Although mold awareness has grown, mycotoxins remain poorly understood — far more dangerous and far more difficult to detect.

Learn about mycotoxins →
Bright airy living room

How Superstratum Solved the Problem of Mycotoxins

A Detox. But for Your Home.

Mold remediation existed, but there was nothing to clean up what remediation leaves behind. So we set out to be the first company to develop a lab-proven solution to detoxify a home from the chemical mycotoxins and VOCs in today's modern living environments.

We call it the Superstratum Whole Home Detox, and it works in three phases.

Read the Whitepaper on Destroying Mycotoxins
Superstratum product lineup — Superstratum Building Cleaner, Superstratum Deodor Bombs, Superstratum Endurance Coating, and equipment

Phase 1

Clean

The first phase of bringing a sick home back to health is physical cleaning — but traditional cleaning chemicals don't have the oxidation power needed to break down mycotoxins. Standard remediation often disturbs mold colonies, triggering their defense response and actually increasing toxin output.

That's why we developed a fogging and wiping method using our Superstratum Building Cleaner — a proprietary formula made from hypochlorous acid (HOCl). A uniquely pure and pH-balanced version of the powerful chemical your own immune system makes, it neutralizes mycotoxins on contact across walls, floors, HVAC systems, and furniture.

Warning: Using the wrong cleaning chemicals — like bleach — can trigger mold's stress response, causing mycotoxin concentrations to spike. Improper cleaning methods can also release more particles into the air or leave behind invisible residue. That's why proper chemistry matters.

Shop Cleaners

Phase 2

Gas

No matter how good the liquid chemistry or how thorough the cleaning, there will always be hidden spaces where invisible, nanoparticle-sized mycotoxins remain. This is what makes detoxifying a home for mycotoxins so much harder than remediating mold.

This is why we developed the Superstratum Deodor Bomb — a delivery system for chlorine dioxide gas that penetrates everywhere mycotoxins hide, neutralizing the contamination you can't see or reach with Phase 1 cleaning.

Shop Gas

Phase 3

Coat

Phase 3 is the proprietary technology that locks in performance. Superstratum Endurance Coating is an invisible, water-resistant coating that resists the growth of mold for up to 10 years. Even a quick spritz in the shower lasts 10 weeks.

Water-resistant mold resistance is the holy grail — and Superstratum Endurance Coating delivers, performing through hundreds of wet and dry cycles, both inside the home and out.

10 Years

of mold resistance from a single application — hundreds of wet/dry cycles, indoors and out

Shop Coatings
Mother and child in a clean home

Ready to Detox Your Home?

Choose the path that fits your situation — grab a pre-made kit to get started fast, or use our calculator to build a custom solution sized to your home.

We guide you every step of the way with detailed videos, clear instructions, and impeccable customer service. You won't do this alone.

What Our Customers Say

· 5/5

"After the first step, the fogging with hypochlorous acid, we felt a huge difference in the air. My son's asthma symptoms disappeared, and my other son had no more PANS/PANDAS-like issues. Clean air is necessary, and I'm so thankful to have found a toxin-free solution!"

— Blanca M.

Product used: Whole Home System

Results: Immediately

· 5/5

"We used bombs in our garage where contaminated belongings sat. Bombing allowed me to sort through stuff with minimal reactions. We bombed our shed, our SUV — all with success. The musty tent has no smell. Read the site info well and follow the protocol."

— Angie S.

Product used: Cleaners, Bombs, Coatings

Results: Immediately

· 5/5

"We used Superstratum products to clean most of our personal items before moving them into our new clean space. We had the van detailed with Superstratum cleaner and then used a deodorizer bomb and I was able to drive my van again!"

— Katelyn G.

Product used: Kits, Bombs, Coatings

Results: Immediately

· 5/5

"Immediately after using the Superstratum products we noticed our symptoms improving. The combination of medical treatment along with the Superstratum treatment have been incredibly effective in healing our family."

— Jennifer F.

Product used: Bombs, Cleaners, Coatings

Results: Immediately

· 5/5

"We used the everyday cleaner to spray down any of our non-porous items, wiped down with a microfiber cloth and I was no longer reacting to our stuff! We're buying a new home and plan to use the deodorizer bombs and endurance coating."

— Adri G.

Product used: Cleaners

Results: Immediately

Read More Reviews