@dotcms/analytics 1.1.1-next.4 → 1.1.1-next.6

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
@@ -108,13 +108,65 @@ track(eventName: string, properties?: Record<string, unknown>): void
108
108
 
109
109
  ## ⚙️ Configuration Options
110
110
 
111
- <<<<<<< HEAD
112
111
  | Option | Type | Required | Default | Description |
113
112
  | -------------- | --------- | -------- | ----------------------------------- | -------------------------------------- |
114
113
  | `siteAuth` | `string` | ✅ | - | Site auth from dotCMS Analytics app |
115
114
  | `server` | `string` | ✅ | - | Your dotCMS server URL |
116
115
  | `debug` | `boolean` | ❌ | `false` | Enable verbose logging |
117
116
  | `autoPageView` | `boolean` | ❌ | React: `true` / Standalone: `false` | Auto track page views on route changes |
117
+ | `queueConfig` | `QueueConfig` | ❌ | See below | Event batching configuration |
118
+
119
+ ### Queue Configuration
120
+
121
+ The `queueConfig` option controls event batching:
122
+
123
+ - **`false`**: Disable queuing, send events immediately
124
+ - **`undefined` (default)**: Enable queuing with default settings
125
+ - **`QueueConfig` object**: Enable queuing with custom settings
126
+
127
+ | Option | Type | Default | Description |
128
+ | ---------------- | -------- | ------- | ------------------------------------------------ |
129
+ | `eventBatchSize` | `number` | `15` | Max events per batch - auto-sends when reached |
130
+ | `flushInterval` | `number` | `5000` | Time between flushes - sends pending events (ms) |
131
+
132
+ **How it works:**
133
+
134
+ - ✅ Send immediately when `eventBatchSize` reached (e.g., 15 events)
135
+ - ✅ Send pending events every `flushInterval` (e.g., 5 seconds)
136
+ - ✅ Auto-flush on page navigation/close using `visibilitychange` + `pagehide` events
137
+ - Example: If you have 10 events and 5 seconds pass → sends those 10
138
+
139
+ **About page unload handling:**
140
+
141
+ The SDK uses modern APIs (`visibilitychange` + `pagehide`) instead of `beforeunload`/`unload` to ensure:
142
+
143
+ - ✅ Better reliability on mobile devices
144
+ - ✅ Compatible with browser back/forward cache (bfcache)
145
+ - ✅ Events are sent via `navigator.sendBeacon()` for guaranteed delivery
146
+ - ✅ No negative impact on page performance
147
+
148
+ **Example: Disable queuing for immediate sends**
149
+
150
+ ```javascript
151
+ const analytics = initializeContentAnalytics({
152
+ siteAuth: 'abc123',
153
+ server: 'https://your-dotcms.com',
154
+ queue: false // Send events immediately without batching
155
+ });
156
+ ```
157
+
158
+ **Example: Custom queue config**
159
+
160
+ ```javascript
161
+ const analytics = initializeContentAnalytics({
162
+ siteAuth: 'abc123',
163
+ server: 'https://your-dotcms.com',
164
+ queue: {
165
+ eventBatchSize: 10, // Auto-send when 10 events queued
166
+ flushInterval: 3000 // Or send every 3 seconds
167
+ }
168
+ });
169
+ ```
118
170
 
119
171
  ## 🛠️ Usage Examples
120
172
 
@@ -3,28 +3,29 @@ import { DotCMSAnalyticsConfig, DotCMSAnalyticsParams } from '../shared/models';
3
3
  * Analytics plugin for tracking page views and custom events in DotCMS applications.
4
4
  * This plugin handles sending analytics data to the DotCMS server, managing initialization,
5
5
  * and processing both automatic and manual tracking events.
6
+ * Supports optional queue management for batching events before sending.
6
7
  *
7
8
  * @param {DotCMSAnalyticsConfig} config - Configuration object containing API key, server URL,
8
- * debug mode and auto page view settings
9
+ * debug mode, auto page view settings, and queue config
9
10
  * @returns {Object} Plugin object with methods for initialization and event tracking
10
11
  */
11
12
  export declare const dotAnalytics: (config: DotCMSAnalyticsConfig) => {
12
13
  name: string;
13
14
  config: DotCMSAnalyticsConfig;
14
15
  /**
15
- * Initialize the plugin
16
+ * Initialize the plugin with optional queue management
16
17
  */
17
18
  initialize: () => Promise<void>;
18
19
  /**
19
20
  * Track a page view event
20
21
  * The enricher plugin has already built the complete request body
21
22
  */
22
- page: (params: DotCMSAnalyticsParams) => Promise<void>;
23
+ page: (params: DotCMSAnalyticsParams) => void;
23
24
  /**
24
25
  * Track a custom event
25
26
  * The enricher plugin has already built the complete request body
26
27
  */
27
- track: (params: DotCMSAnalyticsParams) => Promise<void>;
28
+ track: (params: DotCMSAnalyticsParams) => void;
28
29
  /**
29
30
  * Check if the plugin is loaded
30
31
  */
@@ -1,41 +1,36 @@
1
- import { sendAnalyticsEventToServer as r } from "../shared/dot-content-analytics.http.js";
2
- const s = (a) => {
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) => {
3
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
+ };
4
17
  return {
5
18
  name: "dot-analytics",
6
- config: a,
19
+ config: t,
7
20
  /**
8
- * Initialize the plugin
21
+ * Initialize the plugin with optional queue management
9
22
  */
10
- initialize: () => (n = !0, Promise.resolve()),
23
+ initialize: () => (n = !0, i && (e = d(t), e.initialize()), Promise.resolve()),
11
24
  /**
12
25
  * Track a page view event
13
26
  * The enricher plugin has already built the complete request body
14
27
  */
15
- page: (e) => {
16
- const { config: o, payload: t } = e;
17
- if (!n)
18
- throw new Error("DotCMS Analytics: Plugin not initialized");
19
- const i = {
20
- context: t.context,
21
- events: t.events
22
- };
23
- return r(i, o);
24
- },
28
+ page: o,
25
29
  /**
26
30
  * Track a custom event
27
31
  * The enricher plugin has already built the complete request body
28
32
  */
29
- track: (e) => {
30
- const { config: o, payload: t } = e;
31
- if (!n)
32
- throw new Error("DotCMS Analytics: Plugin not initialized");
33
- const i = {
34
- context: t.context,
35
- events: t.events
36
- };
37
- return r(i, o);
38
- },
33
+ track: o,
39
34
  /**
40
35
  * Check if the plugin is loaded
41
36
  */
@@ -43,5 +38,5 @@ const s = (a) => {
43
38
  };
44
39
  };
45
40
  export {
46
- s as dotAnalytics
41
+ v as dotAnalytics
47
42
  };
@@ -29,8 +29,17 @@ export declare const EXPECTED_UTM_KEYS: readonly ["utm_source", "utm_medium", "u
29
29
  * Session configuration constants
30
30
  */
31
31
  export declare const DEFAULT_SESSION_TIMEOUT_MINUTES = 30;
32
+ /**
33
+ * Session storage key for session ID
34
+ */
32
35
  export declare const SESSION_STORAGE_KEY = "dot_analytics_session_id";
36
+ /**
37
+ * Session storage key for session start time
38
+ */
33
39
  export declare const SESSION_START_KEY = "dot_analytics_session_start";
40
+ /**
41
+ * Session storage key for session UTM data
42
+ */
34
43
  export declare const SESSION_UTM_KEY = "dot_analytics_session_utm";
35
44
  /**
36
45
  * User ID configuration constants
@@ -43,6 +52,13 @@ export declare const USER_ID_KEY = "dot_analytics_user_id";
43
52
  * - visibilitychange: Handled separately to detect tab changes
44
53
  */
45
54
  export declare const ACTIVITY_EVENTS: readonly ["click"];
55
+ /**
56
+ * Default queue configuration for event batching
57
+ */
58
+ export declare const DEFAULT_QUEUE_CONFIG: {
59
+ readonly eventBatchSize: 15;
60
+ readonly flushInterval: 5000;
61
+ };
46
62
  /**
47
63
  * The name of the analytics minified script.
48
64
  */
@@ -1,12 +1,17 @@
1
- const t = "/api/v1/analytics/content/event", _ = {
1
+ const E = "/api/v1/analytics/content/event", e = {
2
2
  PAGEVIEW: "pageview"
3
- }, e = [
3
+ }, n = [
4
4
  "utm_source",
5
5
  "utm_medium",
6
6
  "utm_campaign",
7
7
  "utm_term",
8
8
  "utm_content"
9
- ], E = 30, n = "dot_analytics_session_id", c = "dot_analytics_user_id", s = ["click"], o = [
9
+ ], c = 30, s = "dot_analytics_session_id", T = "dot_analytics_user_id", t = 15, _ = 5e3, o = ["click"], S = {
10
+ eventBatchSize: t,
11
+ // Max events per batch - auto-sends when reached
12
+ flushInterval: _
13
+ // Time between flushes - sends whatever is queued
14
+ }, I = [
10
15
  "title",
11
16
  "url",
12
17
  "path",
@@ -17,12 +22,13 @@ const t = "/api/v1/analytics/content/event", _ = {
17
22
  "referrer"
18
23
  ];
19
24
  export {
20
- s as ACTIVITY_EVENTS,
21
- t as ANALYTICS_ENDPOINT,
22
- o as ANALYTICS_JS_DEFAULT_PROPERTIES,
23
- E as DEFAULT_SESSION_TIMEOUT_MINUTES,
24
- _ as DotCMSPredefinedEventType,
25
- e as EXPECTED_UTM_KEYS,
26
- n as SESSION_STORAGE_KEY,
27
- c as USER_ID_KEY
25
+ o as ACTIVITY_EVENTS,
26
+ E as ANALYTICS_ENDPOINT,
27
+ I as ANALYTICS_JS_DEFAULT_PROPERTIES,
28
+ S as DEFAULT_QUEUE_CONFIG,
29
+ c as DEFAULT_SESSION_TIMEOUT_MINUTES,
30
+ e as DotCMSPredefinedEventType,
31
+ n as EXPECTED_UTM_KEYS,
32
+ s as SESSION_STORAGE_KEY,
33
+ T as USER_ID_KEY
28
34
  };
@@ -1,8 +1,17 @@
1
1
  import { DotCMSAnalyticsConfig, DotCMSEvent, DotCMSRequestBody } from './models';
2
2
  /**
3
- * Send an analytics event to the server
3
+ * Available transport methods for sending analytics events
4
+ */
5
+ export declare const TRANSPORT_TYPES: {
6
+ readonly FETCH: "fetch";
7
+ readonly BEACON: "beacon";
8
+ };
9
+ export type TransportType = (typeof TRANSPORT_TYPES)[keyof typeof TRANSPORT_TYPES];
10
+ /**
11
+ * Send analytics events to the server
4
12
  * @param payload - The event payload data
5
13
  * @param config - The analytics configuration
6
- * @returns A promise that resolves when the request is complete
14
+ * @param transportType - Transport method: 'fetch' (default) or 'beacon' (for page unload)
15
+ * @returns A promise that resolves when the request is complete (fetch only)
7
16
  */
8
- export declare const sendAnalyticsEventToServer: (payload: DotCMSRequestBody<DotCMSEvent>, config: DotCMSAnalyticsConfig) => Promise<void>;
17
+ export declare const sendAnalyticsEvent: (payload: DotCMSRequestBody<DotCMSEvent>, config: DotCMSAnalyticsConfig, transportType?: TransportType) => Promise<void>;
@@ -1,23 +1,34 @@
1
- import { ANALYTICS_ENDPOINT as a } from "./constants/dot-content-analytics.constants.js";
2
- const i = async (o, t) => {
1
+ import { ANALYTICS_ENDPOINT as l } from "./constants/dot-content-analytics.constants.js";
2
+ const d = async (s, n, o = "fetch") => {
3
+ const a = `${n.server}${l}`, c = JSON.stringify(s);
4
+ if (n.debug && console.warn(
5
+ `DotCMS Analytics: Sending ${s.events.length} event(s) via ${o}`,
6
+ o === "fetch" ? { payload: s } : void 0
7
+ ), o === "beacon") {
8
+ if (navigator.sendBeacon) {
9
+ const e = new Blob([c], { type: "application/json" });
10
+ !navigator.sendBeacon(a, e) && n.debug && console.warn("DotCMS Analytics: sendBeacon failed (queue might be full)");
11
+ } else
12
+ return n.debug && console.warn("DotCMS Analytics: sendBeacon not available, using fetch fallback"), d(s, n, "fetch");
13
+ return;
14
+ }
3
15
  try {
4
- t.debug && console.warn("DotCMS Analytics: HTTP Body to send:", JSON.stringify(o, null, 2));
5
- const e = await fetch(`${t.server}${a}`, {
16
+ const e = await fetch(a, {
6
17
  method: "POST",
7
18
  headers: { "Content-Type": "application/json" },
8
- body: JSON.stringify(o)
19
+ body: c
9
20
  });
10
21
  if (!e.ok) {
11
- const n = e.statusText || "Unknown Error", r = `HTTP ${e.status}: ${n}`;
22
+ const i = e.statusText || "Unknown Error", r = `HTTP ${e.status}: ${i}`;
12
23
  try {
13
- const s = await e.json();
14
- s.message ? console.warn(`DotCMS Analytics: ${s.message} (${r})`) : console.warn(
24
+ const t = await e.json();
25
+ t.message ? console.warn(`DotCMS Analytics: ${t.message} (${r})`) : console.warn(
15
26
  `DotCMS Analytics: ${r} - No error message in response`
16
27
  );
17
- } catch (s) {
28
+ } catch (t) {
18
29
  console.warn(
19
30
  `DotCMS Analytics: ${r} - Failed to parse error response:`,
20
- s
31
+ t
21
32
  );
22
33
  }
23
34
  }
@@ -26,5 +37,5 @@ const i = async (o, t) => {
26
37
  }
27
38
  };
28
39
  export {
29
- i as sendAnalyticsEventToServer
40
+ d as sendAnalyticsEvent
30
41
  };
@@ -2,6 +2,16 @@ import { DotCMSAnalyticsEventContext, DotCMSEventPageData, DotCMSEventUtmData }
2
2
  import { JsonObject } from './event.model';
3
3
  import { DotCMSAnalyticsRequestBody } from './request.model';
4
4
  import { DotCMSCustomEventType } from '../constants';
5
+ /**
6
+ * Configuration for event queue management.
7
+ * Controls how events are batched before sending to the server.
8
+ */
9
+ export interface QueueConfig {
10
+ /** Maximum events per batch - auto-sends when reached (default: 15) */
11
+ eventBatchSize?: number;
12
+ /** Time in milliseconds between flushes - sends pending events (default: 5000) */
13
+ flushInterval?: number;
14
+ }
5
15
  /**
6
16
  * Main interface for the DotCMS Analytics SDK.
7
17
  * Provides the core methods for tracking page views and custom events.
@@ -40,6 +50,13 @@ export interface DotCMSAnalyticsConfig {
40
50
  * The site auth for authenticating with the Analytics service.
41
51
  */
42
52
  siteAuth: string;
53
+ /**
54
+ * Queue configuration for event batching:
55
+ * - `false`: Disable queuing, send events immediately
56
+ * - `true` or `undefined` (default): Enable queuing with default settings
57
+ * - `QueueConfig`: Enable queuing with custom settings
58
+ */
59
+ queue?: QueueConfig | boolean;
43
60
  }
44
61
  /**
45
62
  * Track event payload with context.
@@ -0,0 +1,28 @@
1
+ import { DotCMSAnalyticsConfig, DotCMSAnalyticsEventContext, DotCMSEvent } from '../models';
2
+ /**
3
+ * Creates a queue manager for batching analytics events.
4
+ * Uses factory function pattern consistent with the plugin architecture.
5
+ */
6
+ export declare const createAnalyticsQueue: (config: DotCMSAnalyticsConfig) => {
7
+ /**
8
+ * Initialize the queue with smart batching
9
+ */
10
+ initialize: () => void;
11
+ /**
12
+ * Add event to queue
13
+ * smartQueue handles all batching logic automatically:
14
+ * - Sends immediately when eventBatchSize reached (with throttle: false)
15
+ * - Sends pending events every flushInterval
16
+ */
17
+ enqueue: (event: DotCMSEvent, context: DotCMSAnalyticsEventContext) => void;
18
+ /**
19
+ * Get queue size for debugging
20
+ * Returns the number of events in smartQueue
21
+ */
22
+ size: () => number;
23
+ /**
24
+ * Clean up queue resources
25
+ * Flushes remaining events and cleans up listeners
26
+ */
27
+ cleanup: () => void;
28
+ };
@@ -0,0 +1,73 @@
1
+ import p from "@analytics/queue-utils";
2
+ import { DEFAULT_QUEUE_CONFIG as c } from "../constants/dot-content-analytics.constants.js";
3
+ import { sendAnalyticsEvent as y } from "../dot-content-analytics.http.js";
4
+ const z = (n) => {
5
+ let e = null, i = null, o = "fetch";
6
+ const l = {
7
+ ...c,
8
+ ...typeof n.queue == "object" ? n.queue : {}
9
+ }, f = (t) => {
10
+ if (!i) return;
11
+ n.debug && console.log(`DotCMS Analytics Queue: Sending batch of ${t.length} event(s)`, {
12
+ events: t,
13
+ transport: o
14
+ }), y({ context: i, events: t }, n, o);
15
+ }, u = () => {
16
+ !e || e.size() === 0 || !i || (n.debug && console.warn(
17
+ `DotCMS Analytics: Flushing ${e.size()} events (page hidden/unload)`
18
+ ), o = "beacon", e.flush(!0));
19
+ }, d = () => {
20
+ document.visibilityState === "hidden" && u();
21
+ };
22
+ return {
23
+ /**
24
+ * Initialize the queue with smart batching
25
+ */
26
+ initialize: () => {
27
+ e = p(
28
+ (t) => {
29
+ f(t);
30
+ },
31
+ {
32
+ max: l.eventBatchSize,
33
+ interval: l.flushInterval,
34
+ throttle: !1
35
+ // Always false - enables both batch size and interval triggers
36
+ }
37
+ ), typeof window < "u" && typeof document < "u" && (document.addEventListener("visibilitychange", d), window.addEventListener("pagehide", u));
38
+ },
39
+ /**
40
+ * Add event to queue
41
+ * smartQueue handles all batching logic automatically:
42
+ * - Sends immediately when eventBatchSize reached (with throttle: false)
43
+ * - Sends pending events every flushInterval
44
+ */
45
+ enqueue: (t, s) => {
46
+ if (i = s, !!e) {
47
+ if (n.debug) {
48
+ const a = e.size() + 1, r = l.eventBatchSize ?? c.eventBatchSize, h = a >= r;
49
+ console.log(
50
+ `DotCMS Analytics Queue: Event added. Queue size: ${a}/${r}${h ? " (full, sending...)" : ""}`,
51
+ { eventType: t.event_type, event: t }
52
+ );
53
+ }
54
+ e.push(t);
55
+ }
56
+ },
57
+ /**
58
+ * Get queue size for debugging
59
+ * Returns the number of events in smartQueue
60
+ */
61
+ size: () => (e == null ? void 0 : e.size()) ?? 0,
62
+ /**
63
+ * Clean up queue resources
64
+ * Flushes remaining events and cleans up listeners
65
+ */
66
+ cleanup: () => {
67
+ u(), typeof window < "u" && typeof document < "u" && (document.removeEventListener("visibilitychange", d), window.removeEventListener("pagehide", u)), e = null, i = null, o = "fetch";
68
+ }
69
+ };
70
+ };
71
+ export {
72
+ z as createAnalyticsQueue
73
+ };
@@ -0,0 +1 @@
1
+ export { createAnalyticsQueue } from './dot-analytics.queue.utils';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotcms/analytics",
3
- "version": "1.1.1-next.4",
3
+ "version": "1.1.1-next.6",
4
4
  "description": "Official JavaScript library for Content Analytics with DotCMS.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -23,6 +23,7 @@
23
23
  "analytics": "^0.8.0",
24
24
  "@analytics/core": "^0.13.0",
25
25
  "@analytics/storage-utils": "^0.4.0",
26
+ "@analytics/queue-utils": "^0.1.3",
26
27
  "@dotcms/uve": "latest"
27
28
  },
28
29
  "peerDependencies": {