@dotcms/analytics 1.2.0 → 1.2.1
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 +314 -9
- package/lib/core/dot-analytics.content.js +84 -0
- package/lib/core/plugin/click/dot-analytics.click-tracker.d.ts +108 -0
- package/lib/core/plugin/click/dot-analytics.click-tracker.js +144 -0
- package/lib/core/plugin/click/dot-analytics.click.plugin.d.ts +36 -0
- package/lib/core/plugin/click/dot-analytics.click.plugin.js +27 -0
- package/lib/core/plugin/click/dot-analytics.click.utils.d.ts +12 -0
- package/lib/core/plugin/click/dot-analytics.click.utils.js +55 -0
- package/lib/core/plugin/enricher/dot-analytics.enricher.plugin.d.ts +14 -10
- package/lib/core/plugin/enricher/dot-analytics.enricher.plugin.js +26 -38
- package/lib/core/{shared/dot-content-analytics.activity-tracker.d.ts → plugin/identity/dot-analytics.identity.activity-tracker.d.ts} +2 -17
- package/lib/core/{shared/dot-content-analytics.activity-tracker.js → plugin/identity/dot-analytics.identity.activity-tracker.js} +17 -37
- package/lib/core/plugin/identity/dot-analytics.identity.plugin.d.ts +2 -20
- package/lib/core/plugin/identity/dot-analytics.identity.plugin.js +7 -7
- package/lib/core/plugin/identity/dot-analytics.identity.utils.d.ts +0 -16
- package/lib/core/plugin/impression/dot-analytics.impression-tracker.d.ts +62 -0
- package/lib/core/plugin/impression/dot-analytics.impression-tracker.js +202 -0
- package/lib/core/plugin/impression/dot-analytics.impression.plugin.d.ts +40 -0
- package/lib/core/plugin/impression/dot-analytics.impression.plugin.js +27 -0
- package/lib/core/plugin/impression/dot-analytics.impression.utils.d.ts +26 -0
- package/lib/core/plugin/impression/dot-analytics.impression.utils.js +27 -0
- package/lib/core/plugin/impression/index.d.ts +2 -0
- package/lib/core/plugin/main/dot-analytics.plugin.d.ts +46 -0
- package/lib/core/plugin/main/dot-analytics.plugin.js +129 -0
- package/lib/core/shared/constants/{dot-content-analytics.constants.d.ts → dot-analytics.constants.d.ts} +62 -0
- package/lib/core/shared/constants/dot-analytics.constants.js +53 -0
- package/lib/core/shared/constants/index.d.ts +1 -1
- package/lib/core/shared/dot-analytics.logger.d.ts +85 -0
- package/lib/core/shared/dot-analytics.logger.js +90 -0
- package/lib/core/shared/http/dot-analytics.http.d.ts +9 -0
- package/lib/core/shared/http/dot-analytics.http.js +34 -0
- package/lib/core/shared/models/data.model.d.ts +39 -1
- package/lib/core/shared/models/event.model.d.ts +108 -3
- package/lib/core/shared/models/library.model.d.ts +89 -28
- package/lib/core/shared/models/request.model.d.ts +17 -9
- package/lib/core/shared/queue/dot-analytics.queue.utils.js +44 -37
- package/lib/core/shared/{dot-content-analytics.utils.d.ts → utils/dot-analytics.utils.d.ts} +91 -3
- package/lib/core/shared/utils/dot-analytics.utils.js +202 -0
- package/lib/react/hook/useContentAnalytics.js +17 -11
- package/lib/react/hook/useRouterTracker.js +4 -4
- package/lib/react/internal/utils.js +1 -1
- package/package.json +7 -6
- package/lib/core/dot-content-analytics.js +0 -46
- package/lib/core/plugin/dot-analytics.plugin.d.ts +0 -33
- package/lib/core/plugin/dot-analytics.plugin.js +0 -42
- package/lib/core/shared/constants/dot-content-analytics.constants.js +0 -34
- package/lib/core/shared/dot-content-analytics.http.d.ts +0 -17
- package/lib/core/shared/dot-content-analytics.http.js +0 -41
- package/lib/core/shared/dot-content-analytics.utils.js +0 -147
- /package/lib/core/{dot-content-analytics.d.ts → dot-analytics.content.d.ts} +0 -0
|
@@ -1,40 +1,51 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import m from "@analytics/queue-utils";
|
|
2
|
+
import v from "@analytics/router-utils";
|
|
3
|
+
import { DEFAULT_QUEUE_CONFIG as y } from "../constants/dot-analytics.constants.js";
|
|
4
|
+
import { sendAnalyticsEvent as b } from "../http/dot-analytics.http.js";
|
|
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 : "";
|
|
9
|
+
const a = {
|
|
10
|
+
...y,
|
|
11
|
+
...typeof o.queue == "object" ? o.queue : {}
|
|
12
|
+
}, g = (t, s) => {
|
|
13
|
+
if (!n) return;
|
|
14
|
+
i.debug(`Sending batch of ${t.length} event(s)`, {
|
|
12
15
|
events: t,
|
|
13
|
-
|
|
14
|
-
}),
|
|
15
|
-
},
|
|
16
|
-
!e || e.size() === 0 || !
|
|
17
|
-
|
|
18
|
-
),
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
keepalive: u
|
|
17
|
+
}), b({ context: n, events: t }, o, u);
|
|
18
|
+
}, l = () => {
|
|
19
|
+
!e || e.size() === 0 || !n || (i.info(`Flushing ${e.size()} events (page hidden/unload)`), u = !0, e.flush(!0));
|
|
20
|
+
}, c = () => {
|
|
21
|
+
if (i.debug("handleVisibilityChange", document.visibilityState), document.visibilityState === "hidden") {
|
|
22
|
+
if (d) {
|
|
23
|
+
i.debug("Skipping flush (SPA navigation detected)");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
l();
|
|
27
|
+
} else document.visibilityState === "visible" && (d = !1);
|
|
21
28
|
};
|
|
22
29
|
return {
|
|
23
30
|
/**
|
|
24
31
|
* Initialize the queue with smart batching
|
|
25
32
|
*/
|
|
26
33
|
initialize: () => {
|
|
27
|
-
e =
|
|
28
|
-
(t) => {
|
|
29
|
-
|
|
34
|
+
e = m(
|
|
35
|
+
(t, s) => {
|
|
36
|
+
g(t);
|
|
30
37
|
},
|
|
31
38
|
{
|
|
32
|
-
max:
|
|
33
|
-
interval:
|
|
39
|
+
max: a.eventBatchSize,
|
|
40
|
+
interval: a.flushInterval,
|
|
34
41
|
throttle: !1
|
|
35
42
|
// Always false - enables both batch size and interval triggers
|
|
36
43
|
}
|
|
37
|
-
), typeof window < "u" && typeof document < "u" && (document.addEventListener("visibilitychange",
|
|
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(() => {
|
|
46
|
+
d = !1;
|
|
47
|
+
}, 100);
|
|
48
|
+
}));
|
|
38
49
|
},
|
|
39
50
|
/**
|
|
40
51
|
* Add event to queue
|
|
@@ -43,16 +54,12 @@ const z = (n) => {
|
|
|
43
54
|
* - Sends pending events every flushInterval
|
|
44
55
|
*/
|
|
45
56
|
enqueue: (t, s) => {
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
e.push(t);
|
|
55
|
-
}
|
|
57
|
+
if (n = s, !e) return;
|
|
58
|
+
const r = e.size() + 1, p = a.eventBatchSize, h = r >= p;
|
|
59
|
+
i.debug(
|
|
60
|
+
`Event added. Queue size: ${r}/${p}${h ? " (full, sending...)" : ""}`,
|
|
61
|
+
{ eventType: t.event_type, event: t }
|
|
62
|
+
), e.push(t);
|
|
56
63
|
},
|
|
57
64
|
/**
|
|
58
65
|
* Get queue size for debugging
|
|
@@ -64,10 +71,10 @@ const z = (n) => {
|
|
|
64
71
|
* Flushes remaining events and cleans up listeners
|
|
65
72
|
*/
|
|
66
73
|
cleanup: () => {
|
|
67
|
-
|
|
74
|
+
l(), typeof window < "u" && typeof document < "u" && (document.removeEventListener("visibilitychange", c), window.removeEventListener("pagehide", l)), e = null, n = null, u = !1;
|
|
68
75
|
}
|
|
69
76
|
};
|
|
70
77
|
};
|
|
71
78
|
export {
|
|
72
|
-
|
|
79
|
+
L as createAnalyticsQueue
|
|
73
80
|
};
|
|
@@ -1,6 +1,27 @@
|
|
|
1
|
-
import { PageData } from 'analytics';
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { AnalyticsPlugin, PageData } from 'analytics';
|
|
2
|
+
import { DotCMSPredefinedEventType } from '../constants';
|
|
3
|
+
import { DotLogger, LogLevel } from '../dot-analytics.logger';
|
|
4
|
+
import { AnalyticsBasePayloadWithContext, ContentletData, DotCMSAnalyticsConfig, DotCMSAnalyticsEventContext, DotCMSBrowserData, DotCMSEventDeviceData, DotCMSEventUtmData, EnrichedAnalyticsPayload } from '../models';
|
|
5
|
+
export { cleanupActivityTracking, initializeActivityTracking, updateSessionActivity } from '../../plugin/identity/dot-analytics.identity.activity-tracker';
|
|
6
|
+
/**
|
|
7
|
+
* Type guard to check if an event is a predefined event type.
|
|
8
|
+
* Enables TypeScript type narrowing for better type safety.
|
|
9
|
+
*
|
|
10
|
+
* @param event - Event name to check
|
|
11
|
+
* @returns True if event is a predefined type, false for custom events
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* if (isPredefinedEventType(eventName)) {
|
|
16
|
+
* // TypeScript knows eventName is DotCMSPredefinedEventType here
|
|
17
|
+
* console.log('Predefined event:', eventName);
|
|
18
|
+
* } else {
|
|
19
|
+
* // TypeScript knows eventName is string (custom) here
|
|
20
|
+
* console.log('Custom event:', eventName);
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function isPredefinedEventType(event: string): event is DotCMSPredefinedEventType;
|
|
4
25
|
/**
|
|
5
26
|
* Validates required configuration fields for Analytics initialization.
|
|
6
27
|
*
|
|
@@ -170,3 +191,70 @@ export declare const enrichPagePayload: (payload: {
|
|
|
170
191
|
properties: Record<string, unknown>;
|
|
171
192
|
};
|
|
172
193
|
};
|
|
194
|
+
/**
|
|
195
|
+
* Creates a throttled version of a callback function
|
|
196
|
+
* Ensures the callback is executed at most once every `limitMs` milliseconds
|
|
197
|
+
* @param callback - The function to throttle
|
|
198
|
+
* @param limitMs - The time limit in milliseconds
|
|
199
|
+
* @returns A throttled function
|
|
200
|
+
*/
|
|
201
|
+
export declare function createThrottle<T extends (...args: unknown[]) => void>(callback: T, limitMs: number): (...args: Parameters<T>) => void;
|
|
202
|
+
/**
|
|
203
|
+
* Extracts the contentlet identifier from a DOM element
|
|
204
|
+
* @param element - The HTML element containing data attributes
|
|
205
|
+
* @returns The contentlet identifier or null if not found
|
|
206
|
+
*/
|
|
207
|
+
export declare function extractContentletIdentifier(element: HTMLElement): string | null;
|
|
208
|
+
/**
|
|
209
|
+
* Extracts all contentlet data from a DOM element's data attributes
|
|
210
|
+
* @param element - The HTML element containing data attributes
|
|
211
|
+
* @returns Complete contentlet data object
|
|
212
|
+
*/
|
|
213
|
+
export declare function extractContentletData(element: HTMLElement): ContentletData;
|
|
214
|
+
/**
|
|
215
|
+
* Initial scan delay for DOM readiness
|
|
216
|
+
* Allows React/Next.js to finish rendering before scanning for contentlets
|
|
217
|
+
*/
|
|
218
|
+
export declare const INITIAL_SCAN_DELAY_MS = 100;
|
|
219
|
+
/**
|
|
220
|
+
* Checks if code is running in a browser environment
|
|
221
|
+
* @returns true if window and document are available
|
|
222
|
+
*/
|
|
223
|
+
export declare const isBrowser: () => boolean;
|
|
224
|
+
/**
|
|
225
|
+
* Finds all contentlet elements in the DOM
|
|
226
|
+
* @returns Array of contentlet HTMLElements
|
|
227
|
+
*/
|
|
228
|
+
export declare const findContentlets: () => HTMLElement[];
|
|
229
|
+
/**
|
|
230
|
+
* Creates a MutationObserver that watches for contentlet changes in the DOM
|
|
231
|
+
* @param callback - Function to call when mutations are detected
|
|
232
|
+
* @param debounceMs - Debounce time in milliseconds (default: 250ms)
|
|
233
|
+
* @returns Configured and active MutationObserver
|
|
234
|
+
*/
|
|
235
|
+
export declare const createContentletObserver: (callback: () => void, debounceMs?: number) => MutationObserver;
|
|
236
|
+
/**
|
|
237
|
+
* Sets up cleanup handlers for page unload events
|
|
238
|
+
* Registers cleanup function to both 'beforeunload' and 'pagehide' for maximum compatibility
|
|
239
|
+
* @param cleanup - Function to call on page unload
|
|
240
|
+
*/
|
|
241
|
+
export declare const setupPluginCleanup: (cleanup: () => void) => void;
|
|
242
|
+
/**
|
|
243
|
+
* Creates a logger with plugin-specific prefix and configurable log level
|
|
244
|
+
* @param pluginName - Name of the plugin (e.g., 'Click', 'Impression')
|
|
245
|
+
* @param config - Analytics configuration with debug flag and optional logLevel
|
|
246
|
+
* @returns DotLogger instance with configured log level
|
|
247
|
+
*/
|
|
248
|
+
export declare const createPluginLogger: (pluginName: string, config: {
|
|
249
|
+
debug: boolean;
|
|
250
|
+
logLevel?: LogLevel;
|
|
251
|
+
}) => DotLogger;
|
|
252
|
+
/**
|
|
253
|
+
* Gets enhanced tracking plugins based on configuration
|
|
254
|
+
* Returns content impression and click tracking plugins if enabled
|
|
255
|
+
* @param config - Analytics configuration
|
|
256
|
+
* @param impressionPlugin - Impression tracking plugin factory
|
|
257
|
+
* @param clickPlugin - Click tracking plugin factory
|
|
258
|
+
* @returns Array of enabled tracking plugins
|
|
259
|
+
*/
|
|
260
|
+
export declare const getEnhancedTrackingPlugins: (config: DotCMSAnalyticsConfig, impressionPlugin: (config: DotCMSAnalyticsConfig) => AnalyticsPlugin, clickPlugin: (config: DotCMSAnalyticsConfig) => AnalyticsPlugin) => AnalyticsPlugin[];
|
|
@@ -0,0 +1,202 @@
|
|
|
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";
|
|
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;
|
|
6
|
+
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;
|
|
8
|
+
}
|
|
9
|
+
let u = null, l = null;
|
|
10
|
+
const g = (t) => {
|
|
11
|
+
const e = Date.now(), n = Math.random().toString(36).substr(2, 9), s = Math.random().toString(36).substr(2, 9);
|
|
12
|
+
return `${t}_${e}_${n}${s}`;
|
|
13
|
+
}, _ = {
|
|
14
|
+
getItem: (t) => {
|
|
15
|
+
try {
|
|
16
|
+
return localStorage.getItem(t);
|
|
17
|
+
} catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
setItem: (t, e) => {
|
|
22
|
+
try {
|
|
23
|
+
localStorage.setItem(t, e);
|
|
24
|
+
} catch {
|
|
25
|
+
console.warn(`DotCMS Analytics [Core]: Could not save ${t} to localStorage`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}, A = () => {
|
|
29
|
+
let t = _.getItem(w);
|
|
30
|
+
return t || (t = g("user"), _.setItem(w, t)), t;
|
|
31
|
+
}, C = (t) => {
|
|
32
|
+
const e = new Date(t), n = /* @__PURE__ */ new Date(), s = new Date(
|
|
33
|
+
e.getUTCFullYear(),
|
|
34
|
+
e.getUTCMonth(),
|
|
35
|
+
e.getUTCDate()
|
|
36
|
+
), r = new Date(n.getUTCFullYear(), n.getUTCMonth(), n.getUTCDate());
|
|
37
|
+
return s.getTime() !== r.getTime();
|
|
38
|
+
}, v = () => {
|
|
39
|
+
const t = Date.now();
|
|
40
|
+
if (typeof window > "u")
|
|
41
|
+
return g("session_fallback");
|
|
42
|
+
try {
|
|
43
|
+
const e = sessionStorage.getItem(h);
|
|
44
|
+
if (e) {
|
|
45
|
+
const { sessionId: r, startTime: o, lastActivity: a } = JSON.parse(e), i = !C(o), c = t - a < y * 60 * 1e3;
|
|
46
|
+
if (i && c)
|
|
47
|
+
return sessionStorage.setItem(
|
|
48
|
+
h,
|
|
49
|
+
JSON.stringify({
|
|
50
|
+
sessionId: r,
|
|
51
|
+
startTime: o,
|
|
52
|
+
lastActivity: t
|
|
53
|
+
})
|
|
54
|
+
), r;
|
|
55
|
+
}
|
|
56
|
+
const n = g("session"), s = {
|
|
57
|
+
sessionId: n,
|
|
58
|
+
startTime: t,
|
|
59
|
+
lastActivity: t
|
|
60
|
+
};
|
|
61
|
+
return sessionStorage.setItem(h, JSON.stringify(s)), n;
|
|
62
|
+
} catch {
|
|
63
|
+
return g("session_fallback");
|
|
64
|
+
}
|
|
65
|
+
}, x = (t) => {
|
|
66
|
+
const e = v(), n = A(), s = O();
|
|
67
|
+
return {
|
|
68
|
+
site_auth: t.siteAuth,
|
|
69
|
+
session_id: e,
|
|
70
|
+
user_id: n,
|
|
71
|
+
device: s
|
|
72
|
+
};
|
|
73
|
+
}, p = () => u || (u = {
|
|
74
|
+
user_language: navigator.language,
|
|
75
|
+
doc_encoding: document.characterSet || document.charset,
|
|
76
|
+
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;
|
|
79
|
+
return {
|
|
80
|
+
screen_resolution: t.screen_resolution ?? "",
|
|
81
|
+
language: t.user_language ?? "",
|
|
82
|
+
viewport_width: String(e),
|
|
83
|
+
viewport_height: String(n)
|
|
84
|
+
};
|
|
85
|
+
}, N = (t) => {
|
|
86
|
+
const e = t.search;
|
|
87
|
+
if (l && l.search === e)
|
|
88
|
+
return l.params;
|
|
89
|
+
const n = new URLSearchParams(e), s = {};
|
|
90
|
+
return D.forEach((r) => {
|
|
91
|
+
const o = n.get(r);
|
|
92
|
+
if (o) {
|
|
93
|
+
const a = r.replace("utm_", "");
|
|
94
|
+
s[a] = o;
|
|
95
|
+
}
|
|
96
|
+
}), l = { search: e, params: s }, s;
|
|
97
|
+
}, b = () => {
|
|
98
|
+
try {
|
|
99
|
+
const t = (/* @__PURE__ */ new Date()).getTimezoneOffset(), e = t > 0 ? "-" : "+", n = Math.abs(t), s = Math.floor(n / 60), r = n % 60;
|
|
100
|
+
return `${e}${s.toString().padStart(2, "0")}:${r.toString().padStart(2, "0")}`;
|
|
101
|
+
} catch {
|
|
102
|
+
return "+00:00";
|
|
103
|
+
}
|
|
104
|
+
}, M = () => {
|
|
105
|
+
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");
|
|
107
|
+
return `${n}-${s}-${r}T${o}:${a}:${i}${e}`;
|
|
108
|
+
} catch {
|
|
109
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
110
|
+
}
|
|
111
|
+
}, B = (t, e = typeof window < "u" ? window.location : {}) => {
|
|
112
|
+
const n = M(), s = p(), { properties: r } = t, o = {};
|
|
113
|
+
Object.keys(r).forEach((c) => {
|
|
114
|
+
T.includes(c) || (o[c] = r[c]);
|
|
115
|
+
});
|
|
116
|
+
const a = {
|
|
117
|
+
url: e.href,
|
|
118
|
+
doc_encoding: s.doc_encoding,
|
|
119
|
+
doc_hash: e.hash,
|
|
120
|
+
doc_protocol: e.protocol,
|
|
121
|
+
doc_search: e.search,
|
|
122
|
+
doc_host: e.hostname,
|
|
123
|
+
doc_path: e.pathname,
|
|
124
|
+
title: r.title ?? (document == null ? void 0 : document.title)
|
|
125
|
+
}, i = N(e);
|
|
126
|
+
return {
|
|
127
|
+
...t,
|
|
128
|
+
page: a,
|
|
129
|
+
...Object.keys(i).length > 0 && { utm: i },
|
|
130
|
+
// Only include custom if there are user-provided properties
|
|
131
|
+
...Object.keys(o).length > 0 && { custom: o },
|
|
132
|
+
local_time: n
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
function L(t, e) {
|
|
136
|
+
let n = 0;
|
|
137
|
+
return (...s) => {
|
|
138
|
+
const r = Date.now();
|
|
139
|
+
r - n >= e && (t(...s), n = r);
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function F(t) {
|
|
143
|
+
return t.dataset.dotAnalyticsIdentifier || null;
|
|
144
|
+
}
|
|
145
|
+
function k(t) {
|
|
146
|
+
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 || ""
|
|
152
|
+
};
|
|
153
|
+
}
|
|
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) => {
|
|
156
|
+
r.some((a) => a.addedNodes.length === 0 && a.removedNodes.length === 0 ? !1 : [
|
|
157
|
+
...Array.from(a.addedNodes),
|
|
158
|
+
...Array.from(a.removedNodes)
|
|
159
|
+
].some((c) => {
|
|
160
|
+
var f, m;
|
|
161
|
+
if (c.nodeType !== Node.ELEMENT_NODE)
|
|
162
|
+
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;
|
|
165
|
+
})) && n();
|
|
166
|
+
});
|
|
167
|
+
return s.observe(document.body, {
|
|
168
|
+
childList: !0,
|
|
169
|
+
subtree: !0,
|
|
170
|
+
attributes: !1,
|
|
171
|
+
characterData: !1
|
|
172
|
+
}), s;
|
|
173
|
+
}, K = (t) => {
|
|
174
|
+
U() && (window.addEventListener("beforeunload", t), window.addEventListener("pagehide", t));
|
|
175
|
+
}, j = (t, e) => {
|
|
176
|
+
const n = e.logLevel ?? (e.debug ? "debug" : "warn");
|
|
177
|
+
return new E("Analytics", t, n);
|
|
178
|
+
}, W = (t, e, n) => [
|
|
179
|
+
t.impressions && e(t),
|
|
180
|
+
t.clicks && n(t)
|
|
181
|
+
].filter(Boolean);
|
|
182
|
+
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,
|
|
197
|
+
v as getSessionId,
|
|
198
|
+
A as getUserId,
|
|
199
|
+
U as isBrowser,
|
|
200
|
+
K as setupPluginCleanup,
|
|
201
|
+
Y as validateAnalyticsConfig
|
|
202
|
+
};
|
|
@@ -1,27 +1,33 @@
|
|
|
1
|
-
import { useMemo as
|
|
2
|
-
import { getUVEState as
|
|
1
|
+
import { useMemo as s, useCallback as o } from "react";
|
|
2
|
+
import { getUVEState as l } from "../../../uve/src/lib/core/core.utils.js";
|
|
3
3
|
import "../../../uve/src/internal/constants.js";
|
|
4
|
-
import { initializeAnalytics as
|
|
5
|
-
const h = (
|
|
6
|
-
const t =
|
|
4
|
+
import { initializeAnalytics as m } from "../internal/utils.js";
|
|
5
|
+
const h = (i) => {
|
|
6
|
+
const t = s(() => m(i), [i.server, i.siteAuth]), e = s(() => !!l(), []);
|
|
7
7
|
if (!t)
|
|
8
8
|
throw new Error(
|
|
9
9
|
"DotCMS Analytics: Failed to initialize. Please verify the required configuration (server and siteAuth)."
|
|
10
10
|
);
|
|
11
11
|
const a = o(
|
|
12
|
-
(
|
|
13
|
-
e || t.track(
|
|
12
|
+
(r, n = {}) => {
|
|
13
|
+
e || t.track(r, n);
|
|
14
14
|
},
|
|
15
15
|
[t, e]
|
|
16
|
-
),
|
|
17
|
-
(
|
|
18
|
-
e || t.pageView(
|
|
16
|
+
), c = o(
|
|
17
|
+
(r = {}) => {
|
|
18
|
+
e || t.pageView(r);
|
|
19
|
+
},
|
|
20
|
+
[t, e]
|
|
21
|
+
), u = o(
|
|
22
|
+
(r, n = {}) => {
|
|
23
|
+
e || t.conversion(r, n);
|
|
19
24
|
},
|
|
20
25
|
[t, e]
|
|
21
26
|
);
|
|
22
27
|
return {
|
|
23
28
|
track: a,
|
|
24
|
-
pageView:
|
|
29
|
+
pageView: c,
|
|
30
|
+
conversion: u
|
|
25
31
|
};
|
|
26
32
|
};
|
|
27
33
|
export {
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { usePathname as u, useSearchParams as
|
|
2
|
-
import { useRef as
|
|
1
|
+
import { usePathname as u, useSearchParams as c } from "next/navigation";
|
|
2
|
+
import { useRef as p, useEffect as m } from "react";
|
|
3
3
|
import { getUVEState as s } from "../../../uve/src/lib/core/core.utils.js";
|
|
4
4
|
import "../../../uve/src/internal/constants.js";
|
|
5
5
|
const g = (e, t) => `${e}${t != null && t.toString() ? "?" + t.toString() : ""}`;
|
|
6
6
|
function A(e, t = !1) {
|
|
7
|
-
const o =
|
|
7
|
+
const o = p(null), n = u(), r = c();
|
|
8
8
|
m(() => {
|
|
9
9
|
if (!e) return;
|
|
10
10
|
const i = (f) => {
|
|
11
11
|
s() || f !== o.current && (o.current = f, e.pageView());
|
|
12
12
|
};
|
|
13
|
-
t && console.info("
|
|
13
|
+
t && console.info("DotCMS Analytics [React]: using Next.js App Router tracking"), i(g(n, r));
|
|
14
14
|
}, [e, n, r, t]);
|
|
15
15
|
}
|
|
16
16
|
export {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { initializeContentAnalytics as r } from "../../core/dot-
|
|
1
|
+
import { initializeContentAnalytics as r } from "../../core/dot-analytics.content.js";
|
|
2
2
|
let t, i;
|
|
3
3
|
const s = (e) => (i && (i.server !== e.server || i.siteAuth !== e.siteAuth) && (t = void 0), t !== void 0 || (i = e, t = r(e)), t);
|
|
4
4
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dotcms/analytics",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Official JavaScript library for Content Analytics with DotCMS.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -20,20 +20,21 @@
|
|
|
20
20
|
},
|
|
21
21
|
"homepage": "https://github.com/dotCMS/core/tree/main/core-web/libs/sdk/analytics/README.md",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"analytics": "^0.8.0",
|
|
24
23
|
"@analytics/core": "^0.13.0",
|
|
25
|
-
"@analytics/storage-utils": "^0.4.0",
|
|
26
24
|
"@analytics/queue-utils": "^0.1.3",
|
|
27
|
-
"@
|
|
25
|
+
"@analytics/router-utils": "^0.1.1",
|
|
26
|
+
"@analytics/storage-utils": "^0.4.0",
|
|
27
|
+
"@dotcms/uve": "latest",
|
|
28
|
+
"analytics": "^0.8.0"
|
|
28
29
|
},
|
|
29
30
|
"peerDependencies": {
|
|
30
31
|
"react": "^18 || ^19"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
34
|
+
"@dotcms/types": "latest",
|
|
33
35
|
"@testing-library/jest-dom": "^6.1.6",
|
|
34
36
|
"@testing-library/react": "^14.0.0",
|
|
35
|
-
"vite": "~5.0.0"
|
|
36
|
-
"@dotcms/types": "latest"
|
|
37
|
+
"vite": "~5.0.0"
|
|
37
38
|
},
|
|
38
39
|
"main": "./index.js",
|
|
39
40
|
"module": "./index.js",
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { Analytics as a } from "analytics";
|
|
2
|
-
import { ANALYTICS_WINDOWS_ACTIVE_KEY as r, ANALYTICS_WINDOWS_CLEANUP_KEY as s } from "../../uve/src/internal/constants.js";
|
|
3
|
-
import { dotAnalytics as l } from "./plugin/dot-analytics.plugin.js";
|
|
4
|
-
import { dotAnalyticsEnricherPlugin as c } from "./plugin/enricher/dot-analytics.enricher.plugin.js";
|
|
5
|
-
import { dotAnalyticsIdentityPlugin as p } from "./plugin/identity/dot-analytics.identity.plugin.js";
|
|
6
|
-
import { validateAnalyticsConfig as m } from "./shared/dot-content-analytics.utils.js";
|
|
7
|
-
import { cleanupActivityTracking as u } from "./shared/dot-content-analytics.activity-tracker.js";
|
|
8
|
-
const I = (n) => {
|
|
9
|
-
const o = m(n);
|
|
10
|
-
if (o)
|
|
11
|
-
return console.error(`DotCMS Analytics: Missing ${o.join(" and ")} in configuration`), typeof window < "u" && (window[r] = !1), null;
|
|
12
|
-
const i = a({
|
|
13
|
-
app: "dotAnalytics",
|
|
14
|
-
debug: n.debug,
|
|
15
|
-
plugins: [
|
|
16
|
-
p(n),
|
|
17
|
-
// Inject identity context (user_id, session_id, local_tz)
|
|
18
|
-
c(),
|
|
19
|
-
// Enrich and clean payload with page, device, utm data and custom data
|
|
20
|
-
l(n)
|
|
21
|
-
// Send events to server
|
|
22
|
-
]
|
|
23
|
-
}), e = () => u();
|
|
24
|
-
return typeof window < "u" && (window.addEventListener("beforeunload", e), window[s] = e, window[r] = !0, window.dispatchEvent(new CustomEvent("dotcms:analytics:ready"))), {
|
|
25
|
-
/**
|
|
26
|
-
* Track a page view.
|
|
27
|
-
* Session activity is automatically updated by the identity plugin.
|
|
28
|
-
* @param payload - Optional custom data to include with the page view (any valid JSON object)
|
|
29
|
-
*/
|
|
30
|
-
pageView: (t = {}) => {
|
|
31
|
-
i == null || i.page(t);
|
|
32
|
-
},
|
|
33
|
-
/**
|
|
34
|
-
* Track a custom event.
|
|
35
|
-
* Session activity is automatically updated by the identity plugin.
|
|
36
|
-
* @param eventName - The name of the event to track
|
|
37
|
-
* @param payload - Custom data to include with the event (any valid JSON object)
|
|
38
|
-
*/
|
|
39
|
-
track: (t, d = {}) => {
|
|
40
|
-
i == null || i.track(t, d);
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
};
|
|
44
|
-
export {
|
|
45
|
-
I as initializeContentAnalytics
|
|
46
|
-
};
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { DotCMSAnalyticsConfig, DotCMSAnalyticsParams } from '../shared/models';
|
|
2
|
-
/**
|
|
3
|
-
* Analytics plugin for tracking page views and custom events in DotCMS applications.
|
|
4
|
-
* This plugin handles sending analytics data to the DotCMS server, managing initialization,
|
|
5
|
-
* and processing both automatic and manual tracking events.
|
|
6
|
-
* Supports optional queue management for batching events before sending.
|
|
7
|
-
*
|
|
8
|
-
* @param {DotCMSAnalyticsConfig} config - Configuration object containing API key, server URL,
|
|
9
|
-
* debug mode, auto page view settings, and queue config
|
|
10
|
-
* @returns {Object} Plugin object with methods for initialization and event tracking
|
|
11
|
-
*/
|
|
12
|
-
export declare const dotAnalytics: (config: DotCMSAnalyticsConfig) => {
|
|
13
|
-
name: string;
|
|
14
|
-
config: DotCMSAnalyticsConfig;
|
|
15
|
-
/**
|
|
16
|
-
* Initialize the plugin with optional queue management
|
|
17
|
-
*/
|
|
18
|
-
initialize: () => Promise<void>;
|
|
19
|
-
/**
|
|
20
|
-
* Track a page view event
|
|
21
|
-
* The enricher plugin has already built the complete request body
|
|
22
|
-
*/
|
|
23
|
-
page: (params: DotCMSAnalyticsParams) => void;
|
|
24
|
-
/**
|
|
25
|
-
* Track a custom event
|
|
26
|
-
* The enricher plugin has already built the complete request body
|
|
27
|
-
*/
|
|
28
|
-
track: (params: DotCMSAnalyticsParams) => void;
|
|
29
|
-
/**
|
|
30
|
-
* Check if the plugin is loaded
|
|
31
|
-
*/
|
|
32
|
-
loaded: () => boolean;
|
|
33
|
-
};
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { sendAnalyticsEvent as u } from "../shared/dot-content-analytics.http.js";
|
|
2
|
-
import { createAnalyticsQueue as d } from "../shared/queue/dot-analytics.queue.utils.js";
|
|
3
|
-
const v = (t) => {
|
|
4
|
-
let n = !1;
|
|
5
|
-
const i = t.queue !== !1;
|
|
6
|
-
let e = null;
|
|
7
|
-
const o = (r) => {
|
|
8
|
-
const { config: c, payload: l } = r;
|
|
9
|
-
if (!n)
|
|
10
|
-
throw new Error("DotCMS Analytics: Plugin not initialized");
|
|
11
|
-
const a = l.events[0], s = l.context;
|
|
12
|
-
i && e ? e.enqueue(a, s) : u({
|
|
13
|
-
context: s,
|
|
14
|
-
events: [a]
|
|
15
|
-
}, c);
|
|
16
|
-
};
|
|
17
|
-
return {
|
|
18
|
-
name: "dot-analytics",
|
|
19
|
-
config: t,
|
|
20
|
-
/**
|
|
21
|
-
* Initialize the plugin with optional queue management
|
|
22
|
-
*/
|
|
23
|
-
initialize: () => (n = !0, i && (e = d(t), e.initialize()), Promise.resolve()),
|
|
24
|
-
/**
|
|
25
|
-
* Track a page view event
|
|
26
|
-
* The enricher plugin has already built the complete request body
|
|
27
|
-
*/
|
|
28
|
-
page: o,
|
|
29
|
-
/**
|
|
30
|
-
* Track a custom event
|
|
31
|
-
* The enricher plugin has already built the complete request body
|
|
32
|
-
*/
|
|
33
|
-
track: o,
|
|
34
|
-
/**
|
|
35
|
-
* Check if the plugin is loaded
|
|
36
|
-
*/
|
|
37
|
-
loaded: () => n
|
|
38
|
-
};
|
|
39
|
-
};
|
|
40
|
-
export {
|
|
41
|
-
v as dotAnalytics
|
|
42
|
-
};
|