@dotcms/analytics 0.0.1-beta.43 → 0.0.1-beta.44

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
@@ -1,159 +1,226 @@
1
- # @dotcms/analytics
1
+ # dotCMS Content Analytics SDK (@dotcms/analytics)
2
2
 
3
- `@dotcms/analytics` is the official dotCMS JavaScript library for Content Analytics that helps track events and analytics in your webapps. Available for both browser and React applications.
3
+ Lightweight JavaScript SDK for tracking content-aware events in dotCMS. Works in vanilla JS and React apps. Angular & Vue support coming soon.
4
4
 
5
- ## Features
5
+ ## 🚀 Quick Start
6
6
 
7
- - **Simple Browser Integration**: Easy to implement via script tags using IIFE implementation
8
- - **React Support**: Built-in React components and hooks for seamless integration
9
- - **Event Tracking**: Simple API to track custom events with additional properties
10
- - **Automatic PageView**: Option to automatically track page views
11
- - **Debug Mode**: Optional debug logging for development
7
+ ### Vanilla JavaScript
12
8
 
13
- ## Installation
9
+ **CDN (Script Tag - Auto Page View)**
10
+
11
+ ```html
12
+ <script
13
+ src="ca.min.js"
14
+ data-analytics-server="https://demo.dotcms.com"
15
+ data-analytics-key="SITE_KEY"
16
+ data-analytics-auto-page-view></script>
17
+ ```
18
+
19
+ **npm (ES Module)**
14
20
 
15
21
  ```bash
16
22
  npm install @dotcms/analytics
17
23
  ```
18
24
 
19
- Or include the script in your HTML page:
25
+ ```javascript
26
+ import { initializeContentAnalytics } from '@dotcms/analytics';
20
27
 
21
- ```html
22
- <script src="ca.min.js"></script>
23
- ```
28
+ const analytics = initializeContentAnalytics({
29
+ siteKey: 'SITE_KEY',
30
+ server: 'https://demo.dotcms.com'
31
+ });
24
32
 
25
- ## React Integration
33
+ analytics.track('page-loaded');
34
+ ```
26
35
 
27
- ### Provider Setup
36
+ ### React
28
37
 
29
- First, import the provider:
38
+ ```bash
39
+ npm install @dotcms/analytics
40
+ ```
30
41
 
31
42
  ```tsx
32
43
  import { DotContentAnalyticsProvider } from '@dotcms/analytics/react';
33
- ```
34
44
 
35
- Wrap your application with the `DotContentAnalyticsProvider`:
36
-
37
- ```tsx
38
- // Example configuration
39
- const analyticsConfig = {
40
- apiKey: 'your-api-key-from-dotcms-analytics-app',
41
- server: 'https://your-dotcms-instance.com'
45
+ const config = {
46
+ siteKey: 'SITE_KEY',
47
+ server: 'https://demo.dotcms.com',
48
+ autoPageView: true // Optional, default is true
42
49
  };
43
50
 
44
- function App() {
45
- return (
46
- <DotContentAnalyticsProvider config={analyticsConfig}>
47
- <YourApp />
48
- </DotContentAnalyticsProvider>
49
- );
50
- }
51
+ <DotContentAnalyticsProvider config={config}>
52
+ <App />
53
+ </DotContentAnalyticsProvider>;
51
54
  ```
52
55
 
53
- ### Tracking Custom Events
56
+ ## 📘 Core Concepts
54
57
 
55
- Use the `useContentAnalytics` hook to track custom events:
58
+ ### Events
56
59
 
57
- ```tsx
58
- import { useContentAnalytics } from '@dotcms/analytics/react';
60
+ Track any user action as an event using `track('event-name', { payload })`.
59
61
 
60
- function Activity({ title, urlTitle }) {
61
- const { track } = useContentAnalytics();
62
+ ### Page Views
62
63
 
63
- // First parameter: custom event name to identify the action
64
- // Second parameter: object with properties you want to track
64
+ Tracked automatically (or manually) on route changes.
65
65
 
66
- return <button onClick={() => track('btn-click', { title, urlTitle })}>See Details →</button>;
67
- }
66
+ ### Sessions
67
+
68
+ - 30-minute timeout
69
+ - Resets at midnight UTC
70
+ - New session if UTM campaign changes
71
+
72
+ ### Identity
73
+
74
+ - Anonymous user ID persisted across sessions
75
+ - Stored in `dot_analytics_user_id`
76
+
77
+ ## ⚙️ Configuration Options
78
+
79
+ | Option | Type | Required | Default | Description |
80
+ | -------------- | ---------- | -------- | ------- | -------------------------------------- |
81
+ | `siteKey` | `string` | ✅ | - | Site key from dotCMS Analytics app |
82
+ | `server` | `string` | ✅ | - | Your dotCMS server URL |
83
+ | `debug` | `boolean` | ❌ | `false` | Enable verbose logging |
84
+ | `autoPageView` | `boolean` | ❌ | `true` | Auto track page views on route changes |
85
+ | `redirectFn` | `function` | ❌ | - | Custom handler for redirects |
86
+
87
+ ## 🛠️ Usage Examples
88
+
89
+ ### Vanilla JavaScript
90
+
91
+ **Manual Page View & Events**
92
+
93
+ ```javascript
94
+ // After init with the <script> tag the dotAnalytics is added to the window.
95
+ window.dotAnalytics.track('cta-click', { button: 'Buy Now' });
96
+ window.dotAnalytics.pageView();
68
97
  ```
69
98
 
70
- ### Manual Page View Tracking
99
+ **Advanced: Manual Init with Custom Properties**
100
+
101
+ ```javascript
102
+ const analytics = initializeContentAnalytics({
103
+ siteKey: 'abc123',
104
+ server: 'https://your-dotcms.com',
105
+ debug: true,
106
+ autoPageView: false
107
+ });
71
108
 
72
- To manually track page views, first disable automatic tracking in your config:
109
+ analytics.track('custom-event', {
110
+ category: 'Marketing',
111
+ value: 'Banner Clicked'
112
+ });
113
+
114
+ analytics.pageView();
115
+ ```
116
+
117
+ ### React
118
+
119
+ **Track Events**
73
120
 
74
121
  ```tsx
75
- const analyticsConfig = {
76
- apiKey: 'your-api-key-from-dotcms-analytics-app',
77
- server: 'https://your-dotcms-instance.com',
78
- autoPageView: false // Disable automatic tracking
79
- };
122
+ const { track } = useContentAnalytics();
123
+ track('cta-click', { label: 'Download PDF' });
80
124
  ```
81
125
 
82
- Then use the `useContentAnalytics` hook in your layout component:
126
+ **Manual Page View**
83
127
 
84
128
  ```tsx
85
- import { useContentAnalytics } from '@dotcms/analytics/react';
129
+ const { pageView } = useContentAnalytics();
130
+ useEffect(() => {
131
+ pageView();
132
+ }, []);
133
+ ```
134
+
135
+ **Advanced: Manual Tracking with Router**
136
+
137
+ ```tsx
138
+ import { useLocation } from 'react-router-dom';
139
+ const { pageView } = useContentAnalytics();
140
+ const location = useLocation();
86
141
 
87
- function Layout({ children }) {
88
- const { pageView } = useContentAnalytics();
142
+ useEffect(() => {
143
+ pageView();
144
+ }, [location]);
145
+ ```
89
146
 
90
- useEffect(() => {
91
- pageView({
92
- // Add any custom properties you want to track
93
- myCustomValue: '2'
94
- });
95
- }, []);
147
+ ## API Reference
96
148
 
97
- return <div>{children}</div>;
149
+ ```typescript
150
+ interface DotCMSAnalytics {
151
+ track: (eventName: string, payload?: Record<string, unknown>) => void;
152
+ pageView: () => void;
98
153
  }
99
154
  ```
100
155
 
101
- ## Browser Configuration
156
+ **Enriched AnalyticsEvent includes:**
102
157
 
103
- The script can be configured using data attributes:
158
+ - `context`: siteKey, sessionId, userId
159
+ - `page`: URL, title, referrer, path
160
+ - `device`: screen size, language, viewport
161
+ - `utm`: source, medium, campaign, term, etc.
104
162
 
105
- - **data-analytics-server**: URL of the server where events will be sent. If not provided, the current domain will be used
106
- - **data-analytics-debug**: Enables debug logging
107
- - **data-analytics-auto-page-view**: Recommended for IIFE implementation. Enables automatic page view tracking
108
- - **data-analytics-key**: **(Required)** API key for authentication
163
+ ## Under the Hood
109
164
 
110
- ```html
111
- <!-- Example configuration -->
112
- <script
113
- src="ca.min.js"
114
- data-analytics-server="http://localhost:8080"
115
- data-analytics-key="dev-key-123"
116
- data-analytics-auto-page-view
117
- data-analytics-debug></script>
165
+ ### Storage Keys
118
166
 
119
- <!-- Without automatic tracking - events must be sent manually -->
120
- <script
121
- src="ca.min.js"
122
- data-analytics-server="http://localhost:8080"
123
- data-analytics-debug
124
- data-analytics-key="dev-key-123"></script>
125
- ```
167
+ - `dot_analytics_user_id`
168
+ - `dot_analytics_session_id`
169
+ - `dot_analytics_session_utm`
170
+ - `dot_analytics_session_start`
171
+
172
+ ### Editor Detection
173
+
174
+ Analytics are disabled when inside the dotCMS editor.
175
+
176
+ ## Debugging & Troubleshooting
177
+
178
+ **Not seeing events?**
179
+
180
+ - Ensure `siteKey` & `server` are correct
181
+ - Enable debug mode
182
+ - Check network requests to: `https://your-server/api/v1/analytics/content/event`
183
+ - Avoid using inside dotCMS editor (auto-disabled)
126
184
 
127
185
  ## Roadmap
128
186
 
129
- The following features are planned for future releases:
187
+ - Scroll depth & file download tracking
188
+ - Form interaction analytics
189
+ - Angular & Vue support
190
+ - Realtime dashboard
191
+
192
+ ## dotCMS Support
193
+
194
+ We offer multiple channels to get help with the dotCMS React SDK:
130
195
 
131
- 2. **Headless Support**
132
- - Angular integration for event tracking
196
+ - **GitHub Issues**: For bug reports and feature requests, please [open an issue](https://github.com/dotCMS/core/issues/new/choose) in the GitHub repository.
197
+ - **Community Forum**: Join our [community discussions](https://community.dotcms.com/) to ask questions and share solutions.
198
+ - **Stack Overflow**: Use the tag `dotcms-react` when posting questions.
199
+ - **Enterprise Support**: Enterprise customers can access premium support through the [dotCMS Support Portal](https://helpdesk.dotcms.com/support/).
133
200
 
134
- ## Contributing
201
+ When reporting issues, please include:
135
202
 
136
- GitHub pull requests are the preferred method to contribute code to dotCMS. Before any pull requests can be accepted, an automated tool will ask you to agree to the [dotCMS Contributor's Agreement](https://gist.github.com/wezell/85ef45298c48494b90d92755b583acb3).
203
+ - SDK version you're using
204
+ - React version
205
+ - Minimal reproduction steps
206
+ - Expected vs. actual behavior
137
207
 
138
- ## Licensing
208
+ ## How To Contribute
139
209
 
140
- dotCMS comes in multiple editions and as such is dual licensed. The dotCMS Community Edition is licensed under the GPL 3.0 and is freely available for download, customization and deployment for use within organizations of all stripes. dotCMS Enterprise Editions (EE) adds a number of enterprise features and is available via a supported, indemnified commercial license from dotCMS. For the differences between the editions, see [the feature page](http://dotcms.com/cms-platform/features).
210
+ GitHub pull requests are the preferred method to contribute code to dotCMS. We welcome contributions to the DotCMS UVE SDK! If you'd like to contribute, please follow these steps:
141
211
 
142
- ## Support
212
+ 1. Fork the repository [dotCMS/core](https://github.com/dotCMS/core)
213
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
214
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
215
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
216
+ 5. Open a Pull Request
143
217
 
144
- If you need help or have any questions, please [open an issue](https://github.com/dotCMS/core/issues/new/choose) in the GitHub repository.
218
+ Please ensure your code follows the existing style and includes appropriate tests.
145
219
 
146
- ## Documentation
220
+ ## Licensing Information
147
221
 
148
- Always refer to the official [DotCMS documentation](https://www.dotcms.com/docs/latest/) for comprehensive guides and API references.
222
+ dotCMS comes in multiple editions and as such is dual-licensed. The dotCMS Community Edition is licensed under the GPL 3.0 and is freely available for download, customization, and deployment for use within organizations of all stripes. dotCMS Enterprise Editions (EE) adds several enterprise features and is available via a supported, indemnified commercial license from dotCMS. For the differences between the editions, see [the feature page](http://www.dotcms.com/cms-platform/features).
149
223
 
150
- ## Getting Help
224
+ This SDK is part of dotCMS's dual-licensed platform (GPL 3.0 for Community, commercial license for Enterprise).
151
225
 
152
- | Source | Location |
153
- | --------------- | ------------------------------------------------------------------- |
154
- | Installation | [Installation](https://dotcms.com/docs/latest/installation) |
155
- | Documentation | [Documentation](https://dotcms.com/docs/latest/table-of-contents) |
156
- | Videos | [Helpful Videos](http://dotcms.com/videos/) |
157
- | Forums/Listserv | [via Google Groups](https://groups.google.com/forum/#!forum/dotCMS) |
158
- | Twitter | @dotCMS |
159
- | Main Site | [dotCMS.com](https://dotcms.com/) |
226
+ [Learn more ](https://www.dotcms.com)at [dotcms.com](https://www.dotcms.com).
@@ -1,54 +1,79 @@
1
+ import { EVENT_TYPES as y } from "../shared/dot-content-analytics.constants.js";
1
2
  import { sendAnalyticsEventToServer as c } from "../shared/dot-content-analytics.http.js";
2
- const f = (l) => {
3
- let t = !1;
3
+ const p = (v) => {
4
+ let r = !1;
4
5
  return {
5
6
  name: "dot-analytics",
6
- config: l,
7
+ config: v,
7
8
  /**
8
9
  * Initialize the plugin
9
10
  */
10
- initialize: () => (t = !0, Promise.resolve()),
11
+ initialize: () => (r = !0, Promise.resolve()),
11
12
  /**
12
13
  * Track a page view event
13
14
  * Takes enriched data from properties and creates final structured event
14
15
  */
15
- page: (n) => {
16
- const { config: e, payload: o } = n, { context: i, page: s, device: d, utm: r, local_time: g } = o;
17
- if (!t)
16
+ page: (a) => {
17
+ const { config: t, payload: e } = a, { context: n, page: o, device: i, utm: s, local_time: l } = e;
18
+ if (!r)
18
19
  throw new Error("DotAnalytics: Plugin not initialized");
19
- const a = {
20
- context: i,
20
+ if (!n || !o || !i || !l)
21
+ throw new Error("DotAnalytics: Missing required payload data for pageview event");
22
+ const d = {
23
+ context: n,
21
24
  events: [
22
25
  {
23
- event_type: "pageview",
24
- local_time: g,
25
- page: s,
26
- device: d,
27
- ...r && { utm: r }
26
+ event_type: y.PAGEVIEW,
27
+ local_time: l,
28
+ data: {
29
+ page: o,
30
+ device: i,
31
+ ...s && { utm: s }
32
+ }
28
33
  }
29
34
  ]
30
35
  };
31
- return e.debug && console.warn("Event to send:", a), c(a, e);
36
+ return t.debug && console.warn("DotAnalytics: Pageview event to send:", d), c(d, t);
32
37
  },
38
+ // TODO: Fix this when we haver the final design for the track event
33
39
  /**
34
40
  * Track a custom event
35
41
  * Takes enriched data and sends it to the analytics server
36
42
  */
37
- track: (n) => {
38
- const { config: e, payload: o } = n;
39
- if (!t)
43
+ track: (a) => {
44
+ const { config: t, payload: e } = a;
45
+ if (!r)
40
46
  throw new Error("DotAnalytics: Plugin not initialized");
41
- const i = {
42
- context: o.context
47
+ if ("events" in e && Array.isArray(e.events)) {
48
+ const o = e, i = {
49
+ context: o.context,
50
+ events: o.events
51
+ };
52
+ return t.debug && console.warn("DotAnalytics: Track event to send:", i), c(i, t);
53
+ }
54
+ if (!e.context || !e.local_time)
55
+ throw new Error("DotAnalytics: Missing required payload data for track event");
56
+ const n = {
57
+ context: e.context,
58
+ events: [
59
+ {
60
+ event_type: y.TRACK,
61
+ local_time: e.local_time,
62
+ data: {
63
+ event: e.event,
64
+ ...e.properties
65
+ }
66
+ }
67
+ ]
43
68
  };
44
- return c(i, e);
69
+ return t.debug && console.warn("DotAnalytics: Track event to send (fallback):", n), c(n, t);
45
70
  },
46
71
  /**
47
72
  * Check if the plugin is loaded
48
73
  */
49
- loaded: () => t
74
+ loaded: () => r
50
75
  };
51
76
  };
52
77
  export {
53
- f as dotAnalytics
78
+ p as dotAnalytics
54
79
  };
@@ -19,13 +19,12 @@ export declare const dotAnalyticsEnricherPlugin: () => {
19
19
  }) => {
20
20
  local_time: string;
21
21
  utm?: import('../../shared/dot-content-analytics.model').DotCMSUtmData | undefined;
22
- page: import('analytics').PageData;
22
+ page: import('../../shared/dot-content-analytics.model').DotCMSPageData;
23
23
  device: import('../../shared/dot-content-analytics.model').DotCMSDeviceData;
24
- type: string;
25
- properties: Record<string, unknown>;
26
24
  event: string;
25
+ properties: Record<string, unknown>;
27
26
  options: Record<string, unknown>;
28
- context: import('../../shared/dot-content-analytics.model').DotCMSAnalyticsContext;
27
+ context?: import('../../shared/dot-content-analytics.model').DotCMSAnalyticsContext | undefined;
29
28
  };
30
29
  /**
31
30
  * TRACK EVENT ENRICHMENT - Runs after identity context injection
@@ -35,11 +34,11 @@ export declare const dotAnalyticsEnricherPlugin: () => {
35
34
  payload: DotCMSAnalyticsPayload;
36
35
  }) => {
37
36
  events: {
38
- event_type: string;
39
- custom_event: string;
37
+ event_type: "track";
40
38
  local_time: string;
41
- properties: {
39
+ data: {
42
40
  src: string;
41
+ event: string;
43
42
  };
44
43
  }[];
45
44
  };
@@ -1,27 +1,28 @@
1
- import { ANALYTICS_SOURCE_TYPE as r } from "../../shared/dot-content-analytics.constants.js";
2
- import { getLocalTime as n, enrichPagePayloadOptimized as o } from "../../shared/dot-content-analytics.utils.js";
3
- const s = () => ({
1
+ import { ANALYTICS_SOURCE_TYPE as n, EVENT_TYPES as r } from "../../shared/dot-content-analytics.constants.js";
2
+ import { getLocalTime as a, enrichPagePayloadOptimized as i } from "../../shared/dot-content-analytics.utils.js";
3
+ const l = () => ({
4
4
  name: "enrich-dot-analytics",
5
5
  /**
6
6
  * PAGE VIEW ENRICHMENT - Runs after identity context injection
7
7
  * Uses optimized enrichment that leverages analytics.js payload data
8
8
  */
9
- "page:dot-analytics": ({ payload: e }) => o(e),
9
+ "page:dot-analytics": ({ payload: e }) => i(e),
10
+ // TODO: Fix this when we haver the final design for the track event
10
11
  /**
11
12
  * TRACK EVENT ENRICHMENT - Runs after identity context injection
12
13
  * Creates structured track events with pre-injected context
13
14
  */
14
15
  "track:dot-analytics": ({ payload: e }) => {
15
- const t = n();
16
+ const t = a();
16
17
  return {
17
18
  events: [
18
19
  {
19
- event_type: "track",
20
- custom_event: e.event,
20
+ event_type: r.TRACK,
21
21
  local_time: t,
22
- properties: {
22
+ data: {
23
+ event: e.event,
23
24
  ...e.properties,
24
- src: r
25
+ src: n
25
26
  }
26
27
  }
27
28
  ]
@@ -29,5 +30,5 @@ const s = () => ({
29
30
  }
30
31
  });
31
32
  export {
32
- s as dotAnalyticsEnricherPlugin
33
+ l as dotAnalyticsEnricherPlugin
33
34
  };
@@ -1,7 +1,18 @@
1
1
  export declare const ANALYTICS_WINDOWS_KEY = "dotAnalytics";
2
2
  export declare const ANALYTICS_SOURCE_TYPE = "dotAnalytics";
3
3
  export declare const ANALYTICS_ENDPOINT = "/api/v1/analytics/content/event";
4
- export declare const EXPECTED_UTM_KEYS: string[];
4
+ /**
5
+ * Event Types
6
+ * Only two event types are supported in DotCMS Analytics
7
+ */
8
+ export declare const EVENT_TYPES: {
9
+ readonly PAGEVIEW: "pageview";
10
+ readonly TRACK: "track";
11
+ };
12
+ /**
13
+ * Expected UTM parameter keys for campaign tracking
14
+ */
15
+ export declare const EXPECTED_UTM_KEYS: readonly ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content", "utm_id"];
5
16
  /**
6
17
  * Session configuration constants
7
18
  */
@@ -19,4 +30,4 @@ export declare const USER_ID_KEY = "dot_analytics_user_id";
19
30
  * - click: Detects real user interaction with minimal performance impact
20
31
  * - visibilitychange: Handled separately to detect tab changes
21
32
  */
22
- export declare const ACTIVITY_EVENTS: string[];
33
+ export declare const ACTIVITY_EVENTS: readonly ["click"];
@@ -1,10 +1,14 @@
1
- const _ = "dotAnalytics", t = _, n = "/api/v1/analytics/content/event", s = 30, E = "dot_analytics_session_id", S = "dot_analytics_user_id", c = ["click"];
1
+ const t = "dotAnalytics", E = t, _ = "/api/v1/analytics/content/event", c = {
2
+ PAGEVIEW: "pageview",
3
+ TRACK: "track"
4
+ }, n = 30, s = "dot_analytics_session_id", S = "dot_analytics_user_id", T = ["click"];
2
5
  export {
3
- c as ACTIVITY_EVENTS,
4
- n as ANALYTICS_ENDPOINT,
5
- t as ANALYTICS_SOURCE_TYPE,
6
- _ as ANALYTICS_WINDOWS_KEY,
7
- s as DEFAULT_SESSION_TIMEOUT_MINUTES,
8
- E as SESSION_STORAGE_KEY,
6
+ T as ACTIVITY_EVENTS,
7
+ _ as ANALYTICS_ENDPOINT,
8
+ E as ANALYTICS_SOURCE_TYPE,
9
+ t as ANALYTICS_WINDOWS_KEY,
10
+ n as DEFAULT_SESSION_TIMEOUT_MINUTES,
11
+ c as EVENT_TYPES,
12
+ s as SESSION_STORAGE_KEY,
9
13
  S as USER_ID_KEY
10
14
  };
@@ -1,9 +1,9 @@
1
- import { DotCMSAnalyticsConfig, DotCMSPageViewRequestBody, DotCMSTrackRequestBody } from './dot-content-analytics.model';
1
+ import { DotCMSAnalyticsConfig, DotCMSAnalyticsRequestBody } from './dot-content-analytics.model';
2
2
 
3
3
  /**
4
4
  * Send an analytics event to the server
5
- * @param data - The event data
6
- * @param options - The options for the event
7
- * @returns A promise that resolves to the response from the server
5
+ * @param payload - The event payload data
6
+ * @param config - The analytics configuration
7
+ * @returns A promise that resolves when the request is complete
8
8
  */
9
- export declare const sendAnalyticsEventToServer: (payload: DotCMSPageViewRequestBody | DotCMSTrackRequestBody, options: DotCMSAnalyticsConfig) => Promise<void>;
9
+ export declare const sendAnalyticsEventToServer: (payload: DotCMSAnalyticsRequestBody, config: DotCMSAnalyticsConfig) => Promise<void>;
@@ -1,16 +1,29 @@
1
- import { ANALYTICS_ENDPOINT as o } from "./dot-content-analytics.constants.js";
2
- const n = async (r, t) => {
1
+ import { ANALYTICS_ENDPOINT as a } from "./dot-content-analytics.constants.js";
2
+ const i = async (o, t) => {
3
3
  try {
4
- const e = await fetch(`${t.server}${o}`, {
4
+ const e = await fetch(`${t.server}${a}`, {
5
5
  method: "POST",
6
6
  headers: { "Content-Type": "application/json" },
7
- body: JSON.stringify(r)
7
+ body: JSON.stringify(o)
8
8
  });
9
- e.ok || console.error(`DotAnalytics: Server responded with status ${e.status}`);
9
+ if (!e.ok) {
10
+ const n = e.statusText || "Unknown Error", s = `HTTP ${e.status}: ${n}`;
11
+ try {
12
+ const r = await e.json();
13
+ r.message ? console.warn(`DotAnalytics: ${r.message} (${s})`) : console.warn(
14
+ `DotAnalytics: ${s} - No error message in response`
15
+ );
16
+ } catch (r) {
17
+ console.warn(
18
+ `DotAnalytics: ${s} - Failed to parse error response:`,
19
+ r
20
+ );
21
+ }
22
+ }
10
23
  } catch (e) {
11
24
  console.error("DotAnalytics: Error sending event:", e);
12
25
  }
13
26
  };
14
27
  export {
15
- n as sendAnalyticsEventToServer
28
+ i as sendAnalyticsEventToServer
16
29
  };
@@ -1,3 +1,5 @@
1
+ import { EVENT_TYPES } from './dot-content-analytics.constants';
2
+
1
3
  declare global {
2
4
  interface Window {
3
5
  __dotAnalyticsCleanup?: () => void;
@@ -32,21 +34,49 @@ export interface DotCMSAnalyticsConfig {
32
34
  redirectFn?: (url: string) => void;
33
35
  }
34
36
  /**
35
- * Individual analytics event structure for DotCMS.
36
- * Represents a single event within an analytics request sent to the DotCMS analytics server.
37
+ * Supported event types in DotCMS Analytics.
38
+ * Only two event types are supported: pageview and track.
37
39
  */
38
- export interface DotCMSAnalyticsEvent {
40
+ export type DotCMSEventType = (typeof EVENT_TYPES)[keyof typeof EVENT_TYPES];
41
+ /**
42
+ * Base structure for all analytics events.
43
+ * All events share this common structure.
44
+ */
45
+ export interface DotCMSEventBase {
39
46
  /** The type of event being tracked */
40
- event_type: 'pageview' | 'track';
41
- /** Page data associated with the event */
42
- page: DotCMSPageData;
43
- /** Device and browser information */
44
- device: DotCMSDeviceData;
45
- /** UTM parameters for campaign tracking */
46
- utm?: DotCMSUtmData;
47
+ event_type: DotCMSEventType;
47
48
  /** Local timestamp when the event occurred */
48
49
  local_time: string;
49
50
  }
51
+ /**
52
+ * Pageview-specific analytics event structure.
53
+ * Contains data specific to page view tracking.
54
+ */
55
+ export interface DotCMSPageViewEvent extends DotCMSEventBase {
56
+ event_type: 'pageview';
57
+ /** Pageview-specific event data with structured format */
58
+ data: {
59
+ /** Page data associated with the event */
60
+ page: DotCMSPageData;
61
+ /** Device and browser information */
62
+ device: DotCMSDeviceData;
63
+ /** UTM parameters for campaign tracking (optional) */
64
+ utm?: DotCMSUtmData;
65
+ };
66
+ }
67
+ /**
68
+ * Track-specific analytics event structure.
69
+ * Contains data specific to custom event tracking.
70
+ */
71
+ export interface DotCMSTrackEvent extends DotCMSEventBase {
72
+ event_type: 'track';
73
+ /** Track-specific event data with flexible structure */
74
+ data: Record<string, unknown>;
75
+ }
76
+ /**
77
+ * Union type for all possible analytics events.
78
+ */
79
+ export type DotCMSEvent = DotCMSPageViewEvent | DotCMSTrackEvent;
50
80
  /**
51
81
  * Analytics request body for page view events in DotCMS.
52
82
  * Structure sent to the DotCMS analytics server for page tracking.
@@ -54,8 +84,8 @@ export interface DotCMSAnalyticsEvent {
54
84
  export interface DotCMSPageViewRequestBody {
55
85
  /** Context information shared across all events */
56
86
  context: DotCMSAnalyticsContext;
57
- /** Array of analytics events to be tracked */
58
- events: DotCMSAnalyticsEvent[];
87
+ /** Array of pageview analytics events to be tracked */
88
+ events: DotCMSPageViewEvent[];
59
89
  }
60
90
  /**
61
91
  * Analytics request body for track events in DotCMS.
@@ -64,8 +94,22 @@ export interface DotCMSPageViewRequestBody {
64
94
  export interface DotCMSTrackRequestBody {
65
95
  /** Context information shared across all events */
66
96
  context: DotCMSAnalyticsContext;
67
- /** Array of analytics events to be tracked */
68
- events?: DotCMSAnalyticsEvent[];
97
+ /** Array of track analytics events to be tracked */
98
+ events: DotCMSTrackEvent[];
99
+ }
100
+ /**
101
+ * Union type for all possible request bodies.
102
+ */
103
+ export type DotCMSAnalyticsRequestBody = DotCMSPageViewRequestBody | DotCMSTrackRequestBody;
104
+ /**
105
+ * Enriched payload structure returned by the enricher plugin.
106
+ * Contains pre-structured events and context for direct use in analytics requests.
107
+ */
108
+ export interface DotCMSEnrichedPayload {
109
+ /** Analytics context shared across events */
110
+ context: DotCMSAnalyticsContext;
111
+ /** Array of pre-structured analytics events */
112
+ events: DotCMSEvent[];
69
113
  }
70
114
  /**
71
115
  * Browser event data collected from the user's session in DotCMS.
@@ -108,22 +152,22 @@ export interface DotCMSBrowserEventData {
108
152
  * The payload structure for DotCMS analytics events.
109
153
  * This interface represents the complete data structure that flows through
110
154
  * the analytics pipeline, including original event data and enriched context.
155
+ *
156
+ * This is the internal payload used by Analytics.js and our plugins.
111
157
  */
112
158
  export interface DotCMSAnalyticsPayload {
113
- /** The type of analytics event */
114
- type: string;
115
- /** Additional properties associated with the event */
116
- properties: Record<string, unknown>;
117
159
  /** The event name or identifier */
118
160
  event: string;
161
+ /** Additional properties associated with the event */
162
+ properties: Record<string, unknown>;
119
163
  /** Configuration options for the event */
120
164
  options: Record<string, unknown>;
121
165
  /** Analytics context shared across events */
122
- context: DotCMSAnalyticsContext;
166
+ context?: DotCMSAnalyticsContext;
123
167
  /** Page data for the current page */
124
- page: DotCMSPageData;
168
+ page?: DotCMSPageData;
125
169
  /** Device and browser information */
126
- device: DotCMSDeviceData;
170
+ device?: DotCMSDeviceData;
127
171
  /** UTM parameters for campaign tracking */
128
172
  utm?: DotCMSUtmData;
129
173
  /** Local timestamp when the event occurred */
@@ -146,9 +190,8 @@ export interface DotCMSAnalyticsParams {
146
190
  export interface DotCMSAnalytics {
147
191
  /**
148
192
  * Track a page view event.
149
- * @param payload - Optional additional data to include with the page view
150
193
  */
151
- pageView: (payload?: Record<string, unknown>) => void;
194
+ pageView: () => void;
152
195
  /**
153
196
  * Track a custom event.
154
197
  * @param eventName - The name/type of the event to track
@@ -217,14 +260,12 @@ export interface DotCMSPageData {
217
260
  doc_protocol: string | undefined;
218
261
  /** Document search parameters */
219
262
  doc_search: string;
220
- /** DotCMS host domain */
221
- dot_host: string | undefined;
222
- /** DotCMS page path */
223
- dot_path: string | undefined;
263
+ /** Document host domain */
264
+ doc_host: string | undefined;
265
+ /** Document path */
266
+ doc_path: string | undefined;
224
267
  /** Page title */
225
268
  title: string | undefined;
226
- /** User agent string */
227
- user_agent?: string;
228
269
  /** Language identifier */
229
270
  language_id?: string;
230
271
  /** Persona identifier */
@@ -1,4 +1,4 @@
1
- import { DotCMSAnalyticsConfig, DotCMSAnalyticsContext, DotCMSAnalyticsPayload, DotCMSBrowserEventData, DotCMSDeviceData, DotCMSUtmData } from './dot-content-analytics.model';
1
+ import { DotCMSAnalyticsConfig, DotCMSAnalyticsContext, DotCMSAnalyticsPayload, DotCMSBrowserEventData, DotCMSDeviceData, DotCMSPageData, DotCMSUtmData } from './dot-content-analytics.model';
2
2
  import { PageData } from 'analytics';
3
3
 
4
4
  export { cleanupActivityTracking, getLastActivity, getSessionInfo, initializeActivityTracking, isUserInactive, updateSessionActivity } from './dot-content-analytics.activity-tracker';
@@ -52,11 +52,7 @@ export declare const extractUTMParameters: (location: Location) => Record<string
52
52
  */
53
53
  export declare const defaultRedirectFn: (href: string) => string;
54
54
  /**
55
- * Check if we're inside the DotCMS editor
56
- */
57
- export declare const isInsideEditor: () => boolean;
58
- /**
59
- * Gets local time in ISO format
55
+ * Gets local time in ISO format without milliseconds
60
56
  */
61
57
  export declare const getLocalTime: () => string;
62
58
  /**
@@ -83,13 +79,12 @@ export declare const enrichWithUtmData: (payload: DotCMSAnalyticsPayload) => Dot
83
79
  export declare const enrichPagePayloadOptimized: (payload: DotCMSAnalyticsPayload, location?: Location) => {
84
80
  local_time: string;
85
81
  utm?: DotCMSUtmData | undefined;
86
- page: PageData;
82
+ page: DotCMSPageData;
87
83
  device: DotCMSDeviceData;
88
- type: string;
89
- properties: Record<string, unknown>;
90
84
  event: string;
85
+ properties: Record<string, unknown>;
91
86
  options: Record<string, unknown>;
92
- context: DotCMSAnalyticsContext;
87
+ context?: DotCMSAnalyticsContext | undefined;
93
88
  };
94
89
  /**
95
90
  * @deprecated Use enrichPagePayloadOptimized instead to avoid data duplication
@@ -102,10 +97,9 @@ export declare const enrichPagePayload: (payload: DotCMSAnalyticsPayload, locati
102
97
  utm?: DotCMSUtmData | undefined;
103
98
  page: PageData;
104
99
  device: DotCMSDeviceData;
105
- type: string;
106
- properties: Record<string, unknown>;
107
100
  event: string;
101
+ properties: Record<string, unknown>;
108
102
  options: Record<string, unknown>;
109
- context: DotCMSAnalyticsContext;
103
+ context?: DotCMSAnalyticsContext | undefined;
110
104
  };
111
105
  };
@@ -1,9 +1,9 @@
1
- import { SESSION_STORAGE_KEY as l, DEFAULT_SESSION_TIMEOUT_MINUTES as S, USER_ID_KEY as h } from "./dot-content-analytics.constants.js";
2
- let g = null;
1
+ import { SESSION_STORAGE_KEY as h, DEFAULT_SESSION_TIMEOUT_MINUTES as S, USER_ID_KEY as m } from "./dot-content-analytics.constants.js";
2
+ let d = null;
3
3
  const u = (t) => {
4
4
  const e = Date.now(), n = Math.random().toString(36).substr(2, 9), o = Math.random().toString(36).substr(2, 9);
5
5
  return `${t}_${e}_${n}${o}`;
6
- }, m = {
6
+ }, l = {
7
7
  getItem: (t) => {
8
8
  try {
9
9
  return localStorage.getItem(t);
@@ -19,9 +19,9 @@ const u = (t) => {
19
19
  }
20
20
  }
21
21
  }, f = () => {
22
- let t = m.getItem(h);
23
- return t || (t = u("user"), m.setItem(h, t)), t;
24
- }, w = (t) => {
22
+ let t = l.getItem(m);
23
+ return t || (t = u("user"), l.setItem(m, t)), t;
24
+ }, _ = (t) => {
25
25
  const e = new Date(t), n = /* @__PURE__ */ new Date(), o = new Date(
26
26
  e.getUTCFullYear(),
27
27
  e.getUTCMonth(),
@@ -33,15 +33,15 @@ const u = (t) => {
33
33
  if (typeof window > "u")
34
34
  return u("session_fallback");
35
35
  try {
36
- const e = sessionStorage.getItem(l);
36
+ const e = sessionStorage.getItem(h);
37
37
  if (e) {
38
- const { sessionId: s, startTime: i, lastActivity: c } = JSON.parse(e), d = !w(i), r = t - c < S * 60 * 1e3;
39
- if (d && r)
38
+ const { sessionId: s, startTime: c, lastActivity: i } = JSON.parse(e), g = !_(c), a = t - i < S * 60 * 1e3;
39
+ if (g && a)
40
40
  return sessionStorage.setItem(
41
- l,
41
+ h,
42
42
  JSON.stringify({
43
43
  sessionId: s,
44
- startTime: i,
44
+ startTime: c,
45
45
  lastActivity: t
46
46
  })
47
47
  ), s;
@@ -51,7 +51,7 @@ const u = (t) => {
51
51
  startTime: t,
52
52
  lastActivity: t
53
53
  };
54
- return sessionStorage.setItem(l, JSON.stringify(o)), n;
54
+ return sessionStorage.setItem(h, JSON.stringify(o)), n;
55
55
  } catch {
56
56
  return u("session_fallback");
57
57
  }
@@ -65,67 +65,59 @@ const u = (t) => {
65
65
  session_id: e,
66
66
  user_id: n
67
67
  };
68
- }, I = () => g || (g = {
68
+ }, w = () => d || (d = {
69
69
  user_language: navigator.language || void 0,
70
70
  doc_encoding: document.characterSet || document.charset || void 0,
71
71
  screen_resolution: typeof screen < "u" && screen.width && screen.height ? `${screen.width}x${screen.height}` : void 0
72
- }, g), $ = () => {
73
- if (typeof window > "u")
74
- return !1;
75
- try {
76
- const t = window.self !== window.top, e = window.location.href.includes("mode=EDIT_MODE"), n = window.location.href.includes("/vtl/");
77
- return t || e || n;
78
- } catch {
79
- return !1;
80
- }
81
- }, D = () => {
72
+ }, d), I = () => {
82
73
  try {
83
74
  const t = (/* @__PURE__ */ new Date()).getTimezoneOffset(), e = t > 0 ? "-" : "+", n = Math.abs(t), o = Math.floor(n / 60), s = n % 60;
84
75
  return `${e}${o.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
85
76
  } catch {
86
77
  return "+00:00";
87
78
  }
88
- }, y = () => {
79
+ }, D = () => {
89
80
  try {
90
- const t = /* @__PURE__ */ new Date(), e = D(), n = t.getFullYear(), o = (t.getMonth() + 1).toString().padStart(2, "0"), s = t.getDate().toString().padStart(2, "0"), i = t.getHours().toString().padStart(2, "0"), c = t.getMinutes().toString().padStart(2, "0"), d = t.getSeconds().toString().padStart(2, "0"), r = t.getMilliseconds().toString().padStart(3, "0");
91
- return `${n}-${o}-${s}T${i}:${c}:${d}.${r}${e}`;
81
+ const t = /* @__PURE__ */ new Date(), e = I(), n = t.getFullYear(), o = (t.getMonth() + 1).toString().padStart(2, "0"), s = t.getDate().toString().padStart(2, "0"), c = t.getHours().toString().padStart(2, "0"), i = t.getMinutes().toString().padStart(2, "0"), g = t.getSeconds().toString().padStart(2, "0");
82
+ return `${n}-${o}-${s}T${c}:${i}:${g}${e}`;
92
83
  } catch {
93
84
  return (/* @__PURE__ */ new Date()).toISOString();
94
85
  }
95
- }, v = (t, e = typeof window < "u" ? window.location : {}) => {
96
- const n = y(), o = I(), { properties: s } = t, { utm: i } = s, c = {
86
+ }, $ = (t, e = typeof window < "u" ? window.location : {}) => {
87
+ const n = D(), o = w(), { properties: s } = t, { utm: c } = s, i = {
97
88
  url: s.url ?? e.href,
98
- path: s.path ?? e.pathname,
99
- hash: s.hash ?? e.hash ?? "",
100
- search: s.search ?? e.search ?? "",
89
+ doc_encoding: o.doc_encoding,
90
+ doc_hash: s.hash ?? e.hash ?? "",
91
+ doc_protocol: e.protocol,
92
+ doc_search: s.search ?? e.search ?? "",
93
+ doc_host: e.hostname,
94
+ doc_path: s.path ?? e.pathname,
101
95
  title: s.title ?? (document == null ? void 0 : document.title),
102
- width: String(s.width),
103
- height: String(s.height),
104
- referrer: s.referrer ?? (document == null ? void 0 : document.referrer)
105
- }, d = {
96
+ language_id: void 0,
97
+ persona: void 0
98
+ }, g = {
106
99
  screen_resolution: o.screen_resolution,
107
100
  language: o.user_language,
108
101
  viewport_width: String(s.width),
109
102
  viewport_height: String(s.height)
110
- }, r = {};
111
- if (i && typeof i == "object") {
112
- const a = i;
113
- a.medium && (r.medium = a.medium), a.source && (r.source = a.source), a.campaign && (r.campaign = a.campaign), a.term && (r.term = a.term), a.content && (r.content = a.content);
103
+ }, a = {};
104
+ if (c && typeof c == "object") {
105
+ const r = c;
106
+ r.medium && (a.medium = r.medium), r.source && (a.source = r.source), r.campaign && (a.campaign = r.campaign), r.term && (a.term = r.term), r.content && (a.content = r.content);
114
107
  }
115
108
  return {
116
109
  ...t,
117
- page: c,
118
- device: d,
119
- ...Object.keys(r).length > 0 && { utm: r },
110
+ page: i,
111
+ device: g,
112
+ ...Object.keys(a).length > 0 && { utm: a },
120
113
  local_time: n
121
114
  };
122
115
  };
123
116
  export {
124
- v as enrichPagePayloadOptimized,
117
+ $ as enrichPagePayloadOptimized,
125
118
  u as generateSecureId,
126
119
  T as getAnalyticsContext,
127
- y as getLocalTime,
120
+ D as getLocalTime,
128
121
  p as getSessionId,
129
- f as getUserId,
130
- $ as isInsideEditor
122
+ f as getUserId
131
123
  };
@@ -1,34 +1,32 @@
1
- import { useContext as c, useRef as u, useCallback as o } from "react";
2
- import { isInsideEditor as s } from "../../dotAnalytics/shared/dot-content-analytics.utils.js";
1
+ import { useContext as c, useRef as u, useCallback as a } from "react";
2
+ import { getUVEState as i } from "../../../uve/src/lib/core/core.utils.js";
3
+ import "../../../uve/src/internal/constants.js";
3
4
  import l from "../contexts/DotContentAnalyticsContext.js";
4
- const w = () => {
5
- const t = c(l), i = u(null);
5
+ const S = () => {
6
+ const t = c(l), n = u(null);
6
7
  if (!t)
7
8
  throw new Error(
8
9
  "useContentAnalytics must be used within a DotContentAnalyticsProvider and analytics must be successfully initialized"
9
10
  );
10
- const r = o(
11
- (e, n = {}) => {
12
- s() || t.track(e, {
13
- ...n,
11
+ const s = a(
12
+ (o, e = {}) => {
13
+ i() || t.track(o, {
14
+ ...e,
14
15
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
15
16
  });
16
17
  },
17
18
  [t]
18
- ), a = o(
19
- (e = {}) => {
20
- if (!s()) {
21
- const n = window.location.pathname;
22
- n !== i.current && (i.current = n, t.pageView(e));
23
- }
24
- },
25
- [t]
26
- );
19
+ ), r = a(() => {
20
+ if (!i()) {
21
+ const e = window.location.pathname;
22
+ e !== n.current && (n.current = e, t.pageView());
23
+ }
24
+ }, [t]);
27
25
  return {
28
- track: r,
29
- pageView: a
26
+ track: s,
27
+ pageView: r
30
28
  };
31
29
  };
32
30
  export {
33
- w as useContentAnalytics
31
+ S as useContentAnalytics
34
32
  };
@@ -1,13 +1,14 @@
1
- import { useRef as r, useEffect as i } from "react";
2
- import { isInsideEditor as u } from "../../dotAnalytics/shared/dot-content-analytics.utils.js";
3
- function s(t) {
4
- const n = r(null);
1
+ import { useRef as u, useEffect as i } from "react";
2
+ import { getUVEState as a } from "../../../uve/src/lib/core/core.utils.js";
3
+ import "../../../uve/src/internal/constants.js";
4
+ function p(t) {
5
+ const n = u(null);
5
6
  i(() => {
6
7
  if (!t)
7
8
  return;
8
9
  function e() {
9
- const o = window.location.pathname;
10
- o !== n.current && !u() && t && (n.current = o, t.pageView());
10
+ const o = window.location.pathname, r = a();
11
+ o !== n.current && !r && t && (n.current = o, t.pageView());
11
12
  }
12
13
  return e(), window.addEventListener("popstate", e), window.addEventListener("beforeunload", e), () => {
13
14
  window.removeEventListener("popstate", e), window.removeEventListener("beforeunload", e);
@@ -15,5 +16,5 @@ function s(t) {
15
16
  }, [t]);
16
17
  }
17
18
  export {
18
- s as useRouterTracker
19
+ p as useRouterTracker
19
20
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotcms/analytics",
3
- "version": "0.0.1-beta.43",
3
+ "version": "0.0.1-beta.44",
4
4
  "description": "Official JavaScript library for Content Analytics with DotCMS.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -23,7 +23,8 @@
23
23
  "analytics": "^0.8.14"
24
24
  },
25
25
  "peerDependencies": {
26
- "react": "19.1.0"
26
+ "react": "19.1.0",
27
+ "@dotcms/uve": "0.0.1-beta.44"
27
28
  },
28
29
  "devDependencies": {
29
30
  "@testing-library/jest-dom": "^6.1.6",
@@ -0,0 +1,5 @@
1
+ var N = /* @__PURE__ */ ((r) => (r.EDIT = "EDIT_MODE", r.PREVIEW = "PREVIEW_MODE", r.LIVE = "LIVE", r.UNKNOWN = "UNKNOWN", r))(N || {}), E = /* @__PURE__ */ ((r) => (r.CONTENT_CHANGES = "changes", r.PAGE_RELOAD = "page-reload", r.REQUEST_BOUNDS = "request-bounds", r.IFRAME_SCROLL = "iframe-scroll", r.CONTENTLET_HOVERED = "contentlet-hovered", r))(E || {});
2
+ export {
3
+ E as UVEEventType,
4
+ N as UVE_MODE
5
+ };
@@ -0,0 +1,4 @@
1
+ var t = /* @__PURE__ */ ((e) => (e.UVE_RELOAD_PAGE = "uve-reload-page", e.UVE_REQUEST_BOUNDS = "uve-request-bounds", e.UVE_EDITOR_PONG = "uve-editor-pong", e.UVE_SCROLL_INSIDE_IFRAME = "uve-scroll-inside-iframe", e.UVE_SET_PAGE_DATA = "uve-set-page-data", e.UVE_COPY_CONTENTLET_INLINE_EDITING_SUCCESS = "uve-copy-contentlet-inline-editing-success", e))(t || {});
2
+ export {
3
+ t as __DOTCMS_UVE_EVENT__
4
+ };
@@ -0,0 +1,3 @@
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 + "";
@@ -0,0 +1,108 @@
1
+ import { UVEEventType as a } from "../../../types/src/lib/editor/public.js";
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) {
5
+ const t = (n) => {
6
+ n.data.name === s.UVE_SET_PAGE_DATA && o(n.data.payload);
7
+ };
8
+ return window.addEventListener("message", t), {
9
+ unsubscribe: () => {
10
+ window.removeEventListener("message", t);
11
+ },
12
+ event: a.CONTENT_CHANGES
13
+ };
14
+ }
15
+ function V(o) {
16
+ const t = (n) => {
17
+ n.data.name === s.UVE_RELOAD_PAGE && o();
18
+ };
19
+ return window.addEventListener("message", t), {
20
+ unsubscribe: () => {
21
+ window.removeEventListener("message", t);
22
+ },
23
+ event: a.PAGE_RELOAD
24
+ };
25
+ }
26
+ function I(o) {
27
+ const t = (n) => {
28
+ if (n.data.name === s.UVE_REQUEST_BOUNDS) {
29
+ const e = Array.from(
30
+ document.querySelectorAll('[data-dot-object="container"]')
31
+ ), i = S(e);
32
+ o(i);
33
+ }
34
+ };
35
+ return window.addEventListener("message", t), {
36
+ unsubscribe: () => {
37
+ window.removeEventListener("message", t);
38
+ },
39
+ event: a.REQUEST_BOUNDS
40
+ };
41
+ }
42
+ function Y(o) {
43
+ const t = (n) => {
44
+ if (n.data.name === s.UVE_SCROLL_INSIDE_IFRAME) {
45
+ const e = n.data.direction;
46
+ o(e);
47
+ }
48
+ };
49
+ return window.addEventListener("message", t), {
50
+ unsubscribe: () => {
51
+ window.removeEventListener("message", t);
52
+ },
53
+ event: a.IFRAME_SCROLL
54
+ };
55
+ }
56
+ function B(o) {
57
+ const t = (n) => {
58
+ var d, r, E, c, T, l, m, _, u, C;
59
+ const e = M(n.target);
60
+ if (!e)
61
+ return;
62
+ const { x: i, y: g, width: v, height: N } = e.getBoundingClientRect(), f = ((d = e.dataset) == null ? void 0 : d.dotObject) === "container", L = {
63
+ identifier: "TEMP_EMPTY_CONTENTLET",
64
+ title: "TEMP_EMPTY_CONTENTLET",
65
+ contentType: "TEMP_EMPTY_CONTENTLET_TYPE",
66
+ inode: "TEMPY_EMPTY_CONTENTLET_INODE",
67
+ widgetTitle: "TEMP_EMPTY_CONTENTLET",
68
+ baseType: "TEMP_EMPTY_CONTENTLET",
69
+ onNumberOfPages: 1
70
+ }, P = {
71
+ identifier: (r = e.dataset) == null ? void 0 : r.dotIdentifier,
72
+ title: (E = e.dataset) == null ? void 0 : E.dotTitle,
73
+ inode: (c = e.dataset) == null ? void 0 : c.dotInode,
74
+ contentType: (T = e.dataset) == null ? void 0 : T.dotType,
75
+ baseType: (l = e.dataset) == null ? void 0 : l.dotBasetype,
76
+ widgetTitle: (m = e.dataset) == null ? void 0 : m.dotWidgetTitle,
77
+ onNumberOfPages: (_ = e.dataset) == null ? void 0 : _.dotOnNumberOfPages
78
+ }, O = p(e), b = {
79
+ container: (
80
+ // Here extract dot-container from contentlet if it is Headless
81
+ // or search in parent container if it is VTL
82
+ (u = e.dataset) != null && u.dotContainer ? JSON.parse((C = e.dataset) == null ? void 0 : C.dotContainer) : w(e)
83
+ ),
84
+ contentlet: f ? L : P,
85
+ vtlFiles: O
86
+ };
87
+ o({
88
+ x: i,
89
+ y: g,
90
+ width: v,
91
+ height: N,
92
+ payload: b
93
+ });
94
+ };
95
+ return document.addEventListener("pointermove", t), {
96
+ unsubscribe: () => {
97
+ document.removeEventListener("pointermove", t);
98
+ },
99
+ event: a.CONTENTLET_HOVERED
100
+ };
101
+ }
102
+ export {
103
+ U as onContentChanges,
104
+ B as onContentletHovered,
105
+ Y as onIframeScroll,
106
+ V as onPageReload,
107
+ I as onRequestBounds
108
+ };
@@ -0,0 +1,21 @@
1
+ import { UVE_MODE as t } from "../../../../types/src/lib/editor/public.js";
2
+ import "../../internal/constants.js";
3
+ function p() {
4
+ if (typeof window > "u" || window.parent === window || !window.location)
5
+ return;
6
+ const e = new URL(window.location.href), o = Object.values(t);
7
+ let a = e.searchParams.get("mode") ?? t.EDIT;
8
+ const s = e.searchParams.get("language_id"), n = e.searchParams.get("personaId"), r = e.searchParams.get("variantName"), i = e.searchParams.get("experimentId"), c = e.searchParams.get("publishDate"), d = e.searchParams.get("dotCMSHost");
9
+ return o.includes(a) || (a = t.EDIT), {
10
+ mode: a,
11
+ languageId: s,
12
+ persona: n,
13
+ variantName: r,
14
+ experimentId: i,
15
+ publishDate: c,
16
+ dotCMSHost: d
17
+ };
18
+ }
19
+ export {
20
+ p as getUVEState
21
+ };
@@ -0,0 +1,81 @@
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"]')
6
+ );
7
+ return {
8
+ x: o.x,
9
+ y: o.y,
10
+ width: o.width,
11
+ height: o.height,
12
+ payload: JSON.stringify({
13
+ container: u(a)
14
+ }),
15
+ contentlets: f(o, n)
16
+ };
17
+ });
18
+ }
19
+ function f(t, a) {
20
+ return a.map((o) => {
21
+ var d, r, i, e, s, c;
22
+ const n = o.getBoundingClientRect();
23
+ return {
24
+ x: 0,
25
+ y: n.y - t.y,
26
+ width: n.width,
27
+ height: n.height,
28
+ payload: JSON.stringify({
29
+ container: (d = o.dataset) != null && d.dotContainer ? JSON.parse((r = o.dataset) == null ? void 0 : r.dotContainer) : y(o),
30
+ 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
35
+ }
36
+ })
37
+ };
38
+ });
39
+ }
40
+ function u(t) {
41
+ var a, o, n, d;
42
+ 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) || ""
47
+ };
48
+ }
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);
52
+ }
53
+ function g(t) {
54
+ var o, n, d;
55
+ if (!t)
56
+ return null;
57
+ const a = t.querySelector('[data-dot-object="empty-content"]');
58
+ 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
59
+ ((n = t == null ? void 0 : t.dataset) == null ? void 0 : n.dotObject) === "container" && a || // The container inside Traditional have no content inside
60
+ ((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);
61
+ }
62
+ function h(t) {
63
+ const a = t.querySelectorAll(
64
+ '[data-dot-object="vtl-file"]'
65
+ );
66
+ return a.length ? Array.from(a).map((o) => {
67
+ var n, d;
68
+ return {
69
+ inode: (n = o.dataset) == null ? void 0 : n.dotInode,
70
+ name: (d = o.dataset) == null ? void 0 : d.dotUrl
71
+ };
72
+ }) : null;
73
+ }
74
+ export {
75
+ g as findDotCMSElement,
76
+ h as findDotCMSVTLData,
77
+ y as getClosestDotCMSContainerData,
78
+ u as getDotCMSContainerData,
79
+ f as getDotCMSContentletsBound,
80
+ C as getDotCMSPageBounds
81
+ };