@dotcms/analytics 1.2.0-next.10 → 1.2.0-next.11
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 +117 -2
- package/lib/core/dot-analytics.content.js +47 -26
- package/lib/core/plugin/enricher/dot-analytics.enricher.plugin.js +12 -12
- package/lib/core/plugin/impression/dot-analytics.impression-tracker.js +8 -6
- package/lib/core/plugin/main/dot-analytics.plugin.js +60 -45
- package/lib/core/shared/constants/dot-analytics.constants.d.ts +1 -0
- package/lib/core/shared/constants/dot-analytics.constants.js +5 -4
- package/lib/core/shared/models/event.model.d.ts +49 -15
- package/lib/core/shared/models/library.model.d.ts +12 -3
- package/lib/react/hook/useContentAnalytics.js +17 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -79,6 +79,67 @@ pageView(customData?: Record<string, unknown>): void
|
|
|
79
79
|
- **React**: In development (API may change)
|
|
80
80
|
- Custom data is optional and gets attached to the pageview event under the `custom` property alongside all automatically captured data.
|
|
81
81
|
|
|
82
|
+
### Conversion Tracking
|
|
83
|
+
|
|
84
|
+
The `conversion()` method tracks user conversions (purchases, downloads, sign-ups, etc.) from your application.
|
|
85
|
+
|
|
86
|
+
**⚠️ IMPORTANT: Conversion events are business events that should only be tracked after a successful action or completed goal.** Tracking conversions on clicks or attempts (before success) diminishes their value as conversion metrics. Only track conversions when:
|
|
87
|
+
|
|
88
|
+
- ✅ Purchase is completed and payment is confirmed
|
|
89
|
+
- ✅ Download is successfully completed
|
|
90
|
+
- ✅ Sign-up form is submitted and account is created
|
|
91
|
+
- ✅ Form submission is successful and data is saved
|
|
92
|
+
- ✅ Any business goal is actually achieved
|
|
93
|
+
|
|
94
|
+
**Method signature:**
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
conversion(name: string): void
|
|
98
|
+
conversion(name: string, options?: Record<string, unknown>): void
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Usage examples:**
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// Basic conversion tracking (after successful download)
|
|
105
|
+
analytics.conversion('download');
|
|
106
|
+
|
|
107
|
+
// Conversion with custom metadata (after successful purchase)
|
|
108
|
+
analytics.conversion('purchase', {
|
|
109
|
+
value: 99.99,
|
|
110
|
+
currency: 'USD',
|
|
111
|
+
category: 'ecommerce',
|
|
112
|
+
productId: 'SKU-12345'
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Conversion with additional context (after successful signup)
|
|
116
|
+
analytics.conversion('signup', {
|
|
117
|
+
source: 'homepage',
|
|
118
|
+
plan: 'premium'
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Event payload structure:**
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"event_type": "conversion",
|
|
127
|
+
"local_time": "2025-10-01T16:08:33-04:00",
|
|
128
|
+
"data": {
|
|
129
|
+
"conversion": { "name": "download" },
|
|
130
|
+
"page": { "url": "...", "title": "..." },
|
|
131
|
+
"custom": { "value": 99.99, "currency": "USD", "source": "homepage" }
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Important:**
|
|
137
|
+
|
|
138
|
+
- `name` is required and identifies the conversion type
|
|
139
|
+
- All properties in `options` go into the `custom` object
|
|
140
|
+
- Page data (url, title) is automatically added by the SDK
|
|
141
|
+
- **Only track conversions after successful completion of business goals**
|
|
142
|
+
|
|
82
143
|
### Custom Events
|
|
83
144
|
|
|
84
145
|
The `track()` method allows you to track any custom user action with a unique event name and optional properties.
|
|
@@ -91,7 +152,7 @@ track(eventName: string, properties?: Record<string, unknown>): void
|
|
|
91
152
|
|
|
92
153
|
**Important:**
|
|
93
154
|
|
|
94
|
-
- `eventName` cannot be `"pageview"` (reserved for
|
|
155
|
+
- `eventName` cannot be `"pageview"` or `"conversion"` (reserved for specific tracking methods)
|
|
95
156
|
- `eventName` should be a descriptive string like `"button-click"`, `"form-submit"`, `"video-play"`, etc.
|
|
96
157
|
- `properties` is optional and can contain any custom data relevant to the event
|
|
97
158
|
|
|
@@ -487,10 +548,18 @@ interface DotCMSAnalytics {
|
|
|
487
548
|
|
|
488
549
|
/**
|
|
489
550
|
* Track a custom event
|
|
490
|
-
* @param eventName - Name of the custom event (cannot be "pageview")
|
|
551
|
+
* @param eventName - Name of the custom event (cannot be "pageview" or "conversion")
|
|
491
552
|
* @param properties - Optional object with event-specific properties
|
|
492
553
|
*/
|
|
493
554
|
track: (eventName: string, properties?: Record<string, unknown>) => void;
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* Track a conversion event (purchase, download, sign-up, etc.)
|
|
558
|
+
* ⚠️ IMPORTANT: Only track conversions after successful completion of business goals
|
|
559
|
+
* @param name - Name of the conversion (e.g., "purchase", "download", "signup")
|
|
560
|
+
* @param options - Optional object with conversion metadata (all properties go into custom object)
|
|
561
|
+
*/
|
|
562
|
+
conversion: (name: string, options?: Record<string, unknown>) => void;
|
|
494
563
|
}
|
|
495
564
|
```
|
|
496
565
|
|
|
@@ -580,6 +649,52 @@ When you call `track(eventName, properties)`, the following structure is sent:
|
|
|
580
649
|
}
|
|
581
650
|
```
|
|
582
651
|
|
|
652
|
+
### Conversion Event Structure
|
|
653
|
+
|
|
654
|
+
When you call `conversion(name, options)`, the following structure is sent:
|
|
655
|
+
|
|
656
|
+
```typescript
|
|
657
|
+
{
|
|
658
|
+
context: {
|
|
659
|
+
site_key: string; // Your site key
|
|
660
|
+
session_id: string; // Current session ID
|
|
661
|
+
user_id: string; // Anonymous user ID
|
|
662
|
+
device: { // 🤖 AUTOMATIC - Device & Browser Info
|
|
663
|
+
screen_resolution: string; // Screen size
|
|
664
|
+
language: string; // Browser language
|
|
665
|
+
viewport_width: string; // Viewport width
|
|
666
|
+
viewport_height: string; // Viewport height
|
|
667
|
+
}
|
|
668
|
+
},
|
|
669
|
+
events: [{
|
|
670
|
+
event_type: "conversion",
|
|
671
|
+
local_time: string, // ISO 8601 timestamp
|
|
672
|
+
data: {
|
|
673
|
+
conversion: { // 🤖 AUTOMATIC - Conversion Info
|
|
674
|
+
name: string; // Your conversion name
|
|
675
|
+
},
|
|
676
|
+
page: { // 🤖 AUTOMATIC - Page Information
|
|
677
|
+
url: string; // Full URL
|
|
678
|
+
title: string; // Page title
|
|
679
|
+
},
|
|
680
|
+
custom?: { // 👤 YOUR DATA (optional)
|
|
681
|
+
// All properties from options parameter
|
|
682
|
+
value?: number;
|
|
683
|
+
currency?: string;
|
|
684
|
+
category?: string;
|
|
685
|
+
// ... any other custom properties
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
}]
|
|
689
|
+
}
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
**Key Points:**
|
|
693
|
+
|
|
694
|
+
- 🤖 Conversion name and page data are captured **automatically**
|
|
695
|
+
- 👤 All properties in `options` go into the `custom` object
|
|
696
|
+
- ⚠️ **Only track conversions after successful completion of business goals**
|
|
697
|
+
|
|
583
698
|
## Under the Hood
|
|
584
699
|
|
|
585
700
|
### Storage Keys
|
|
@@ -1,63 +1,84 @@
|
|
|
1
|
-
import { Analytics as
|
|
2
|
-
import { ANALYTICS_WINDOWS_ACTIVE_KEY as
|
|
3
|
-
import { dotAnalyticsClickPlugin as
|
|
1
|
+
import { Analytics as l } from "analytics";
|
|
2
|
+
import { ANALYTICS_WINDOWS_ACTIVE_KEY as a, ANALYTICS_WINDOWS_CLEANUP_KEY as d } from "../../uve/src/internal/constants.js";
|
|
3
|
+
import { dotAnalyticsClickPlugin as y } from "./plugin/click/dot-analytics.click.plugin.js";
|
|
4
4
|
import { dotAnalyticsEnricherPlugin as m } from "./plugin/enricher/dot-analytics.enricher.plugin.js";
|
|
5
5
|
import { dotAnalyticsIdentityPlugin as u } from "./plugin/identity/dot-analytics.identity.plugin.js";
|
|
6
6
|
import { dotAnalyticsImpressionPlugin as p } from "./plugin/impression/dot-analytics.impression.plugin.js";
|
|
7
|
-
import { dotAnalytics as
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
import { dotAnalytics as A } from "./plugin/main/dot-analytics.plugin.js";
|
|
8
|
+
import { DotCMSPredefinedEventType as f } from "./shared/constants/dot-analytics.constants.js";
|
|
9
|
+
import { validateAnalyticsConfig as C, getEnhancedTrackingPlugins as w } from "./shared/utils/dot-analytics.utils.js";
|
|
10
|
+
import { cleanupActivityTracking as g } from "./plugin/identity/dot-analytics.identity.activity-tracker.js";
|
|
11
|
+
const _ = (t) => {
|
|
12
|
+
const e = C(t);
|
|
13
|
+
if (e)
|
|
13
14
|
return console.error(
|
|
14
|
-
`DotCMS Analytics [Core]: Missing ${
|
|
15
|
-
), typeof window < "u" && (window[
|
|
16
|
-
const
|
|
17
|
-
|
|
15
|
+
`DotCMS Analytics [Core]: Missing ${e.join(" and ")} in configuration`
|
|
16
|
+
), typeof window < "u" && (window[a] = !1), null;
|
|
17
|
+
const s = w(
|
|
18
|
+
t,
|
|
18
19
|
p,
|
|
19
|
-
|
|
20
|
-
), i =
|
|
20
|
+
y
|
|
21
|
+
), i = l({
|
|
21
22
|
app: "dotAnalytics",
|
|
22
|
-
debug:
|
|
23
|
+
debug: t.debug,
|
|
23
24
|
plugins: [
|
|
24
|
-
u(
|
|
25
|
+
u(t),
|
|
25
26
|
// Inject identity context
|
|
26
|
-
...
|
|
27
|
+
...s,
|
|
27
28
|
//Track content impressions & clicks (conditionally loaded)
|
|
28
29
|
m(),
|
|
29
30
|
// Enrich and clean payload with page, device, utm data and custom data
|
|
30
|
-
|
|
31
|
+
A(t)
|
|
31
32
|
// Send events to server
|
|
32
33
|
]
|
|
33
|
-
}),
|
|
34
|
-
return typeof window < "u" && (window.addEventListener("beforeunload",
|
|
34
|
+
}), r = () => g();
|
|
35
|
+
return typeof window < "u" && (window.addEventListener("beforeunload", r), window[d] = r, window[a] = !0, window.dispatchEvent(new CustomEvent("dotcms:analytics:ready"))), {
|
|
35
36
|
/**
|
|
36
37
|
* Track a page view.
|
|
37
38
|
* Session activity is automatically updated by the identity plugin.
|
|
38
39
|
* @param payload - Optional custom data to include with the page view (any valid JSON object)
|
|
39
40
|
*/
|
|
40
|
-
pageView: (
|
|
41
|
+
pageView: (n = {}) => {
|
|
41
42
|
if (!i) {
|
|
42
43
|
console.warn("DotCMS Analytics [Core]: Analytics instance not initialized");
|
|
43
44
|
return;
|
|
44
45
|
}
|
|
45
|
-
i.page(
|
|
46
|
+
i.page(n);
|
|
46
47
|
},
|
|
47
48
|
/**
|
|
48
49
|
* Track a custom event.
|
|
49
50
|
* @param eventName - The name of the event to track
|
|
50
51
|
* @param payload - Custom data to include with the event (any valid JSON object)
|
|
51
52
|
*/
|
|
52
|
-
track: (
|
|
53
|
+
track: (n, o = {}) => {
|
|
53
54
|
if (!i) {
|
|
54
55
|
console.warn("DotCMS Analytics [Core]: Analytics instance not initialized");
|
|
55
56
|
return;
|
|
56
57
|
}
|
|
57
|
-
i.track(
|
|
58
|
+
i.track(n, o);
|
|
59
|
+
},
|
|
60
|
+
/**
|
|
61
|
+
* Track a conversion event.
|
|
62
|
+
* @param name - Name of the conversion (e.g., 'purchase', 'download', 'signup')
|
|
63
|
+
* @param options - Optional custom data
|
|
64
|
+
*/
|
|
65
|
+
conversion: (n, o = {}) => {
|
|
66
|
+
if (!i) {
|
|
67
|
+
console.warn("DotCMS Analytics [Core]: Analytics instance not initialized");
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (!n || n.trim() === "") {
|
|
71
|
+
console.warn("DotCMS Analytics [Core]: Conversion name cannot be empty");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const c = {
|
|
75
|
+
name: n,
|
|
76
|
+
...Object.keys(o).length > 0 && { custom: o }
|
|
77
|
+
};
|
|
78
|
+
i.track(f.CONVERSION, c);
|
|
58
79
|
}
|
|
59
80
|
};
|
|
60
81
|
};
|
|
61
82
|
export {
|
|
62
|
-
|
|
83
|
+
_ as initializeContentAnalytics
|
|
63
84
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DotCMSPredefinedEventType as
|
|
1
|
+
import { DotCMSPredefinedEventType as r } from "../../shared/constants/dot-analytics.constants.js";
|
|
2
2
|
import { getLocalTime as i, enrichPagePayloadOptimized as o } from "../../shared/utils/dot-analytics.utils.js";
|
|
3
3
|
const l = () => ({
|
|
4
4
|
name: "enrich-dot-analytics",
|
|
@@ -8,12 +8,12 @@ const l = () => ({
|
|
|
8
8
|
* @returns {EnrichedAnalyticsPayload} Enriched payload ready for event creation
|
|
9
9
|
*/
|
|
10
10
|
"page:dot-analytics": ({
|
|
11
|
-
payload:
|
|
11
|
+
payload: e
|
|
12
12
|
}) => {
|
|
13
|
-
const
|
|
14
|
-
if (!
|
|
13
|
+
const t = o(e);
|
|
14
|
+
if (!t.page)
|
|
15
15
|
throw new Error("DotCMS Analytics: Missing required page data");
|
|
16
|
-
return
|
|
16
|
+
return t;
|
|
17
17
|
},
|
|
18
18
|
/**
|
|
19
19
|
* TRACK EVENT ENRICHMENT - Runs after identity context injection
|
|
@@ -23,19 +23,19 @@ const l = () => ({
|
|
|
23
23
|
* @returns {EnrichedTrackPayload} Enriched payload ready for event structuring
|
|
24
24
|
*/
|
|
25
25
|
"track:dot-analytics": ({
|
|
26
|
-
payload:
|
|
26
|
+
payload: e
|
|
27
27
|
}) => {
|
|
28
|
-
const { event:
|
|
29
|
-
return
|
|
30
|
-
...
|
|
28
|
+
const { event: t } = e, n = i();
|
|
29
|
+
return t === r.CONTENT_IMPRESSION || t === r.CONTENT_CLICK || t === r.CONVERSION ? {
|
|
30
|
+
...e,
|
|
31
31
|
page: {
|
|
32
32
|
title: document.title,
|
|
33
33
|
url: window.location.href
|
|
34
34
|
},
|
|
35
|
-
local_time:
|
|
35
|
+
local_time: n
|
|
36
36
|
} : {
|
|
37
|
-
...
|
|
38
|
-
local_time:
|
|
37
|
+
...e,
|
|
38
|
+
local_time: n
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
});
|
|
@@ -2,8 +2,8 @@ import { getUVEState as m } from "../../../../uve/src/lib/core/core.utils.js";
|
|
|
2
2
|
import "../../../../uve/src/internal/constants.js";
|
|
3
3
|
import { getViewportMetrics as d, isElementMeetingVisibilityThreshold as u } from "./dot-analytics.impression.utils.js";
|
|
4
4
|
import { DEFAULT_IMPRESSION_CONFIG as l, IMPRESSION_EVENT_TYPE as g } from "../../shared/constants/dot-analytics.constants.js";
|
|
5
|
-
import { createPluginLogger as p, isBrowser as a, findContentlets as b, extractContentletIdentifier as c, createContentletObserver as
|
|
6
|
-
class
|
|
5
|
+
import { createPluginLogger as p, isBrowser as a, INITIAL_SCAN_DELAY_MS as f, findContentlets as b, extractContentletIdentifier as c, createContentletObserver as v, extractContentletData as I } from "../../shared/utils/dot-analytics.utils.js";
|
|
6
|
+
class E {
|
|
7
7
|
constructor(e) {
|
|
8
8
|
this.observer = null, this.mutationObserver = null, this.elementImpressionStates = /* @__PURE__ */ new Map(), this.sessionTrackedImpressions = /* @__PURE__ */ new Set(), this.currentPagePath = "", this.subscribers = /* @__PURE__ */ new Set(), this.logger = p("Impression", e), this.impressionConfig = this.resolveImpressionConfig(e.impressions);
|
|
9
9
|
}
|
|
@@ -43,7 +43,9 @@ class C {
|
|
|
43
43
|
this.logger.warn("Impression tracking disabled in editor mode");
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
|
-
this.initializeIntersectionObserver(),
|
|
46
|
+
this.initializeIntersectionObserver(), typeof window < "u" && setTimeout(() => {
|
|
47
|
+
this.logger.debug("Running initial scan after timeout..."), this.findAndObserveContentletElements();
|
|
48
|
+
}, f), this.initializeDynamicContentDetector(), this.initializePageVisibilityHandler(), this.initializePageNavigationHandler(), this.logger.info("Impression tracking initialized with config:", this.impressionConfig);
|
|
47
49
|
}
|
|
48
50
|
}
|
|
49
51
|
/** Sets up IntersectionObserver with configured visibility threshold */
|
|
@@ -90,7 +92,7 @@ class C {
|
|
|
90
92
|
}
|
|
91
93
|
/** Watches for new contentlets added to DOM (debounced for performance) */
|
|
92
94
|
initializeDynamicContentDetector() {
|
|
93
|
-
a() && (this.mutationObserver =
|
|
95
|
+
a() && (this.mutationObserver = v(() => {
|
|
94
96
|
this.findAndObserveContentletElements();
|
|
95
97
|
}), this.logger.info("MutationObserver enabled for dynamic content detection"));
|
|
96
98
|
}
|
|
@@ -148,7 +150,7 @@ class C {
|
|
|
148
150
|
trackAndSendImpression(e, i) {
|
|
149
151
|
const t = this.elementImpressionStates.get(e);
|
|
150
152
|
if (!t) return;
|
|
151
|
-
const s = t.visibleSince ? Date.now() - t.visibleSince : 0, n =
|
|
153
|
+
const s = t.visibleSince ? Date.now() - t.visibleSince : 0, n = I(i), r = d(i), o = parseInt(i.dataset.dotAnalyticsDomIndex || "-1", 10), h = {
|
|
152
154
|
content: {
|
|
153
155
|
identifier: n.identifier,
|
|
154
156
|
inode: n.inode,
|
|
@@ -196,5 +198,5 @@ class C {
|
|
|
196
198
|
}
|
|
197
199
|
}
|
|
198
200
|
export {
|
|
199
|
-
|
|
201
|
+
E as DotCMSImpressionTracker
|
|
200
202
|
};
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { DotCMSPredefinedEventType as
|
|
2
|
-
import { sendAnalyticsEvent as
|
|
1
|
+
import { DotCMSPredefinedEventType as r } from "../../shared/constants/dot-analytics.constants.js";
|
|
2
|
+
import { sendAnalyticsEvent as N } from "../../shared/http/dot-analytics.http.js";
|
|
3
3
|
import { createAnalyticsQueue as w } from "../../shared/queue/dot-analytics.queue.utils.js";
|
|
4
|
-
const _ = (
|
|
4
|
+
const _ = (d) => {
|
|
5
5
|
let u = !1;
|
|
6
|
-
const m =
|
|
7
|
-
let
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
m &&
|
|
6
|
+
const m = d.queue !== !1;
|
|
7
|
+
let p = null;
|
|
8
|
+
const v = (e) => {
|
|
9
|
+
const c = e.events[0], t = e.context;
|
|
10
|
+
m && p ? p.enqueue(c, t) : N(e, d);
|
|
11
11
|
};
|
|
12
12
|
return {
|
|
13
13
|
name: "dot-analytics",
|
|
14
|
-
config:
|
|
14
|
+
config: d,
|
|
15
15
|
/**
|
|
16
16
|
* Initialize the plugin with optional queue management
|
|
17
17
|
*/
|
|
18
|
-
initialize: () => (u = !0, m && (
|
|
18
|
+
initialize: () => (u = !0, m && (p = w(d), p.initialize()), Promise.resolve()),
|
|
19
19
|
/**
|
|
20
20
|
* Track a page view event
|
|
21
21
|
* Receives enriched payload from the enricher plugin and structures it into a pageview event
|
|
@@ -23,24 +23,24 @@ const _ = (l) => {
|
|
|
23
23
|
page: ({ payload: e }) => {
|
|
24
24
|
if (!u)
|
|
25
25
|
throw new Error("DotCMS Analytics: Plugin not initialized");
|
|
26
|
-
const { context:
|
|
26
|
+
const { context: c, page: t, utm: E, custom: s, local_time: a } = e;
|
|
27
27
|
if (!t)
|
|
28
28
|
throw new Error("DotCMS Analytics: Missing required page data");
|
|
29
|
-
const
|
|
30
|
-
context:
|
|
29
|
+
const y = {
|
|
30
|
+
context: c,
|
|
31
31
|
events: [
|
|
32
32
|
{
|
|
33
|
-
event_type:
|
|
34
|
-
local_time:
|
|
33
|
+
event_type: r.PAGEVIEW,
|
|
34
|
+
local_time: a,
|
|
35
35
|
data: {
|
|
36
36
|
page: t,
|
|
37
|
-
...
|
|
38
|
-
...
|
|
37
|
+
...E && { utm: E },
|
|
38
|
+
...s && { custom: s }
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
]
|
|
42
42
|
};
|
|
43
|
-
y
|
|
43
|
+
v(y);
|
|
44
44
|
},
|
|
45
45
|
/**
|
|
46
46
|
* Track a custom or predefined event
|
|
@@ -53,44 +53,59 @@ const _ = (l) => {
|
|
|
53
53
|
track: ({ payload: e }) => {
|
|
54
54
|
if (!u)
|
|
55
55
|
throw new Error("DotCMS Analytics: Plugin not initialized");
|
|
56
|
-
const { event:
|
|
57
|
-
let
|
|
58
|
-
switch (
|
|
59
|
-
case
|
|
60
|
-
const
|
|
61
|
-
if (!
|
|
56
|
+
const { event: c, properties: t, context: E, local_time: s } = e;
|
|
57
|
+
let a;
|
|
58
|
+
switch (c) {
|
|
59
|
+
case r.CONTENT_IMPRESSION: {
|
|
60
|
+
const l = t, { content: n, position: i } = l, { page: o } = e;
|
|
61
|
+
if (!n || !i || !o)
|
|
62
62
|
throw new Error("DotCMS Analytics: Missing required impression data");
|
|
63
|
-
|
|
64
|
-
event_type:
|
|
65
|
-
local_time:
|
|
63
|
+
a = {
|
|
64
|
+
event_type: r.CONTENT_IMPRESSION,
|
|
65
|
+
local_time: s,
|
|
66
66
|
data: {
|
|
67
|
-
content:
|
|
68
|
-
position:
|
|
69
|
-
page:
|
|
67
|
+
content: n,
|
|
68
|
+
position: i,
|
|
69
|
+
page: o
|
|
70
70
|
}
|
|
71
71
|
};
|
|
72
72
|
break;
|
|
73
73
|
}
|
|
74
|
-
case
|
|
75
|
-
const
|
|
76
|
-
if (!
|
|
74
|
+
case r.CONTENT_CLICK: {
|
|
75
|
+
const l = t, { content: n, position: i, element: o } = l, { page: C } = e;
|
|
76
|
+
if (!n || !i || !o || !C)
|
|
77
77
|
throw new Error("DotCMS Analytics: Missing required click data");
|
|
78
|
-
|
|
79
|
-
event_type:
|
|
80
|
-
local_time:
|
|
78
|
+
a = {
|
|
79
|
+
event_type: r.CONTENT_CLICK,
|
|
80
|
+
local_time: s,
|
|
81
81
|
data: {
|
|
82
|
-
content:
|
|
83
|
-
position:
|
|
84
|
-
element:
|
|
82
|
+
content: n,
|
|
83
|
+
position: i,
|
|
84
|
+
element: o,
|
|
85
85
|
page: C
|
|
86
86
|
}
|
|
87
87
|
};
|
|
88
88
|
break;
|
|
89
89
|
}
|
|
90
|
+
case r.CONVERSION: {
|
|
91
|
+
const l = t, { name: n, custom: i } = l, { page: o } = e;
|
|
92
|
+
if (!n || !o)
|
|
93
|
+
throw new Error("DotCMS Analytics: Missing required conversion data");
|
|
94
|
+
a = {
|
|
95
|
+
event_type: r.CONVERSION,
|
|
96
|
+
local_time: s,
|
|
97
|
+
data: {
|
|
98
|
+
conversion: { name: n },
|
|
99
|
+
page: o,
|
|
100
|
+
...i && { custom: i }
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
90
105
|
default: {
|
|
91
|
-
|
|
92
|
-
event_type:
|
|
93
|
-
local_time:
|
|
106
|
+
a = {
|
|
107
|
+
event_type: c,
|
|
108
|
+
local_time: s,
|
|
94
109
|
data: {
|
|
95
110
|
custom: t
|
|
96
111
|
}
|
|
@@ -98,9 +113,9 @@ const _ = (l) => {
|
|
|
98
113
|
break;
|
|
99
114
|
}
|
|
100
115
|
}
|
|
101
|
-
|
|
102
|
-
context:
|
|
103
|
-
events: [
|
|
116
|
+
v({
|
|
117
|
+
context: E,
|
|
118
|
+
events: [a]
|
|
104
119
|
});
|
|
105
120
|
},
|
|
106
121
|
/**
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
const I = "/api/v1/analytics/content/event", c = {
|
|
2
2
|
PAGEVIEW: "pageview",
|
|
3
3
|
CONTENT_IMPRESSION: "content_impression",
|
|
4
|
-
CONTENT_CLICK: "content_click"
|
|
4
|
+
CONTENT_CLICK: "content_click",
|
|
5
|
+
CONVERSION: "conversion"
|
|
5
6
|
}, s = [
|
|
6
7
|
"utm_source",
|
|
7
8
|
"utm_medium",
|
|
@@ -27,13 +28,13 @@ const I = "/api/v1/analytics/content/event", c = {
|
|
|
27
28
|
dwellMs: T,
|
|
28
29
|
maxNodes: n,
|
|
29
30
|
throttleMs: S
|
|
30
|
-
}, U = "content_impression", M = "content_click", D = 300,
|
|
31
|
+
}, U = "content_impression", M = "content_click", D = 300, R = "a, button", a = "dotcms-analytics-contentlet";
|
|
31
32
|
export {
|
|
32
33
|
L as ACTIVITY_EVENTS,
|
|
33
|
-
|
|
34
|
+
a as ANALYTICS_CONTENTLET_CLASS,
|
|
34
35
|
I as ANALYTICS_ENDPOINT,
|
|
35
36
|
i as ANALYTICS_JS_DEFAULT_PROPERTIES,
|
|
36
|
-
|
|
37
|
+
R as CLICKABLE_ELEMENTS_SELECTOR,
|
|
37
38
|
M as CLICK_EVENT_TYPE,
|
|
38
39
|
D as DEFAULT_CLICK_THROTTLE_MS,
|
|
39
40
|
C as DEFAULT_IMPRESSION_CONFIG,
|
|
@@ -50,6 +50,24 @@ export type DotCMSCustomEventData = {
|
|
|
50
50
|
/** Custom data associated with the event (any valid JSON) */
|
|
51
51
|
custom: JsonObject;
|
|
52
52
|
};
|
|
53
|
+
/**
|
|
54
|
+
* Element information for analytics events.
|
|
55
|
+
* Base type for element metadata in click and conversion events.
|
|
56
|
+
*/
|
|
57
|
+
export type DotCMSElementData = {
|
|
58
|
+
/** Text content of the element */
|
|
59
|
+
text: string;
|
|
60
|
+
/** Type of element (anchor, button, input, etc.) */
|
|
61
|
+
type: string;
|
|
62
|
+
/** Element ID (required by backend, empty string if not present) */
|
|
63
|
+
id: string;
|
|
64
|
+
/** Element classes (required by backend, empty string if not present) */
|
|
65
|
+
class: string;
|
|
66
|
+
/** Link destination as written in HTML (relative path, only for <a> elements, empty string for buttons) */
|
|
67
|
+
href: string;
|
|
68
|
+
/** Additional element attributes in key:value format (e.g., ['data-category:val', 'data-campaign:val2']) */
|
|
69
|
+
attributes: string[];
|
|
70
|
+
};
|
|
53
71
|
/**
|
|
54
72
|
* Partial content impression data sent by producer plugins.
|
|
55
73
|
* Contains only impression-specific data (content and position).
|
|
@@ -81,20 +99,17 @@ export type DotCMSContentImpressionPayload = {
|
|
|
81
99
|
*/
|
|
82
100
|
export type DotCMSContentClickPayload = DotCMSContentImpressionPayload & {
|
|
83
101
|
/** Clicked element information */
|
|
84
|
-
element:
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
/** Additional element attributes in key:value format (e.g., ['data-category:val', 'data-campaign:val2']) */
|
|
96
|
-
attributes: string[];
|
|
97
|
-
};
|
|
102
|
+
element: DotCMSElementData;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Conversion payload sent when tracking conversions.
|
|
106
|
+
* Contains conversion name and optional custom data.
|
|
107
|
+
*/
|
|
108
|
+
export type DotCMSConversionPayload = {
|
|
109
|
+
/** Name of the conversion event */
|
|
110
|
+
name: string;
|
|
111
|
+
/** Optional custom user data (any valid JSON) */
|
|
112
|
+
custom?: JsonObject;
|
|
98
113
|
};
|
|
99
114
|
/**
|
|
100
115
|
* Complete data structure for content impression events after enrichment.
|
|
@@ -112,6 +127,21 @@ export type DotCMSContentClickEventData = DotCMSContentClickPayload & {
|
|
|
112
127
|
/** Minimal page data where the click occurred (added by enricher) */
|
|
113
128
|
page: DotCMSContentImpressionPageData;
|
|
114
129
|
};
|
|
130
|
+
/**
|
|
131
|
+
* Complete data structure for conversion events after enrichment.
|
|
132
|
+
* Includes page data added by the enricher plugin.
|
|
133
|
+
*/
|
|
134
|
+
export type DotCMSConversionEventData = {
|
|
135
|
+
/** Conversion information */
|
|
136
|
+
conversion: {
|
|
137
|
+
/** Name of the user-defined conversion */
|
|
138
|
+
name: string;
|
|
139
|
+
};
|
|
140
|
+
/** Page data where the conversion occurred (added by enricher) */
|
|
141
|
+
page: DotCMSContentImpressionPageData;
|
|
142
|
+
/** Optional custom user data (any valid JSON) */
|
|
143
|
+
custom?: JsonObject;
|
|
144
|
+
};
|
|
115
145
|
/**
|
|
116
146
|
* Pageview event structure.
|
|
117
147
|
*/
|
|
@@ -124,6 +154,10 @@ export type DotCMSContentImpressionEvent = DotCMSEventBase<typeof DotCMSPredefin
|
|
|
124
154
|
* Content click event structure.
|
|
125
155
|
*/
|
|
126
156
|
export type DotCMSContentClickEvent = DotCMSEventBase<typeof DotCMSPredefinedEventType.CONTENT_CLICK, DotCMSContentClickEventData>;
|
|
157
|
+
/**
|
|
158
|
+
* Conversion event structure.
|
|
159
|
+
*/
|
|
160
|
+
export type DotCMSConversionEvent = DotCMSEventBase<typeof DotCMSPredefinedEventType.CONVERSION, DotCMSConversionEventData>;
|
|
127
161
|
/**
|
|
128
162
|
* Custom event structure.
|
|
129
163
|
*/
|
|
@@ -132,4 +166,4 @@ export type DotCMSCustomEvent = DotCMSEventBase<DotCMSCustomEventType, DotCMSCus
|
|
|
132
166
|
* Union type for all possible analytics events.
|
|
133
167
|
* Used primarily for type documentation and validation.
|
|
134
168
|
*/
|
|
135
|
-
export type DotCMSEvent = DotCMSPageViewEvent | DotCMSContentImpressionEvent | DotCMSContentClickEvent | DotCMSCustomEvent;
|
|
169
|
+
export type DotCMSEvent = DotCMSPageViewEvent | DotCMSContentImpressionEvent | DotCMSContentClickEvent | DotCMSConversionEvent | DotCMSCustomEvent;
|
|
@@ -45,20 +45,29 @@ export interface ViewportMetrics {
|
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
47
47
|
* Main interface for the DotCMS Analytics SDK.
|
|
48
|
-
* Provides the core methods for tracking page views
|
|
48
|
+
* Provides the core methods for tracking page views, custom events, and conversions.
|
|
49
49
|
*/
|
|
50
50
|
export interface DotCMSAnalytics {
|
|
51
51
|
/**
|
|
52
52
|
* Track a page view event.
|
|
53
53
|
* @param payload - Optional custom data to include with the page view (any valid JSON object)
|
|
54
54
|
*/
|
|
55
|
-
pageView
|
|
55
|
+
pageView(): void;
|
|
56
|
+
pageView(payload: JsonObject): void;
|
|
56
57
|
/**
|
|
57
58
|
* Track a custom event.
|
|
58
59
|
* @param eventName - The name/type of the event to track
|
|
59
60
|
* @param payload - Custom data to include with the event (any valid JSON object)
|
|
60
61
|
*/
|
|
61
|
-
track
|
|
62
|
+
track(eventName: string): void;
|
|
63
|
+
track(eventName: string, payload: JsonObject): void;
|
|
64
|
+
/**
|
|
65
|
+
* Track a conversion event.
|
|
66
|
+
* @param name - Name of the conversion (e.g., 'purchase', 'download', 'signup')
|
|
67
|
+
* @param options - Optional custom data and element information
|
|
68
|
+
*/
|
|
69
|
+
conversion(name: string): void;
|
|
70
|
+
conversion(name: string, options: JsonObject): void;
|
|
62
71
|
}
|
|
63
72
|
/**
|
|
64
73
|
* Configuration interface for DotCMS Analytics SDK.
|
|
@@ -1,27 +1,33 @@
|
|
|
1
|
-
import { useMemo as
|
|
2
|
-
import { getUVEState as
|
|
1
|
+
import { useMemo as s, useCallback as o } from "react";
|
|
2
|
+
import { getUVEState as l } from "../../../uve/src/lib/core/core.utils.js";
|
|
3
3
|
import "../../../uve/src/internal/constants.js";
|
|
4
|
-
import { initializeAnalytics as
|
|
5
|
-
const h = (
|
|
6
|
-
const t =
|
|
4
|
+
import { initializeAnalytics as m } from "../internal/utils.js";
|
|
5
|
+
const h = (i) => {
|
|
6
|
+
const t = s(() => m(i), [i.server, i.siteAuth]), e = s(() => !!l(), []);
|
|
7
7
|
if (!t)
|
|
8
8
|
throw new Error(
|
|
9
9
|
"DotCMS Analytics: Failed to initialize. Please verify the required configuration (server and siteAuth)."
|
|
10
10
|
);
|
|
11
11
|
const a = o(
|
|
12
|
-
(
|
|
13
|
-
e || t.track(
|
|
12
|
+
(r, n = {}) => {
|
|
13
|
+
e || t.track(r, n);
|
|
14
14
|
},
|
|
15
15
|
[t, e]
|
|
16
|
-
),
|
|
17
|
-
(
|
|
18
|
-
e || t.pageView(
|
|
16
|
+
), c = o(
|
|
17
|
+
(r = {}) => {
|
|
18
|
+
e || t.pageView(r);
|
|
19
|
+
},
|
|
20
|
+
[t, e]
|
|
21
|
+
), u = o(
|
|
22
|
+
(r, n = {}) => {
|
|
23
|
+
e || t.conversion(r, n);
|
|
19
24
|
},
|
|
20
25
|
[t, e]
|
|
21
26
|
);
|
|
22
27
|
return {
|
|
23
28
|
track: a,
|
|
24
|
-
pageView:
|
|
29
|
+
pageView: c,
|
|
30
|
+
conversion: u
|
|
25
31
|
};
|
|
26
32
|
};
|
|
27
33
|
export {
|