UNPKG

@dotcms/analytics

Version:

Official JavaScript library for Content Analytics with DotCMS.

238 lines (237 loc) 7.3 kB
import { ANALYTICS_JS_DEFAULT_PROPERTIES as T, SESSION_STORAGE_KEY as h, DEFAULT_SESSION_TIMEOUT_MINUTES as p, USER_ID_KEY as f, EXPECTED_UTM_KEYS as I, CONTENTLET_CLASS as m, DEFAULT_IMPRESSION_MUTATION_OBSERVER_DEBOUNCE_MS as D } from "../constants/dot-analytics.constants.js"; import { DotLogger as y } from "../dot-analytics.logger.js"; function P(t) { const e = []; return t.siteAuth?.trim() || e.push('"siteAuth"'), t.server?.trim() || e.push('"server"'), e.length > 0 ? e : null; } let u = null, l = null; const g = (t) => { const e = Date.now(), n = Math.random().toString(36).substr(2, 9), s = Math.random().toString(36).substr(2, 9); return `${t}_${e}_${n}${s}`; }, w = { getItem: (t) => { try { return localStorage.getItem(t); } catch { return null; } }, setItem: (t, e) => { try { localStorage.setItem(t, e); } catch (n) { throw console.warn(`DotCMS Analytics [Core]: Could not save ${t} to localStorage`), n; } } }, R = { getItem: (t) => { try { return sessionStorage.getItem(t); } catch { return null; } }, setItem: (t, e) => { try { sessionStorage.setItem(t, e); } catch (n) { throw console.warn(`DotCMS Analytics [Core]: Could not save ${t} to sessionStorage`), n; } }, removeItem: (t) => { try { sessionStorage.removeItem(t); } catch { console.warn(`DotCMS Analytics [Core]: Could not remove ${t} from sessionStorage`); } } }, E = () => { let t = w.getItem(f); if (!t) { t = g("user"); try { w.setItem(f, t); } catch { } } return t; }, C = (t) => { const e = new Date(t), n = /* @__PURE__ */ new Date(), s = new Date( e.getUTCFullYear(), e.getUTCMonth(), e.getUTCDate() ), o = new Date(n.getUTCFullYear(), n.getUTCMonth(), n.getUTCDate()); return s.getTime() !== o.getTime(); }, v = () => { const t = Date.now(); if (typeof window > "u") return g("session_fallback"); try { const e = sessionStorage.getItem(h); if (e) { const { sessionId: o, startTime: r, lastActivity: c } = JSON.parse(e), a = !C(r), d = t - c < p * 60 * 1e3; if (a && d) return sessionStorage.setItem( h, JSON.stringify({ sessionId: o, startTime: r, lastActivity: t }) ), o; } const n = g("session"), s = { sessionId: n, startTime: t, lastActivity: t }; return sessionStorage.setItem(h, JSON.stringify(s)), n; } catch { return g("session_fallback"); } }, x = (t) => { const e = v(), n = E(), s = A(); return { site_auth: t.siteAuth, session_id: e, user_id: n, device: s }; }, _ = () => u || (u = { user_language: navigator.language, doc_encoding: document.characterSet || document.charset, screen_resolution: typeof screen < "u" && screen.width && screen.height ? `${screen.width}x${screen.height}` : "" }, u), A = () => { const t = _(), e = window.innerWidth || document.documentElement.clientWidth || 0, n = window.innerHeight || document.documentElement.clientHeight || 0; return { screen_resolution: t.screen_resolution ?? "", language: t.user_language ?? "", viewport_width: String(e), viewport_height: String(n) }; }, b = (t) => { const e = t.search; if (l && l.search === e) return l.params; const n = new URLSearchParams(e), s = {}; return I.forEach((o) => { const r = n.get(o); if (r) { const c = o.replace("utm_", ""); s[c] = r; } }), l = { search: e, params: s }, s; }, O = () => { try { const t = (/* @__PURE__ */ new Date()).getTimezoneOffset(), e = t > 0 ? "-" : "+", n = Math.abs(t), s = Math.floor(n / 60), o = n % 60; return `${e}${s.toString().padStart(2, "0")}:${o.toString().padStart(2, "0")}`; } catch { return "+00:00"; } }, M = () => { try { const t = /* @__PURE__ */ new Date(), e = O(), n = t.getFullYear(), s = (t.getMonth() + 1).toString().padStart(2, "0"), o = t.getDate().toString().padStart(2, "0"), r = t.getHours().toString().padStart(2, "0"), c = t.getMinutes().toString().padStart(2, "0"), a = t.getSeconds().toString().padStart(2, "0"); return `${n}-${s}-${o}T${r}:${c}:${a}${e}`; } catch { return (/* @__PURE__ */ new Date()).toISOString(); } }, Y = (t, e = typeof window < "u" ? window.location : {}) => { const n = M(), s = _(), { properties: o } = t, r = {}; Object.keys(o).forEach((i) => { T.includes(i) || (r[i] = o[i]); }); const c = t.context?.device?.language?.toLowerCase() ?? "", a = { url: e.href, doc_encoding: s.doc_encoding, doc_hash: e.hash, doc_protocol: e.protocol, doc_search: e.search, doc_host: e.hostname, doc_path: e.pathname, title: o.title ?? document?.title, locale_id: c }, d = b(e); return { ...t, page: a, ...Object.keys(d).length > 0 && { utm: d }, // Only include custom if there are user-provided properties ...Object.keys(r).length > 0 && { custom: r }, local_time: n }; }; function L(t, e) { let n = 0; return (...s) => { const o = Date.now(); o - n >= e && (t(...s), n = o); }; } function B(t) { return t.dataset.dotIdentifier || null; } function F(t) { return { identifier: t.dataset.dotIdentifier || "", inode: t.dataset.dotInode || "", contentType: t.dataset.dotType || "", title: t.dataset.dotTitle || "", baseType: t.dataset.dotBasetype || "" }; } const z = 100, N = () => typeof window < "u" && typeof document < "u", H = () => Array.from(document.querySelectorAll(`.${m}`)), J = (t, e = D) => { const n = L(t, e), s = new MutationObserver((r) => { r.some((a) => a.addedNodes.length === 0 && a.removedNodes.length === 0 ? !1 : [ ...Array.from(a.addedNodes), ...Array.from(a.removedNodes) ].some((i) => { if (i.nodeType !== Node.ELEMENT_NODE) return !1; const S = i; return S.classList?.contains(m) ? !0 : S.querySelector?.(`.${m}`) !== null; })) && n(); }), o = document.body || document.documentElement; return o ? s.observe(o, { childList: !0, subtree: !0, attributes: !1, characterData: !1 }) : window.addEventListener("DOMContentLoaded", () => { document.body && s.observe(document.body, { childList: !0, subtree: !0, attributes: !1, characterData: !1 }); }), s; }, K = (t) => { N() && (window.addEventListener("beforeunload", t), window.addEventListener("pagehide", t)); }, j = (t, e) => { const n = e.logLevel ?? (e.debug ? "debug" : "warn"); return new y("Analytics", t, n); }, W = (t, e, n) => [ t.impressions && e(t), t.clicks && n(t) ].filter(Boolean); export { z as INITIAL_SCAN_DELAY_MS, J as createContentletObserver, j as createPluginLogger, L as createThrottle, Y as enrichPagePayloadOptimized, F as extractContentletData, B as extractContentletIdentifier, b as extractUTMParameters, H as findContentlets, g as generateSecureId, x as getAnalyticsContext, A as getDeviceDataForContext, W as getEnhancedTrackingPlugins, M as getLocalTime, v as getSessionId, E as getUserId, N as isBrowser, R as safeSessionStorage, K as setupPluginCleanup, P as validateAnalyticsConfig };