1/* Attribution capture + Polar checkout metadata - Content ROI. 2 Loaded on every Atlas page. Captures the first-touch landing path of the 3 session and forwards it onto Polar checkout links/buttons as metadata, so the 4 analytics dashboard can attribute each sale to the page that earned the visit. 5 6 The dashboard reads order.metadata.landing_path (primary) or .ta_landing 7 (fallback) and matches it against Umami entry-page paths. Value is a bare 8 pathname (window.location.pathname) - no domain, query or hash. 9 10 NOTE: custom metadata via checkout-LINK query params is best-effort per Polar 11 docs (they document only reference_id + utm_* as link params; custom metadata 12 officially needs the Checkout API). We send both metadata[landing_path] and a 13 reference_id backstop, and verify with a test purchase. If metadata[] does not 14 land on order.metadata, switch to a server-side Checkout Session. */ 15(function () { 16 var STORAGE; 17 try { STORAGE = window.localStorage; } catch (e) { return; } 18 19 function setIfMissing(key, value) { 20 if (!value) return; 21 try { if (!STORAGE.getItem(key)) STORAGE.setItem(key, value); } catch (e) {} 22 } 23 24 /* ---- Capture first-touch attribution (never overwritten on later pages) ---- */ 25 try { 26 var params = new URLSearchParams(window.location.search); 27 var refHost = null; 28 if (document.referrer) { 29 try { 30 var ru = new URL(document.referrer); 31 if (ru.hostname && ru.hostname !== window.location.hostname) { 32 refHost = ru.hostname.replace(/^www\./, ''); 33 } 34 } catch (e) {} 35 } 36 setIfMissing('ta_source', params.get('utm_source') || refHost); 37 setIfMissing('ta_medium', params.get('utm_medium')); 38 setIfMissing('ta_campaign', params.get('utm_campaign')); 39 setIfMissing('ta_term', params.get('utm_term')); 40 setIfMissing('ta_content', params.get('utm_content')); 41 setIfMissing('ta_ref', refHost); 42 setIfMissing('ta_landing', window.location.pathname); // the entry page that earned the visit 43 setIfMissing('ta_first_at', new Date().toISOString()); 44 } catch (e) {} 45 46 /* ---- Build a Polar checkout URL carrying attribution + landing_path ---- */ 47 function buildPolarUrl(rawUrl) { 48 var u; 49 try { u = new URL(rawUrl, window.location.origin); } catch (e) { return rawUrl; } 50 var utm = { utm_source: 'ta_source', utm_medium: 'ta_medium', utm_campaign: 'ta_campaign', utm_term: 'ta_term', utm_content: 'ta_content' }; 51 Object.keys(utm).forEach(function (k) { 52 var v = STORAGE.getItem(utm[k]); if (v) u.searchParams.set(k, v); 53 }); 54 var landing = STORAGE.getItem('ta_landing') || window.location.pathname || ''; 55 var firstAt = STORAGE.getItem('ta_first_at') || ''; 56 if (landing) { 57 u.searchParams.set('metadata[landing_path]', landing); // primary key the dashboard reads 58 u.searchParams.set('metadata[ta_landing]', landing); // fallback key 59 } 60 // Officially-supported backstop: reference_id -> order.metadata.reference_id 61 var refId = ['atlas', landing, firstAt].filter(Boolean).join('|'); 62 if (refId) u.searchParams.set('reference_id', refId); 63 return u.toString(); 64 } 65 window.atlasBuildCheckout = buildPolarUrl; // used by demo.js buy buttons 66 67 /* ---- Intercept clicks on static Polar checkout links (e.g. blog CTAs) ---- */ 68 document.addEventListener('click', function (e) { 69 var link = e.target.closest ? e.target.closest('a[href*="buy.polar.sh"]') : null; 70 if (!link) return; 71 e.preventDefault(); 72 var url = buildPolarUrl(link.getAttribute('href')); 73 try { 74 if (typeof umami !== 'undefined' && umami.track) { 75 umami.track('purchase_click', { source: STORAGE.getItem('ta_source') || 'direct', product: 'atlas' }); 76 } 77 } catch (e) {} 78 setTimeout(function () { window.location.href = url; }, 120); 79 }); 80 81 /* ---- Keep the footer copyright year current (house standard) ---- */ 82 function atlasUpdateCopyYear() { 83 var y = String(new Date().getFullYear()); 84 var els = document.querySelectorAll('.copy-year'); 85 for (var i = 0; i < els.length;
85 i++) els[i].textContent = y; 86 } 87 if (document.readyState === 'loading') { 88 document.addEventListener('DOMContentLoaded', atlasUpdateCopyYear); 89 } else { 90 atlasUpdateCopyYear(); 91 } 92})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.