@dotcms/analytics 1.2.1 → 1.2.2

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.
package/README.md CHANGED
@@ -247,7 +247,7 @@ The `impressions` option controls automatic tracking of content visibility:
247
247
 
248
248
  **How it works:**
249
249
 
250
- - ✅ Tracks contentlets marked with `dotcms-analytics-contentlet` class and `data-dot-analytics-*` attributes
250
+ - ✅ Tracks contentlets marked with `dotcms-contentlet` class and `data-dot-*` attributes (e.g., `data-dot-identifier`, `data-dot-inode`, `data-dot-type`)
251
251
  - ✅ Uses Intersection Observer API for high performance and battery efficiency
252
252
  - ✅ Only fires when element is ≥50% visible for ≥750ms (configurable)
253
253
  - ✅ Only tracks during active tab (respects page visibility)
@@ -299,7 +299,7 @@ The `clicks` option controls automatic tracking of user interactions with conten
299
299
  **How it works:**
300
300
 
301
301
  - ✅ Tracks clicks on `<a>` and `<button>` elements within contentlets
302
- - ✅ Contentlets must be marked with `dotcms-analytics-contentlet` class and `data-dot-analytics-*` attributes
302
+ - ✅ Contentlets must be marked with `dotcms-contentlet` class and `data-dot-*` attributes (e.g., `data-dot-identifier`, `data-dot-inode`, `data-dot-type`)
303
303
  - ✅ Captures semantic attributes (`href`, `aria-label`, `data-*`) and excludes CSS classes
304
304
  - ✅ Throttles rapid clicks to prevent duplicate tracking (300ms fixed)
305
305
  - ✅ One click event per interaction
@@ -341,7 +341,7 @@ The `attributes` array captures additional semantic data in `'key:value'` string
341
341
  - `class` - Already captured as top-level property
342
342
  - `id` - Already captured as top-level property
343
343
  - `href` - Already captured as top-level property
344
- - `data-dot-analytics-*` - Internal SDK attributes
344
+ - `data-dot-*` - Internal SDK attributes (e.g., `data-dot-identifier`, `data-dot-inode`, `data-dot-type`)
345
345
 
346
346
  **Example: Enable click tracking**
347
347
 
@@ -1,4 +1,4 @@
1
- import { ANALYTICS_WINDOWS_ACTIVE_KEY, ANALYTICS_WINDOWS_CLEANUP_KEY } from '../../../../uve/src/internal.ts';
1
+ import { ANALYTICS_WINDOWS_ACTIVE_KEY, ANALYTICS_WINDOWS_CLEANUP_KEY } from './shared/constants/dot-analytics.constants';
2
2
  import { DotCMSAnalytics, DotCMSAnalyticsConfig } from './shared/models';
3
3
  declare global {
4
4
  interface Window {
@@ -1,14 +1,13 @@
1
1
  import { Analytics as l } from "analytics";
2
- import { ANALYTICS_WINDOWS_ACTIVE_KEY as a, ANALYTICS_WINDOWS_CLEANUP_KEY as d } from "../../uve/src/internal/constants.js";
3
- import { dotAnalyticsClickPlugin as y } from "./plugin/click/dot-analytics.click.plugin.js";
4
- import { dotAnalyticsEnricherPlugin as m } from "./plugin/enricher/dot-analytics.enricher.plugin.js";
2
+ import { dotAnalyticsClickPlugin as d } from "./plugin/click/dot-analytics.click.plugin.js";
3
+ import { dotAnalyticsEnricherPlugin as y } from "./plugin/enricher/dot-analytics.enricher.plugin.js";
5
4
  import { dotAnalyticsIdentityPlugin as u } from "./plugin/identity/dot-analytics.identity.plugin.js";
6
- import { dotAnalyticsImpressionPlugin as p } from "./plugin/impression/dot-analytics.impression.plugin.js";
5
+ import { dotAnalyticsImpressionPlugin as m } from "./plugin/impression/dot-analytics.impression.plugin.js";
7
6
  import { dotAnalytics as A } from "./plugin/main/dot-analytics.plugin.js";
8
- import { DotCMSPredefinedEventType as f } from "./shared/constants/dot-analytics.constants.js";
7
+ import { ANALYTICS_WINDOWS_ACTIVE_KEY as a, ANALYTICS_WINDOWS_CLEANUP_KEY as p, DotCMSPredefinedEventType as f } from "./shared/constants/dot-analytics.constants.js";
9
8
  import { validateAnalyticsConfig as C, getEnhancedTrackingPlugins as w } from "./shared/utils/dot-analytics.utils.js";
10
9
  import { cleanupActivityTracking as g } from "./plugin/identity/dot-analytics.identity.activity-tracker.js";
11
- const _ = (t) => {
10
+ const T = (t) => {
12
11
  const e = C(t);
13
12
  if (e)
14
13
  return console.error(
@@ -16,8 +15,8 @@ const _ = (t) => {
16
15
  ), typeof window < "u" && (window[a] = !1), null;
17
16
  const s = w(
18
17
  t,
19
- p,
20
- y
18
+ m,
19
+ d
21
20
  ), i = l({
22
21
  app: "dotAnalytics",
23
22
  debug: t.debug,
@@ -26,13 +25,13 @@ const _ = (t) => {
26
25
  // Inject identity context
27
26
  ...s,
28
27
  //Track content impressions & clicks (conditionally loaded)
29
- m(),
28
+ y(),
30
29
  // Enrich and clean payload with page, device, utm data and custom data
31
30
  A(t)
32
31
  // Send events to server
33
32
  ]
34
33
  }), r = () => g();
35
- return typeof window < "u" && (window.addEventListener("beforeunload", r), window[d] = r, window[a] = !0, window.dispatchEvent(new CustomEvent("dotcms:analytics:ready"))), {
34
+ return typeof window < "u" && (window.addEventListener("beforeunload", r), window[p] = r, window[a] = !0, window.dispatchEvent(new CustomEvent("dotcms:analytics:ready"))), {
36
35
  /**
37
36
  * Track a page view.
38
37
  * Session activity is automatically updated by the identity plugin.
@@ -80,5 +79,5 @@ const _ = (t) => {
80
79
  };
81
80
  };
82
81
  export {
83
- _ as initializeContentAnalytics
82
+ T as initializeContentAnalytics
84
83
  };
@@ -1,4 +1,4 @@
1
- import { ANALYTICS_WINDOWS_ACTIVE_KEY, ANALYTICS_WINDOWS_CLEANUP_KEY } from '../../../../../../uve/src/internal.ts';
1
+ import { ANALYTICS_WINDOWS_ACTIVE_KEY, ANALYTICS_WINDOWS_CLEANUP_KEY } from '../../shared/constants';
2
2
  import { DotCMSAnalyticsConfig } from '../../shared/models';
3
3
  declare global {
4
4
  interface Window {
@@ -1,5 +1,4 @@
1
- import { ANALYTICS_WINDOWS_ACTIVE_KEY as a, ANALYTICS_WINDOWS_CLEANUP_KEY as o } from "../../../../uve/src/internal/constants.js";
2
- import { DEFAULT_SESSION_TIMEOUT_MINUTES as r, ACTIVITY_EVENTS as l } from "../../shared/constants/dot-analytics.constants.js";
1
+ import { ANALYTICS_WINDOWS_ACTIVE_KEY as a, ANALYTICS_WINDOWS_CLEANUP_KEY as o, DEFAULT_SESSION_TIMEOUT_MINUTES as r, ACTIVITY_EVENTS as l } from "../../shared/constants/dot-analytics.constants.js";
3
2
  class v {
4
3
  constructor() {
5
4
  this.activityListeners = [], this.lastActivityTime = Date.now(), this.inactivityTimer = null, this.isThrottled = !1, this.config = null, this.ACTIVITY_THROTTLE_MS = 1e3;
@@ -11,8 +10,7 @@ class v {
11
10
  updateActivityTime() {
12
11
  this.lastActivityTime = Date.now(), this.inactivityTimer && clearTimeout(this.inactivityTimer), this.inactivityTimer = setTimeout(
13
12
  () => {
14
- var i;
15
- (i = this.config) != null && i.debug && console.warn("DotCMS Analytics [Activity]: User became inactive after timeout"), this.inactivityTimer = null;
13
+ this.config?.debug && console.warn("DotCMS Analytics [Activity]: User became inactive after timeout"), this.inactivityTimer = null;
16
14
  },
17
15
  r * 60 * 1e3
18
16
  );
@@ -53,15 +51,15 @@ class v {
53
51
  this.activityListeners.forEach((i) => i()), this.activityListeners = [], this.inactivityTimer && (clearTimeout(this.inactivityTimer), this.inactivityTimer = null), this.config = null;
54
52
  }
55
53
  }
56
- const t = new v(), d = () => {
54
+ const t = new v(), T = () => {
57
55
  t.updateSessionActivity();
58
- }, u = (e) => {
56
+ }, d = (e) => {
59
57
  t.initialize(e);
60
- }, y = () => {
58
+ }, u = () => {
61
59
  t.cleanup(), typeof window < "u" && (window[a] = !1, window[o] = void 0, window.dispatchEvent(new CustomEvent("dotcms:analytics:cleanup")));
62
60
  };
63
61
  export {
64
- y as cleanupActivityTracking,
65
- u as initializeActivityTracking,
66
- d as updateSessionActivity
62
+ u as cleanupActivityTracking,
63
+ d as initializeActivityTracking,
64
+ T as updateSessionActivity
67
65
  };
@@ -78,7 +78,7 @@ class E {
78
78
  this.logger.debug(`Skipping element ${r} (${o})`);
79
79
  continue;
80
80
  }
81
- this.elementImpressionStates.has(r) || (n.dataset.dotAnalyticsDomIndex || (n.dataset.dotAnalyticsDomIndex = String(s)), this.observer.observe(n), this.elementImpressionStates.set(r, {
81
+ this.elementImpressionStates.has(r) || (n.dataset.dotDomIndex || (n.dataset.dotDomIndex = String(s)), this.observer.observe(n), this.elementImpressionStates.set(r, {
82
82
  timer: null,
83
83
  visibleSince: null,
84
84
  tracked: this.hasBeenTrackedInSession(r),
@@ -150,7 +150,7 @@ class E {
150
150
  trackAndSendImpression(e, i) {
151
151
  const t = this.elementImpressionStates.get(e);
152
152
  if (!t) return;
153
- const s = t.visibleSince ? Date.now() - t.visibleSince : 0, n = I(i), r = d(i), o = parseInt(i.dataset.dotAnalyticsDomIndex || "-1", 10), h = {
153
+ const s = t.visibleSince ? Date.now() - t.visibleSince : 0, n = I(i), r = d(i), o = parseInt(i.dataset.dotDomIndex || "-1", 10), h = {
154
154
  content: {
155
155
  identifier: n.identifier,
156
156
  inode: n.inode,
@@ -127,6 +127,32 @@ export declare const CLICKABLE_ELEMENTS_SELECTOR = "a, button";
127
127
  */
128
128
  export declare const IMPRESSION_SESSION_KEY = "dot_analytics_impressions";
129
129
  /**
130
- * CSS class selector for trackable contentlets
131
- */
132
- export declare const ANALYTICS_CONTENTLET_CLASS = "dotcms-analytics-contentlet";
130
+ * Window property key for analytics active state
131
+ * Used to track if analytics is initialized and active
132
+ */
133
+ export declare const ANALYTICS_WINDOWS_ACTIVE_KEY = "__dotAnalyticsActive__";
134
+ /**
135
+ * Window property key for analytics cleanup function
136
+ * Used to store the cleanup function for analytics instance
137
+ */
138
+ export declare const ANALYTICS_WINDOWS_CLEANUP_KEY = "__dotAnalyticsCleanup__";
139
+ /**
140
+ * CSS class selector for contentlet elements
141
+ *
142
+ * @important This constant is intentionally duplicated in @dotcms/react SDK
143
+ * (core-web/libs/sdk/react/src/lib/next/components/Contentlet/Contentlet.tsx).
144
+ * Both constants MUST have the same value ('dotcms-contentlet') for analytics
145
+ * tracking to work correctly with React-rendered contentlets.
146
+ *
147
+ * This duplication is intentional to maintain SDK independence:
148
+ * - @dotcms/analytics can be used standalone without React
149
+ * - @dotcms/react can be used without analytics
150
+ * - When both are used together, they must share the same class name
151
+ *
152
+ * If you need to change this value, you MUST update it in both locations:
153
+ * 1. This file (analytics SDK)
154
+ * 2. Contentlet.tsx in React SDK
155
+ *
156
+ * @see core-web/libs/sdk/react/src/lib/next/components/Contentlet/Contentlet.tsx
157
+ */
158
+ export declare const CONTENTLET_CLASS = "dotcms-contentlet";
@@ -3,18 +3,18 @@ const I = "/api/v1/analytics/content/event", c = {
3
3
  CONTENT_IMPRESSION: "content_impression",
4
4
  CONTENT_CLICK: "content_click",
5
5
  CONVERSION: "conversion"
6
- }, s = [
6
+ }, o = [
7
7
  "utm_source",
8
8
  "utm_medium",
9
9
  "utm_campaign",
10
10
  "utm_term",
11
11
  "utm_content"
12
- ], o = 30, e = "dot_analytics_session_id", N = "dot_analytics_user_id", E = 15, _ = 5e3, L = ["click"], O = {
13
- eventBatchSize: E,
12
+ ], s = 30, e = "dot_analytics_session_id", N = "dot_analytics_user_id", _ = 15, E = 5e3, A = ["click"], L = {
13
+ eventBatchSize: _,
14
14
  // Max events per batch - auto-sends when reached
15
- flushInterval: _
15
+ flushInterval: E
16
16
  // Time between flushes - sends whatever is queued
17
- }, i = [
17
+ }, O = [
18
18
  "title",
19
19
  "url",
20
20
  "path",
@@ -23,30 +23,32 @@ const I = "/api/v1/analytics/content/event", c = {
23
23
  "width",
24
24
  "height",
25
25
  "referrer"
26
- ], t = 0.5, T = 750, n = 100, S = 100, A = 250, C = {
26
+ ], t = 0.5, n = 750, T = 100, S = 100, i = 250, C = {
27
27
  visibilityThreshold: t,
28
- dwellMs: T,
29
- maxNodes: n,
28
+ dwellMs: n,
29
+ maxNodes: T,
30
30
  throttleMs: S
31
- }, U = "content_impression", M = "content_click", D = 300, R = "a, button", a = "dotcms-analytics-contentlet";
31
+ }, U = "content_impression", D = "content_click", M = 300, a = "a, button", R = "__dotAnalyticsActive__", l = "__dotAnalyticsCleanup__", r = "dotcms-contentlet";
32
32
  export {
33
- L as ACTIVITY_EVENTS,
34
- a as ANALYTICS_CONTENTLET_CLASS,
33
+ A as ACTIVITY_EVENTS,
35
34
  I as ANALYTICS_ENDPOINT,
36
- i as ANALYTICS_JS_DEFAULT_PROPERTIES,
37
- R as CLICKABLE_ELEMENTS_SELECTOR,
38
- M as CLICK_EVENT_TYPE,
39
- D as DEFAULT_CLICK_THROTTLE_MS,
35
+ O as ANALYTICS_JS_DEFAULT_PROPERTIES,
36
+ R as ANALYTICS_WINDOWS_ACTIVE_KEY,
37
+ l as ANALYTICS_WINDOWS_CLEANUP_KEY,
38
+ a as CLICKABLE_ELEMENTS_SELECTOR,
39
+ D as CLICK_EVENT_TYPE,
40
+ r as CONTENTLET_CLASS,
41
+ M as DEFAULT_CLICK_THROTTLE_MS,
40
42
  C as DEFAULT_IMPRESSION_CONFIG,
41
- T as DEFAULT_IMPRESSION_DWELL_MS,
42
- n as DEFAULT_IMPRESSION_MAX_NODES,
43
- A as DEFAULT_IMPRESSION_MUTATION_OBSERVER_DEBOUNCE_MS,
43
+ n as DEFAULT_IMPRESSION_DWELL_MS,
44
+ T as DEFAULT_IMPRESSION_MAX_NODES,
45
+ i as DEFAULT_IMPRESSION_MUTATION_OBSERVER_DEBOUNCE_MS,
44
46
  S as DEFAULT_IMPRESSION_THROTTLE_MS,
45
47
  t as DEFAULT_IMPRESSION_VISIBILITY_THRESHOLD,
46
- O as DEFAULT_QUEUE_CONFIG,
47
- o as DEFAULT_SESSION_TIMEOUT_MINUTES,
48
+ L as DEFAULT_QUEUE_CONFIG,
49
+ s as DEFAULT_SESSION_TIMEOUT_MINUTES,
48
50
  c as DotCMSPredefinedEventType,
49
- s as EXPECTED_UTM_KEYS,
51
+ o as EXPECTED_UTM_KEYS,
50
52
  U as IMPRESSION_EVENT_TYPE,
51
53
  e as SESSION_STORAGE_KEY,
52
54
  N as USER_ID_KEY
@@ -3,20 +3,20 @@ import v from "@analytics/router-utils";
3
3
  import { DEFAULT_QUEUE_CONFIG as y } from "../constants/dot-analytics.constants.js";
4
4
  import { sendAnalyticsEvent as b } from "../http/dot-analytics.http.js";
5
5
  import { createPluginLogger as w } from "../utils/dot-analytics.utils.js";
6
- const L = (o) => {
7
- const i = w("Queue", o);
8
- let e = null, n = null, u = !1, d = !1, f = typeof window < "u" ? window.location.pathname : "";
6
+ const L = (u) => {
7
+ const i = w("Queue", u);
8
+ let t = null, n = null, o = !1, d = !1, f = typeof window < "u" ? window.location.pathname : "";
9
9
  const a = {
10
10
  ...y,
11
- ...typeof o.queue == "object" ? o.queue : {}
12
- }, g = (t, s) => {
11
+ ...typeof u.queue == "object" ? u.queue : {}
12
+ }, g = (e, s) => {
13
13
  if (!n) return;
14
- i.debug(`Sending batch of ${t.length} event(s)`, {
15
- events: t,
16
- keepalive: u
17
- }), b({ context: n, events: t }, o, u);
14
+ i.debug(`Sending batch of ${e.length} event(s)`, {
15
+ events: e,
16
+ keepalive: o
17
+ }), b({ context: n, events: e }, u, o);
18
18
  }, l = () => {
19
- !e || e.size() === 0 || !n || (i.info(`Flushing ${e.size()} events (page hidden/unload)`), u = !0, e.flush(!0));
19
+ !t || t.size() === 0 || !n || (i.info(`Flushing ${t.size()} events (page hidden/unload)`), o = !0, t.flush(!0));
20
20
  }, c = () => {
21
21
  if (i.debug("handleVisibilityChange", document.visibilityState), document.visibilityState === "hidden") {
22
22
  if (d) {
@@ -31,9 +31,9 @@ const L = (o) => {
31
31
  * Initialize the queue with smart batching
32
32
  */
33
33
  initialize: () => {
34
- e = m(
35
- (t, s) => {
36
- g(t);
34
+ t = m(
35
+ (e, s) => {
36
+ g(e);
37
37
  },
38
38
  {
39
39
  max: a.eventBatchSize,
@@ -41,8 +41,8 @@ const L = (o) => {
41
41
  throttle: !1
42
42
  // Always false - enables both batch size and interval triggers
43
43
  }
44
- ), typeof window < "u" && typeof document < "u" && (document.addEventListener("visibilitychange", c), window.addEventListener("pagehide", l), v((t) => {
45
- d = !0, f = t, i.debug(`SPA navigation detected (${f})`), setTimeout(() => {
44
+ ), typeof window < "u" && typeof document < "u" && (document.addEventListener("visibilitychange", c), window.addEventListener("pagehide", l), v((e) => {
45
+ d = !0, f = e, i.debug(`SPA navigation detected (${f})`), setTimeout(() => {
46
46
  d = !1;
47
47
  }, 100);
48
48
  }));
@@ -53,25 +53,25 @@ const L = (o) => {
53
53
  * - Sends immediately when eventBatchSize reached (with throttle: false)
54
54
  * - Sends pending events every flushInterval
55
55
  */
56
- enqueue: (t, s) => {
57
- if (n = s, !e) return;
58
- const r = e.size() + 1, p = a.eventBatchSize, h = r >= p;
56
+ enqueue: (e, s) => {
57
+ if (n = s, !t) return;
58
+ const r = t.size() + 1, p = a.eventBatchSize, h = r >= p;
59
59
  i.debug(
60
60
  `Event added. Queue size: ${r}/${p}${h ? " (full, sending...)" : ""}`,
61
- { eventType: t.event_type, event: t }
62
- ), e.push(t);
61
+ { eventType: e.event_type, event: e }
62
+ ), t.push(e);
63
63
  },
64
64
  /**
65
65
  * Get queue size for debugging
66
66
  * Returns the number of events in smartQueue
67
67
  */
68
- size: () => (e == null ? void 0 : e.size()) ?? 0,
68
+ size: () => t?.size() ?? 0,
69
69
  /**
70
70
  * Clean up queue resources
71
71
  * Flushes remaining events and cleans up listeners
72
72
  */
73
73
  cleanup: () => {
74
- l(), typeof window < "u" && typeof document < "u" && (document.removeEventListener("visibilitychange", c), window.removeEventListener("pagehide", l)), e = null, n = null, u = !1;
74
+ l(), typeof window < "u" && typeof document < "u" && (document.removeEventListener("visibilitychange", c), window.removeEventListener("pagehide", l)), t = null, n = null, o = !1;
75
75
  }
76
76
  };
77
77
  };
@@ -1,16 +1,14 @@
1
- import { ANALYTICS_JS_DEFAULT_PROPERTIES as T, SESSION_STORAGE_KEY as h, DEFAULT_SESSION_TIMEOUT_MINUTES as y, USER_ID_KEY as w, DEFAULT_IMPRESSION_MUTATION_OBSERVER_DEBOUNCE_MS as I, EXPECTED_UTM_KEYS as D, ANALYTICS_CONTENTLET_CLASS as S } from "../constants/dot-analytics.constants.js";
1
+ import { ANALYTICS_JS_DEFAULT_PROPERTIES as _, SESSION_STORAGE_KEY as g, DEFAULT_SESSION_TIMEOUT_MINUTES as p, USER_ID_KEY as m, DEFAULT_IMPRESSION_MUTATION_OBSERVER_DEBOUNCE_MS as T, EXPECTED_UTM_KEYS as D, CONTENTLET_CLASS as h } from "../constants/dot-analytics.constants.js";
2
2
  import { DotLogger as E } from "../dot-analytics.logger.js";
3
- import "../../../../uve/src/internal/constants.js";
4
- function Y(t) {
5
- var n, s;
3
+ function $(t) {
6
4
  const e = [];
7
- return (n = t.siteAuth) != null && n.trim() || e.push('"siteAuth"'), (s = t.server) != null && s.trim() || e.push('"server"'), e.length > 0 ? e : null;
5
+ return t.siteAuth?.trim() || e.push('"siteAuth"'), t.server?.trim() || e.push('"server"'), e.length > 0 ? e : null;
8
6
  }
9
- let u = null, l = null;
10
- const g = (t) => {
7
+ let d = null, u = null;
8
+ const l = (t) => {
11
9
  const e = Date.now(), n = Math.random().toString(36).substr(2, 9), s = Math.random().toString(36).substr(2, 9);
12
10
  return `${t}_${e}_${n}${s}`;
13
- }, _ = {
11
+ }, f = {
14
12
  getItem: (t) => {
15
13
  try {
16
14
  return localStorage.getItem(t);
@@ -25,10 +23,10 @@ const g = (t) => {
25
23
  console.warn(`DotCMS Analytics [Core]: Could not save ${t} to localStorage`);
26
24
  }
27
25
  }
28
- }, A = () => {
29
- let t = _.getItem(w);
30
- return t || (t = g("user"), _.setItem(w, t)), t;
31
- }, C = (t) => {
26
+ }, I = () => {
27
+ let t = f.getItem(m);
28
+ return t || (t = l("user"), f.setItem(m, t)), t;
29
+ }, y = (t) => {
32
30
  const e = new Date(t), n = /* @__PURE__ */ new Date(), s = new Date(
33
31
  e.getUTCFullYear(),
34
32
  e.getUTCMonth(),
@@ -38,14 +36,14 @@ const g = (t) => {
38
36
  }, v = () => {
39
37
  const t = Date.now();
40
38
  if (typeof window > "u")
41
- return g("session_fallback");
39
+ return l("session_fallback");
42
40
  try {
43
- const e = sessionStorage.getItem(h);
41
+ const e = sessionStorage.getItem(g);
44
42
  if (e) {
45
- const { sessionId: r, startTime: o, lastActivity: a } = JSON.parse(e), i = !C(o), c = t - a < y * 60 * 1e3;
43
+ const { sessionId: r, startTime: o, lastActivity: a } = JSON.parse(e), i = !y(o), c = t - a < p * 60 * 1e3;
46
44
  if (i && c)
47
45
  return sessionStorage.setItem(
48
- h,
46
+ g,
49
47
  JSON.stringify({
50
48
  sessionId: r,
51
49
  startTime: o,
@@ -53,39 +51,39 @@ const g = (t) => {
53
51
  })
54
52
  ), r;
55
53
  }
56
- const n = g("session"), s = {
54
+ const n = l("session"), s = {
57
55
  sessionId: n,
58
56
  startTime: t,
59
57
  lastActivity: t
60
58
  };
61
- return sessionStorage.setItem(h, JSON.stringify(s)), n;
59
+ return sessionStorage.setItem(g, JSON.stringify(s)), n;
62
60
  } catch {
63
- return g("session_fallback");
61
+ return l("session_fallback");
64
62
  }
65
- }, x = (t) => {
66
- const e = v(), n = A(), s = O();
63
+ }, P = (t) => {
64
+ const e = v(), n = I(), s = C();
67
65
  return {
68
66
  site_auth: t.siteAuth,
69
67
  session_id: e,
70
68
  user_id: n,
71
69
  device: s
72
70
  };
73
- }, p = () => u || (u = {
71
+ }, w = () => d || (d = {
74
72
  user_language: navigator.language,
75
73
  doc_encoding: document.characterSet || document.charset,
76
74
  screen_resolution: typeof screen < "u" && screen.width && screen.height ? `${screen.width}x${screen.height}` : ""
77
- }, u), O = () => {
78
- const t = p(), e = window.innerWidth || document.documentElement.clientWidth || 0, n = window.innerHeight || document.documentElement.clientHeight || 0;
75
+ }, d), C = () => {
76
+ const t = w(), e = window.innerWidth || document.documentElement.clientWidth || 0, n = window.innerHeight || document.documentElement.clientHeight || 0;
79
77
  return {
80
78
  screen_resolution: t.screen_resolution ?? "",
81
79
  language: t.user_language ?? "",
82
80
  viewport_width: String(e),
83
81
  viewport_height: String(n)
84
82
  };
85
- }, N = (t) => {
83
+ }, A = (t) => {
86
84
  const e = t.search;
87
- if (l && l.search === e)
88
- return l.params;
85
+ if (u && u.search === e)
86
+ return u.params;
89
87
  const n = new URLSearchParams(e), s = {};
90
88
  return D.forEach((r) => {
91
89
  const o = n.get(r);
@@ -93,25 +91,25 @@ const g = (t) => {
93
91
  const a = r.replace("utm_", "");
94
92
  s[a] = o;
95
93
  }
96
- }), l = { search: e, params: s }, s;
97
- }, b = () => {
94
+ }), u = { search: e, params: s }, s;
95
+ }, O = () => {
98
96
  try {
99
97
  const t = (/* @__PURE__ */ new Date()).getTimezoneOffset(), e = t > 0 ? "-" : "+", n = Math.abs(t), s = Math.floor(n / 60), r = n % 60;
100
98
  return `${e}${s.toString().padStart(2, "0")}:${r.toString().padStart(2, "0")}`;
101
99
  } catch {
102
100
  return "+00:00";
103
101
  }
104
- }, M = () => {
102
+ }, N = () => {
105
103
  try {
106
- const t = /* @__PURE__ */ new Date(), e = b(), n = t.getFullYear(), s = (t.getMonth() + 1).toString().padStart(2, "0"), r = t.getDate().toString().padStart(2, "0"), o = t.getHours().toString().padStart(2, "0"), a = t.getMinutes().toString().padStart(2, "0"), i = t.getSeconds().toString().padStart(2, "0");
104
+ const t = /* @__PURE__ */ new Date(), e = O(), n = t.getFullYear(), s = (t.getMonth() + 1).toString().padStart(2, "0"), r = t.getDate().toString().padStart(2, "0"), o = t.getHours().toString().padStart(2, "0"), a = t.getMinutes().toString().padStart(2, "0"), i = t.getSeconds().toString().padStart(2, "0");
107
105
  return `${n}-${s}-${r}T${o}:${a}:${i}${e}`;
108
106
  } catch {
109
107
  return (/* @__PURE__ */ new Date()).toISOString();
110
108
  }
111
- }, B = (t, e = typeof window < "u" ? window.location : {}) => {
112
- const n = M(), s = p(), { properties: r } = t, o = {};
109
+ }, R = (t, e = typeof window < "u" ? window.location : {}) => {
110
+ const n = N(), s = w(), { properties: r } = t, o = {};
113
111
  Object.keys(r).forEach((c) => {
114
- T.includes(c) || (o[c] = r[c]);
112
+ _.includes(c) || (o[c] = r[c]);
115
113
  });
116
114
  const a = {
117
115
  url: e.href,
@@ -121,8 +119,8 @@ const g = (t) => {
121
119
  doc_search: e.search,
122
120
  doc_host: e.hostname,
123
121
  doc_path: e.pathname,
124
- title: r.title ?? (document == null ? void 0 : document.title)
125
- }, i = N(e);
122
+ title: r.title ?? document?.title
123
+ }, i = A(e);
126
124
  return {
127
125
  ...t,
128
126
  page: a,
@@ -132,36 +130,35 @@ const g = (t) => {
132
130
  local_time: n
133
131
  };
134
132
  };
135
- function L(t, e) {
133
+ function b(t, e) {
136
134
  let n = 0;
137
135
  return (...s) => {
138
136
  const r = Date.now();
139
137
  r - n >= e && (t(...s), n = r);
140
138
  };
141
139
  }
142
- function F(t) {
143
- return t.dataset.dotAnalyticsIdentifier || null;
140
+ function x(t) {
141
+ return t.dataset.dotIdentifier || null;
144
142
  }
145
- function k(t) {
143
+ function Y(t) {
146
144
  return {
147
- identifier: t.dataset.dotAnalyticsIdentifier || "",
148
- inode: t.dataset.dotAnalyticsInode || "",
149
- contentType: t.dataset.dotAnalyticsContenttype || "",
150
- title: t.dataset.dotAnalyticsTitle || "",
151
- baseType: t.dataset.dotAnalyticsBasetype || ""
145
+ identifier: t.dataset.dotIdentifier || "",
146
+ inode: t.dataset.dotInode || "",
147
+ contentType: t.dataset.dotType || "",
148
+ title: t.dataset.dotTitle || "",
149
+ baseType: t.dataset.dotBasetype || ""
152
150
  };
153
151
  }
154
- const z = 100, U = () => typeof window < "u" && typeof document < "u", H = () => Array.from(document.querySelectorAll(`.${S}`)), J = (t, e = I) => {
155
- const n = L(t, e), s = new MutationObserver((r) => {
152
+ const B = 100, M = () => typeof window < "u" && typeof document < "u", F = () => Array.from(document.querySelectorAll(`.${h}`)), k = (t, e = T) => {
153
+ const n = b(t, e), s = new MutationObserver((r) => {
156
154
  r.some((a) => a.addedNodes.length === 0 && a.removedNodes.length === 0 ? !1 : [
157
155
  ...Array.from(a.addedNodes),
158
156
  ...Array.from(a.removedNodes)
159
157
  ].some((c) => {
160
- var f, m;
161
158
  if (c.nodeType !== Node.ELEMENT_NODE)
162
159
  return !1;
163
- const d = c;
164
- return (f = d.classList) != null && f.contains(S) ? !0 : ((m = d.querySelector) == null ? void 0 : m.call(d, `.${S}`)) !== null;
160
+ const S = c;
161
+ return S.classList?.contains(h) ? !0 : S.querySelector?.(`.${h}`) !== null;
165
162
  })) && n();
166
163
  });
167
164
  return s.observe(document.body, {
@@ -170,33 +167,33 @@ const z = 100, U = () => typeof window < "u" && typeof document < "u", H = () =>
170
167
  attributes: !1,
171
168
  characterData: !1
172
169
  }), s;
173
- }, K = (t) => {
174
- U() && (window.addEventListener("beforeunload", t), window.addEventListener("pagehide", t));
175
- }, j = (t, e) => {
170
+ }, z = (t) => {
171
+ M() && (window.addEventListener("beforeunload", t), window.addEventListener("pagehide", t));
172
+ }, H = (t, e) => {
176
173
  const n = e.logLevel ?? (e.debug ? "debug" : "warn");
177
174
  return new E("Analytics", t, n);
178
- }, W = (t, e, n) => [
175
+ }, J = (t, e, n) => [
179
176
  t.impressions && e(t),
180
177
  t.clicks && n(t)
181
178
  ].filter(Boolean);
182
179
  export {
183
- z as INITIAL_SCAN_DELAY_MS,
184
- J as createContentletObserver,
185
- j as createPluginLogger,
186
- L as createThrottle,
187
- B as enrichPagePayloadOptimized,
188
- k as extractContentletData,
189
- F as extractContentletIdentifier,
190
- N as extractUTMParameters,
191
- H as findContentlets,
192
- g as generateSecureId,
193
- x as getAnalyticsContext,
194
- O as getDeviceDataForContext,
195
- W as getEnhancedTrackingPlugins,
196
- M as getLocalTime,
180
+ B as INITIAL_SCAN_DELAY_MS,
181
+ k as createContentletObserver,
182
+ H as createPluginLogger,
183
+ b as createThrottle,
184
+ R as enrichPagePayloadOptimized,
185
+ Y as extractContentletData,
186
+ x as extractContentletIdentifier,
187
+ A as extractUTMParameters,
188
+ F as findContentlets,
189
+ l as generateSecureId,
190
+ P as getAnalyticsContext,
191
+ C as getDeviceDataForContext,
192
+ J as getEnhancedTrackingPlugins,
193
+ N as getLocalTime,
197
194
  v as getSessionId,
198
- A as getUserId,
199
- U as isBrowser,
200
- K as setupPluginCleanup,
201
- Y as validateAnalyticsConfig
195
+ I as getUserId,
196
+ M as isBrowser,
197
+ z as setupPluginCleanup,
198
+ $ as validateAnalyticsConfig
202
199
  };
@@ -1,18 +1,18 @@
1
- import { usePathname as u, useSearchParams as c } from "next/navigation";
2
- import { useRef as p, useEffect as m } from "react";
3
- import { getUVEState as s } from "../../../uve/src/lib/core/core.utils.js";
1
+ import { usePathname as s, useSearchParams as u } from "next/navigation";
2
+ import { useRef as c, useEffect as a } from "react";
3
+ import { getUVEState as m } from "../../../uve/src/lib/core/core.utils.js";
4
4
  import "../../../uve/src/internal/constants.js";
5
- const g = (e, t) => `${e}${t != null && t.toString() ? "?" + t.toString() : ""}`;
6
- function A(e, t = !1) {
7
- const o = p(null), n = u(), r = c();
8
- m(() => {
9
- if (!e) return;
5
+ const p = (t, e) => `${t}${e?.toString() ? "?" + e.toString() : ""}`;
6
+ function l(t, e = !1) {
7
+ const r = c(null), o = s(), n = u();
8
+ a(() => {
9
+ if (!t) return;
10
10
  const i = (f) => {
11
- s() || f !== o.current && (o.current = f, e.pageView());
11
+ m() || f !== r.current && (r.current = f, t.pageView());
12
12
  };
13
- t && console.info("DotCMS Analytics [React]: using Next.js App Router tracking"), i(g(n, r));
14
- }, [e, n, r, t]);
13
+ e && console.info("DotCMS Analytics [React]: using Next.js App Router tracking"), i(p(o, n));
14
+ }, [t, o, n, e]);
15
15
  }
16
16
  export {
17
- A as useRouterTracker
17
+ l as useRouterTracker
18
18
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotcms/analytics",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "Official JavaScript library for Content Analytics with DotCMS.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,8 +1,3 @@
1
- import { UVEEventType as t } from "../../../types/src/lib/editor/public.js";
2
- import { onContentletHovered as e, onIframeScroll as o, onRequestBounds as r, onPageReload as E, onContentChanges as _ } from "./events.js";
3
- t.CONTENT_CHANGES + "", t.PAGE_RELOAD + "", t.REQUEST_BOUNDS + "", t.IFRAME_SCROLL + "", t.CONTENTLET_HOVERED + "";
4
- const N = "__dotAnalyticsActive__", T = "__dotAnalyticsCleanup";
5
- export {
6
- N as ANALYTICS_WINDOWS_ACTIVE_KEY,
7
- T as ANALYTICS_WINDOWS_CLEANUP_KEY
8
- };
1
+ import { UVEEventType as n } from "../../../types/src/lib/editor/public.js";
2
+ import { onContentletHovered as r, onIframeScroll as o, onRequestBounds as t, onPageReload as E, onContentChanges as u } from "./events.js";
3
+ n.CONTENT_CHANGES + "", n.PAGE_RELOAD + "", n.REQUEST_BOUNDS + "", n.IFRAME_SCROLL + "", n.CONTENTLET_HOVERED + "";
@@ -1,7 +1,7 @@
1
1
  import { UVEEventType as a } from "../../../types/src/lib/editor/public.js";
2
2
  import { __DOTCMS_UVE_EVENT__ as s } from "../../../types/src/lib/events/internal.js";
3
- import { findDotCMSElement as M, findDotCMSVTLData as p, getClosestDotCMSContainerData as w, getDotCMSPageBounds as S } from "../lib/dom/dom.utils.js";
4
- function U(o) {
3
+ import { findDotCMSElement as u, findDotCMSVTLData as C, getClosestDotCMSContainerData as g, getDotCMSPageBounds as N } from "../lib/dom/dom.utils.js";
4
+ function O(o) {
5
5
  const t = (n) => {
6
6
  n.data.name === s.UVE_SET_PAGE_DATA && o(n.data.payload);
7
7
  };
@@ -12,7 +12,7 @@ function U(o) {
12
12
  event: a.CONTENT_CHANGES
13
13
  };
14
14
  }
15
- function V(o) {
15
+ function p(o) {
16
16
  const t = (n) => {
17
17
  n.data.name === s.UVE_RELOAD_PAGE && o();
18
18
  };
@@ -23,12 +23,12 @@ function V(o) {
23
23
  event: a.PAGE_RELOAD
24
24
  };
25
25
  }
26
- function I(o) {
26
+ function b(o) {
27
27
  const t = (n) => {
28
28
  if (n.data.name === s.UVE_REQUEST_BOUNDS) {
29
29
  const e = Array.from(
30
30
  document.querySelectorAll('[data-dot-object="container"]')
31
- ), i = S(e);
31
+ ), i = N(e);
32
32
  o(i);
33
33
  }
34
34
  };
@@ -39,7 +39,7 @@ function I(o) {
39
39
  event: a.REQUEST_BOUNDS
40
40
  };
41
41
  }
42
- function Y(o) {
42
+ function S(o) {
43
43
  const t = (n) => {
44
44
  if (n.data.name === s.UVE_SCROLL_INSIDE_IFRAME) {
45
45
  const e = n.data.direction;
@@ -53,12 +53,11 @@ function Y(o) {
53
53
  event: a.IFRAME_SCROLL
54
54
  };
55
55
  }
56
- function B(o) {
56
+ function M(o) {
57
57
  const t = (n) => {
58
- var d, r, E, c, T, l, m, _, u, C;
59
- const e = M(n.target);
58
+ const e = u(n.target);
60
59
  if (!e) return;
61
- const { x: i, y: g, width: v, height: N } = e.getBoundingClientRect(), f = ((d = e.dataset) == null ? void 0 : d.dotObject) === "container", L = {
60
+ const { x: i, y: d, width: r, height: E } = e.getBoundingClientRect(), c = e.dataset?.dotObject === "container", T = {
62
61
  identifier: "TEMP_EMPTY_CONTENTLET",
63
62
  title: "TEMP_EMPTY_CONTENTLET",
64
63
  contentType: "TEMP_EMPTY_CONTENTLET_TYPE",
@@ -66,29 +65,32 @@ function B(o) {
66
65
  widgetTitle: "TEMP_EMPTY_CONTENTLET",
67
66
  baseType: "TEMP_EMPTY_CONTENTLET",
68
67
  onNumberOfPages: 1
69
- }, P = {
70
- identifier: (r = e.dataset) == null ? void 0 : r.dotIdentifier,
71
- title: (E = e.dataset) == null ? void 0 : E.dotTitle,
72
- inode: (c = e.dataset) == null ? void 0 : c.dotInode,
73
- contentType: (T = e.dataset) == null ? void 0 : T.dotType,
74
- baseType: (l = e.dataset) == null ? void 0 : l.dotBasetype,
75
- widgetTitle: (m = e.dataset) == null ? void 0 : m.dotWidgetTitle,
76
- onNumberOfPages: (_ = e.dataset) == null ? void 0 : _.dotOnNumberOfPages
77
- }, O = p(e), b = {
68
+ }, l = {
69
+ identifier: e.dataset?.dotIdentifier,
70
+ title: e.dataset?.dotTitle,
71
+ inode: e.dataset?.dotInode,
72
+ contentType: e.dataset?.dotType,
73
+ baseType: e.dataset?.dotBasetype,
74
+ widgetTitle: e.dataset?.dotWidgetTitle,
75
+ onNumberOfPages: e.dataset?.dotOnNumberOfPages,
76
+ ...e.dataset?.dotStyleProperties && {
77
+ dotStyleProperties: JSON.parse(e.dataset.dotStyleProperties)
78
+ }
79
+ }, m = C(e), _ = {
78
80
  container: (
79
81
  // Here extract dot-container from contentlet if it is Headless
80
82
  // or search in parent container if it is VTL
81
- (u = e.dataset) != null && u.dotContainer ? JSON.parse((C = e.dataset) == null ? void 0 : C.dotContainer) : w(e)
83
+ e.dataset?.dotContainer ? JSON.parse(e.dataset?.dotContainer) : g(e)
82
84
  ),
83
- contentlet: f ? L : P,
84
- vtlFiles: O
85
+ contentlet: c ? T : l,
86
+ vtlFiles: m
85
87
  };
86
88
  o({
87
89
  x: i,
88
- y: g,
89
- width: v,
90
- height: N,
91
- payload: b
90
+ y: d,
91
+ width: r,
92
+ height: E,
93
+ payload: _
92
94
  });
93
95
  };
94
96
  return document.addEventListener("pointermove", t), {
@@ -99,9 +101,9 @@ function B(o) {
99
101
  };
100
102
  }
101
103
  export {
102
- U as onContentChanges,
103
- B as onContentletHovered,
104
- Y as onIframeScroll,
105
- V as onPageReload,
106
- I as onRequestBounds
104
+ O as onContentChanges,
105
+ M as onContentletHovered,
106
+ S as onIframeScroll,
107
+ p as onPageReload,
108
+ b as onRequestBounds
107
109
  };
@@ -1,80 +1,74 @@
1
1
  import "../../internal/constants.js";
2
- function C(t) {
3
- return t.map((a) => {
4
- const o = a.getBoundingClientRect(), n = Array.from(
5
- a.querySelectorAll('[data-dot-object="contentlet"]')
2
+ function c(t) {
3
+ return t.map((n) => {
4
+ const e = n.getBoundingClientRect(), o = Array.from(
5
+ n.querySelectorAll('[data-dot-object="contentlet"]')
6
6
  );
7
7
  return {
8
- x: o.x,
9
- y: o.y,
10
- width: o.width,
11
- height: o.height,
8
+ x: e.x,
9
+ y: e.y,
10
+ width: e.width,
11
+ height: e.height,
12
12
  payload: JSON.stringify({
13
- container: u(a)
13
+ container: a(n)
14
14
  }),
15
- contentlets: f(o, n)
15
+ contentlets: d(e, o)
16
16
  };
17
17
  });
18
18
  }
19
- function f(t, a) {
20
- return a.map((o) => {
21
- var d, r, i, e, s, c;
22
- const n = o.getBoundingClientRect();
19
+ function d(t, n) {
20
+ return n.map((e) => {
21
+ const o = e.getBoundingClientRect();
23
22
  return {
24
23
  x: 0,
25
- y: n.y - t.y,
26
- width: n.width,
27
- height: n.height,
24
+ y: o.y - t.y,
25
+ width: o.width,
26
+ height: o.height,
28
27
  payload: JSON.stringify({
29
- container: (d = o.dataset) != null && d.dotContainer ? JSON.parse((r = o.dataset) == null ? void 0 : r.dotContainer) : y(o),
28
+ container: e.dataset?.dotContainer ? JSON.parse(e.dataset?.dotContainer) : r(e),
30
29
  contentlet: {
31
- identifier: (i = o.dataset) == null ? void 0 : i.dotIdentifier,
32
- title: (e = o.dataset) == null ? void 0 : e.dotTitle,
33
- inode: (s = o.dataset) == null ? void 0 : s.dotInode,
34
- contentType: (c = o.dataset) == null ? void 0 : c.dotType
30
+ identifier: e.dataset?.dotIdentifier,
31
+ title: e.dataset?.dotTitle,
32
+ inode: e.dataset?.dotInode,
33
+ contentType: e.dataset?.dotType
35
34
  }
36
35
  })
37
36
  };
38
37
  });
39
38
  }
40
- function u(t) {
41
- var a, o, n, d;
39
+ function a(t) {
42
40
  return {
43
- acceptTypes: ((a = t.dataset) == null ? void 0 : a.dotAcceptTypes) || "",
44
- identifier: ((o = t.dataset) == null ? void 0 : o.dotIdentifier) || "",
45
- maxContentlets: ((n = t.dataset) == null ? void 0 : n.maxContentlets) || "",
46
- uuid: ((d = t.dataset) == null ? void 0 : d.dotUuid) || ""
41
+ acceptTypes: t.dataset?.dotAcceptTypes || "",
42
+ identifier: t.dataset?.dotIdentifier || "",
43
+ maxContentlets: t.dataset?.maxContentlets || "",
44
+ uuid: t.dataset?.dotUuid || ""
47
45
  };
48
46
  }
49
- function y(t) {
50
- const a = t.closest('[data-dot-object="container"]');
51
- return a ? u(a) : (console.warn("No container found for the contentlet"), null);
47
+ function r(t) {
48
+ const n = t.closest('[data-dot-object="container"]');
49
+ return n ? a(n) : (console.warn("No container found for the contentlet"), null);
52
50
  }
53
- function g(t) {
54
- var o, n, d;
51
+ function i(t) {
55
52
  if (!t) return null;
56
- const a = t.querySelector('[data-dot-object="empty-content"]');
57
- return ((o = t == null ? void 0 : t.dataset) == null ? void 0 : o.dotObject) === "contentlet" || // The container inside Headless components have a span with the data-dot-object="container" attribute
58
- ((n = t == null ? void 0 : t.dataset) == null ? void 0 : n.dotObject) === "container" && a || // The container inside Traditional have no content inside
59
- ((d = t == null ? void 0 : t.dataset) == null ? void 0 : d.dotObject) === "container" && t.children.length === 0 ? t : g(t == null ? void 0 : t.parentElement);
53
+ const n = t.querySelector('[data-dot-object="empty-content"]');
54
+ return t?.dataset?.dotObject === "contentlet" || // The container inside Headless components have a span with the data-dot-object="container" attribute
55
+ t?.dataset?.dotObject === "container" && n || // The container inside Traditional have no content inside
56
+ t?.dataset?.dotObject === "container" && t.children.length === 0 ? t : i(t?.parentElement);
60
57
  }
61
- function h(t) {
62
- const a = t.querySelectorAll(
58
+ function u(t) {
59
+ const n = t.querySelectorAll(
63
60
  '[data-dot-object="vtl-file"]'
64
61
  );
65
- return a.length ? Array.from(a).map((o) => {
66
- var n, d;
67
- return {
68
- inode: (n = o.dataset) == null ? void 0 : n.dotInode,
69
- name: (d = o.dataset) == null ? void 0 : d.dotUrl
70
- };
71
- }) : null;
62
+ return n.length ? Array.from(n).map((e) => ({
63
+ inode: e.dataset?.dotInode,
64
+ name: e.dataset?.dotUrl
65
+ })) : null;
72
66
  }
73
67
  export {
74
- g as findDotCMSElement,
75
- h as findDotCMSVTLData,
76
- y as getClosestDotCMSContainerData,
77
- u as getDotCMSContainerData,
78
- f as getDotCMSContentletsBound,
79
- C as getDotCMSPageBounds
68
+ i as findDotCMSElement,
69
+ u as findDotCMSVTLData,
70
+ r as getClosestDotCMSContainerData,
71
+ a as getDotCMSContainerData,
72
+ d as getDotCMSContentletsBound,
73
+ c as getDotCMSPageBounds
80
74
  };