1window.startedForms = []; 2 3document.addEventListener("DOMContentLoaded", function () { 4 domLoaded(); 5}); 6 7function domLoaded() { 8 setUtmData(); 9 setCookies(); 10 setupCtas(); 11 hubspotFormListener(); 12 navClickListener(); 13 documentClickListener(); 14 vimeoListener(); 15 expandMobileMenus(); 16 setupOpenInNewTab(); 17 18 /** Event IDs */ 19 var r = Math.random().toString(36).substring(7); 20 window.kcm_event_id = "fbe_" + r + "_" + Date.now(); 21 22 sendFBConversion("PageView", window.kcm_event_id); 23 24 document.addEventListener("click", function (e) { 25 if (e.target.matches(".main-menu-trial-link, .main-menu-trial-link *")) { 26 try { 27 ga("send", "event", "Navigation", "Free Trial Button", "Clicks"); 28 } catch (error) { 29 console.log("failed to track ga event: ", error); 30 } 31 } 32 }); 33} 34 35function setUtmData() { 36 var utmParams = [ 37 "utm_source", 38 "utm_medium", 39 "utm_campaign", 40 "utm_term", 41 "utm_content", 42 ]; 43 var dataLayerPush = {}; 44 45 var params = getParams(window.location.href); 46 47 for (var i = 0; i < utmParams.length; i++) { 48 var param = utmParams[i]; 49 var value = params[param]; 50 if (value) { 51 sessionStorage.setItem(param, value); 52 } 53 var storedValue = sessionStorage.getItem(param); 54 if (storedValue) { 55 dataLayerPush[param] = storedValue; 56 } 57 } 58 59 if (Object.keys(dataLayerPush).length > 0) { 60 window.dataLayer = window.dataLayer || []; 61 window.dataLayer.push(dataLayerPush); 62 } 63} 64 65function hubspotFormListener() { 66 document.addEventListener("submit", function (event) { 67 const targetForm = event.target; 68 69 if (targetForm.classList.contains("hs-form")) { 70 const formNameInput = targetForm.querySelector('input[name="kcm_formname"]'); 71 72 if (formNameInput) { 73 const formName = formNameInput.value; 74 75 window.dataLayer = window.dataLayer || []; 76 window.dataLayer.push({ 77 event: "form_submit", 78 form_name: formName, 79 }); 80 } 81 } 82 }); 83 84 console.log("HubSpot form listeners registered"); 85} 86 87 88function navClickListener() { 89 var overrides = { 90 "avia-menu": "header", 91 "menu-site-map-footer": "footer", 92 }; 93 94 var navs = document.querySelectorAll("ul.menu"); 95 96 navs.forEach((node) => { 97 node.addEventListener("click", function (event) { 98 let targetElement = event.target; 99 100 // If it's a span within an a tag, adjust the targetElement 101 // thanks to avia's menus 102 if ( 103 targetElement.tagName === "SPAN" && 104 targetElement.parentNode.tagName === "A" 105 ) { 106 targetElement = targetElement.parentNode; 107 } 108 109 // Check if the clicked element or its parent is an "a" tag 110 if (targetElement.tagName === "A") { 111 console.log("Link clicked:", targetElement.innerText); 112 console.log("Link href:", targetElement.href); 113 114 var menuName = node.id; 115 if (Object.keys(overrides).includes(node.id)) { 116 menuName = overrides[node.id]; 117 } 118 119 const data = { 120 event: "navigation_click", 121 menu_type: menuName, 122 menu_item_name: targetElement.innerText, 123 }; 124 window.dataLayer.push(data); 125 } 126 }); 127 }); 128 console.log("registered navigation listeners"); 129} 130 131function documentClickListener() { 132 document.addEventListener("click", function (event) { 133 let targetElement = event.target; 134 // If it's a span within an a tag, adjust the targetElement 135 if ( 136 targetElement.tagName === "SPAN" && 137 targetElement.parentNode.tagName === "A" 138 ) { 139 targetElement = targetElement.parentNode; 140 } 141 142 if (targetElement) { 143 downloadListener(targetElement); 144 ctaListener(targetElement); 145 accordionListener(targetElement); 146 shareButtonListener(targetElement); 147 } 148 }); 149 150 console.log("registered download listeners"); 151 console.log("registered cta listeners"); 152 console.log("registered accordion listeners"); 153 console.log("registered share listeners"); 154} 155 156function vimeoListener() { 157 const iframes = document.querySelectorAll("iframe"); 158 159 iframes.forEach(function (iframe) { 160 iframe.addEventListener("load", () => { 161 setupVimeoListeners(iframe); 162 }); 163 }); 164} 165 166function setupVimeoListeners(iframe) { 167 const cuepoints = [ 168 { 169 label: "25%", 170 multiplier: 0.25, 171 }, 172 { 173 label: "50%", 174 multiplier: 0.5, 175 }, 176 { 177 label: "75%", 178 multiplier: 0.75, 179 }, 180 ]; 181 182 try { 183 const player = new Vimeo.Player(iframe); 184 185 // Listen to play event 186 player.on("play", function () { 187 player.getVideoTitle().then((title) => { 188 const data = { 189 event: "video_start", 190 video_title: title, 191 }; 192 193 window.dataLayer.push(data); 194 195 // downloads on the /dl/ pages should trigger a secondary event for generating leads 196 if (window.location.pathname.includes("/replay/")) { 197 newEvent = Object.assign({}, data); 198 newEvent.event = "generate_lead"; 199 newEvent.file_name = title; 200 window.dataLayer.push(newEvent); 201 } 202 }); 203 }); 204 205 player.on("ended", function () { 206 player.getVideoTitle().then((title) => { 207 const data = { 208 event: "video_complete", 209 video_title: title, 210 }; 211 212 window.dataLayer.push(data); 213 }); 214 }); 215 216 player.getDuration().then((duration) => {
217 cuepoints.forEach((cuepoint) => { 218 player.addCuePoint(Math.ceil(duration * cuepoint.multiplier), { 219 action: cuepoint.label, 220 }); 221 }); 222 }); 223 224 player.on("cuepoint", function (cuepoint) { 225 player.getVideoTitle().then((title) => { 226 const data = { 227 event: "video_progress", 228 video_title: title, 229 video_percent: cuepoint.data.label, 230 }; 231 232 window.dataLayer.push(data); 233 }); 234 }); 235 } catch (err) { 236 //not a vimeo video 237 } 238} 239 240function shareButtonListener(targetElement) { 241 if ( 242 targetElement.parentNode && 243 targetElement.parentNode.classList.contains("essb_item") 244 ) { 245 const networkNameSpan = targetElement.querySelector(".essb_network_name"); 246 const data = { 247 event: "social_interact", 248 media: networkNameSpan ? networkNameSpan.innerText : "", 249 action: "share", 250 }; 251 252 window.dataLayer.push(data); 253 } 254} 255 256function downloadListener(targetElement) { 257 if (targetElement.tagName !== "A") { 258 return; 259 } 260 261 const href = targetElement.getAttribute("href"); 262 const fileExtensionPattern = 263 /\.(pdf|xlsx?|docx?|txt|rtf|csv|exe|key|pp(s|t|tx)|7z|pkg|rar|gz|zip|avi|mov|mp4|mpe?g|wmv|midi?|mp3|wav|wma)$/i; 264 265 // Check if the link ends with one of the specified extensions 266 const match = href.match(fileExtensionPattern); 267 if (match) { 268 const fileName = href.split("/").pop(); 269 const fileExtension = match[0].substring(1); 270 const data = { 271 event: "file_download", 272 file_name: fileName, 273 file_extension: fileExtension, 274 }; 275 window.dataLayer.push(data); 276 277 // downloads on the /dl/ pages should trigger a secondary event for generating leads 278 if (window.location.pathname.includes("/dl/")) { 279 data.event = "generate_lead"; 280 window.dataLayer.push(data); 281 } 282 } 283} 284 285function setupCtas() { 286 // Select all elements with the class 'kcm-cta' 287 var elements = document.querySelectorAll(".kcm-cta"); 288 289 // Iterate through each element 290 elements.forEach(function (element) { 291 // Set the 'data-click-category' attribute to 'call_to_action' 292 element.setAttribute("data-click-category", "call_to_action"); 293 294 // Get the value of the 'title' attribute 295 var titleValue = element.getAttribute("title"); 296 297 // Set the 'data-click-label' attribute to the value of the 'title' attribute 298 element.setAttribute("data-click-label", titleValue); 299 }); 300} 301 302function ctaListener(targetElement) { 303 // If the clicked element or its parent has the class "kcm-cta" 304 if ( 305 targetElement.classList.contains("kcm-cta") || 306 (targetElement.parentNode && 307 targetElement.parentNode.classList.contains("kcm-cta")) 308 ) { 309 // Adjust targetElement if it's a child element within an element with "kcm-cta" class 310 if (!targetElement.classList.contains("kcm-cta")) { 311 targetElement = targetElement.parentNode; 312 } 313 314 let clickCategory = 315 targetElement.getAttribute("data-click-category") || "N/A"; 316 let clickLabel = targetElement.getAttribute("data-click-label") || "N/A"; 317 318 const data = { 319 event: "call_to_action", 320 event_category: clickCategory, 321 event_label: clickLabel, 322 }; 323 window.dataLayer.push(data); 324 } 325} 326 327function accordionListener(targetElement) { 328 if ( 329 targetElement.tagName === "P" && 330 targetElement.classList.contains("toggler") && 331 targetElement.classList.contains("activeTitle") 332 ) { 333 let pInnerText = targetElement.innerText; 334 let pageTitle = document.title; 335 336 const data = { 337 event: "expand_list", 338 list_name: pageTitle, 339 list_item: pInnerText, 340 }; 341 window.dataLayer.push(data); 342 } 343} 344 345function formErrorListeners() { 346 window.addEventListener("message", function (event) { 347 console.log(event.data); 348 }); 349} 350 351function setupOpenInNewTab() { 352 document.querySelectorAll("a").forEach(function (anchor) { 353 var a = new RegExp("/" + window.location.host + "/"); 354 var b = new RegExp( 355 "/" + "files.(keepingcurrentmatters|simplifyingthemarket).com" + "/" 356 ); 357 var c = new RegExp("/" + "vimeo.com" + "/"); 358 var d = new RegExp("/" + "www.mykcm.com" + "/"); 359 360 if ( 361 !a.test(anchor.href) && 362 !b.test(anchor.href) && 363 !c.test(anchor.href) && 364 !d.test(anchor.href) 365 ) { 366 if ( 367 !anchor.classList.contains("chzn-single") && 368 !anchor.classList.contains("av-masonry-item-with-image") 369 ) { 370 anchor.addEventListener("click", function (event) { 371 if (!anchor.getAttribute("onclick")) { 372 event.preventDefault(); 373 event.stopPropagation(); 374 window.open(anchor.href, "_blank"); 375 } 376 }); 377 } 378 } 379 }); 380} 381 382function expandMobileMenus() { 383 document.addEventListener("DOMContentLoaded", function () { 384 var menuItems = document.querySelectorAll("li.menu-item-has-children"); 385
386 menuItems.forEach(function (menuItem) { 387 var subMenuIcon = document.createElement("div"); 388 subMenuIcon.className = "subMenuIcon"; 389 subMenuIcon.textContent = "+"; 390 menuItem.appendChild(subMenuIcon); 391 menuItem.classList.add("hideSubmenu"); 392 }); 393 394 document.addEventListener("click", function (event) { 395 if (event.target.classList.contains("subMenuIcon")) { 396 console.log("menu was clicked"); 397 event.target 398 .closest("li.menu-item-has-children") 399 .classList.toggle("hideSubmenu"); 400 } 401 }); 402 }); 403} 404 405function sendFBConversion(eventName, eventId) { 406 /** Prevent server side tracking if page is loaded via iframe */ 407 if (window.location !== window.parent.location) { 408 console.log("Skip event, loaded in iframe"); 409 return false; 410 } 411 412 var params = getParams(window.location.href); 413 var uc = params.utm_campaign; 414 var us = params.utm_source; 415 var uct = params.utm_content; 416 var ut = params.utm_term; 417 var fbp = getCookie("_fbp"); 418 419 fetch("/wp-admin/admin-ajax.php?action=kcm_fbcon_event", { 420 method: "POST", 421 headers: { 422 "Content-Type": "application/json", 423 }, 424 body: JSON.stringify({ 425 event_name: eventName, 426 event_id: eventId, 427 event_source_url: window.location.href.split("?")[0], 428 utm: { 429 campaign: uc, 430 source: us, 431 content: uct, 432 term: ut, 433 }, 434 fbp: fbp, 435 }), 436 }) 437 .then((response) => response.json()) 438 .then((data) => { 439 console.log(data); 440 }) 441 .catch((error) => { 442 console.log("Error:", error); 443 }); 444} 445 446function getParams(url) { 447 var params = {}; 448 var parser = document.createElement("a"); 449 parser.href = url; 450 var query = parser.search.substring(1); 451 var vars = query.split("&"); 452 for (var i = 0; i < vars.length; i++) { 453 var pair = vars[i].split("="); 454 params[pair[0]] = decodeURIComponent(pair[1]); 455 } 456 return params; 457} 458 459function getCookie(cname) { 460 var name = cname + "="; 461 var decodedCookie = decodeURIComponent(document.cookie); 462 var ca = decodedCookie.split(";"); 463 for (var i = 0; i < ca.length; i++) { 464 var c = ca[i]; 465 while (c.charAt(0) == " ") { 466 c = c.substring(1); 467 } 468 if (c.indexOf(name) == 0) { 469 return c.substring(name.length, c.length); 470 } 471 } 472 return null; 473} 474 475function setCookie(name, value, expires) { 476 document.cookie = `${name}=${encodeURIComponent( 477 value 478 )}; expires=${expires.toUTCString()}; path=/; domain=keepingcurrentmatters.com; secure`; 479} 480 481async function setCookies() { 482 // Parse the URL query string to get parameters 483 const urlParams = new URLSearchParams(window.location.search); 484 485 if (urlParams.get("affiliate")) { 486 const tenYearsFromNow = new Date(); 487 tenYearsFromNow.setFullYear(tenYearsFromNow.getFullYear() + 10);
488 setCookie("KCMAffiliateID", urlParams.get("affiliate"), tenYearsFromNow); 489 } 490 491 if (urlParams.get("fbclid")) { 492 const unixMilliseconds = Date.now(); 493 let clickId = `fb.1.${unixMilliseconds}.${urlParams.get("fbclid")}`; 494 clickId = btoa(clickId); 495 496 const expirationTime = new Date(); 497 expirationTime.setDate(expirationTime.getDate() + 180); 498 setCookie("kcmclid", clickId, expirationTime); 499 } 500 501 // if (urlParams.get("email")) { 502 // const e = await sha256Hash(urlParams.get("email")); 503 // const expirationTime = new Date(); 504 // expirationTime.setDate(expirationTime.getDate() + 180); 505 // setCookie("kcm_em", e, expirationTime); 506 // } 507 508 // if (urlParams.get("firstname")) { 509 // const fn = await sha256Hash(urlParams.get("firstname")); 510 // const expirationTime = new Date(); 511 // expirationTime.setDate(expirationTime.getDate() + 180); 512 // setCookie("kcm_fn", fn, expirationTime); 513 // } 514 515 // if (urlParams.get("lastname")) { 516 // const ln = await sha256Hash(urlParams.get("lastname")); 517 // console.log("ln = ", ln); 518 // const expirationTime = new Date(); 519 // expirationTime.setDate(expirationTime.getDate() + 180); 520 // setCookie("kcm_ln", ln, expirationTime); 521 // } 522} 523 524function sha256Hash(name) { 525 // Convert the string to a Uint8Array 526 const encoder = new TextEncoder(); 527 const data = encoder.encode(name); 528 529 // Generate the SHA-256 hash and return a hex string 530 return crypto.subtle 531 .digest("SHA-256", data) 532 .then((hashBuffer) => { 533 // Convert the hash buffer to a byte array 534 const hashArray = Array.from(new Uint8Array(hashBuffer)); 535 // Convert the byte array to a hex string 536 return hashArray 537 .map((byte) => byte.toString(16).padStart(2, "0")) 538 .join(""); 539 }) 540 .catch((error) => { 541 console.error("Hashing error:", error); 542 return null; 543 }); 544}
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.