@dotcms/analytics 1.1.1 → 1.2.0-next.10

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.
Files changed (64) hide show
  1. package/README.md +475 -72
  2. package/lib/core/{dot-content-analytics.d.ts → dot-analytics.content.d.ts} +8 -1
  3. package/lib/core/dot-analytics.content.js +63 -0
  4. package/lib/core/plugin/click/dot-analytics.click-tracker.d.ts +108 -0
  5. package/lib/core/plugin/click/dot-analytics.click-tracker.js +144 -0
  6. package/lib/core/plugin/click/dot-analytics.click.plugin.d.ts +36 -0
  7. package/lib/core/plugin/click/dot-analytics.click.plugin.js +27 -0
  8. package/lib/core/plugin/click/dot-analytics.click.utils.d.ts +12 -0
  9. package/lib/core/plugin/click/dot-analytics.click.utils.js +55 -0
  10. package/lib/core/plugin/enricher/dot-analytics.enricher.plugin.d.ts +18 -30
  11. package/lib/core/plugin/enricher/dot-analytics.enricher.plugin.js +30 -20
  12. package/lib/core/plugin/identity/dot-analytics.identity.activity-tracker.d.ts +20 -0
  13. package/lib/core/{shared/dot-content-analytics.activity-tracker.js → plugin/identity/dot-analytics.identity.activity-tracker.js} +19 -38
  14. package/lib/core/plugin/identity/dot-analytics.identity.plugin.d.ts +13 -31
  15. package/lib/core/plugin/identity/dot-analytics.identity.plugin.js +14 -12
  16. package/lib/core/plugin/identity/dot-analytics.identity.utils.d.ts +7 -22
  17. package/lib/core/plugin/impression/dot-analytics.impression-tracker.d.ts +62 -0
  18. package/lib/core/plugin/impression/dot-analytics.impression-tracker.js +200 -0
  19. package/lib/core/plugin/impression/dot-analytics.impression.plugin.d.ts +40 -0
  20. package/lib/core/plugin/impression/dot-analytics.impression.plugin.js +27 -0
  21. package/lib/core/plugin/impression/dot-analytics.impression.utils.d.ts +26 -0
  22. package/lib/core/plugin/impression/dot-analytics.impression.utils.js +27 -0
  23. package/lib/core/plugin/impression/index.d.ts +2 -0
  24. package/lib/core/plugin/main/dot-analytics.plugin.d.ts +46 -0
  25. package/lib/core/plugin/main/dot-analytics.plugin.js +114 -0
  26. package/lib/core/shared/constants/dot-analytics.constants.d.ts +131 -0
  27. package/lib/core/shared/constants/dot-analytics.constants.js +52 -0
  28. package/lib/core/shared/constants/index.d.ts +4 -0
  29. package/lib/core/shared/dot-analytics.logger.d.ts +85 -0
  30. package/lib/core/shared/dot-analytics.logger.js +90 -0
  31. package/lib/core/shared/http/dot-analytics.http.d.ts +9 -0
  32. package/lib/core/shared/http/dot-analytics.http.js +34 -0
  33. package/lib/core/shared/models/data.model.d.ts +141 -0
  34. package/lib/core/shared/models/event.model.d.ts +135 -0
  35. package/lib/core/shared/models/index.d.ts +7 -0
  36. package/lib/core/shared/models/library.model.d.ts +243 -0
  37. package/lib/core/shared/models/request.model.d.ts +32 -0
  38. package/lib/core/shared/queue/dot-analytics.queue.utils.d.ts +28 -0
  39. package/lib/core/shared/queue/dot-analytics.queue.utils.js +80 -0
  40. package/lib/core/shared/queue/index.d.ts +1 -0
  41. package/lib/core/shared/utils/dot-analytics.utils.d.ts +260 -0
  42. package/lib/core/shared/utils/dot-analytics.utils.js +202 -0
  43. package/lib/react/components/DotContentAnalytics.d.ts +1 -1
  44. package/lib/react/hook/useContentAnalytics.d.ts +43 -15
  45. package/lib/react/hook/useContentAnalytics.js +18 -21
  46. package/lib/react/hook/useRouterTracker.d.ts +1 -1
  47. package/lib/react/hook/useRouterTracker.js +4 -4
  48. package/lib/react/internal/utils.d.ts +1 -1
  49. package/lib/react/internal/utils.js +3 -3
  50. package/lib/react/public-api.d.ts +1 -1
  51. package/lib/standalone.d.ts +2 -2
  52. package/package.json +7 -5
  53. package/uve/src/internal/constants.js +8 -3
  54. package/lib/core/dot-content-analytics.js +0 -43
  55. package/lib/core/plugin/dot-analytics.plugin.d.ts +0 -32
  56. package/lib/core/plugin/dot-analytics.plugin.js +0 -79
  57. package/lib/core/shared/dot-content-analytics.activity-tracker.d.ts +0 -28
  58. package/lib/core/shared/dot-content-analytics.constants.d.ts +0 -37
  59. package/lib/core/shared/dot-content-analytics.constants.js +0 -14
  60. package/lib/core/shared/dot-content-analytics.http.d.ts +0 -8
  61. package/lib/core/shared/dot-content-analytics.http.js +0 -29
  62. package/lib/core/shared/dot-content-analytics.model.d.ts +0 -351
  63. package/lib/core/shared/dot-content-analytics.utils.d.ts +0 -111
  64. package/lib/core/shared/dot-content-analytics.utils.js +0 -123
@@ -0,0 +1,260 @@
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;
25
+ /**
26
+ * Validates required configuration fields for Analytics initialization.
27
+ *
28
+ * @param config - The analytics configuration to validate
29
+ * @returns Array of missing field names, or null if all required fields are present
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * const missing = validateAnalyticsConfig(config);
34
+ * if (missing) {
35
+ * console.error(`Missing: ${missing.join(' and ')}`);
36
+ * }
37
+ * ```
38
+ */
39
+ export declare function validateAnalyticsConfig(config: DotCMSAnalyticsConfig): string[] | null;
40
+ /**
41
+ * Generates a cryptographically secure random ID.
42
+ * @internal This function is for internal use only and should not be used outside of the SDK.
43
+ * @param prefix - The prefix for the generated ID
44
+ * @returns A unique ID string with the given prefix
45
+ */
46
+ export declare const generateSecureId: (prefix: string) => string;
47
+ /**
48
+ * Safe sessionStorage wrapper with error handling
49
+ */
50
+ export declare const safeSessionStorage: {
51
+ getItem: (key: string) => string | null;
52
+ setItem: (key: string, value: string) => void;
53
+ };
54
+ /**
55
+ * Gets or generates a user ID from localStorage.
56
+ * @internal This function is for internal use only.
57
+ * @returns The user ID string
58
+ */
59
+ export declare const getUserId: () => string;
60
+ /**
61
+ * Gets session ID with comprehensive lifecycle management.
62
+ * Returns existing valid session ID or creates a new one if needed.
63
+ * @internal This function is for internal use only.
64
+ *
65
+ * Session validation criteria:
66
+ * 1. User is still active (< 30 min inactivity)
67
+ * 2. Session hasn't passed midnight (UTC)
68
+ *
69
+ * @returns The session ID string
70
+ */
71
+ export declare const getSessionId: () => string;
72
+ /**
73
+ * Gets analytics context with user and session identification.
74
+ * Used by the identity plugin to inject context into analytics events.
75
+ *
76
+ * @param config - The analytics configuration object
77
+ * @returns The analytics context with site_key, session_id, and user_id
78
+ */
79
+ export declare const getAnalyticsContext: (config: DotCMSAnalyticsConfig) => DotCMSAnalyticsEventContext;
80
+ /**
81
+ * Configuration result with warnings for analytics setup
82
+ */
83
+ export interface AnalyticsConfigResult {
84
+ config: DotCMSAnalyticsConfig;
85
+ warnings?: string[];
86
+ missingAttributes?: string[];
87
+ hasIssues: boolean;
88
+ }
89
+ /**
90
+ * Gets analytics configuration from script tag attributes.
91
+ * Always returns a config (with defaults if needed).
92
+ *
93
+ * - If no data-analytics-server attribute is found, uses the current domain as the server endpoint
94
+ * - Both debug and autoPageView default to false (must be explicitly set to "true")
95
+ *
96
+ * @returns The analytics configuration object
97
+ */
98
+ export declare const getAnalyticsConfig: () => DotCMSAnalyticsConfig;
99
+ /**
100
+ * Gets current device data for analytics.
101
+ * Combines static browser data with dynamic viewport information.
102
+ * Used by the identity plugin to inject device data into context.
103
+ *
104
+ * @returns Device data with screen resolution, language, and viewport dimensions
105
+ */
106
+ export declare const getDeviceDataForContext: () => DotCMSEventDeviceData;
107
+ /**
108
+ * Retrieves the browser event data - optimized but accurate.
109
+ * @internal This function is for internal use only.
110
+ * @param location - The Location object to extract data from
111
+ * @returns Browser event data with all relevant information
112
+ */
113
+ export declare const getBrowserEventData: (location: Location) => DotCMSBrowserData;
114
+ /**
115
+ * Extracts and transforms UTM parameters from the URL - cached for performance.
116
+ * Returns UTM data in DotCMS format (without 'utm_' prefix).
117
+ * @internal This function is for internal use only.
118
+ * @param location - The Location object to extract UTM parameters from
119
+ * @returns DotCMSEventUtmData object with transformed UTM parameters (source, medium, campaign, etc.)
120
+ */
121
+ export declare const extractUTMParameters: (location: Location) => DotCMSEventUtmData;
122
+ /**
123
+ * Default redirect function.
124
+ * @internal This function is for internal use only.
125
+ * @param href - The URL to redirect to
126
+ */
127
+ export declare const defaultRedirectFn: (href: string) => string;
128
+ /**
129
+ * Gets local time in ISO format without milliseconds.
130
+ * Used by enricher plugins to add local_time to events.
131
+ *
132
+ * @returns Local time string in ISO 8601 format with timezone offset (e.g., "2024-01-01T12:00:00-05:00")
133
+ */
134
+ export declare const getLocalTime: () => string;
135
+ /**
136
+ * Gets page data from browser event data and payload.
137
+ * @internal This function is for internal use only.
138
+ * @param browserData - Browser event data
139
+ * @param payload - Payload with properties
140
+ * @returns PageData object for Analytics.js
141
+ */
142
+ export declare const getPageData: (browserData: DotCMSBrowserData, payload: {
143
+ properties: Record<string, unknown>;
144
+ }) => PageData;
145
+ /**
146
+ * Gets device data from browser event data.
147
+ * @internal This function is for internal use only.
148
+ * @param browserData - Browser event data
149
+ * @returns Device data with screen resolution, language, and viewport dimensions
150
+ */
151
+ export declare const getDeviceData: (browserData: DotCMSBrowserData) => DotCMSEventDeviceData;
152
+ /**
153
+ * Gets UTM data from browser event data.
154
+ * @internal This function is for internal use only.
155
+ * @param browserData - Browser event data
156
+ * @returns UTM data with source, medium, campaign, etc.
157
+ */
158
+ export declare const getUtmData: (browserData: DotCMSBrowserData) => DotCMSEventUtmData;
159
+ /**
160
+ * Enriches payload with UTM data.
161
+ * @internal This function is for internal use only.
162
+ * @param payload - The payload to enrich
163
+ * @returns The payload with UTM data added
164
+ */
165
+ export declare const enrichWithUtmData: <T extends Record<string, unknown>>(payload: T) => T;
166
+ /**
167
+ * Optimized payload enrichment using existing analytics.js data.
168
+ * Filters out Analytics.js default properties and only keeps user-provided properties in custom.
169
+ * Used by the enricher plugin to transform Analytics.js payload into DotCMS event format.
170
+ *
171
+ * @param payload - The Analytics.js payload with context already injected by identity plugin
172
+ * @param location - The Location object to extract page data from (defaults to window.location)
173
+ * @returns Enriched payload with page, UTM, custom data, and local_time (device is in context)
174
+ */
175
+ export declare const enrichPagePayloadOptimized: (payload: AnalyticsBasePayloadWithContext, location?: Location) => EnrichedAnalyticsPayload;
176
+ /**
177
+ * Legacy function that enriches page payload with all data in one call.
178
+ * @internal This function is for internal use only.
179
+ * @param payload - The payload to enrich
180
+ * @param location - The Location object to extract data from
181
+ * @returns Object with enriched payload
182
+ */
183
+ export declare const enrichPagePayload: (payload: {
184
+ properties: Record<string, unknown>;
185
+ } & Record<string, unknown>, location?: Location) => {
186
+ payload: {
187
+ local_time: string;
188
+ utm?: DotCMSEventUtmData | undefined;
189
+ page: PageData;
190
+ device: DotCMSEventDeviceData;
191
+ properties: Record<string, unknown>;
192
+ };
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,5 +1,5 @@
1
1
  import { ReactElement } from 'react';
2
- import { DotCMSAnalyticsConfig } from '../../core/shared/dot-content-analytics.model';
2
+ import { DotCMSAnalyticsConfig } from '../../core/shared/models';
3
3
  /**
4
4
  * Client bootstrapper for dotCMS Analytics in React/Next.
5
5
  * - No UI: initializes the analytics singleton from props or env config.
@@ -1,29 +1,57 @@
1
- import { DotCMSAnalytics, DotCMSAnalyticsConfig } from '../../core/shared/dot-content-analytics.model';
1
+ import { DotCMSAnalytics, DotCMSAnalyticsConfig } from '../../core/shared/models';
2
2
  /**
3
- * Custom hook that handles analytics tracking for anonymous users.
4
- * Provides methods to track events and page views with automatic timestamp injection.
5
- * Automatically disables tracking when inside the UVE editor.
3
+ * React hook for tracking user interactions and page views in your DotCMS application.
4
+ *
5
+ * Use this hook to add analytics tracking to your React components. It automatically
6
+ * handles user sessions, device information, and UTM campaign parameters.
7
+ *
8
+ * **Important:** Tracking is automatically disabled when editing content in DotCMS to avoid
9
+ * polluting your analytics data with editor activity.
6
10
  *
7
11
  * @example
12
+ * Basic usage - Track custom events
8
13
  * ```tsx
9
- * function Button({ title, urlTitle }) {
14
+ * function ProductCard({ title, price }) {
10
15
  * const { track } = useContentAnalytics({
11
16
  * server: 'https://demo.dotcms.com',
12
- * siteKey: 'my-site-key',
17
+ * siteAuth: 'my-site-auth',
13
18
  * debug: false
14
19
  * });
15
20
  *
16
- * // Track button click with custom properties
17
- * return (
18
- * <button onClick={() => track('btn-click', { title, urlTitle })}>
19
- * See Details →
20
- * </button>
21
- * );
21
+ * const handleAddToCart = () => {
22
+ * track('add-to-cart', {
23
+ * product: title,
24
+ * price: price
25
+ * });
26
+ * };
27
+ *
28
+ * return <button onClick={handleAddToCart}>Add to Cart</button>;
29
+ * }
30
+ * ```
31
+ *
32
+ * @example
33
+ * Track page views manually
34
+ * ```tsx
35
+ * function ArticlePage({ article }) {
36
+ * const { pageView } = useContentAnalytics({
37
+ * server: 'https://demo.dotcms.com',
38
+ * siteKey: 'your-site-key'
39
+ * });
40
+ *
41
+ * useEffect(() => {
42
+ * pageView({
43
+ * category: article.category,
44
+ * author: article.author
45
+ * });
46
+ * }, [article.id]);
22
47
  * }
23
48
  * ```
24
49
  *
25
- * @param {DotCMSAnalyticsConfig} config - Required configuration object for analytics initialization
26
- * @returns {DotCMSAnalytics} The analytics instance with tracking capabilities
27
- * @throws {Error} When analytics initialization fails due to invalid configuration
50
+ * @param config - Configuration object with server URL and site key
51
+ * @param config.server - The URL of your DotCMS Analytics server
52
+ * @param config.siteKey - Your unique site key for authentication
53
+ * @param config.debug - Optional. Set to true to see analytics events in the console
54
+ * @returns Object with `track()` and `pageView()` methods for analytics tracking
55
+ * @throws {Error} If the configuration is invalid (missing server or siteKey)
28
56
  */
29
57
  export declare const useContentAnalytics: (config: DotCMSAnalyticsConfig) => DotCMSAnalytics;
@@ -1,32 +1,29 @@
1
- import { useRef as l, useCallback as n } from "react";
2
- import { getUVEState as r } from "../../../uve/src/lib/core/core.utils.js";
1
+ import { useMemo as n, useCallback as o } from "react";
2
+ import { getUVEState as u } from "../../../uve/src/lib/core/core.utils.js";
3
3
  import "../../../uve/src/internal/constants.js";
4
- import { initializeAnalytics as f } from "../internal/utils.js";
5
- const g = (o) => {
6
- const t = f(o), i = l(null);
4
+ import { initializeAnalytics as l } from "../internal/utils.js";
5
+ const h = (r) => {
6
+ const t = n(() => l(r), [r.server, r.siteAuth]), e = n(() => !!u(), []);
7
7
  if (!t)
8
8
  throw new Error(
9
- "Failed to initialize DotContentAnalytics. Please verify the required configuration (server and siteKey)."
9
+ "DotCMS Analytics: Failed to initialize. Please verify the required configuration (server and siteAuth)."
10
10
  );
11
- const a = n(
12
- (e, s = {}) => {
13
- r() || t.track(e, {
14
- ...s,
15
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
16
- });
11
+ const a = o(
12
+ (i, c = {}) => {
13
+ e || t.track(i, c);
17
14
  },
18
- [t]
19
- ), c = n(() => {
20
- if (!r()) {
21
- const e = window.location.pathname;
22
- e !== i.current && (i.current = e, t.pageView());
23
- }
24
- }, [t]);
15
+ [t, e]
16
+ ), s = o(
17
+ (i = {}) => {
18
+ e || t.pageView(i);
19
+ },
20
+ [t, e]
21
+ );
25
22
  return {
26
23
  track: a,
27
- pageView: c
24
+ pageView: s
28
25
  };
29
26
  };
30
27
  export {
31
- g as useContentAnalytics
28
+ h as useContentAnalytics
32
29
  };
@@ -1,4 +1,4 @@
1
- import { DotCMSAnalytics } from '../../core/shared/dot-content-analytics.model';
1
+ import { DotCMSAnalytics } from '../../core/shared/models';
2
2
  /**
3
3
  * Tracks page views on route changes using Next.js App Router signals.
4
4
  * - Fires a single pageView per unique path+search.
@@ -1,16 +1,16 @@
1
- import { usePathname as u, useSearchParams as p } from "next/navigation";
2
- import { useRef as c, useEffect as m } from "react";
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 = c(null), n = u(), r = p();
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("DotContentAnalytics: using Next.js App Router tracking"), i(g(n, r));
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 { DotCMSAnalytics, DotCMSAnalyticsConfig } from '../../core/shared/dot-content-analytics.model';
1
+ import { DotCMSAnalytics, DotCMSAnalyticsConfig } from '../../core/shared/models';
2
2
  /**
3
3
  * Initializes analytics with explicit configuration.
4
4
  * Resets singleton if config changes.
@@ -1,6 +1,6 @@
1
- import { initializeContentAnalytics as r } from "../../core/dot-content-analytics.js";
2
- let e, t;
3
- const s = (i) => (t && (t.server !== i.server || t.siteKey !== i.siteKey) && (e = void 0), e !== void 0 || (t = i, e = r(i)), e);
1
+ import { initializeContentAnalytics as r } from "../../core/dot-analytics.content.js";
2
+ let t, i;
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 {
5
5
  s as initializeAnalytics
6
6
  };
@@ -1,3 +1,3 @@
1
- export type { DotCMSAnalyticsConfig } from '../core/shared/dot-content-analytics.model';
1
+ export type { DotCMSAnalyticsConfig } from '../core/shared/models';
2
2
  export { DotContentAnalytics } from './components/DotContentAnalytics';
3
3
  export { useContentAnalytics } from './hook/useContentAnalytics';
@@ -1,5 +1,5 @@
1
- import { ANALYTICS_WINDOWS_KEY } from './core/shared/dot-content-analytics.constants';
2
- import { DotCMSAnalytics } from './core/shared/dot-content-analytics.model';
1
+ import { ANALYTICS_WINDOWS_KEY } from './core/shared/constants';
2
+ import { DotCMSAnalytics } from './core/shared/models';
3
3
  declare global {
4
4
  interface Window {
5
5
  [ANALYTICS_WINDOWS_KEY]: DotCMSAnalytics | null;