1/** 2 * Easy UTM tracking with Contact Form 7 front-end capture script. 3 * Stores UTM parameters, ad click IDs, landing page and external referrer 4 * in first-party cookies (first-touch and last-touch). 5 */ 6(function () { 7 'use strict'; 8 9 var config = window.easyUtmCf7 || {}; 10 var cookieDays = parseInt(config.cookieDays, 10) || 60; 11 var trackedParams = config.params || [ 12 'utm_source', 'utm_medium', 'utm_term', 'utm_campaign', 'utm_content', 13 'gclid', 'fbclid', 'msclkid', 'ttclid' 14 ]; 15 16 function createCookie(name, value, days) { 17 var expires = ''; 18 if (days) { 19 var date = new Date(); 20 date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); 21 expires = '; expires=' + date.toUTCString(); 22 } 23 document.cookie = name + '=' + value + expires + '; path=/; SameSite=Lax'; 24 } 25 26 function readCookie(name) { 27 var nameEQ = name + '='; 28 var ca = document.cookie.split(';'); 29 for (var i = 0; i < ca.length; i++) { 30 var c = ca[i]; 31 while (c.charAt(0) === ' ') { 32 c = c.substring(1); 33 } 34 if (c.indexOf(nameEQ) === 0) { 35 return c.substring(nameEQ.length); 36 } 37 } 38 return null; 39 } 40 41 function getParams() { 42 var search = window.location.search; 43 var found = {}; 44 var hasAny = false; 45 46 if (!search) { 47 return null; 48 } 49 50 var query = search.substring(1).split('&'); 51 for (var i = 0; i < query.length; i++) { 52 var pair = query[i].split('='); 53 var key = decodeURIComponent(pair[0] || ''); 54 if (trackedParams.indexOf(key) === -1) { 55 continue; 56 } 57 var value = decodeURIComponent((pair[1] || '').replace(/\+/g, ' ')); 58 if (value !== '') { 59 found[key] = value; 60 hasAny = true; 61 } 62 } 63 return hasAny ? found : null; 64 } 65 66 var params = getParams(); 67 68 if (params) { 69 params.landing = window.location.href.split('?')[0]; 70 params.ts = Math.floor(Date.now() / 1000); 71 72 var encoded = encodeURIComponent(JSON.stringify(params)); 73 74 // Last touch: always overwritten by the newest tagged visit. 75 createCookie('_easy_utm_last', encoded, cookieDays); 76 77 // First touch: only set once. 78 if (!readCookie('_easy_utm_first')) { 79 createCookie('_easy_utm_first', encoded, cookieDays); 80 } 81 } 82 83 // Store the referrer only when it is EXTERNAL, and only once, 84 // so the original traffic source isn't overwritten by internal navigation. 85 var internalPrefix = location.protocol + '//' + location.host; 86 if ( 87 document.referrer && 88 document.referrer.indexOf(internalPrefix) !== 0 && 89 !readCookie('_easy_utm_referrer') 90 ) { 91 createCookie('_easy_utm_referrer', encodeURIComponent(document.referrer), cookieDays); 92 } 93})();
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.