top of page

Schedule your service

With Coach Andre

Check out our availability and book the date and time that works for you

bottom of page
/* UTM Tracker v2.0 - first/latest touch attribution and form autofill */ (function (window, document) { "use strict"; var userConfig = window.UTM_TRACKER_CONFIG || {}; var config = { storageKey: userConfig.storageKey || "utm_attribution_v2", cookieName: userConfig.cookieName || "utm_attribution_v2", ownedDomains: Array.isArray(userConfig.ownedDomains) ? userConfig.ownedDomains : [], defaultTouch: userConfig.defaultTouch === "latest" ? "latest" : "first", cookieDays: Math.min(Number(userConfig.cookieDays) || 400, 400), linkerMinutes: Math.min(Number(userConfig.linkerMinutes) || 30, 1440), decorateLinks: userConfig.decorateLinks !== false, removeLinkerFromUrl: userConfig.removeLinkerFromUrl !== false, debug: userConfig.debug === true, canStore: typeof userConfig.canStore === "function" ? userConfig.canStore : function () { return true; } }; var PARAMS = [ "utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content", "utm_id", "utm_source_platform", "utm_creative_format", "utm_marketing_tactic", "gclid", "gbraid", "wbraid", "fbclid", "msclkid", "ttclid", "twclid", "li_fat_id", "dclid", "srsltid" ]; var META = ["landing_page", "referrer", "captured_at"]; var LINKER_PARAM = "_utm_attribution"; var MAX_VALUE_LENGTH = 2048; var memoryData = emptyData(); var observedRoots = []; var scheduled = false; function emptyData() { return { first: null, latest: null }; } function log() { if (config.debug && window.console) { window.console.log.apply(window.console, ["[UTM Tracker]"].concat([].slice.call(arguments))); } } function clean(value, max) { if (typeof value !== "string") return ""; return value.replace(/[\u0000-\u001F\u007F]/g, "").trim().slice(0, max || MAX_VALUE_LENGTH); } function parseJSON(value) { try { var parsed = JSON.parse(value); return parsed && typeof parsed === "object" ? parsed : null; } catch (_) { return null; } } function storageAllowed() { try { return config.canStore() === true; } catch (_) { return false; } } function validTouch(value) { if (!value || typeof value !== "object") return null; var result = {}; PARAMS.concat(META).forEach(function (key) { var item = clean(value[key] || "", key === "captured_at" ? 40 : MAX_VALUE_LENGTH); if (item) result[key] = item; }); return Object.keys(result).length ? result : null; } function validData(value) { return { first: validTouch(value && value.first), latest: validTouch(value && value.latest) }; } function readCookie() { var match = document.cookie.match(new RegExp("(?:^|; )" + config.cookieName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "=([^;]*)")); if (!match) return null; try { return parseJSON(decodeURIComponent(match[1])); } catch (_) { return null; } } function compactData(data) { function compactTouch(touch) { if (!touch) return null; var result = {}; PARAMS.forEach(function (key) { if (touch[key]) result[key] = clean(touch[key], 250); }); if (touch.captured_at) result.captured_at = touch.captured_at; return Object.keys(result).length ? result : null; } return { first: compactTouch(data.first), latest: compactTouch(data.latest) }; } function cookieData(data) { var compact = compactData(data); var encoded = encodeURIComponent(JSON.stringify(compact)); if (encoded.length <= 3800) return encoded; /* Stay below the practical 4 KB cookie limit by retaining values in priority order. localStorage still keeps the complete record. */ var priority = ["utm_source", "utm_medium", "utm_campaign", "utm_id", "utm_term", "utm_content", "gclid", "gbraid", "wbraid", "fbclid", "msclkid", "ttclid", "twclid", "li_fat_id", "dclid", "srsltid"]; var reduced = emptyData(); ["first", "latest"].forEach(function (touchName) { if (!compact[touchName]) return; reduced[touchName] = {}; priority.forEach(function (key) { if (!compact[touchName][key]) return; var candidate = JSON.parse(JSON.stringify(reduced)); candidate[touchName][key] = clean(compact[touchName][key], 120); var candidateEncoded = encodeURIComponent(JSON.stringify(candidate)); if (candidateEncoded.length <= 3800) reduced = candidate; }); }); return encodeURIComponent(JSON.stringify(reduced)); } function readData() { if (!storageAllowed()) return memoryData; var parsed = null; try { parsed = parseJSON(window.localStorage.getItem(config.storageKey)); } catch (_) {} if (!parsed) parsed = readCookie(); memoryData = validData(parsed || memoryData); return memoryData; } function writeData(data) { memoryData = validData(data); if (!storageAllowed()) return; try { window.localStorage.setItem(config.storageKey, JSON.stringify(memoryData)); } catch (error) { log("localStorage unavailable", error); } try { var value = cookieData(memoryData); document.cookie = config.cookieName + "=" + value + "; Path=/; Max-Age=" + Math.floor(config.cookieDays * 86400) + "; SameSite=Lax" + (location.protocol === "https:" ? "; Secure" : ""); } catch (error) { log("cookie unavailable", error); } } function allParamValues(search, key) { var values = search.getAll(key); for (var i = 0; i < values.length; i += 1) { var value = clean(values[i]); if (value) return value; } return ""; } function base64UrlEncode(value) { var bytes = new TextEncoder().encode(value), binary = ""; bytes.forEach(function (byte) { binary += String.fromCharCode(byte); }); return window.btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""); } function base64UrlDecode(value) { var input = value.replace(/-/g, "+").replace(/_/g, "/"); input += "===".slice((input.length + 3) % 4); var binary = window.atob(input), bytes = new Uint8Array(binary.length); for (var i = 0; i < binary.length; i += 1) bytes[i] = binary.charCodeAt(i); return new TextDecoder().decode(bytes); } function readLinker(search) { var raw = clean(search.get(LINKER_PARAM) || "", 12000); if (!raw) return null; try { var payload = parseJSON(base64UrlDecode(raw)); if (!payload || !Number.isFinite(payload.created)) return null; if (Math.abs(Date.now() - payload.created) > config.linkerMinutes * 60000) return null; return validData(payload.data); } catch (_) { return null; } } function removeLinker() { if (!config.removeLinkerFromUrl || !window.history || !window.history.replaceState) return; try { var url = new URL(location.href); if (!url.searchParams.has(LINKER_PARAM)) return; url.searchParams.delete(LINKER_PARAM); history.replaceState(history.state, "", url.href); } catch (_) {} } function capture() { var search = new URL(location.href).searchParams; var linked = readLinker(search); var data = readData(); if (linked) { if (!data.first && linked.first) data.first = linked.first; if (linked.latest) data.latest = linked.latest; removeLinker(); } var touch = {}; PARAMS.forEach(function (key) { var value = allParamValues(search, key); if (value) touch[key] = value; }); if (Object.keys(touch).length) { touch.landing_page = clean(location.href); touch.referrer = clean(document.referrer || ""); touch.captured_at = new Date().toISOString(); if (!data.first) data.first = touch; data.latest = touch; } writeData(data); return data; } function normalizeName(field) { return clean(field.getAttribute("data-utm-field") || field.name || field.id || "", 200) .toLowerCase().replace(/\[\]$/, "").replace(/[\s.-]+/g, "_"); } function fieldInfo(field) { var name = normalizeName(field), touch = config.defaultTouch; if (/^(first_touch_|first_|original_)/.test(name)) { touch = "first"; name = name.replace(/^(first_touch_|first_|original_)/, ""); } else if (/^(latest_touch_|latest_|last_touch_|last_)/.test(name)) { touch = "latest"; name = name.replace(/^(latest_touch_|latest_|last_touch_|last_)/, ""); } var aliases = { landing_url: "landing_page", utm_landing_page: "landing_page", utm_referrer: "referrer", utm_captured_at: "captured_at" }; name = aliases[name] || name; return PARAMS.concat(META).indexOf(name) === -1 ? null : { key: name, touch: touch }; } function setNativeValue(field, value) { var prototype = field.tagName === "TEXTAREA" ? window.HTMLTextAreaElement.prototype : window.HTMLInputElement.prototype; var setter = Object.getOwnPropertyDescriptor(prototype, "value"); if (setter && setter.set) setter.set.call(field, value); else field.value = value; field.setAttribute("value", value); field.dispatchEvent(new Event("input", { bubbles: true })); field.dispatchEvent(new Event("change", { bubbles: true })); } function fillField(field, data) { if (!field || field.disabled || /^(button|submit|reset|file|checkbox|radio)$/i.test(field.type || "")) return; var info = fieldInfo(field); if (!info) return; var existing = clean(field.value || ""); if (existing && existing.toLowerCase() !== "no utm") return; var primary = data[info.touch], fallback = data[info.touch === "first" ? "latest" : "first"]; var value = (primary && primary[info.key]) || (fallback && fallback[info.key]) || ""; if (value) setNativeValue(field, value); } function scan(root) { var data = readData(), fields = []; if (root.matches && root.matches("input,textarea")) fields.push(root); if (root.querySelectorAll) fields = fields.concat([].slice.call(root.querySelectorAll("input,textarea"))); fields.forEach(function (field) { fillField(field, data); }); if (root.querySelectorAll) { [].slice.call(root.querySelectorAll("*")).forEach(function (element) { if (element.shadowRoot) observeRoot(element.shadowRoot); }); } } function scheduleScan() { if (scheduled) return; scheduled = true; (window.requestAnimationFrame || window.setTimeout)(function () { scheduled = false; scan(document); }, 0); } function observeRoot(root) { if (!root || observedRoots.indexOf(root) !== -1) return; observedRoots.push(root); scan(root); new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { [].slice.call(mutation.addedNodes).forEach(function (node) { if (node.nodeType === 1) scan(node); }); }); }).observe(root, { childList: true, subtree: true }); } function owned(hostname) { var host = hostname.toLowerCase().replace(/^www\./, ""); return config.ownedDomains.some(function (domain) { var candidate = clean(domain, 253).toLowerCase().replace(/^https?:\/\//, "").split("/")[0].replace(/^www\./, "").replace(/:\d+$/, ""); return host === candidate || host.slice(-candidate.length - 1) === "." + candidate; }); } function decorate(anchor) { if (!config.decorateLinks || !anchor || !config.ownedDomains.length) return; try { var url = new URL(anchor.href, location.href); if (!/^https?:$/.test(url.protocol) || !owned(url.hostname) || url.hostname === location.hostname || url.searchParams.has(LINKER_PARAM)) return; var data = readData(); if (!data.first && !data.latest) return; var payload = base64UrlEncode(JSON.stringify({ created: Date.now(), data: compactData(data) })); if (payload.length <= 6000) url.searchParams.set(LINKER_PARAM, payload); anchor.href = url.href; } catch (_) {} } function handleRouteChange() { window.setTimeout(function () { capture(); scheduleScan(); }, 0); } function clearData() { memoryData = emptyData(); try { window.localStorage.removeItem(config.storageKey); } catch (_) {} try { document.cookie = config.cookieName + "=; Path=/; Max-Age=0; SameSite=Lax" + (location.protocol === "https:" ? "; Secure" : ""); } catch (_) {} } function patchHistory(method) { if (!window.history || !history[method]) return; var original = history[method]; history[method] = function () { var result = original.apply(this, arguments); handleRouteChange(); return result; }; } function init() { capture(); observeRoot(document.documentElement); document.addEventListener("submit", function (event) { scan(event.target); }, true); document.addEventListener("focusin", function (event) { fillField(event.target, readData()); }, true); document.addEventListener("pointerdown", function (event) { decorate(event.target.closest && event.target.closest("a[href]")); }, true); document.addEventListener("click", function (event) { decorate(event.target.closest && event.target.closest("a[href]")); }, true); document.addEventListener("contextmenu", function (event) { decorate(event.target.closest && event.target.closest("a[href]")); }, true); document.addEventListener("keydown", function (event) { if (event.key === "Enter") decorate(event.target.closest && event.target.closest("a[href]")); }, true); window.addEventListener("popstate", handleRouteChange); patchHistory("pushState"); patchHistory("replaceState"); } /* Useful for consent managers and debugging. Call refresh() immediately after analytics/marketing consent is granted. */ window.UTMTracker = { refresh: function () { var data = capture(); scheduleScan(); return data; }, get: function () { return validData(readData()); }, clear: clearData }; if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", init, { once: true }); else init(); })(window, document);