1(function() { 2 // --------------------------------------------------------------------------- 3 // Constants â mirrored exactly in src/lib/marketing/utm-store.ts 4 // --------------------------------------------------------------------------- 5 6 var STORAGE_KEYS = { 7 utm_source: 'spoki_utm_source', 8 utm_medium: 'spoki_utm_medium', 9 utm_campaign: 'spoki_utm_campaign', 10 utm_id: 'spoki_utm_id', 11 utm_term: 'spoki_utm_term', 12 utm_content: 'spoki_utm_content', 13 gclid: 'spoki_gclid', 14 fbclid: 'spoki_fbclid' 15 }; 16 17 var UTM_CAMPAIGN_PARAMS = [ 18 'utm_source', 'source', 'utm_medium', 'utm_id', 19 'utm_campaign', 'utm_content', 'utm_term' 20 ]; 21 22 var CLICK_ID_PARAMS = ['gclid', 'fbclid']; 23 24 var ALL_STORAGE_KEYS = Object.keys(STORAGE_KEYS).map(function(k) { return STORAGE_KEYS[k]; }); 25 26 // --------------------------------------------------------------------------- 27 // Cookie helpers 28 // --------------------------------------------------------------------------- 29 30 function setCookie(name, value, days) { 31 try { 32 var expires = ''; 33 if (days) { 34 var date = new Date(); 35 date.setTime(date.getTime() + (days * 86400000)); 36 expires = '; expires=' + date.toUTCString(); 37 } 38 document.cookie = name + '=' + encodeURIComponent(value) + expires + '; path=/; SameSite=Lax'; 39 } catch (e) { /* ignore */ } 40 } 41 42 function getCookie(name) { 43 try { 44 var nameEQ = name + '='; 45 var cookies = document.cookie.split(';'); 46 for (var i = 0; i < cookies.length; i++) { 47 var c = cookies[i].trim(); 48 if (c.indexOf(nameEQ) === 0) { 49 return decodeURIComponent(c.substring(nameEQ.length)); 50 } 51 } 52 } catch (e) { /* ignore */ } 53 return null; 54 } 55 56 // --------------------------------------------------------------------------- 57 // Migration: old keys -> new keys (v1.0.271) 58 // --------------------------------------------------------------------------- 59 60 function migrateOldUtmKeys() { 61 try { 62 var migrations = [ 63 ['spoki_source', 'spoki_utm_source'], 64 ['spoki_medium', 'spoki_utm_medium'], 65 ['spoki_id', 'spoki_utm_id'], 66 ['spoki_campaign', 'spoki_utm_campaign'], 67 ['spoki_content', 'spoki_utm_content'], 68 ['spoki_term', 'spoki_utm_term'] 69 ]; 70 migrations.forEach(function(pair) { 71 var value = localStorage.getItem(pair[0]); 72 if (value && !localStorage.getItem(pair[1])) { 73 localStorage.setItem(pair[1], value); 74 localStorage.removeItem(pair[0]); 75 } 76 }); 77 } catch (e) { /* ignore */ } 78 } 79 80 // --------------------------------------------------------------------------- 81 // UTM history: sync + save 82 // --------------------------------------------------------------------------- 83 84 function syncUtmHistoryStorage() { 85 try { 86 var localData = localStorage.getItem('utm_history_json'); 87 var cookieData = getCookie('utm_history_json'); 88 89 if (localData && !cookieData) { 90 setCookie('utm_history_json', localData, 730); 91 } else if (cookieData && !localData) { 92 localStorage.setItem('utm_history_json', cookieData); 93 } else if (localData && cookieData) { 94 try { 95 var localArr = JSON.parse(localData); 96 var cookieArr = JSON.parse(cookieData); 97 if (cookieArr.length > localArr.length) { 98 localStorage.setItem('utm_history_json', cookieData); 99 } else if (localArr.length > cookieArr.length) { 100 setCookie('utm_history_json', localData, 730); 101 } 102 } catch (e) { /* ignore parse errors */ } 103 } 104 } catch (e) { /* ignore */ } 105 } 106 107 function saveUtmHistory() { 108 try { 109 var source = localStorage.getItem('spoki_utm_source') || ''; 110 var gclid = localStorage.getItem('spoki_gclid') || ''; 111 var fbclid = localStorage.getItem('spoki_fbclid') || ''; 112 113 if (!source && !gclid && !fbclid) return; 114 115 var nuovoTocco = { 116 spoki_utm_source: source, 117 spoki_utm_medium: localStorage.getItem('spoki_utm_medium') || '', 118 spoki_utm_campaign: localStorage.getItem('spoki_utm_campaign') || '', 119 spoki_utm_id: localStorage.getItem('spoki_utm_id') || '', 120 spoki_utm_content: localStorage.getItem('spoki_utm_content') || '', 121 spoki_utm_term: localStorage.getItem('spoki_utm_term') || '', 122 spoki_gclid: gclid, 123 spoki_fbclid: fbclid, 124 ga_id: getGAClientId(), 125 fb_id: getFBPixelId(), 126 timestamp: new Date().toISOString() 127 }; 128 129 var storia = [];
130 try { storia = JSON.parse(localStorage.getItem('utm_history_json') || '[]'); } catch (e) { storia = []; } 131 132 // Deduplication (ignore timestamp and ga_id) 133 var ultimo = storia[storia.length - 1]; 134 var cur = Object.assign({}, nuovoTocco); cur.timestamp = ''; cur.ga_id = ''; 135 var prev = ''; 136 if (ultimo) { var p = Object.assign({}, ultimo); p.timestamp = ''; p.ga_id = ''; prev = JSON.stringify(p); } 137 138 if (JSON.stringify(cur) !== prev) { 139 storia.push(nuovoTocco); 140 if (storia.length > 20) storia.shift(); 141 var json = JSON.stringify(storia); 142 localStorage.setItem('utm_history_json', json); 143 setCookie('utm_history_json', json, 730); 144 } 145 } catch (e) { /* ignore */ } 146 } 147 148 function getGAClientId() { 149 try { 150 var cookies = document.cookie.split(';'); 151 var ga = cookies.find(function(c) { return c.trim().startsWith('_ga='); }); 152 if (ga) { var p = ga.split('.'); if (p.length >= 4) return p.slice(2).join('.'); } 153 } catch (e) { /* ignore */ } 154 return ''; 155 } 156 157 function getFBPixelId() { 158 try { 159 var cookies = document.cookie.split(';'); 160 var fb = cookies.find(function(c) { return c.trim().startsWith('_fbp='); }); 161 if (fb) return fb.split('=')[1].trim(); 162 } catch (e) { /* ignore */ } 163 return ''; 164 } 165 166 // --------------------------------------------------------------------------- 167 // Core: capture UTM from URL â cookie + localStorage 168 // UTMs stay in the URL (middleware no longer strips them). This function 169 // copies them to cookies + localStorage so HubSpot forms can read them. 170 // --------------------------------------------------------------------------- 171 172 function clearAllUTMStorage() { 173 ALL_STORAGE_KEYS.forEach(function(key) { 174 localStorage.removeItem(key); 175 setCookie(key, '', -1); 176 }); 177 } 178 179 function writeParam(urlParam, value) { 180 var storageKey = STORAGE_KEYS[urlParam]; 181 if (!storageKey || !value) return; 182 localStorage.setItem(storageKey, value); 183 setCookie(storageKey, value, 730); 184 } 185 186 function captureUTMFromURL() { 187 var params = new URLSearchParams(window.location.search); 188 var hasFullUTM = UTM_CAMPAIGN_PARAMS.some(function(p) { return params.has(p); }); 189 var hasClickIds = CLICK_ID_PARAMS.some(function(p) { return params.has(p); }); 190 191 if (hasFullUTM) { 192 var source = params.get('utm_source') || params.get('source') || ''; 193 if (source === 'web_site') source = 'organic'; 194 195 // Only wipe existing storage when we have a real source to replace it. 196 // Otherwise update the other params without losing a previously captured source. 197 if (source) { 198 clearAllUTMStorage(); 199 writeParam('utm_source', source); 200 } 201 202 writeParam('utm_medium', params.get('utm_medium')); 203 writeParam('utm_campaign', params.get('utm_campaign')); 204 writeParam('utm_id', params.get('utm_id')); 205 writeParam('utm_term', params.get('utm_term')); 206 writeParam('utm_content', params.get('utm_content')); 207 writeParam('gclid', params.get('gclid')); 208 writeParam('fbclid', params.get('fbclid')); 209 210 saveUtmHistory(); 211 return; 212 } 213 214 if (hasClickIds) { 215 writeParam('gclid', params.get('gclid')); 216 writeParam('fbclid', params.get('fbclid')); 217 } 218 219 syncCookiesToLocalStorage(); 220 } 221 222 function syncCookiesToLocalStorage() { 223 var hasCookieUTM = !!getCookie('spoki_utm_source'); 224 if (!hasCookieUTM) return; 225 226 var needsSync = false; 227 for (var i = 0; i < ALL_STORAGE_KEYS.length; i++) { 228 if ((getCookie(ALL_STORAGE_KEYS[i]) || '') !== (localStorage.getItem(ALL_STORAGE_KEYS[i]) || '')) { 229 needsSync = true; 230 break; 231 } 232 } 233 234 if (needsSync) { 235 ALL_STORAGE_KEYS.forEach(function(key) { 236 var cv = getCookie(key); 237 if (cv) { localStorage.setItem(key, cv); } else { localStorage.removeItem(key); } 238 }); 239 saveUtmHistory(); 240 } 241 } 242 243 // --------------------------------------------------------------------------- 244 // Init: capture UTMs from URL to storage, sync history 245 // v1.0.658: Removed URL restoration, history interception, and link handlers. 246 // UTMs stay in the URL naturally (middleware no longer strips them). 247 // This script only captures UTMs to cookies/localStorage for HubSpot forms. 248 // --------------------------------------------------------------------------- 249 250 migrateOldUtmKeys(); 251 syncUtmHistoryStorage(); 252 253 try { 254 captureUTMFromURL(); 255 } catch (e) { /* ignore */ } 256})();
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.