). */ (function () { const UTM_KEYS = [ "utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content", ]; // 1. Read UTM params from the current URL function getUTMParams() { const params = new URLSearchParams(window.location.search); const utms = {}; UTM_KEYS.forEach((key) => { if (params.has(key)) utms[key] = params.get(key); }); return utms; } // 2. Check if a link is internal (same hostname) function isInternalLink(anchor) { try { const url = new URL(anchor.href, window.location.origin); return url.hostname === window.location.hostname; } catch { return false; } } // 3. Append UTM params to a single anchor element function appendUTMs(anchor, utms) { try { const url = new URL(anchor.href, window.location.origin); Object.entries(utms).forEach(([key, value]) => { // Don't overwrite UTMs already present on the link if (!url.searchParams.has(key)) { url.searchParams.set(key, value); } }); anchor.href = url.toString(); } catch { // Skip malformed hrefs } } // 4. Process all current links on the page function processLinks(utms) { document.querySelectorAll("a[href]").forEach((anchor) => { if (isInternalLink(anchor)) appendUTMs(anchor, utms); }); } // 5. Watch for dynamically added links (SPAs, lazy-loaded content) function observeDOM(utms) { const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if (node.nodeType !== Node.ELEMENT_NODE) return; // Handle the node itself if it's an anchor if (node.tagName === "A" && node.href && isInternalLink(node)) { appendUTMs(node, utms); } // Handle any anchor descendants node.querySelectorAll?.("a[href]").forEach((anchor) => { if (isInternalLink(anchor)) appendUTMs(anchor, utms); }); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); } // --- Init --- const utms = getUTMParams(); if (Object.keys(utms).length === 0) return; // No UTM params → do nothing // Run once DOM is ready if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", () => { processLinks(utms); observeDOM(utms); }); } else { processLinks(utms); observeDOM(utms); } })();