@rtstic.dev/pulse 0.0.91 → 0.0.92
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(()=>{function c(){return{firstName:sessionStorage.getItem("ty_firstName")??"",lastName:sessionStorage.getItem("ty_lastName")??"",email:sessionStorage.getItem("ty_email")??"",showCalendar:sessionStorage.getItem("ty_showCalendar")==="true",calendarName:sessionStorage.getItem("ty_calendarName")??"",embedUrl:sessionStorage.getItem("ty_embedUrl")??"",flow:sessionStorage.getItem("ty_flow")??""}}function u(e){let t=document.querySelector("[hs-calender-block]");if(!t)return;if(!e.showCalendar||!e.embedUrl){t.setAttribute("hs-calender-block-active","false"),t.innerHTML="",document.querySelectorAll("[hs-thankyou-block-active]").forEach(n=>n.setAttribute("hs-thankyou-block-active","true"));return}t.setAttribute("hs-calender-block-active","true"),t.innerHTML="",document.querySelectorAll("[hs-thankyou-block-active]").forEach(n=>n.setAttribute("hs-thankyou-block-active","false"));let s=new URLSearchParams;e.firstName&&s.set("firstName",e.firstName),e.lastName&&s.set("lastName",e.lastName),e.email&&s.set("email",e.email);let m=e.embedUrl.includes("?")?"&":"?",l=s.toString()?`${e.embedUrl}${m}${s.toString()}`:e.embedUrl,o=document.createElement("div");o.className="meetings-iframe-container",o.setAttribute("data-src",l),t.appendChild(o);let a="https://static.hsappstatic.net/MeetingsEmbed/ex/MeetingsEmbedCode.js",i=document.querySelector(`script[src="${a}"]`);i&&i.remove();let r=document.createElement("script");r.type="text/javascript",r.src=a,t.appendChild(r)}function d(){let e=sessionStorage.getItem("ty_flow")??"";e&&document.querySelectorAll("[hs-thankyou-flow]").forEach(t=>{let s=t.getAttribute("hs-thankyou-flow");t.setAttribute("form-flow-active",s===e?"true":"false")})}document.addEventListener("DOMContentLoaded",()=>{let e=c();d(),u(e)});})();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/form/book-a-demo/thank-you.ts"],
|
|
4
|
+
"sourcesContent": ["import { CALENDAR_ENTRIES } from \"./config/calendarConfig\";\n\nfunction getSessionData() {\n return {\n firstName: sessionStorage.getItem(\"ty_firstName\") ?? \"\",\n lastName: sessionStorage.getItem(\"ty_lastName\") ?? \"\",\n email: sessionStorage.getItem(\"ty_email\") ?? \"\",\n showCalendar: sessionStorage.getItem(\"ty_showCalendar\") === \"true\",\n calendarName: sessionStorage.getItem(\"ty_calendarName\") ?? \"\",\n embedUrl: sessionStorage.getItem(\"ty_embedUrl\") ?? \"\",\n flow: sessionStorage.getItem(\"ty_flow\") ?? \"\",\n };\n}\n\nfunction loadCalendar(data: ReturnType<typeof getSessionData>): void {\n const container = document.querySelector<HTMLElement>(\"[hs-calender-block]\");\n if (!container) return;\n\n if (!data.showCalendar || !data.embedUrl) {\n // hide calendar, show thank you\n container.setAttribute(\"hs-calender-block-active\", \"false\");\n container.innerHTML = \"\";\n document.querySelectorAll<HTMLElement>(\"[hs-thankyou-block-active]\")\n .forEach((el) => el.setAttribute(\"hs-thankyou-block-active\", \"true\"));\n return;\n }\n\n // show calendar, hide thank you\n container.setAttribute(\"hs-calender-block-active\", \"true\");\n container.innerHTML = \"\";\n document.querySelectorAll<HTMLElement>(\"[hs-thankyou-block-active]\")\n .forEach((el) => el.setAttribute(\"hs-thankyou-block-active\", \"false\"));\n\n // build prefill params\n const prefillParams = new URLSearchParams();\n if (data.firstName) prefillParams.set(\"firstName\", data.firstName);\n if (data.lastName) prefillParams.set(\"lastName\", data.lastName);\n if (data.email) prefillParams.set(\"email\", data.email);\n\n const separator = data.embedUrl.includes(\"?\") ? \"&\" : \"?\";\n const embedUrl = prefillParams.toString()\n ? `${data.embedUrl}${separator}${prefillParams.toString()}`\n : data.embedUrl;\n\n // inject iframe\n const meetingsDiv = document.createElement(\"div\");\n meetingsDiv.className = \"meetings-iframe-container\";\n meetingsDiv.setAttribute(\"data-src\", embedUrl);\n container.appendChild(meetingsDiv);\n\n // inject HubSpot script\n const scriptSrc = \"https://static.hsappstatic.net/MeetingsEmbed/ex/MeetingsEmbedCode.js\";\n const existingScript = document.querySelector<HTMLScriptElement>(`script[src=\"${scriptSrc}\"]`);\n if (existingScript) existingScript.remove();\n\n const script = document.createElement(\"script\");\n script.type = \"text/javascript\";\n script.src = scriptSrc;\n container.appendChild(script);\n}\n\nfunction setFlowAttribute(): void {\n const flow = sessionStorage.getItem(\"ty_flow\") ?? \"\";\n if (!flow) return;\n\n document.querySelectorAll<HTMLElement>(\"[hs-thankyou-flow]\")\n .forEach((el) => {\n const elFlow = el.getAttribute(\"hs-thankyou-flow\");\n el.setAttribute(\n \"form-flow-active\",\n elFlow === flow ? \"true\" : \"false\"\n );\n });\n}\n\nfunction clearSessionData(): void {\n sessionStorage.removeItem(\"ty_firstName\");\n sessionStorage.removeItem(\"ty_lastName\");\n sessionStorage.removeItem(\"ty_email\");\n sessionStorage.removeItem(\"ty_showCalendar\");\n sessionStorage.removeItem(\"ty_calendarName\");\n sessionStorage.removeItem(\"ty_embedUrl\");\n sessionStorage.removeItem(\"ty_flow\");\n}\n\n// Boot\ndocument.addEventListener(\"DOMContentLoaded\", () => {\n const data = getSessionData();\n setFlowAttribute();\n loadCalendar(data);\n // clearSessionData();\n});"],
|
|
5
|
+
"mappings": ";;;AAEA,WAAS,iBAAiB;AACtB,WAAO;AAAA,MACH,WAAW,eAAe,QAAQ,cAAc,KAAK;AAAA,MACrD,UAAU,eAAe,QAAQ,aAAa,KAAK;AAAA,MACnD,OAAO,eAAe,QAAQ,UAAU,KAAK;AAAA,MAC7C,cAAc,eAAe,QAAQ,iBAAiB,MAAM;AAAA,MAC5D,cAAc,eAAe,QAAQ,iBAAiB,KAAK;AAAA,MAC3D,UAAU,eAAe,QAAQ,aAAa,KAAK;AAAA,MACnD,MAAM,eAAe,QAAQ,SAAS,KAAK;AAAA,IAC/C;AAAA,EACJ;AAEA,WAAS,aAAa,MAA+C;AACjE,UAAM,YAAY,SAAS,cAA2B,qBAAqB;AAC3E,QAAI,CAAC,UAAW;AAEhB,QAAI,CAAC,KAAK,gBAAgB,CAAC,KAAK,UAAU;AAEtC,gBAAU,aAAa,4BAA4B,OAAO;AAC1D,gBAAU,YAAY;AACtB,eAAS,iBAA8B,4BAA4B,EAC9D,QAAQ,CAAC,OAAO,GAAG,aAAa,4BAA4B,MAAM,CAAC;AACxE;AAAA,IACJ;AAGA,cAAU,aAAa,4BAA4B,MAAM;AACzD,cAAU,YAAY;AACtB,aAAS,iBAA8B,4BAA4B,EAC9D,QAAQ,CAAC,OAAO,GAAG,aAAa,4BAA4B,OAAO,CAAC;AAGzE,UAAM,gBAAgB,IAAI,gBAAgB;AAC1C,QAAI,KAAK,UAAW,eAAc,IAAI,aAAa,KAAK,SAAS;AACjE,QAAI,KAAK,SAAU,eAAc,IAAI,YAAY,KAAK,QAAQ;AAC9D,QAAI,KAAK,MAAO,eAAc,IAAI,SAAS,KAAK,KAAK;AAErD,UAAM,YAAY,KAAK,SAAS,SAAS,GAAG,IAAI,MAAM;AACtD,UAAM,WAAW,cAAc,SAAS,IAClC,GAAG,KAAK,QAAQ,GAAG,SAAS,GAAG,cAAc,SAAS,CAAC,KACvD,KAAK;AAGX,UAAM,cAAc,SAAS,cAAc,KAAK;AAChD,gBAAY,YAAY;AACxB,gBAAY,aAAa,YAAY,QAAQ;AAC7C,cAAU,YAAY,WAAW;AAGjC,UAAM,YAAY;AAClB,UAAM,iBAAiB,SAAS,cAAiC,eAAe,SAAS,IAAI;AAC7F,QAAI,eAAgB,gBAAe,OAAO;AAE1C,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,OAAO;AACd,WAAO,MAAM;AACb,cAAU,YAAY,MAAM;AAAA,EAChC;AAEA,WAAS,mBAAyB;AAC9B,UAAM,OAAO,eAAe,QAAQ,SAAS,KAAK;AAClD,QAAI,CAAC,KAAM;AAEX,aAAS,iBAA8B,oBAAoB,EACtD,QAAQ,CAAC,OAAO;AACb,YAAM,SAAS,GAAG,aAAa,kBAAkB;AACjD,SAAG;AAAA,QACC;AAAA,QACA,WAAW,OAAO,SAAS;AAAA,MAC/B;AAAA,IACJ,CAAC;AAAA,EACT;AAaA,WAAS,iBAAiB,oBAAoB,MAAM;AAChD,UAAM,OAAO,eAAe;AAC5B,qBAAiB;AACjB,iBAAa,IAAI;AAAA,EAErB,CAAC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/form/utm-propagation.ts"],
|
|
4
|
-
"sourcesContent": ["// UTM Attribution & Propagation Script (TypeScript)\n// \u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\n// 1. Captures UTM params, gclid, msclkid, fbclid from URL\n// 2. Falls back to referrer analysis when no UTMs are present\n// 3. Categorises visitors into channels using an 11-rule priority cascade\n// (mirrors Attributer's logic)\n// 4. Propagates UTM params to internal links (without overriding existing params)\n// 5. Fills form fields marked with data-utm-input (without overriding existing values)\n// 6. Persists attribution data in a first-party cookie (with sessionStorage fallback)\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Types\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\ninterface UTMParams {\n [key: string]: string;\n}\n\ninterface AttributionResult {\n channel: string;\n channelDrilldown1: string;\n channelDrilldown2: string;\n channelDrilldown3: string;\n landingPage: string;\n landingPageGroup: string;\n}\n\ninterface AttributionData {\n params: UTMParams;\n attribution: AttributionResult;\n}\n\ninterface UTMConfig {\n /** Standard UTM keys to capture from the URL */\n utmKeys: string[];\n /** Non-UTM click ID keys to capture */\n clickIdKeys: string[];\n /** CSS selectors for elements whose href should receive UTM params */\n linkSelectors: string[];\n /** CSS selector for form fields that should receive attribution values */\n inputSelector: string;\n /** Cookie name for persisting attribution */\n cookieName: string;\n /** Cookie lifespan in days */\n cookieDays: number;\n /** sessionStorage key (fallback) */\n storageKey: string;\n /** Maps data-utm-input shorthand names \u2192 internal keys */\n inputKeyMap: Record<string, string>;\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Recognised Domain Lists\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nconst SEARCH_ENGINES: string[] = [\n \"google.\",\n \"bing.com\",\n \"yahoo.\",\n \"duckduckgo.com\",\n \"baidu.com\",\n \"yandex.\",\n \"ask.com\",\n \"ecosia.org\",\n \"aol.com\",\n \"startpage.com\",\n \"qwant.com\",\n \"brave.com\",\n \"search.brave.com\",\n \"naver.com\",\n \"daum.net\",\n \"sogou.com\",\n \"so.com\",\n \"seznam.cz\",\n \"onesearch.com\",\n \"swisscows.com\",\n \"mojeek.com\",\n \"presearch.com\",\n \"search.yahoo.com\",\n \"googlesyndication.com\",\n \"googleadservices.com\",\n];\n\nconst SOCIAL_NETWORKS: string[] = [\n \"facebook.com\",\n \"fb.com\",\n \"fb.me\",\n \"l.facebook.com\",\n \"lm.facebook.com\",\n \"m.facebook.com\",\n \"instagram.com\",\n \"l.instagram.com\",\n \"twitter.com\",\n \"t.co\",\n \"x.com\",\n \"linkedin.com\",\n \"lnkd.in\",\n \"pinterest.com\",\n \"pin.it\",\n \"reddit.com\",\n \"tiktok.com\",\n \"youtube.com\",\n \"youtu.be\",\n \"snapchat.com\",\n \"tumblr.com\",\n \"threads.net\",\n \"mastodon.social\",\n \"bsky.app\",\n \"whatsapp.com\",\n \"wechat.com\",\n \"weibo.com\",\n \"vk.com\",\n \"quora.com\",\n \"medium.com\",\n \"discord.com\",\n \"discord.gg\",\n \"telegram.org\",\n \"t.me\",\n \"slack.com\",\n];\n\n// Friendly display names for recognised sources\nconst SOCIAL_DISPLAY_NAMES: Record<string, string> = {\n \"facebook.com\": \"Facebook\",\n \"fb.com\": \"Facebook\",\n \"fb.me\": \"Facebook\",\n \"l.facebook.com\": \"Facebook\",\n \"lm.facebook.com\": \"Facebook\",\n \"m.facebook.com\": \"Facebook\",\n \"instagram.com\": \"Instagram\",\n \"l.instagram.com\": \"Instagram\",\n \"twitter.com\": \"Twitter\",\n \"t.co\": \"Twitter\",\n \"x.com\": \"Twitter\",\n \"linkedin.com\": \"LinkedIn\",\n \"lnkd.in\": \"LinkedIn\",\n \"pinterest.com\": \"Pinterest\",\n \"pin.it\": \"Pinterest\",\n \"reddit.com\": \"Reddit\",\n \"tiktok.com\": \"TikTok\",\n \"youtube.com\": \"YouTube\",\n \"youtu.be\": \"YouTube\",\n \"snapchat.com\": \"Snapchat\",\n \"tumblr.com\": \"Tumblr\",\n \"threads.net\": \"Threads\",\n \"mastodon.social\": \"Mastodon\",\n \"bsky.app\": \"Bluesky\",\n \"whatsapp.com\": \"WhatsApp\",\n \"wechat.com\": \"WeChat\",\n \"weibo.com\": \"Weibo\",\n \"vk.com\": \"VK\",\n \"quora.com\": \"Quora\",\n \"medium.com\": \"Medium\",\n \"discord.com\": \"Discord\",\n \"discord.gg\": \"Discord\",\n \"telegram.org\": \"Telegram\",\n \"t.me\": \"Telegram\",\n \"slack.com\": \"Slack\",\n};\n\nconst SEARCH_DISPLAY_NAMES: Record<string, string> = {\n \"google.\": \"Google\",\n \"bing.com\": \"Bing\",\n \"yahoo.\": \"Yahoo\",\n \"duckduckgo.com\": \"DuckDuckGo\",\n \"baidu.com\": \"Baidu\",\n \"yandex.\": \"Yandex\",\n \"ask.com\": \"Ask\",\n \"ecosia.org\": \"Ecosia\",\n \"aol.com\": \"AOL\",\n \"startpage.com\": \"Startpage\",\n \"qwant.com\": \"Qwant\",\n \"brave.com\": \"Brave\",\n \"search.brave.com\": \"Brave\",\n \"naver.com\": \"Naver\",\n \"daum.net\": \"Daum\",\n \"sogou.com\": \"Sogou\",\n \"so.com\": \"360 Search\",\n \"seznam.cz\": \"Seznam\",\n \"googlesyndication.com\": \"Google\",\n \"googleadservices.com\": \"Google\",\n};\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Main IIFE\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n(function (): void {\n \"use strict\";\n\n const config: UTMConfig = {\n utmKeys: [\n \"utm_source\",\n \"utm_medium\",\n \"utm_campaign\",\n \"utm_term\",\n \"utm_content\",\n \"utm_id\",\n ],\n clickIdKeys: [\"gclid\", \"msclkid\", \"fbclid\"],\n linkSelectors: [\n \"a[href]\",\n \"button[onclick*='location']\",\n \"button[onclick*='window.open']\",\n \"button[onclick*='href']\",\n \"[data-href]\",\n ],\n inputSelector: \"[data-utm-input]\",\n cookieName: \"_attrib_data\",\n cookieDays: 30,\n storageKey: \"utm_attribution\",\n inputKeyMap: {\n // UTM shorthand \u2192 param key\n source: \"utm_source\",\n medium: \"utm_medium\",\n campaign: \"utm_campaign\",\n term: \"utm_term\",\n content: \"utm_content\",\n id: \"utm_id\",\n // Full UTM names\n utm_source: \"utm_source\",\n utm_medium: \"utm_medium\",\n utm_campaign: \"utm_campaign\",\n utm_term: \"utm_term\",\n utm_content: \"utm_content\",\n utm_id: \"utm_id\",\n // Click IDs\n gclid: \"gclid\",\n msclkid: \"msclkid\",\n fbclid: \"fbclid\",\n // Attribution outputs\n channel: \"_channel\",\n channeldrilldown1: \"_channelDrilldown1\",\n channeldrilldown2: \"_channelDrilldown2\",\n channeldrilldown3: \"_channelDrilldown3\",\n landingpage: \"_landingPage\",\n landingpagegroup: \"_landingPageGroup\",\n },\n };\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Helper: Domain Matching\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function domainMatches(hostname: string, pattern: string): boolean {\n const h = hostname.toLowerCase();\n const p = pattern.toLowerCase();\n // Patterns ending with \".\" are prefix matches (e.g., \"google.\" matches \"google.com\", \"google.co.uk\")\n if (p.endsWith(\".\")) {\n return h === p.slice(0, -1) || h.includes(\".\" + p.slice(0, -1) + \".\") || h.startsWith(p);\n }\n return h === p || h.endsWith(\".\" + p);\n }\n\n function isRecognisedSearchEngine(hostname: string): boolean {\n return SEARCH_ENGINES.some((pattern) => domainMatches(hostname, pattern));\n }\n\n function isRecognisedSocialNetwork(hostname: string): boolean {\n return SOCIAL_NETWORKS.some((domain) => domainMatches(hostname, domain));\n }\n\n function getSearchEngineName(hostname: string): string {\n for (const [pattern, name] of Object.entries(SEARCH_DISPLAY_NAMES)) {\n if (domainMatches(hostname, pattern)) return name;\n }\n return cleanDomain(hostname);\n }\n\n function getSocialNetworkName(hostname: string): string {\n for (const [domain, name] of Object.entries(SOCIAL_DISPLAY_NAMES)) {\n if (domainMatches(hostname, domain)) return name;\n }\n return cleanDomain(hostname);\n }\n\n /** Strips \"www.\" and returns the domain */\n function cleanDomain(hostname: string): string {\n return hostname.replace(/^www\\./, \"\");\n }\n\n /** Check if a value is the name of a recognised social network */\n function valueIsSocialNetwork(value: string): boolean {\n const v = value.toLowerCase().trim();\n // Check against display names (case-insensitive)\n const allNames = Object.values(SOCIAL_DISPLAY_NAMES).map((n) =>\n n.toLowerCase()\n );\n if (allNames.includes(v)) return true;\n // Check against domain patterns\n return SOCIAL_NETWORKS.some(\n (domain) => v === domain || v === domain.replace(\".com\", \"\")\n );\n }\n\n /** Check if a value is the name of a recognised search engine */\n function valueIsSearchEngine(value: string): boolean {\n const v = value.toLowerCase().trim();\n const allNames = Object.values(SEARCH_DISPLAY_NAMES).map((n) =>\n n.toLowerCase()\n );\n if (allNames.includes(v)) return true;\n return SEARCH_ENGINES.some((pattern) => {\n const clean = pattern.replace(/\\.$/, \"\");\n return v === clean || v === clean.replace(\".com\", \"\");\n });\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Helper: String checks\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function containsAny(value: string | undefined, ...terms: string[]): boolean {\n if (!value) return false;\n const v = value.toLowerCase();\n return terms.some((t) => v.includes(t.toLowerCase()));\n }\n\n function equalsAny(value: string | undefined, ...terms: string[]): boolean {\n if (!value) return false;\n const v = value.toLowerCase().trim();\n return terms.some((t) => v === t.toLowerCase());\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Cookie Persistence\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function setCookie(name: string, value: string, days: number): void {\n const expires = new Date(Date.now() + days * 864e5).toUTCString();\n document.cookie = `${name}=${encodeURIComponent(value)};expires=${expires};path=/;SameSite=Lax`;\n }\n\n function getCookie(name: string): string | null {\n const match = document.cookie.match(\n new RegExp(\"(?:^|; )\" + name.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\") + \"=([^;]*)\")\n );\n return match ? decodeURIComponent(match[1]) : null;\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Persistence Layer (Cookie \u2192 sessionStorage fallback)\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function storeAttribution(data: AttributionData): void {\n const json = JSON.stringify(data);\n try {\n setCookie(config.cookieName, json, config.cookieDays);\n } catch (e) {\n console.warn(\"UTM: Could not set cookie\", e);\n }\n try {\n sessionStorage.setItem(config.storageKey, json);\n } catch (e) {\n console.warn(\"UTM: Could not write to sessionStorage\", e);\n }\n }\n\n function getStoredAttribution(): AttributionData | null {\n try {\n const fromCookie = getCookie(config.cookieName);\n if (fromCookie) return JSON.parse(fromCookie);\n } catch (e) {\n console.warn(\"UTM: Could not parse cookie\", e);\n }\n try {\n const fromStorage = sessionStorage.getItem(config.storageKey);\n if (fromStorage) return JSON.parse(fromStorage);\n } catch (e) {\n console.warn(\"UTM: Could not read sessionStorage\", e);\n }\n return null;\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Param Capture from URL\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function getCapturedParams(): UTMParams {\n const urlParams = new URLSearchParams(window.location.search);\n const captured: UTMParams = {};\n\n // Standard UTM keys\n config.utmKeys.forEach((key) => {\n const value = urlParams.get(key);\n if (value) captured[key] = value;\n });\n\n // Click IDs (gclid, msclkid, fbclid)\n config.clickIdKeys.forEach((key) => {\n const value = urlParams.get(key);\n if (value) captured[key] = value;\n });\n\n // Bare \"source\" parameter (non-standard, but used by some tools)\n const bareSource = urlParams.get(\"source\");\n if (bareSource && !captured[\"utm_source\"]) {\n captured[\"source\"] = bareSource;\n }\n\n return captured;\n }\n\n function hasTrackingParams(params: UTMParams): boolean {\n return (\n !!params.utm_source ||\n !!params.utm_medium ||\n !!params.utm_campaign ||\n !!params.source ||\n !!params.gclid ||\n !!params.msclkid ||\n !!params.fbclid\n );\n }\n\n function hasUTMParams(params: UTMParams): boolean {\n return (\n !!params.utm_source || !!params.utm_medium || !!params.utm_campaign\n );\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Referrer Analysis\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function getReferrerHostname(): string {\n try {\n if (!document.referrer) return \"\";\n const url = new URL(document.referrer);\n // Ignore self-referrals\n if (url.hostname === window.location.hostname) return \"\";\n return url.hostname.toLowerCase();\n } catch {\n return \"\";\n }\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Landing Page Info\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function getLandingPage(): string {\n return window.location.pathname + window.location.search;\n }\n\n function getLandingPageGroup(): string {\n const path = window.location.pathname;\n // Return the first directory segment, or \"/\" for root\n const segments = path.split(\"/\").filter(Boolean);\n return segments.length > 0 ? \"/\" + segments[0] : \"/\";\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Channel Categorisation Engine (11-rule cascade)\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function categorise(params: UTMParams, referrerHost: string): AttributionResult {\n const utm_source = params.utm_source || \"\";\n const utm_medium = params.utm_medium || \"\";\n const utm_campaign = params.utm_campaign || \"\";\n const utm_term = params.utm_term || \"\";\n const utm_content = params.utm_content || \"\";\n const bare_source = params.source || \"\";\n const gclid = params.gclid || \"\";\n const msclkid = params.msclkid || \"\";\n const fbclid = params.fbclid || \"\";\n\n const landingPage = getLandingPage();\n const landingPageGroup = getLandingPageGroup();\n\n const base: Pick<AttributionResult, \"landingPage\" | \"landingPageGroup\"> = {\n landingPage,\n landingPageGroup,\n };\n\n // \u2500\u2500 Rule 1: Organic Social \u2500\u2500\n // utm_medium = \"social\" AND (utm_source is a recognised social network\n // OR referrer is a recognised social network)\n if (equalsAny(utm_medium, \"social\")) {\n if (valueIsSocialNetwork(utm_source) || isRecognisedSocialNetwork(referrerHost)) {\n const sourceName =\n valueIsSocialNetwork(utm_source)\n ? capitalise(utm_source)\n : getSocialNetworkName(referrerHost);\n return {\n ...base,\n channel: \"Organic Social\",\n channelDrilldown1: sourceName,\n channelDrilldown2: utm_campaign || \"\",\n channelDrilldown3: utm_content || \"\",\n };\n }\n }\n\n // \u2500\u2500 Rule 2: Email Marketing \u2500\u2500\n // utm_medium = \"email\"\n if (equalsAny(utm_medium, \"email\")) {\n return {\n ...base,\n channel: \"Email Marketing\",\n channelDrilldown1: utm_source || \"Email\",\n channelDrilldown2: utm_campaign || \"\",\n channelDrilldown3: utm_content || \"\",\n };\n }\n\n // \u2500\u2500 Rule 3: Paid Social \u2500\u2500\n // utm_source or utm_medium contains \"paidsocial\"\n // OR utm_medium contains \"paid\"/\"ppc\"/\"cpc\" AND utm_source is a recognised social network\n // OR utm_medium contains \"paid\"/\"ppc\"/\"cpc\" AND referrer is a recognised social network\n if (\n containsAny(utm_source, \"paidsocial\") ||\n containsAny(utm_medium, \"paidsocial\") ||\n (containsAny(utm_medium, \"paid\", \"ppc\", \"cpc\") &&\n valueIsSocialNetwork(utm_source)) ||\n (containsAny(utm_medium, \"paid\", \"ppc\", \"cpc\") &&\n isRecognisedSocialNetwork(referrerHost))\n ) {\n const sourceName = valueIsSocialNetwork(utm_source)\n ? capitalise(utm_source)\n : isRecognisedSocialNetwork(referrerHost)\n ? getSocialNetworkName(referrerHost)\n : utm_source || \"Paid Social\";\n return {\n ...base,\n channel: \"Paid Social\",\n channelDrilldown1: sourceName,\n channelDrilldown2: utm_campaign || \"\",\n channelDrilldown3: utm_term || utm_content || \"\",\n };\n }\n\n // \u2500\u2500 Rule 4: Paid Search \u2500\u2500\n // utm_source or utm_medium contains \"paidsearch\"\n // OR utm_source / utm_medium / utm_campaign contains \"adwords\" / \"ppc\" / \"cpc\"\n // OR gclid or msclkid is present\n // OR any utm param is present AND referrer is a recognised search engine\n if (\n containsAny(utm_source, \"paidsearch\") ||\n containsAny(utm_medium, \"paidsearch\") ||\n containsAny(utm_source, \"adwords\", \"ppc\", \"cpc\") ||\n containsAny(utm_medium, \"adwords\", \"ppc\", \"cpc\") ||\n containsAny(utm_campaign, \"adwords\", \"ppc\", \"cpc\") ||\n gclid ||\n msclkid ||\n (hasUTMParams(params) && isRecognisedSearchEngine(referrerHost))\n ) {\n let sourceName = \"Paid Search\";\n if (gclid) {\n sourceName = \"Google\";\n } else if (msclkid) {\n sourceName = \"Bing\";\n } else if (valueIsSearchEngine(utm_source)) {\n sourceName = capitalise(utm_source);\n } else if (isRecognisedSearchEngine(referrerHost)) {\n sourceName = getSearchEngineName(referrerHost);\n } else if (utm_source) {\n sourceName = utm_source;\n }\n return {\n ...base,\n channel: \"Paid Search\",\n channelDrilldown1: sourceName,\n channelDrilldown2: utm_campaign || \"\",\n channelDrilldown3: utm_term || \"\",\n };\n }\n\n // \u2500\u2500 Rule 5: Display \u2500\u2500\n // utm_medium = \"display\"\n if (equalsAny(utm_medium, \"display\")) {\n return {\n ...base,\n channel: \"Display\",\n channelDrilldown1: utm_source || \"Display\",\n channelDrilldown2: utm_campaign || \"\",\n channelDrilldown3: utm_content || \"\",\n };\n }\n\n // \u2500\u2500 Rule 6: Affiliates \u2500\u2500\n // utm_medium contains \"affiliate\" or \"affiliates\"\n if (containsAny(utm_medium, \"affiliate\")) {\n return {\n ...base,\n channel: \"Affiliates\",\n channelDrilldown1: utm_source || \"Affiliate\",\n channelDrilldown2: utm_campaign || \"\",\n channelDrilldown3: utm_content || \"\",\n };\n }\n\n // \u2500\u2500 Rule 7: Other Campaigns \u2500\u2500\n // Any tracking param is present (utm_source, utm_medium, utm_campaign, source)\n // but none of the above rules matched\n if (hasTrackingParams(params)) {\n return {\n ...base,\n channel: \"Other Campaigns\",\n channelDrilldown1: utm_source || bare_source || \"\",\n channelDrilldown2: utm_medium || \"\",\n channelDrilldown3: utm_campaign || \"\",\n };\n }\n\n // \u2500\u2500 Rules 8\u201311: No tracking params \u2192 fall back to referrer \u2500\u2500\n\n // \u2500\u2500 Rule 8: Organic Social (by referrer) \u2500\u2500\n if (referrerHost && isRecognisedSocialNetwork(referrerHost)) {\n return {\n ...base,\n channel: \"Organic Social\",\n channelDrilldown1: getSocialNetworkName(referrerHost),\n channelDrilldown2: \"\",\n channelDrilldown3: \"\",\n };\n }\n\n // \u2500\u2500 Rule 9: Organic Search (by referrer) \u2500\u2500\n if (referrerHost && isRecognisedSearchEngine(referrerHost)) {\n return {\n ...base,\n channel: \"Organic Search\",\n channelDrilldown1: getSearchEngineName(referrerHost),\n channelDrilldown2: \"\",\n channelDrilldown3: \"\",\n };\n }\n\n // \u2500\u2500 Rule 10: Referral \u2500\u2500\n if (referrerHost) {\n return {\n ...base,\n channel: \"Referral\",\n channelDrilldown1: cleanDomain(referrerHost),\n channelDrilldown2: landingPage,\n channelDrilldown3: \"\",\n };\n }\n\n // \u2500\u2500 Rule 11: Direct \u2500\u2500\n return {\n ...base,\n channel: \"Direct\",\n channelDrilldown1: \"Direct\",\n channelDrilldown2: landingPage,\n channelDrilldown3: \"\",\n };\n }\n\n function capitalise(str: string): string {\n if (!str) return str;\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Link Processing (propagate UTM params only)\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function isInternalLink(url: string, currentHost: string): boolean {\n try {\n if (\n url.startsWith(\"/\") ||\n url.startsWith(\"./\") ||\n url.startsWith(\"../\")\n ) {\n return true;\n }\n if (/^[a-z]+:/i.test(url) && !url.startsWith(\"http\")) {\n return false;\n }\n if (url.startsWith(\"http\")) {\n return new URL(url).hostname === currentHost;\n }\n if (url.startsWith(\"//\")) {\n return new URL(\"https:\" + url).hostname === currentHost;\n }\n if (!url.includes(\"://\")) {\n return true;\n }\n return false;\n } catch (e) {\n console.warn(\"UTM: Error parsing URL:\", url, e);\n return false;\n }\n }\n\n function addUTMToURL(url: string, utmParams: UTMParams): string {\n try {\n const urlObj = new URL(url, window.location.origin);\n\n Object.entries(utmParams).forEach(([key, value]) => {\n // Only propagate standard UTM keys (not click IDs or internal keys)\n if (!config.utmKeys.includes(key)) return;\n // NEVER override existing params in the URL\n if (urlObj.searchParams.has(key)) return;\n urlObj.searchParams.set(key, value);\n });\n\n return urlObj.toString();\n } catch (e) {\n console.warn(\"UTM: Error processing URL:\", url, e);\n return url;\n }\n }\n\n function hasUTMException(element: Element): boolean {\n return element.getAttribute(\"data-utm-exception\") === \"true\";\n }\n\n function processLink(element: Element, utmParams: UTMParams): void {\n if (hasUTMException(element)) return;\n\n const currentHost = window.location.hostname;\n let url: string | null = null;\n\n if (element instanceof HTMLAnchorElement && element.href) {\n url = element.href;\n } else if (element instanceof HTMLElement && element.dataset.href) {\n url = element.dataset.href;\n }\n\n if (url && isInternalLink(url, currentHost)) {\n const updatedURL = addUTMToURL(url, utmParams);\n\n if (element instanceof HTMLAnchorElement) {\n element.href = updatedURL;\n } else if (element instanceof HTMLElement && element.dataset.href) {\n element.dataset.href = updatedURL;\n }\n }\n }\n\n function processAllLinks(utmParams: UTMParams): void {\n const links = document.querySelectorAll(config.linkSelectors.join(\", \"));\n links.forEach((el) => processLink(el, utmParams));\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Input Field Processing\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n //\n // Usage:\n // <input type=\"hidden\" data-utm-input=\"source\" />\n // <input type=\"hidden\" data-utm-input=\"medium\" />\n // <input type=\"hidden\" data-utm-input=\"campaign\" />\n // <input type=\"hidden\" data-utm-input=\"term\" />\n // <input type=\"hidden\" data-utm-input=\"content\" />\n // <input type=\"hidden\" data-utm-input=\"id\" />\n // <input type=\"hidden\" data-utm-input=\"gclid\" />\n // <input type=\"hidden\" data-utm-input=\"msclkid\" />\n // <input type=\"hidden\" data-utm-input=\"channel\" />\n // <input type=\"hidden\" data-utm-input=\"channelDrilldown1\" />\n // <input type=\"hidden\" data-utm-input=\"channelDrilldown2\" />\n // <input type=\"hidden\" data-utm-input=\"channelDrilldown3\" />\n // <input type=\"hidden\" data-utm-input=\"landingPage\" />\n // <input type=\"hidden\" data-utm-input=\"landingPageGroup\" />\n\n function processInput(\n element: Element,\n allValues: Record<string, string>\n ): void {\n if (hasUTMException(element)) return;\n\n const shortKey = element\n .getAttribute(\"data-utm-input\")\n ?.trim()\n .toLowerCase();\n if (!shortKey) return;\n\n // Resolve shorthand \u2192 internal key\n const internalKey = config.inputKeyMap[shortKey];\n if (!internalKey) {\n console.warn(`UTM: Unknown data-utm-input value \"${shortKey}\"`);\n return;\n }\n\n const value = allValues[internalKey];\n if (!value) return;\n\n if (\n element instanceof HTMLInputElement ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement\n ) {\n // NEVER override a field that already has a value\n if (element.value && element.value.trim() !== \"\") return;\n\n element.value = value;\n\n // Dispatch events so frameworks (React, Vue, etc.) pick up the change\n element.dispatchEvent(new Event(\"input\", { bubbles: true }));\n element.dispatchEvent(new Event(\"change\", { bubbles: true }));\n }\n }\n\n function processAllInputs(allValues: Record<string, string>): void {\n const inputs = document.querySelectorAll(config.inputSelector);\n inputs.forEach((el) => processInput(el, allValues));\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Build a flat key\u2192value map for form fields\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function buildValueMap(data: AttributionData): Record<string, string> {\n const map: Record<string, string> = {};\n\n // Raw UTM params and click IDs\n Object.entries(data.params).forEach(([key, value]) => {\n map[key] = value;\n });\n\n // Attribution results (prefixed with _ to avoid collision with raw params)\n map[\"_channel\"] = data.attribution.channel;\n map[\"_channelDrilldown1\"] = data.attribution.channelDrilldown1;\n map[\"_channelDrilldown2\"] = data.attribution.channelDrilldown2;\n map[\"_channelDrilldown3\"] = data.attribution.channelDrilldown3;\n map[\"_landingPage\"] = data.attribution.landingPage;\n map[\"_landingPageGroup\"] = data.attribution.landingPageGroup;\n\n return map;\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // MutationObserver (handles dynamically added content)\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function observeNewContent(\n utmParams: UTMParams,\n allValues: Record<string, string>\n ): void {\n const allSelectors = [...config.linkSelectors, config.inputSelector].join(\n \", \"\n );\n\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n let pendingNodes: Element[] = [];\n\n function flushPending(): void {\n const nodes = pendingNodes.slice();\n pendingNodes = [];\n debounceTimer = null;\n\n nodes.forEach((element) => {\n if (element.matches && element.matches(config.inputSelector)) {\n processInput(element, allValues);\n } else if (\n element.matches &&\n element.matches(config.linkSelectors.join(\", \"))\n ) {\n processLink(element, utmParams);\n }\n\n // Also check children of added nodes\n element.querySelectorAll?.(allSelectors).forEach((child) => {\n if (child.matches(config.inputSelector)) {\n processInput(child, allValues);\n } else {\n processLink(child, utmParams);\n }\n });\n });\n }\n\n const observer = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n mutation.addedNodes.forEach((node) => {\n if (node.nodeType === Node.ELEMENT_NODE) {\n pendingNodes.push(node as Element);\n }\n });\n });\n\n if (pendingNodes.length > 0 && !debounceTimer) {\n debounceTimer = setTimeout(flushPending, 50);\n }\n });\n\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Init\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function init(): void {\n const freshParams = getCapturedParams();\n const referrerHost = getReferrerHostname();\n const hasFreshTracking = hasTrackingParams(freshParams);\n\n let data: AttributionData;\n\n if (hasFreshTracking) {\n // Fresh URL params always win \u2014 categorise from scratch\n const attribution = categorise(freshParams, referrerHost);\n data = { params: freshParams, attribution };\n storeAttribution(data);\n } else if (referrerHost) {\n // No URL params but we have a referrer \u2014 categorise based on referrer\n // Only do this if there's no existing stored attribution\n // (to avoid overwriting a previous paid click with a later organic visit)\n const stored = getStoredAttribution();\n if (stored) {\n data = stored;\n } else {\n const attribution = categorise(freshParams, referrerHost);\n data = { params: freshParams, attribution };\n storeAttribution(data);\n }\n } else {\n // No URL params and no referrer \u2014 use stored data or fall back to Direct\n const stored = getStoredAttribution();\n if (stored) {\n data = stored;\n } else {\n const attribution = categorise(freshParams, referrerHost);\n data = { params: {}, attribution };\n storeAttribution(data);\n }\n }\n\n const allValues = buildValueMap(data);\n\n const run = (): void => {\n processAllLinks(data.params);\n processAllInputs(allValues);\n observeNewContent(data.params, allValues);\n // console.log(\"UTM Attribution:\", data.attribution);\n // console.log(\"UTM Params:\", data.params);\n };\n\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", run);\n } else {\n run();\n }\n }\n\n init();\n})();"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["// UTM Attribution & Propagation Script (TypeScript)\n// \u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\n// 1. Captures UTM params, gclid, msclkid, fbclid from URL\n// 2. Falls back to referrer analysis when no UTMs are present\n// 3. Categorises visitors into channels using an 11-rule priority cascade\n// (mirrors Attributer's logic)\n// 4. Propagates UTM params to internal links (without overriding existing params)\n// 5. Fills form fields marked with data-utm-input (without overriding existing values)\n// 6. No cookies or storage \u2014 reads fresh from URL on every page load\n// (UTMs persist across pages via link propagation in rule 4)\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Types\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\ninterface UTMParams {\n [key: string]: string;\n}\n\ninterface AttributionResult {\n channel: string;\n channelDrilldown1: string;\n channelDrilldown2: string;\n channelDrilldown3: string;\n landingPage: string;\n landingPageGroup: string;\n}\n\ninterface AttributionData {\n params: UTMParams;\n attribution: AttributionResult;\n}\n\ninterface UTMConfig {\n utmKeys: string[];\n clickIdKeys: string[];\n linkSelectors: string[];\n inputSelector: string;\n inputKeyMap: Record<string, string>;\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Recognised Domain Lists\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nconst SEARCH_ENGINES: string[] = [\n \"google.\",\n \"bing.com\",\n \"yahoo.\",\n \"duckduckgo.com\",\n \"baidu.com\",\n \"yandex.\",\n \"ask.com\",\n \"ecosia.org\",\n \"aol.com\",\n \"startpage.com\",\n \"qwant.com\",\n \"brave.com\",\n \"search.brave.com\",\n \"naver.com\",\n \"daum.net\",\n \"sogou.com\",\n \"so.com\",\n \"seznam.cz\",\n \"onesearch.com\",\n \"swisscows.com\",\n \"mojeek.com\",\n \"presearch.com\",\n \"search.yahoo.com\",\n \"googlesyndication.com\",\n \"googleadservices.com\",\n];\n\nconst SOCIAL_NETWORKS: string[] = [\n \"facebook.com\",\n \"fb.com\",\n \"fb.me\",\n \"l.facebook.com\",\n \"lm.facebook.com\",\n \"m.facebook.com\",\n \"instagram.com\",\n \"l.instagram.com\",\n \"twitter.com\",\n \"t.co\",\n \"x.com\",\n \"linkedin.com\",\n \"lnkd.in\",\n \"pinterest.com\",\n \"pin.it\",\n \"reddit.com\",\n \"tiktok.com\",\n \"youtube.com\",\n \"youtu.be\",\n \"snapchat.com\",\n \"tumblr.com\",\n \"threads.net\",\n \"mastodon.social\",\n \"bsky.app\",\n \"whatsapp.com\",\n \"wechat.com\",\n \"weibo.com\",\n \"vk.com\",\n \"quora.com\",\n \"medium.com\",\n \"discord.com\",\n \"discord.gg\",\n \"telegram.org\",\n \"t.me\",\n \"slack.com\",\n];\n\nconst SOCIAL_DISPLAY_NAMES: Record<string, string> = {\n \"facebook.com\": \"Facebook\",\n \"fb.com\": \"Facebook\",\n \"fb.me\": \"Facebook\",\n \"l.facebook.com\": \"Facebook\",\n \"lm.facebook.com\": \"Facebook\",\n \"m.facebook.com\": \"Facebook\",\n \"instagram.com\": \"Instagram\",\n \"l.instagram.com\": \"Instagram\",\n \"twitter.com\": \"Twitter\",\n \"t.co\": \"Twitter\",\n \"x.com\": \"Twitter\",\n \"linkedin.com\": \"LinkedIn\",\n \"lnkd.in\": \"LinkedIn\",\n \"pinterest.com\": \"Pinterest\",\n \"pin.it\": \"Pinterest\",\n \"reddit.com\": \"Reddit\",\n \"tiktok.com\": \"TikTok\",\n \"youtube.com\": \"YouTube\",\n \"youtu.be\": \"YouTube\",\n \"snapchat.com\": \"Snapchat\",\n \"tumblr.com\": \"Tumblr\",\n \"threads.net\": \"Threads\",\n \"mastodon.social\": \"Mastodon\",\n \"bsky.app\": \"Bluesky\",\n \"whatsapp.com\": \"WhatsApp\",\n \"wechat.com\": \"WeChat\",\n \"weibo.com\": \"Weibo\",\n \"vk.com\": \"VK\",\n \"quora.com\": \"Quora\",\n \"medium.com\": \"Medium\",\n \"discord.com\": \"Discord\",\n \"discord.gg\": \"Discord\",\n \"telegram.org\": \"Telegram\",\n \"t.me\": \"Telegram\",\n \"slack.com\": \"Slack\",\n};\n\nconst SEARCH_DISPLAY_NAMES: Record<string, string> = {\n \"google.\": \"Google\",\n \"bing.com\": \"Bing\",\n \"yahoo.\": \"Yahoo\",\n \"duckduckgo.com\": \"DuckDuckGo\",\n \"baidu.com\": \"Baidu\",\n \"yandex.\": \"Yandex\",\n \"ask.com\": \"Ask\",\n \"ecosia.org\": \"Ecosia\",\n \"aol.com\": \"AOL\",\n \"startpage.com\": \"Startpage\",\n \"qwant.com\": \"Qwant\",\n \"brave.com\": \"Brave\",\n \"search.brave.com\": \"Brave\",\n \"naver.com\": \"Naver\",\n \"daum.net\": \"Daum\",\n \"sogou.com\": \"Sogou\",\n \"so.com\": \"360 Search\",\n \"seznam.cz\": \"Seznam\",\n \"googlesyndication.com\": \"Google\",\n \"googleadservices.com\": \"Google\",\n};\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Main IIFE\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n(function (): void {\n \"use strict\";\n\n const config: UTMConfig = {\n utmKeys: [\n \"utm_source\",\n \"utm_medium\",\n \"utm_campaign\",\n \"utm_term\",\n \"utm_content\",\n \"utm_id\",\n ],\n clickIdKeys: [\"gclid\", \"msclkid\", \"fbclid\"],\n linkSelectors: [\n \"a[href]\",\n \"button[onclick*='location']\",\n \"button[onclick*='window.open']\",\n \"button[onclick*='href']\",\n \"[data-href]\",\n ],\n inputSelector: \"[data-utm-input]\",\n inputKeyMap: {\n source: \"utm_source\",\n medium: \"utm_medium\",\n campaign: \"utm_campaign\",\n term: \"utm_term\",\n content: \"utm_content\",\n id: \"utm_id\",\n utm_source: \"utm_source\",\n utm_medium: \"utm_medium\",\n utm_campaign: \"utm_campaign\",\n utm_term: \"utm_term\",\n utm_content: \"utm_content\",\n utm_id: \"utm_id\",\n gclid: \"gclid\",\n msclkid: \"msclkid\",\n fbclid: \"fbclid\",\n channel: \"_channel\",\n channeldrilldown1: \"_channelDrilldown1\",\n channeldrilldown2: \"_channelDrilldown2\",\n channeldrilldown3: \"_channelDrilldown3\",\n landingpage: \"_landingPage\",\n landingpagegroup: \"_landingPageGroup\",\n },\n };\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Helper: Domain Matching\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function domainMatches(hostname: string, pattern: string): boolean {\n const h = hostname.toLowerCase();\n const p = pattern.toLowerCase();\n if (p.endsWith(\".\")) {\n return h === p.slice(0, -1) || h.includes(\".\" + p.slice(0, -1) + \".\") || h.startsWith(p);\n }\n return h === p || h.endsWith(\".\" + p);\n }\n\n function isRecognisedSearchEngine(hostname: string): boolean {\n return SEARCH_ENGINES.some((pattern) => domainMatches(hostname, pattern));\n }\n\n function isRecognisedSocialNetwork(hostname: string): boolean {\n return SOCIAL_NETWORKS.some((domain) => domainMatches(hostname, domain));\n }\n\n function getSearchEngineName(hostname: string): string {\n for (const [pattern, name] of Object.entries(SEARCH_DISPLAY_NAMES)) {\n if (domainMatches(hostname, pattern)) return name;\n }\n return cleanDomain(hostname);\n }\n\n function getSocialNetworkName(hostname: string): string {\n for (const [domain, name] of Object.entries(SOCIAL_DISPLAY_NAMES)) {\n if (domainMatches(hostname, domain)) return name;\n }\n return cleanDomain(hostname);\n }\n\n function cleanDomain(hostname: string): string {\n return hostname.replace(/^www\\./, \"\");\n }\n\n function valueIsSocialNetwork(value: string): boolean {\n const v = value.toLowerCase().trim();\n const allNames = Object.values(SOCIAL_DISPLAY_NAMES).map((n) => n.toLowerCase());\n if (allNames.includes(v)) return true;\n return SOCIAL_NETWORKS.some((domain) => v === domain || v === domain.replace(\".com\", \"\"));\n }\n\n function valueIsSearchEngine(value: string): boolean {\n const v = value.toLowerCase().trim();\n const allNames = Object.values(SEARCH_DISPLAY_NAMES).map((n) => n.toLowerCase());\n if (allNames.includes(v)) return true;\n return SEARCH_ENGINES.some((pattern) => {\n const clean = pattern.replace(/\\.$/, \"\");\n return v === clean || v === clean.replace(\".com\", \"\");\n });\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Helper: String checks\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function containsAny(value: string | undefined, ...terms: string[]): boolean {\n if (!value) return false;\n const v = value.toLowerCase();\n return terms.some((t) => v.includes(t.toLowerCase()));\n }\n\n function equalsAny(value: string | undefined, ...terms: string[]): boolean {\n if (!value) return false;\n const v = value.toLowerCase().trim();\n return terms.some((t) => v === t.toLowerCase());\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Param Capture from URL\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function getCapturedParams(): UTMParams {\n const urlParams = new URLSearchParams(window.location.search);\n const captured: UTMParams = {};\n\n config.utmKeys.forEach((key) => {\n const value = urlParams.get(key);\n if (value) captured[key] = value;\n });\n\n config.clickIdKeys.forEach((key) => {\n const value = urlParams.get(key);\n if (value) captured[key] = value;\n });\n\n const bareSource = urlParams.get(\"source\");\n if (bareSource && !captured[\"utm_source\"]) {\n captured[\"source\"] = bareSource;\n }\n\n return captured;\n }\n\n function hasTrackingParams(params: UTMParams): boolean {\n return (\n !!params.utm_source ||\n !!params.utm_medium ||\n !!params.utm_campaign ||\n !!params.source ||\n !!params.gclid ||\n !!params.msclkid ||\n !!params.fbclid\n );\n }\n\n function hasUTMParams(params: UTMParams): boolean {\n return !!params.utm_source || !!params.utm_medium || !!params.utm_campaign;\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Referrer Analysis\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function getReferrerHostname(): string {\n try {\n if (!document.referrer) return \"\";\n const url = new URL(document.referrer);\n if (url.hostname === window.location.hostname) return \"\";\n return url.hostname.toLowerCase();\n } catch {\n return \"\";\n }\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Landing Page Info\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function getLandingPage(): string {\n return window.location.pathname + window.location.search;\n }\n\n function getLandingPageGroup(): string {\n const segments = window.location.pathname.split(\"/\").filter(Boolean);\n return segments.length > 0 ? \"/\" + segments[0] : \"/\";\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Channel Categorisation Engine (11-rule cascade)\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function categorise(params: UTMParams, referrerHost: string): AttributionResult {\n const utm_source = params.utm_source || \"\";\n const utm_medium = params.utm_medium || \"\";\n const utm_campaign = params.utm_campaign || \"\";\n const utm_term = params.utm_term || \"\";\n const utm_content = params.utm_content || \"\";\n const bare_source = params.source || \"\";\n const gclid = params.gclid || \"\";\n const msclkid = params.msclkid || \"\";\n\n const landingPage = getLandingPage();\n const landingPageGroup = getLandingPageGroup();\n\n const base = { landingPage, landingPageGroup };\n\n // Rule 1: Organic Social\n if (equalsAny(utm_medium, \"social\")) {\n if (valueIsSocialNetwork(utm_source) || isRecognisedSocialNetwork(referrerHost)) {\n const sourceName = valueIsSocialNetwork(utm_source)\n ? capitalise(utm_source)\n : getSocialNetworkName(referrerHost);\n return { ...base, channel: \"Organic Social\", channelDrilldown1: sourceName, channelDrilldown2: utm_campaign, channelDrilldown3: utm_content };\n }\n }\n\n // Rule 2: Email Marketing\n if (equalsAny(utm_medium, \"email\")) {\n return { ...base, channel: \"Email Marketing\", channelDrilldown1: utm_source || \"Email\", channelDrilldown2: utm_campaign, channelDrilldown3: utm_content };\n }\n\n // Rule 3: Paid Social\n if (\n containsAny(utm_source, \"paidsocial\") ||\n containsAny(utm_medium, \"paidsocial\") ||\n (containsAny(utm_medium, \"paid\", \"ppc\", \"cpc\") && valueIsSocialNetwork(utm_source)) ||\n (containsAny(utm_medium, \"paid\", \"ppc\", \"cpc\") && isRecognisedSocialNetwork(referrerHost))\n ) {\n const sourceName = valueIsSocialNetwork(utm_source)\n ? capitalise(utm_source)\n : isRecognisedSocialNetwork(referrerHost)\n ? getSocialNetworkName(referrerHost)\n : utm_source || \"Paid Social\";\n return { ...base, channel: \"Paid Social\", channelDrilldown1: sourceName, channelDrilldown2: utm_campaign, channelDrilldown3: utm_term || utm_content };\n }\n\n // Rule 4: Paid Search\n if (\n containsAny(utm_source, \"paidsearch\") ||\n containsAny(utm_medium, \"paidsearch\") ||\n containsAny(utm_source, \"adwords\", \"ppc\", \"cpc\") ||\n containsAny(utm_medium, \"adwords\", \"ppc\", \"cpc\") ||\n containsAny(utm_campaign, \"adwords\", \"ppc\", \"cpc\") ||\n gclid || msclkid ||\n (hasUTMParams(params) && isRecognisedSearchEngine(referrerHost))\n ) {\n let sourceName = \"Paid Search\";\n if (gclid) sourceName = \"Google\";\n else if (msclkid) sourceName = \"Bing\";\n else if (valueIsSearchEngine(utm_source)) sourceName = capitalise(utm_source);\n else if (isRecognisedSearchEngine(referrerHost)) sourceName = getSearchEngineName(referrerHost);\n else if (utm_source) sourceName = utm_source;\n return { ...base, channel: \"Paid Search\", channelDrilldown1: sourceName, channelDrilldown2: utm_campaign, channelDrilldown3: utm_term };\n }\n\n // Rule 5: Display\n if (equalsAny(utm_medium, \"display\")) {\n return { ...base, channel: \"Display\", channelDrilldown1: utm_source || \"Display\", channelDrilldown2: utm_campaign, channelDrilldown3: utm_content };\n }\n\n // Rule 6: Affiliates\n if (containsAny(utm_medium, \"affiliate\")) {\n return { ...base, channel: \"Affiliates\", channelDrilldown1: utm_source || \"Affiliate\", channelDrilldown2: utm_campaign, channelDrilldown3: utm_content };\n }\n\n // Rule 7: Other Campaigns\n if (hasTrackingParams(params)) {\n return { ...base, channel: \"Other Campaigns\", channelDrilldown1: utm_source || bare_source, channelDrilldown2: utm_medium, channelDrilldown3: utm_campaign };\n }\n\n // Rule 8: Organic Social (by referrer)\n if (referrerHost && isRecognisedSocialNetwork(referrerHost)) {\n return { ...base, channel: \"Organic Social\", channelDrilldown1: getSocialNetworkName(referrerHost), channelDrilldown2: \"\", channelDrilldown3: \"\" };\n }\n\n // Rule 9: Organic Search (by referrer)\n if (referrerHost && isRecognisedSearchEngine(referrerHost)) {\n return { ...base, channel: \"Organic Search\", channelDrilldown1: getSearchEngineName(referrerHost), channelDrilldown2: \"\", channelDrilldown3: \"\" };\n }\n\n // Rule 10: Referral\n if (referrerHost) {\n return { ...base, channel: \"Referral\", channelDrilldown1: cleanDomain(referrerHost), channelDrilldown2: landingPage, channelDrilldown3: \"\" };\n }\n\n // Rule 11: Direct\n return { ...base, channel: \"Direct\", channelDrilldown1: \"Direct\", channelDrilldown2: landingPage, channelDrilldown3: \"\" };\n }\n\n function capitalise(str: string): string {\n if (!str) return str;\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Link Processing (propagate UTM params to internal links)\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function isInternalLink(url: string, currentHost: string): boolean {\n try {\n if (url.startsWith(\"/\") || url.startsWith(\"./\") || url.startsWith(\"../\")) return true;\n if (/^[a-z]+:/i.test(url) && !url.startsWith(\"http\")) return false;\n if (url.startsWith(\"http\")) return new URL(url).hostname === currentHost;\n if (url.startsWith(\"//\")) return new URL(\"https:\" + url).hostname === currentHost;\n if (!url.includes(\"://\")) return true;\n return false;\n } catch (e) {\n console.warn(\"UTM: Error parsing URL:\", url, e);\n return false;\n }\n }\n\n function addUTMToURL(url: string, utmParams: UTMParams): string {\n try {\n const urlObj = new URL(url, window.location.origin);\n Object.entries(utmParams).forEach(([key, value]) => {\n if (!config.utmKeys.includes(key)) return;\n if (urlObj.searchParams.has(key)) return; // never override existing\n urlObj.searchParams.set(key, value);\n });\n return urlObj.toString();\n } catch (e) {\n console.warn(\"UTM: Error processing URL:\", url, e);\n return url;\n }\n }\n\n function hasUTMException(element: Element): boolean {\n return element.getAttribute(\"data-utm-exception\") === \"true\";\n }\n\n function processLink(element: Element, utmParams: UTMParams): void {\n if (hasUTMException(element)) return;\n\n const currentHost = window.location.hostname;\n let url: string | null = null;\n\n if (element instanceof HTMLAnchorElement && element.href) {\n url = element.href;\n } else if (element instanceof HTMLElement && element.dataset.href) {\n url = element.dataset.href;\n }\n\n if (url && isInternalLink(url, currentHost)) {\n const updatedURL = addUTMToURL(url, utmParams);\n if (element instanceof HTMLAnchorElement) {\n element.href = updatedURL;\n } else if (element instanceof HTMLElement && element.dataset.href) {\n element.dataset.href = updatedURL;\n }\n }\n }\n\n function processAllLinks(utmParams: UTMParams): void {\n document.querySelectorAll(config.linkSelectors.join(\", \")).forEach((el) => processLink(el, utmParams));\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Input Field Processing\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function processInput(element: Element, allValues: Record<string, string>): void {\n if (hasUTMException(element)) return;\n\n const shortKey = element.getAttribute(\"data-utm-input\")?.trim().toLowerCase();\n if (!shortKey) return;\n\n const internalKey = config.inputKeyMap[shortKey];\n if (!internalKey) {\n console.warn(`UTM: Unknown data-utm-input value \"${shortKey}\"`);\n return;\n }\n\n const value = allValues[internalKey];\n if (!value) return;\n\n if (\n element instanceof HTMLInputElement ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement\n ) {\n if (element.value && element.value.trim() !== \"\") return; // never override\n element.value = value;\n element.dispatchEvent(new Event(\"input\", { bubbles: true }));\n element.dispatchEvent(new Event(\"change\", { bubbles: true }));\n }\n }\n\n function processAllInputs(allValues: Record<string, string>): void {\n document.querySelectorAll(config.inputSelector).forEach((el) => processInput(el, allValues));\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Build flat key\u2192value map for form fields\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function buildValueMap(data: AttributionData): Record<string, string> {\n const map: Record<string, string> = {};\n Object.entries(data.params).forEach(([key, value]) => { map[key] = value; });\n map[\"_channel\"] = data.attribution.channel;\n map[\"_channelDrilldown1\"] = data.attribution.channelDrilldown1;\n map[\"_channelDrilldown2\"] = data.attribution.channelDrilldown2;\n map[\"_channelDrilldown3\"] = data.attribution.channelDrilldown3;\n map[\"_landingPage\"] = data.attribution.landingPage;\n map[\"_landingPageGroup\"] = data.attribution.landingPageGroup;\n return map;\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // MutationObserver (handles dynamically added content)\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function observeNewContent(utmParams: UTMParams, allValues: Record<string, string>): void {\n const allSelectors = [...config.linkSelectors, config.inputSelector].join(\", \");\n\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n let pendingNodes: Element[] = [];\n\n function flushPending(): void {\n const nodes = pendingNodes.slice();\n pendingNodes = [];\n debounceTimer = null;\n\n nodes.forEach((element) => {\n if (element.matches?.(config.inputSelector)) {\n processInput(element, allValues);\n } else if (element.matches?.(config.linkSelectors.join(\", \"))) {\n processLink(element, utmParams);\n }\n element.querySelectorAll?.(allSelectors).forEach((child) => {\n if (child.matches(config.inputSelector)) {\n processInput(child, allValues);\n } else {\n processLink(child, utmParams);\n }\n });\n });\n }\n\n new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n mutation.addedNodes.forEach((node) => {\n if (node.nodeType === Node.ELEMENT_NODE) {\n pendingNodes.push(node as Element);\n }\n });\n });\n if (pendingNodes.length > 0 && !debounceTimer) {\n debounceTimer = setTimeout(flushPending, 50);\n }\n }).observe(document.body, { childList: true, subtree: true });\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Init \u2014 no cookies, no storage, fresh on every load\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function init(): void {\n const freshParams = getCapturedParams();\n const referrerHost = getReferrerHostname();\n\n const attribution = categorise(freshParams, referrerHost);\n const data: AttributionData = { params: freshParams, attribution };\n const allValues = buildValueMap(data);\n\n const run = (): void => {\n processAllLinks(data.params);\n processAllInputs(allValues);\n observeNewContent(data.params, allValues);\n };\n\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", run);\n } else {\n run();\n }\n }\n\n init();\n})();"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|