* 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.21-2'; 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 getQuery() { var out = {}; var qs = location.search.replace(/^\?/, ''); if (!qs) return out; qs.split('&').forEach(function (p) { var i = p.indexOf('='); if (i < 0) { out[decodeURIComponent(p)] = ''; return; } out[decodeURIComponent(p.slice(0, i))] = decodeURIComponent(p.slice(i + 1)); }); return out; } 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(); } 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) // ------------------------------------------------------------------------- function captureOrigin() { var existing = parseCookieJSON(COOKIE_NAME); var qp = getQuery(); var changed = false; var hasAnyTrackingParam = ALL_PARAMS.some(function (k) { return qp[k]; }); 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. ALL_PARAMS.forEach(function (k) { if (qp[k]) existing[k] = qp[k]; }); // FIX 1: derive source/medium from the referrer when the URL carried no // campaign of its own. Never overwrites an authored utm_source. if (!existing.utm_source) { var derived = classifyReferrer(externalRef ? ref : ''); if (derived) { existing.utm_source = derived.source; if (!existing.utm_medium) existing.utm_medium = derived.medium; existing.source_derived = '1'; } } existing.captured_at = new Date().toISOString(); existing.landing_host = location.hostname; existing.landing_path = trimPath(location.pathname + (location.search || '')); existing.landing_referrer = ref || null; changed = true; log('first-touch captured', existing); } else if (existing.source_derived === '1' && 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. ALL_PARAMS.forEach(function (k) { if (qp[k]) existing[k] = qp[k]; }); delete existing.source_derived; 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 + (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. ALL_PARAMS.forEach(function (k) { if (!qp[k]) return; var lastKey = 'last_' + k; var current = existing[lastKey] != null ? existing[lastKey] : existing[k]; if (qp[k] !== current) { existing[lastKey] = qp[k]; changed = true; } }); if (changed) { // 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; 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) { existing.last_utm_source = d.source; existing.last_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); } } } 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; if (data.last_utm_source) { 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); // Precedence: current-URL param (this hop) > stored last-touch > frozen // first-touch. A live campaign click still wins over the cookie, and // decorated links carry the most recent campaign, not the frozen first. UTM_PARAMS.concat(CLICK_IDS).forEach(function (k) { var v = qp[k] || data['last_' + k] || data[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); Object.keys(params).forEach(function (k) { // Authored params win: a link that hardcodes utm_* keeps it. 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(); Object.keys(params).forEach(function (k) { 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(); var alreadyHasUtm = UTM_PARAMS.some(function (k) { return qp[k]; }); if (alreadyHasUtm) { log('shop reconcile: URL already has UTMs'); return false; } var params = new URLSearchParams(location.search); var added = 0; var dropDirect = isDerivedDirect(data, qp); // FIX 5 — see isDerivedDirect UTM_PARAMS.concat(CLICK_IDS).forEach(function (k) { if (dropDirect && (k === 'utm_source' || k === 'utm_medium')) return; // Prefer last-touch, fall back to frozen first-touch. var v = (data['last_' + k] != null ? data['last_' + k] : data[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) { payload['ssl_' + k] = data[k]; }); window.dataLayer.push(payload); log('dataLayer pushed', payload); } function stampCartAttributes() { if (!window.fetch) return; var data = parseCookieJSON(COOKIE_NAME); if (!data || !Object.keys(data).length) return; var pairs = []; Object.keys(data).forEach(function (k) { pairs.push( encodeURIComponent('attributes[ssl_' + k + ']') + '=' + encodeURIComponent(String(data[k] == null ? '' : data[k])) ); }); if (!pairs.length) return; fetch('/cart/update.js', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' }, body: pairs.join('&'), credentials: 'same-origin', keepalive: true }).then(function (r) { log('cart.attributes stamped', r.status); }) .catch(function (e) { log('cart.attributes error', 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 can wait for DOMContentLoaded. onReady(stampCartAttributes); } 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(); }); } })();

You're in. Start with the routine, or jump to the matrix.

Editorial cross-section illustration of a home

The Home Detox Playbook

A practical, room-by-room guide to a mold-free, low-toxin home.

The routine

Your healthy home routine

Five tiers, organized by how often you'll do them. Daily and weekly are the foundation. Everything else layers in over time.

The matrix

Find a problem

Something specific going on? Find your place, find your problem, get the protocol.

Tap any cell to see the protocol for that situation.

Common · protocol applies Sometimes occurs Not typical · left blank

Deep clean protocols

Deep clean protocols

Targeted resets for the spots where normal cleaning falls short. Tap any card to open the full step-by-step.

Reference

Cleaning Chemicals 101

What's actually in the bottles under your sink, what each one does, what it doesn't do, and what you must never mix. Read this once — your lungs will thank you.

Effectiveness × Safety quadrant

Top-right is the goal: kills pathogens hard and is safe for the people and surfaces in the room.

159159Effectiveness →Safety →Use theseSafe / weakRiskyAvoidHOClH₂O₂OzoneIPABleachVinegarBaking sodaNH₃QuatsFragrance

Chemical scorecard

Each chemical scored 1–10 across four dimensions. Tap a chemical to expand details.

AntimicrobialAM
OxidizerOX
SafetySF
No ResidueNR

Chemical combinations

Tap a pair to see what it produces and why it matters.

What's actually safe

These six cover ~95% of household cleaning, without the VOCs and disinfection byproducts.

HOCl spray

Disinfect

Daily disinfection of countertops, bathrooms, toys, pet areas, and food-contact surfaces.

Shop →

3% Hydrogen peroxide

Stain

Grout, tile, stain lifting, and as a step in two-stage bathroom disinfection.

Distilled white vinegar

Descale

Glass, mineral scale, washing machines, condensate lines, kettles.

Baking soda

Scrub

Scrubbing pastes, deodorizing carpets and fridges, mild abrasive on tubs and stovetops.

Castile soap

Wash

Floors, dishes, hands, laundry — diluted in water for almost anything.

HOCl wipes

Mechanical

Mechanical removal plus HOCl wins every time. Disinfects on contact and leaves nothing behind but salt water.

Next step

Want a personalized plan?

The Whole Home Detox Calculator builds a room-by-room product and protocol plan specific to your home.

Take the Calculator
Free Guide

The Home
Detox Playbook

Drop your email for the printable PDF, room-by-room checklists, and quarterly updates. Or keep reading — it's all free either way.

No spam. Unsubscribe anytime.