1 2 function calendlyBuildUtmParamObject(key, params, currentParams) { 3 const obj = {}; 4 5 //If in current url 6 params.forEach(param => { 7 let adjusted = param; 8 9 // Replace utm_ with utm__ 10 if (param.includes('utm_')) { 11 adjusted = param.replace('utm_', 'utm__'); 12 } 13 14 if (currentParams.get(param)) { 15 obj[adjusted] = currentParams.get(param); 16 } 17 }); 18 19 //If in sessionStorage 20 const storageParams = [ 21 'utm_source', 22 'utm_medium', 23 'utm_campaign', 24 'utm_content', 25 'utm_term', 26 ]; 27 28 console.log('obj', obj); 29 30 let storageParam, storageParamVal; 31 for(var i = storageParams.length - 1; i >= 0; i--) { 32 storageParam = storageParams[i]; 33 if(params.includes(storageParam)) { 34 storageParamVal = sessionStorage.getItem(storageParam); 35 if(!obj.hasOwnProperty(storageParam) && storageParamVal) { 36 let adjusted = storageParam.replace('utm_', 'utm__'); 37 obj[adjusted] = storageParamVal; 38 } 39 } 40 } 41 42 console.log('obj', obj); 43 44 return obj; 45 } 46 47 function calendlyAddUtmParams(url) { 48 const parsedUrl = new URL(url, window.location.origin); 49 const currentParams = new URLSearchParams(window.location.search); 50 51 // Clone existing query 52 const query = new URLSearchParams(parsedUrl.search); 53 54 // Basic params (same as PHP) 55 const params = [ 56 // 'utm_source', 57 'utm_medium', 58 'utm_campaign', 59 // 'utm_content', 60 // 'utm_term', 61 ]; 62 63 params.forEach(param => { 64 if (currentParams.get(param)) { 65 query.set(param, currentParams.get(param)); 66 } 67 }); 68 69 // Custom param objects (same structure as PHP) 70 const paramObjects = { 71 utm_medium: ['utm_source', 'utm_medium'], 72 utm_source: ['gclid', 'fbclid', 'msclkid'], 73 utm_content: ['utm_content'], 74 utm_term: ['utm_term'], 75 }; 76 77 Object.keys(paramObjects).forEach(key => { 78 const obj = calendlyBuildUtmParamObject( 79 key, 80 paramObjects[key], 81 currentParams 82 ); 83 84 query.set(key, JSON.stringify(obj)); 85 }); 86 87 // Rebuild URL 88 parsedUrl.search = query.toString(); 89 90 return parsedUrl.toString(); 91 } 92 93 function calendlyHtmlAddUtmParams() { 94 //Convert to dynamic-data-url 95 const elements = document.querySelectorAll('.calendly-inline-widget[data-url]'); 96 elements.forEach(el => { 97 let url = el.getAttribute('data-url'); 98 99 // Replace attribute (like your PHP) 100 el.removeAttribute('data-url'); 101 el.setAttribute('dynamic-data-url', url); 102 }); 103 104 const dynamicElements = document.querySelectorAll('.calendly-inline-widget[dynamic-data-url]'); 105 dynamicElements.forEach(el => { 106 let url = el.getAttribute('dynamic-data-url'); 107 if (!url) return; 108 109 // Decode HTML entities (like PHP html_entity_decode) 110 const txt = document.createElement('textarea'); 111 txt.innerHTML = url; 112 url = txt.value; 113 114 const updatedUrl = calendlyAddUtmParams(url); 115 116 console.log(updatedUrl); 117 118 // Replace attribute (like your PHP) 119 el.setAttribute('dynamic-data-url', updatedUrl); 120 }); 121 } 122 123 // Run before Calendly initializes 124 if (document.readyState === 'loading') { 125 console.log('page loading'); 126 calendlyHtmlAddUtmParams(); 127 } else { 128 console.log('page loaded'); 129 calendlyHtmlAddUtmParams(); 130 }
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.