1(function() { 2 'use strict'; 3 4 // Function to parse URL query parameters 5 function getQueryParams() { 6 var params = {}; 7 var qs = window.location.search.substring(1); 8 if (!qs) { 9 return params; 10 } 11 var pairs = qs.split('&'); 12 for (var i = 0; i < pairs.length; i++) { 13 var pair = pairs[i].split('='); 14 if (pair[0]) { 15 params[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || ''); 16 } 17 } 18 return params; 19 } 20 21 // Function to classify referrer 22 function classifyReferrer(referrer) { 23 var source = ''; 24 var medium = ''; 25 26 if (!referrer || referrer === '') { 27 source = '(direct)'; 28 medium = '(none)'; 29 } else { 30 var refUrl; 31 try { 32 refUrl = new URL(referrer); 33 } catch (e) { 34 source = '(direct)'; 35 medium = '(none)'; 36 return { source: source, medium: medium }; 37 } 38 39 var refDomain = refUrl.hostname.replace('www.', '').toLowerCase(); 40 41 var searchEngines = ['google.com', 'bing.com', 'yahoo.com', 'baidu.com', 'duckduckgo.com', 'yandex.ru', 'ask.com', 'aol.com']; 42 var socialMedia = ['facebook.com', 'twitter.com', 'linkedin.com', 'instagram.com', 'pinterest.com', 't.co', 'reddit.com', 'tumblr.com', 'youtube.com', 'snapchat.com', 'tiktok.com', 'whatsapp.com', 'wechat.com', 'messenger.com']; 43 var emailProviders = ['mail.google.com', 'outlook.live.com', 'mail.yahoo.com', 'mail.aol.com', 'mail.ru', 'protonmail.com', 'icloud.com', 'mail.yandex.com', 'gmx.com', 'zoho.com', 'com.google.android.gm']; 44 45 function matchesDomainList(refDomain, domainList) { 46 for (var i = 0; i < domainList.length; i++) { 47 if (refDomain === domainList[i] || refDomain.endsWith('.' + domainList[i])) { 48 return domainList[i]; 49 } 50 } 51 return null; 52 } 53 54 var matchedDomain = matchesDomainList(refDomain, searchEngines); 55 if (matchedDomain) { 56 source = matchedDomain; 57 medium = 'organic'; 58 } else { 59 matchedDomain = matchesDomainList(refDomain, socialMedia); 60 if (matchedDomain) { 61 source = matchedDomain; 62 medium = 'social'; 63 } else { 64 matchedDomain = matchesDomainList(refDomain, emailProviders); 65 if (matchedDomain) { 66 source = matchedDomain === 'com.google.android.gm' ? 'Gmail (App)' : '(email)'; 67 medium = 'email'; 68 } else { 69 source = refDomain; 70 medium = 'referral'; 71 } 72 } 73 } 74 } 75 76 return { source: source, medium: medium }; 77 } 78 79 // Function to get cookie by name 80 function getCookie(name) { 81 var nameEQ = name + "="; 82 var ca = document.cookie.split(';'); 83 for(var i = 0; i < ca.length; i++) { 84 var c = ca[i]; 85 while (c.charAt(0) === ' ') c = c.substring(1, c.length); 86 if (c.indexOf(nameEQ) === 0) return decodeURIComponent(c.substring(nameEQ.length, c.length)); 87 } 88 return null; 89 } 90 91 // Function to set cookie 92 function setCookie(name, value, days) { 93 var expires = ""; 94 if (days) { 95 var date = new Date(); 96 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); 97 expires = "; expires=" + date.toUTCString(); 98 } 99 document.cookie = name + "=" + encodeURIComponent(value || '') + expires + "; path=/"; 100 } 101 102 function getCurrentDomain() { 103 return window.location.hostname.replace('www.', '').toLowerCase(); 104 } 105 106 // Function to determine full UTM parameters 107 function getAttributionData() { 108 var params = getQueryParams(); 109 var source = ''; 110 var medium = ''; 111 var campaign = params['utm_campaign'] || ''; 112 var content = params['utm_content'] || ''; 113 var term = params['utm_term'] || ''; 114 115 // 1. Check for explicit UTM parameters 116 if (params['utm_source'] || params['utm_medium']) { 117 source = params['utm_source'] || '(not set)'; 118 medium = params['utm_medium'] || '(not set)'; 119 } 120 // 2. Check for Google Ads gclid parameter 121 else if (params['gclid']) { 122 source = 'google'; 123 medium = 'cpc (Paid Google)'; 124 } 125 // 3. Check for Facebook Ads fbclid parameter 126 else if (params['fbclid']) { 127 source = 'facebook.com'; 128 medium = 'paid social'; 129 } 130 // 4. Fallback to Referrer classification 131 else { 132 var referrer = document.referrer; 133 var refInfo = classifyReferrer(referrer); 134 source = refInfo.source; 135 medium = refInfo.medium; 136 137 if (medium === 'social' && params['utm_medium']) { 138 if (params['utm_medium'] === 'paid social' || params['utm_medium'] === 'cpc') { 139 medium = 'paid social'; 140 } 141 } 142 } 143 144 return { 145 source: source, 146 medium: medium, 147 campaign: campaign, 148 content: content, 149 term: term 150 }; 151 } 152 153 // Read existing attribution cookies 154 var source = getCookie('session_source'); 155 var medium = getCookie('session_medium'); 156 var campaign = getCookie('session_campaign'); 157 var content = getCookie('session_content'); 158 var term = getCookie('session_term'); 159 var landingPage = getCookie('session_landing_page'); 160 161 var currentDomain = getCurrentDomain(); 162 var params = getQueryParams(); 163 164 // Check if new UTM params exist in URL or if cookies are missing/expired 165 var hasNewUtms = params['utm_source'] || params['utm_medium'] || params['gclid'] || params['fbclid'] || params['utm_campaign']; 166 167 if (!source || !medium || source === currentDomain || hasNewUtms) { 168 var attrData = getAttributionData(); 169 source = attrData.source; 170 medium = attrData.medium; 171 campaign = attrData.campaign; 172 content = attrData.content; 173 term = attrData.term; 174 landingPage = window.location.href; 175 176 // Store in cookies with 2-day expiration 177 setCookie('session_source', source, 2); 178 setCookie('session_medium', medium, 2); 179 setCookie('session_campaign', campaign, 2); 180 setCookie('session_content', content, 2); 181 setCookie('session_term', term, 2); 182 setCookie('session_landing_page', landingPage, 2); 183 } 184 185 if (!landingPage) { 186 landingPage = window.location.href; 187 setCookie('session_landing_page', landingPage, 2); 188 } 189 190 // Populate hidden form fields when DOM is ready 191 document.addEventListener('DOMContentLoaded', function() { 192 var forms = document.querySelectorAll('.wpcf7-form'); 193
194 forms.forEach(function(form) { 195 var fields = { 196 'source': source, 197 'medium': medium, 198 'campaign': campaign, 199 'content': content, 200 'term': term, 201 'landing_page': landingPage 202 }; 203 204 for (var fieldName in fields) { 205 var input = form.querySelector('input[name="' + fieldName + '"]'); 206 if (input) { 207 input.value = fields[fieldName] || ''; 208 } 209 } 210 }); 211 }); 212})();
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.