1(function () { 2 const STORAGE_KEY = 'ohlala_attribution'; 3 const TTL_MS = 90 * 24 * 60 * 60 * 1000; 4 const QUERY_KEYS = [ 5 'utm_source', 6 'utm_medium', 7 'utm_campaign', 8 'utm_content', 9 'utm_term', 10 'fbclid', 11 'gclid', 12 'ci', 13 't1', 14 't2', 15 'ai', 16 'psource', 17 'source' 18 ]; 19 20 function compact(object) { 21 return Object.keys(object).reduce((memo, key) => { 22 const value = object[key]; 23 if (value !== null && value !== undefined && value !== '') { 24 memo[key] = value; 25 } 26 return memo; 27 }, {}); 28 } 29 30 function readCookie(name) { 31 const value = `; ${document.cookie}`; 32 const parts = value.split(`; ${name}=`); 33 if (parts.length === 2) return decodeURIComponent(parts.pop().split(';').shift()); 34 return null; 35 } 36 37 function cookieDomainAttribute() { 38 const hostname = window.location.hostname; 39 if (!hostname || hostname === 'localhost' || /^\d+\.\d+\.\d+\.\d+$/.test(hostname)) return ''; 40 41 const parts = hostname.split('.'); 42 if (parts.length < 2) return ''; 43 44 return `; domain=.${parts.slice(-2).join('.')}`; 45 } 46 47 function writeCookie(name, value) { 48 const expires = new Date(Date.now() + TTL_MS).toUTCString(); 49 document.cookie = `${name}=${encodeURIComponent(value)}; path=/; expires=${expires}; SameSite=Lax${cookieDomainAttribute()}`; 50 } 51 52 function queryValues(params) { 53 return QUERY_KEYS.reduce((memo, key) => { 54 const value = params.get(key); 55 if (value) memo[key] = value; 56 return memo; 57 }, {}); 58 } 59 60 function readStore() { 61 try { 62 const stored = JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}'); 63 if (!stored.expires_at || stored.expires_at < Date.now()) return {}; 64 return stored; 65 } catch (_error) { 66 return {}; 67 } 68 } 69 70 function writeStore(store) { 71 localStorage.setItem(STORAGE_KEY, JSON.stringify({ 72 ...store, 73 expires_at: Date.now() + TTL_MS 74 })); 75 } 76 77 function ensureFbc(params) { 78 const fbc = readCookie('_fbc'); 79 if (fbc) return fbc; 80 81 const fbclid = params.get('fbclid'); 82 if (!fbclid) return null; 83 84 const generatedFbc = `fb.1.${Date.now()}.${fbclid}`; 85 writeCookie('_fbc', generatedFbc); 86 return generatedFbc; 87 } 88 89 function gaClientId() { 90 const ga = readCookie('_ga'); 91 if (!ga) return null; 92 93 const parts = ga.split('.'); 94 return parts.length >= 4 ? parts.slice(-2).join('.') : ga; 95 } 96 97 function currentTouch(params) { 98 const query = queryValues(params); 99 100 return compact({ 101 ...query, 102 psource: query.psource || query.source, 103 landing_page: window.location.href, 104 page_location: window.location.href, 105 referrer: document.referrer, 106 captured_at: new Date().toISOString() 107 }); 108 } 109 110 function capture() { 111 const params = new URLSearchParams(window.location.search); 112 const stored = readStore(); 113 const touch = currentTouch(params); 114 const fbc = ensureFbc(params); 115 const fbp = readCookie('_fbp'); 116 117 const nextStore = { 118 first_touch: stored.first_touch || touch, 119 last_touch: touch 120 }; 121 writeStore(nextStore); 122 123 const affiliateId = params.get('ai') || touch.ai || nextStore.first_touch.ai; 124 if (affiliateId) localStorage.setItem('affiliate_id', affiliateId); 125 if (fbc) window.FBC = fbc; 126 if (fbp) window.FBP = fbp; 127 128 return nextStore; 129 } 130 131 function getPayload() { 132 const params = new URLSearchParams(window.location.search); 133 const stored = readStore(); 134 const firstTouch = stored.first_touch || {}; 135 const lastTouch = stored.last_touch || currentTouch(params); 136 const fbc = readCookie('_fbc') || window.FBC; 137 const fbp = readCookie('_fbp') || window.FBP; 138 139 return compact({ 140 utm_source: lastTouch.utm_source || firstTouch.utm_source, 141 utm_medium: lastTouch.utm_medium || firstTouch.utm_medium, 142 utm_campaign: lastTouch.utm_campaign || firstTouch.utm_campaign, 143 utm_content: lastTouch.utm_content || firstTouch.utm_content, 144 utm_term: lastTouch.utm_term || firstTouch.utm_term, 145 fbclid: lastTouch.fbclid || firstTouch.fbclid, 146 gclid: lastTouch.gclid || firstTouch.gclid, 147 fbc: fbc, 148 fbp: fbp, 149 landing_page: firstTouch.landing_page || lastTouch.landing_page, 150 page_location: window.location.href, 151 referrer: firstTouch.referrer || lastTouch.referrer || document.referrer, 152 first_touch: firstTouch, 153 last_touch: lastTouch, 154 psource: lastTouch.psource || firstTouch.psource, 155 affiliate: compact({ 156 ai: lastTouch.ai || firstTouch.ai || localStorage.getItem('affiliate_id'), 157 ci: lastTouch.ci || firstTouch.ci, 158 t1: lastTouch.t1 || firstTouch.t1, 159 t2: lastTouch.t2 || firstTouch.t2 160 }), 161 client_id: gaClientId() 162 }); 163 } 164 165 function appendToUrl(url) { 166 const payload = getPayload(); 167 168 ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term', 'fbclid', 'gclid', 'fbc', 'fbp', 'psource', 'client_id'].forEach((key) => { 169 if (payload[key]) url.searchParams.set(key, payload[key]); 170 }); 171 172 if (payload.affiliate) { 173 if (payload.affiliate.ai) url.searchParams.set('ai', payload.affiliate.ai); 174 if (payload.affiliate.ci) url.searchParams.set('ci', payload.affiliate.ci); 175 if (payload.affiliate.t1) url.searchParams.set('t1', payload.affiliate.t1); 176 if (payload.affiliate.t2) url.searchParams.set('t2', payload.affiliate.t2); 177 } 178 179 return url; 180 } 181 182 function mergeIntoPayload(data) { 183 return { 184 ...data, 185 attribution: getPayload() 186 }; 187 } 188 189 capture(); 190 191 window.OhlalaAttribution = { 192 appendToUrl: appendToUrl, 193 getAffiliateId: function () { 194 return getPayload().affiliate && getPayload().affiliate.ai; 195 }, 196 getPayload: getPayload, 197 getParams: getPayload, 198 mergeIntoPayload: mergeIntoPayload 199 }; 200 201 window.getAffiliateIdFromStorage = window.getAffiliateIdFromStorage || function () { 202 return localStorage.getItem('affiliate_id'); 203 }; 204})();
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.