/*! Match Live TV first-party site analytics (click + scroll). Requires analytics cookie consent. */ (function () { "use strict"; var ENDPOINT = "/analytics/events"; var STORAGE_KEY = "mltv_cookie_consent"; var COOKIE_NAME = "mltv_cookie_consent"; var FLUSH_MS = 8000; var MAX_QUEUE = 40; var queue = []; var maxScroll = 0; var flushTimer = null; var started = false; function excludedPath(pathname) { var p = pathname || "/"; if (p.indexOf("/admin") === 0) return true; if (p.indexOf("/regia") === 0) return true; if (p.indexOf("/analytics") === 0) return true; if (/^\/live\/[^/]+/.test(p)) return true; if (/^\/replay\/[^/]+/.test(p)) return true; return false; } function hasAnalyticsConsent() { try { var raw = localStorage.getItem(STORAGE_KEY); if (raw) { var parsed = JSON.parse(raw); if (parsed && parsed.analytics) return true; } } catch (e) { /* ignore */ } var match = document.cookie.match( new RegExp("(?:^|; )" + COOKIE_NAME.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "=([^;]*)") ); return !!(match && decodeURIComponent(match[1]) === "all"); } function deviceBucket() { var w = window.innerWidth || document.documentElement.clientWidth || 1024; if (w < 768) return "mobile"; if (w < 1024) return "tablet"; return "desktop"; } function scrollPct() { var doc = document.documentElement; var body = document.body; var scrollTop = window.pageYOffset || doc.scrollTop || body.scrollTop || 0; var height = Math.max( body.scrollHeight || 0, doc.scrollHeight || 0, body.offsetHeight || 0, doc.offsetHeight || 0, doc.clientHeight || 0 ); var view = window.innerHeight || doc.clientHeight || 0; var maxScrollable = Math.max(height - view, 1); var pct = ((scrollTop + view) / height) * 100; if (scrollTop <= 0 && view >= height) return 100; return Math.max(0, Math.min(100, Math.round(pct))); } function pushEvent(evt) { if (!started) return; queue.push(evt); if (queue.length >= MAX_QUEUE) flush(true); } function flush(useBeacon) { if (!queue.length || !hasAnalyticsConsent()) { queue = []; return; } var batch = queue.splice(0, MAX_QUEUE); var body = JSON.stringify({ events: batch }); try { if (useBeacon && navigator.sendBeacon) { var blob = new Blob([body], { type: "application/json" }); navigator.sendBeacon(ENDPOINT, blob); return; } } catch (e) { /* fall through */ } try { fetch(ENDPOINT, { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json" }, body: body, keepalive: true, credentials: "same-origin" }).catch(function () { /* ignore */ }); } catch (err) { /* ignore */ } } function trackPageview() { pushEvent({ type: "pageview", path: location.pathname, device: deviceBucket(), ts: Date.now() }); } function onClick(event) { var target = event.target; if (!(target instanceof Element)) return; if (target.closest("input, textarea, select, [contenteditable='true']")) return; var doc = document.documentElement; var body = document.body; var width = Math.max(body.scrollWidth || 0, doc.scrollWidth || 0, window.innerWidth || 1); var height = Math.max(body.scrollHeight || 0, doc.scrollHeight || 0, window.innerHeight || 1); var x = event.pageX; var y = event.pageY; if (typeof x !== "number" || typeof y !== "number") return; pushEvent({ type: "click", path: location.pathname, device: deviceBucket(), x: Math.max(0, Math.min(100, (x / width) * 100)), y: Math.max(0, Math.min(100, (y / height) * 100)), ts: Date.now() }); } function onScroll() { var pct = scrollPct(); if (pct > maxScroll) maxScroll = pct; } function flushScroll() { if (maxScroll <= 0) return; pushEvent({ type: "scroll", path: location.pathname, device: deviceBucket(), scroll: maxScroll, ts: Date.now() }); } function scheduleFlush() { if (flushTimer) return; flushTimer = setInterval(function () { flushScroll(); flush(false); }, FLUSH_MS); } function start() { if (started) return; if (excludedPath(location.pathname)) return; if (!hasAnalyticsConsent()) return; started = true; maxScroll = scrollPct(); trackPageview(); document.addEventListener("click", onClick, true); window.addEventListener("scroll", onScroll, { passive: true }); document.addEventListener("visibilitychange", function () { if (document.visibilityState === "hidden") { flushScroll(); flush(true); } }); window.addEventListener("pagehide", function () { flushScroll(); flush(true); }); scheduleFlush(); } window.mltvSiteAnalyticsStart = start; if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", start); } else { start(); } })();