@dotcms/analytics
Version:
Official JavaScript library for Content Analytics with DotCMS.
238 lines (237 loc) • 7.3 kB
JavaScript
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
};