@dotcms/analytics 1.2.4 → 1.2.5
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 +495 -535
- package/lib/core/dot-analytics.content.js +25 -21
- package/lib/core/plugin/impression/dot-analytics.impression-tracker.js +13 -21
- package/lib/react/hook/useContentAnalytics.d.ts +1 -2
- package/lib/react/hook/useContentAnalytics.js +35 -23
- package/lib/react/hook/useRouterTracker.d.ts +1 -1
- package/lib/react/hook/useRouterTracker.js +11 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,645 +1,562 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @dotcms/analytics
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Content Analytics SDK for tracking content-aware events in dotCMS-powered React applications.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Quick Start
|
|
6
6
|
|
|
7
|
-
###
|
|
8
|
-
|
|
9
|
-
```html
|
|
10
|
-
<script
|
|
11
|
-
src="ca.min.js"
|
|
12
|
-
data-analytics-server="https://demo.dotcms.com"
|
|
13
|
-
data-analytics-auth="SITE_AUTH"
|
|
14
|
-
data-analytics-auto-page-view="true"
|
|
15
|
-
data-analytics-debug="false"></script>
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
**npm (ES Module)**
|
|
7
|
+
### 1. Install
|
|
19
8
|
|
|
20
9
|
```bash
|
|
21
10
|
npm install @dotcms/analytics
|
|
22
11
|
```
|
|
23
12
|
|
|
24
|
-
|
|
25
|
-
import { initializeContentAnalytics } from '@dotcms/analytics';
|
|
26
|
-
|
|
27
|
-
const analytics = initializeContentAnalytics({
|
|
28
|
-
siteAuth: 'SITE_AUTH',
|
|
29
|
-
server: 'https://demo.dotcms.com'
|
|
30
|
-
});
|
|
13
|
+
### 2. Create a centralized config file
|
|
31
14
|
|
|
32
|
-
|
|
15
|
+
```javascript
|
|
16
|
+
// src/config/analytics.config.js
|
|
17
|
+
export const analyticsConfig = {
|
|
18
|
+
siteAuth: process.env.NEXT_PUBLIC_DOTCMS_ANALYTICS_SITE_KEY,
|
|
19
|
+
server: process.env.NEXT_PUBLIC_DOTCMS_ANALYTICS_HOST,
|
|
20
|
+
autoPageView: true,
|
|
21
|
+
debug: process.env.NEXT_PUBLIC_DOTCMS_ANALYTICS_DEBUG === 'true',
|
|
22
|
+
impressions: true,
|
|
23
|
+
clicks: true
|
|
24
|
+
};
|
|
33
25
|
```
|
|
34
26
|
|
|
35
|
-
###
|
|
27
|
+
### 3. Add automatic page view tracking to your layout
|
|
36
28
|
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
```tsx
|
|
29
|
+
```jsx
|
|
30
|
+
// src/app/layout.js
|
|
42
31
|
import { DotContentAnalytics } from '@dotcms/analytics/react';
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
32
|
+
import { analyticsConfig } from '@/config/analytics.config';
|
|
33
|
+
|
|
34
|
+
export default function RootLayout({ children }) {
|
|
35
|
+
return (
|
|
36
|
+
<html lang="en">
|
|
37
|
+
<body>
|
|
38
|
+
<DotContentAnalytics config={analyticsConfig} />
|
|
39
|
+
{children}
|
|
40
|
+
</body>
|
|
41
|
+
</html>
|
|
42
|
+
);
|
|
52
43
|
}
|
|
53
44
|
```
|
|
54
45
|
|
|
55
|
-
|
|
46
|
+
### 4. Track events in your components
|
|
56
47
|
|
|
57
|
-
|
|
48
|
+
```jsx
|
|
49
|
+
'use client';
|
|
58
50
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
The `pageView()` method tracks page navigation events. **It automatically enriches the event with comprehensive data**, including:
|
|
51
|
+
import { useContentAnalytics } from '@dotcms/analytics/react';
|
|
52
|
+
import { analyticsConfig } from '@/config/analytics.config';
|
|
62
53
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
- **UTM parameters**: Campaign tracking data (source, medium, campaign, etc.)
|
|
66
|
-
- **Context**: Site key, session ID, user ID, timestamp
|
|
54
|
+
function ContactForm() {
|
|
55
|
+
const { conversion } = useContentAnalytics(analyticsConfig);
|
|
67
56
|
|
|
68
|
-
|
|
57
|
+
const handleSubmit = (e) => {
|
|
58
|
+
e.preventDefault();
|
|
59
|
+
// ... submit form logic ...
|
|
69
60
|
|
|
70
|
-
|
|
61
|
+
// Track conversion ONLY after successful submission
|
|
62
|
+
conversion('form-submit', {
|
|
63
|
+
formName: 'contact-us',
|
|
64
|
+
formType: 'lead-gen'
|
|
65
|
+
});
|
|
66
|
+
};
|
|
71
67
|
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
return <form onSubmit={handleSubmit}>{/* form fields */}</form>;
|
|
69
|
+
}
|
|
74
70
|
```
|
|
75
71
|
|
|
76
|
-
|
|
72
|
+
## Understanding the Components
|
|
77
73
|
|
|
78
|
-
|
|
79
|
-
- **React**: In development (API may change)
|
|
80
|
-
- Custom data is optional and gets attached to the pageview event under the `custom` property alongside all automatically captured data.
|
|
74
|
+
The SDK exports two React primitives. Understanding their roles is critical for correct usage.
|
|
81
75
|
|
|
82
|
-
###
|
|
83
|
-
|
|
84
|
-
The `conversion()` method tracks user conversions (purchases, downloads, sign-ups, etc.) from your application.
|
|
76
|
+
### `<DotContentAnalytics />` -- Automatic Page View Tracker
|
|
85
77
|
|
|
86
|
-
|
|
78
|
+
- Its **only purpose** is to automatically track page views on route changes
|
|
79
|
+
- It is **NOT** a React Context Provider
|
|
80
|
+
- It does **NOT** share config with child components
|
|
81
|
+
- Place it once in your root layout
|
|
87
82
|
|
|
88
|
-
|
|
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
|
|
83
|
+
### `useContentAnalytics(config)` -- Manual Tracking Hook
|
|
93
84
|
|
|
94
|
-
|
|
85
|
+
- Used for custom events, conversions, and manual page views
|
|
86
|
+
- **ALWAYS requires `config` as a parameter** -- it does not read from context
|
|
87
|
+
- Import the centralized config in every component that uses the hook
|
|
95
88
|
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
|
|
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:**
|
|
89
|
+
```jsx
|
|
90
|
+
// Every component that tracks events must import config explicitly
|
|
91
|
+
import { useContentAnalytics } from '@dotcms/analytics/react';
|
|
92
|
+
import { analyticsConfig } from '@/config/analytics.config';
|
|
123
93
|
|
|
124
|
-
|
|
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
|
-
}
|
|
94
|
+
const { track, pageView, conversion } = useContentAnalytics(analyticsConfig);
|
|
134
95
|
```
|
|
135
96
|
|
|
136
|
-
**
|
|
97
|
+
> **Why centralize config?** You must import it in each component, but having a single file prevents duplication and makes updates easier.
|
|
137
98
|
|
|
138
|
-
|
|
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**
|
|
99
|
+
## Configuration
|
|
142
100
|
|
|
143
|
-
###
|
|
101
|
+
### Environment Variables
|
|
144
102
|
|
|
145
|
-
|
|
103
|
+
Add these to your `.env.local` file:
|
|
146
104
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
105
|
+
```bash
|
|
106
|
+
NEXT_PUBLIC_DOTCMS_ANALYTICS_SITE_KEY=YOUR_ANALYTICS_SITE_KEY
|
|
107
|
+
NEXT_PUBLIC_DOTCMS_ANALYTICS_HOST=http://localhost:8080
|
|
108
|
+
NEXT_PUBLIC_DOTCMS_ANALYTICS_DEBUG=true
|
|
151
109
|
```
|
|
152
110
|
|
|
153
|
-
|
|
111
|
+
| Variable | Description |
|
|
112
|
+
| --- | --- |
|
|
113
|
+
| `NEXT_PUBLIC_DOTCMS_ANALYTICS_SITE_KEY` | Site auth key from the Content Analytics app in dotCMS |
|
|
114
|
+
| `NEXT_PUBLIC_DOTCMS_ANALYTICS_HOST` | URL where your dotCMS instance is running |
|
|
115
|
+
| `NEXT_PUBLIC_DOTCMS_ANALYTICS_DEBUG` | Set to `"true"` to enable verbose console logging |
|
|
154
116
|
|
|
155
|
-
|
|
156
|
-
- `eventName` should be a descriptive string like `"button-click"`, `"form-submit"`, `"video-play"`, etc.
|
|
157
|
-
- `properties` is optional and can contain any custom data relevant to the event
|
|
117
|
+
### Config Options
|
|
158
118
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
- Stored in `dot_analytics_user_id`
|
|
169
|
-
|
|
170
|
-
## ⚙️ Configuration Options
|
|
171
|
-
|
|
172
|
-
| Option | Type | Required | Default | Description |
|
|
173
|
-
| -------------- | --------------------------- | -------- | ----------------------------------- | ---------------------------------------------------------------- |
|
|
174
|
-
| `siteAuth` | `string` | ✅ | - | Site auth from dotCMS Analytics app |
|
|
175
|
-
| `server` | `string` | ✅ | - | Your dotCMS server URL |
|
|
176
|
-
| `debug` | `boolean` | ❌ | `false` | Enable verbose logging |
|
|
177
|
-
| `autoPageView` | `boolean` | ❌ | React: `true` / Standalone: `false` | Auto track page views on route changes |
|
|
178
|
-
| `queueConfig` | `QueueConfig` | ❌ | See below | Event batching configuration |
|
|
179
|
-
| `impressions` | `ImpressionConfig\|boolean` | ❌ | `false` | Content impression tracking (disabled by default) |
|
|
180
|
-
| `clicks` | `boolean` | ❌ | `false` | Content click tracking with 300ms throttle (disabled by default) |
|
|
119
|
+
| Option | Type | Required | Default | Description |
|
|
120
|
+
| --- | --- | --- | --- | --- |
|
|
121
|
+
| `siteAuth` | `string` | Yes | -- | Site auth from dotCMS Analytics app |
|
|
122
|
+
| `server` | `string` | Yes | -- | Your dotCMS server URL |
|
|
123
|
+
| `debug` | `boolean` | No | `false` | Enable verbose logging |
|
|
124
|
+
| `autoPageView` | `boolean` | No | `true` | Auto track page views on route changes |
|
|
125
|
+
| `queue` | `QueueConfig \| false` | No | See below | Event batching configuration |
|
|
126
|
+
| `impressions` | `ImpressionConfig \| boolean` | No | `false` | Content impression tracking |
|
|
127
|
+
| `clicks` | `boolean` | No | `false` | Content click tracking (300ms throttle) |
|
|
181
128
|
|
|
182
129
|
### Queue Configuration
|
|
183
130
|
|
|
184
|
-
|
|
131
|
+
Controls how events are batched before being sent to the server:
|
|
185
132
|
|
|
186
133
|
- **`false`**: Disable queuing, send events immediately
|
|
187
134
|
- **`undefined` (default)**: Enable queuing with default settings
|
|
188
|
-
- **`QueueConfig` object**:
|
|
135
|
+
- **`QueueConfig` object**: Custom settings
|
|
189
136
|
|
|
190
|
-
| Option
|
|
191
|
-
|
|
|
192
|
-
| `eventBatchSize` | `number` | `15`
|
|
193
|
-
| `flushInterval`
|
|
137
|
+
| Option | Type | Default | Description |
|
|
138
|
+
| --- | --- | --- | --- |
|
|
139
|
+
| `eventBatchSize` | `number` | `15` | Max events per batch -- auto-sends when reached |
|
|
140
|
+
| `flushInterval` | `number` | `5000` | Time between flushes in milliseconds |
|
|
194
141
|
|
|
195
|
-
|
|
142
|
+
How it works:
|
|
196
143
|
|
|
197
|
-
-
|
|
198
|
-
-
|
|
199
|
-
-
|
|
200
|
-
-
|
|
201
|
-
|
|
202
|
-
**About page unload handling:**
|
|
203
|
-
|
|
204
|
-
The SDK uses modern APIs (`visibilitychange` + `pagehide`) instead of `beforeunload`/`unload` to ensure:
|
|
205
|
-
|
|
206
|
-
- ✅ Better reliability on mobile devices
|
|
207
|
-
- ✅ Compatible with browser back/forward cache (bfcache)
|
|
208
|
-
- ✅ Events are sent via `navigator.sendBeacon()` for guaranteed delivery
|
|
209
|
-
- ✅ No negative impact on page performance
|
|
210
|
-
|
|
211
|
-
**Example: Disable queuing for immediate sends**
|
|
144
|
+
- Sends immediately when `eventBatchSize` is reached
|
|
145
|
+
- Sends pending events every `flushInterval` milliseconds
|
|
146
|
+
- Auto-flushes on page navigation/close using `visibilitychange` + `pagehide`
|
|
147
|
+
- Uses `navigator.sendBeacon()` for reliable delivery on page unload
|
|
212
148
|
|
|
213
149
|
```javascript
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
**Example: Custom queue config**
|
|
150
|
+
// Disable queuing (send immediately)
|
|
151
|
+
export const analyticsConfig = {
|
|
152
|
+
siteAuth: process.env.NEXT_PUBLIC_DOTCMS_ANALYTICS_SITE_KEY,
|
|
153
|
+
server: process.env.NEXT_PUBLIC_DOTCMS_ANALYTICS_HOST,
|
|
154
|
+
queue: false
|
|
155
|
+
};
|
|
222
156
|
|
|
223
|
-
|
|
224
|
-
const
|
|
225
|
-
siteAuth:
|
|
226
|
-
server:
|
|
157
|
+
// Custom queue settings
|
|
158
|
+
export const analyticsConfig = {
|
|
159
|
+
siteAuth: process.env.NEXT_PUBLIC_DOTCMS_ANALYTICS_SITE_KEY,
|
|
160
|
+
server: process.env.NEXT_PUBLIC_DOTCMS_ANALYTICS_HOST,
|
|
227
161
|
queue: {
|
|
228
|
-
eventBatchSize: 10,
|
|
229
|
-
flushInterval: 3000
|
|
162
|
+
eventBatchSize: 10,
|
|
163
|
+
flushInterval: 3000
|
|
230
164
|
}
|
|
231
|
-
}
|
|
165
|
+
};
|
|
232
166
|
```
|
|
233
167
|
|
|
234
|
-
### Impression Tracking
|
|
168
|
+
### Impression Tracking
|
|
235
169
|
|
|
236
|
-
|
|
170
|
+
Controls automatic tracking of content visibility in the viewport:
|
|
237
171
|
|
|
238
|
-
- **`false` or `undefined` (default)**:
|
|
239
|
-
- **`true`**:
|
|
240
|
-
- **`ImpressionConfig` object**:
|
|
172
|
+
- **`false` or `undefined` (default)**: Disabled
|
|
173
|
+
- **`true`**: Enabled with default settings
|
|
174
|
+
- **`ImpressionConfig` object**: Custom settings
|
|
241
175
|
|
|
242
|
-
| Option
|
|
243
|
-
|
|
|
244
|
-
| `visibilityThreshold` | `number` | `0.5`
|
|
245
|
-
| `dwellMs`
|
|
246
|
-
| `maxNodes`
|
|
176
|
+
| Option | Type | Default | Description |
|
|
177
|
+
| --- | --- | --- | --- |
|
|
178
|
+
| `visibilityThreshold` | `number` | `0.5` | Min percentage visible (0.0 to 1.0) |
|
|
179
|
+
| `dwellMs` | `number` | `750` | Min time visible in milliseconds |
|
|
180
|
+
| `maxNodes` | `number` | `1000` | Max elements to track (performance limit) |
|
|
247
181
|
|
|
248
|
-
|
|
182
|
+
How it works:
|
|
249
183
|
|
|
250
|
-
-
|
|
251
|
-
-
|
|
252
|
-
-
|
|
253
|
-
-
|
|
254
|
-
-
|
|
255
|
-
- ✅ Respects user consent settings
|
|
256
|
-
- ✅ Automatically disabled in dotCMS editor mode
|
|
257
|
-
|
|
258
|
-
**Example: Enable with defaults**
|
|
184
|
+
- Tracks contentlets marked with `dotcms-contentlet` class and `data-dot-*` attributes
|
|
185
|
+
- Uses Intersection Observer API for performance
|
|
186
|
+
- Only fires when an element is visible for the configured threshold and dwell time
|
|
187
|
+
- One impression per contentlet per session (no duplicates)
|
|
188
|
+
- Automatically disabled in dotCMS editor mode
|
|
259
189
|
|
|
260
190
|
```javascript
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
impressions: true
|
|
265
|
-
}
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
**Example: Custom thresholds**
|
|
191
|
+
// Enable with defaults (50% visible, 750ms dwell)
|
|
192
|
+
export const analyticsConfig = {
|
|
193
|
+
// ...required fields
|
|
194
|
+
impressions: true
|
|
195
|
+
};
|
|
269
196
|
|
|
270
|
-
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
server: 'https://your-dotcms.com',
|
|
197
|
+
// Custom thresholds
|
|
198
|
+
export const analyticsConfig = {
|
|
199
|
+
// ...required fields
|
|
274
200
|
impressions: {
|
|
275
|
-
visibilityThreshold: 0.7,
|
|
276
|
-
dwellMs: 1000,
|
|
277
|
-
maxNodes: 500
|
|
201
|
+
visibilityThreshold: 0.7,
|
|
202
|
+
dwellMs: 1000,
|
|
203
|
+
maxNodes: 500
|
|
278
204
|
}
|
|
279
|
-
}
|
|
205
|
+
};
|
|
280
206
|
```
|
|
281
207
|
|
|
282
|
-
|
|
208
|
+
### Click Tracking
|
|
283
209
|
|
|
284
|
-
|
|
285
|
-
const analytics = initializeContentAnalytics({
|
|
286
|
-
siteAuth: 'abc123',
|
|
287
|
-
server: 'https://your-dotcms.com',
|
|
288
|
-
impressions: false // Explicitly disabled (also default if omitted)
|
|
289
|
-
});
|
|
290
|
-
```
|
|
210
|
+
Controls automatic tracking of user clicks on content elements:
|
|
291
211
|
|
|
292
|
-
|
|
212
|
+
- **`false` or `undefined` (default)**: Disabled
|
|
213
|
+
- **`true`**: Enabled with 300ms throttle
|
|
293
214
|
|
|
294
|
-
|
|
215
|
+
How it works:
|
|
295
216
|
|
|
296
|
-
-
|
|
297
|
-
-
|
|
217
|
+
- Tracks clicks on `<a>` and `<button>` elements within contentlets
|
|
218
|
+
- Contentlets must be marked with `dotcms-contentlet` class and `data-dot-*` attributes
|
|
219
|
+
- Captures semantic attributes (`href`, `aria-label`, `data-*`) and excludes CSS classes
|
|
220
|
+
- Throttles rapid clicks to prevent duplicates (300ms)
|
|
221
|
+
- Automatically disabled in dotCMS editor mode
|
|
298
222
|
|
|
299
|
-
**
|
|
223
|
+
**Captured data per click:**
|
|
300
224
|
|
|
301
|
-
-
|
|
302
|
-
-
|
|
303
|
-
-
|
|
304
|
-
- ✅ Throttles rapid clicks to prevent duplicate tracking (300ms fixed)
|
|
305
|
-
- ✅ One click event per interaction
|
|
306
|
-
- ✅ Respects user consent settings
|
|
307
|
-
- ✅ Automatically disabled in dotCMS editor mode
|
|
225
|
+
- **Content Info**: `identifier`, `inode`, `title`, `content_type`
|
|
226
|
+
- **Element Info**: `text`, `type` (a/button), `id`, `class`, `href`, `attributes`
|
|
227
|
+
- **Position Info**: `viewport_offset_pct`, `dom_index`
|
|
308
228
|
|
|
309
|
-
|
|
229
|
+
You can enrich click data using `data-*` attributes in your HTML:
|
|
310
230
|
|
|
311
|
-
|
|
231
|
+
```html
|
|
232
|
+
<a
|
|
233
|
+
href="/signup"
|
|
234
|
+
id="cta-signup"
|
|
235
|
+
data-category="primary-cta"
|
|
236
|
+
data-campaign="summer-sale"
|
|
237
|
+
aria-label="Sign up for free trial">
|
|
238
|
+
Start Free Trial
|
|
239
|
+
</a>
|
|
312
240
|
|
|
313
|
-
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
- `id` - Element ID (required by backend, empty string if not present)
|
|
318
|
-
- `class` - Element CSS classes (required by backend, empty string if not present)
|
|
319
|
-
- `href` - Link destination as written in HTML (e.g., `/signup` not `http://...`, only for `<a>`, empty string for buttons)
|
|
320
|
-
- `attributes` - Additional useful attributes (see below)
|
|
321
|
-
- **Position Info**:
|
|
322
|
-
- `viewport_offset_pct` - Position relative to viewport (0-100%)
|
|
323
|
-
- `dom_index` - Element position in DOM
|
|
241
|
+
<button data-action="download" data-file-type="pdf" data-category="lead-magnet">
|
|
242
|
+
Download Whitepaper
|
|
243
|
+
</button>
|
|
244
|
+
```
|
|
324
245
|
|
|
325
|
-
|
|
246
|
+
## Core Concepts
|
|
326
247
|
|
|
327
|
-
|
|
248
|
+
### Event Types
|
|
328
249
|
|
|
329
|
-
The
|
|
250
|
+
The SDK sends four types of events, identified by `event_type`:
|
|
330
251
|
|
|
331
|
-
|
|
252
|
+
| Event Type | Trigger | Requires |
|
|
253
|
+
| --- | --- | --- |
|
|
254
|
+
| `pageview` | Automatically on route change, or manually via `pageView()` | `autoPageView: true` or manual call |
|
|
255
|
+
| `content_impression` | When a contentlet becomes visible in the viewport | `impressions` config enabled |
|
|
256
|
+
| `content_click` | When a user clicks a link/button inside a contentlet | `clicks` config enabled |
|
|
257
|
+
| `conversion` | Explicitly via `conversion()` after a successful business action | Manual call |
|
|
332
258
|
|
|
333
|
-
|
|
334
|
-
- `aria-*` - Accessibility attributes (e.g., `'aria-label:Sign up now'`)
|
|
335
|
-
- `title` - Element title
|
|
336
|
-
- `target` - Link target (e.g., `'target:_blank'`)
|
|
337
|
-
- Any other standard HTML attributes
|
|
259
|
+
### Page Views
|
|
338
260
|
|
|
339
|
-
|
|
261
|
+
The `pageView()` method tracks page navigation events. It **automatically enriches** the event with:
|
|
340
262
|
|
|
341
|
-
-
|
|
342
|
-
-
|
|
343
|
-
-
|
|
344
|
-
-
|
|
263
|
+
- **Page data**: URL, title, referrer, path, protocol, search params
|
|
264
|
+
- **Device data**: Screen resolution, viewport size, language, user agent
|
|
265
|
+
- **UTM parameters**: Campaign tracking data (source, medium, campaign, term, content)
|
|
266
|
+
- **Context**: Site key, session ID, user ID, timestamp
|
|
345
267
|
|
|
346
|
-
**
|
|
268
|
+
You can optionally pass custom data that will be sent **in addition** to all the automatic enrichment.
|
|
347
269
|
|
|
348
|
-
|
|
349
|
-
const analytics = initializeContentAnalytics({
|
|
350
|
-
siteAuth: 'abc123',
|
|
351
|
-
server: 'https://your-dotcms.com',
|
|
352
|
-
clicks: true // Enable with 300ms throttle (fixed)
|
|
353
|
-
});
|
|
354
|
-
```
|
|
270
|
+
### Conversion Tracking
|
|
355
271
|
|
|
356
|
-
|
|
272
|
+
The `conversion()` method tracks user conversions (purchases, downloads, sign-ups, etc.).
|
|
357
273
|
|
|
358
|
-
|
|
274
|
+
**Only track conversions after a successful action or completed goal.** Tracking on clicks or attempts (before success) diminishes their value as conversion metrics. Track when:
|
|
359
275
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
id="cta-signup"
|
|
365
|
-
data-category="primary-cta"
|
|
366
|
-
data-campaign="summer-sale"
|
|
367
|
-
aria-label="Sign up for free trial">
|
|
368
|
-
Start Free Trial →
|
|
369
|
-
</a>
|
|
276
|
+
- Purchase is completed and payment is confirmed
|
|
277
|
+
- Download is successfully completed
|
|
278
|
+
- Sign-up form is submitted and account is created
|
|
279
|
+
- Any business goal is actually achieved
|
|
370
280
|
|
|
371
|
-
|
|
372
|
-
<a href="/products/123" data-product-id="123" data-product-name="Premium Plan" data-price="29.99">
|
|
373
|
-
View Product
|
|
374
|
-
</a>
|
|
281
|
+
### Custom Events
|
|
375
282
|
|
|
376
|
-
|
|
377
|
-
<button data-action="download" data-file-type="pdf" data-category="lead-magnet">
|
|
378
|
-
Download Whitepaper
|
|
379
|
-
</button>
|
|
380
|
-
```
|
|
283
|
+
The `track()` method tracks any custom user action with a unique event name and optional properties.
|
|
381
284
|
|
|
382
|
-
|
|
285
|
+
- `eventName` cannot be `"pageview"` or `"conversion"` (reserved)
|
|
286
|
+
- Use descriptive names: `"button-click"`, `"form-submit"`, `"video-play"`, etc.
|
|
383
287
|
|
|
384
|
-
|
|
385
|
-
{
|
|
386
|
-
"content": {
|
|
387
|
-
"identifier": "abc123",
|
|
388
|
-
"inode": "xyz789",
|
|
389
|
-
"title": "Product Page",
|
|
390
|
-
"content_type": "Page"
|
|
391
|
-
},
|
|
392
|
-
"element": {
|
|
393
|
-
"text": "Start Free Trial →",
|
|
394
|
-
"type": "a",
|
|
395
|
-
"id": "cta-signup",
|
|
396
|
-
"class": "btn btn-primary text-white",
|
|
397
|
-
"href": "/signup",
|
|
398
|
-
"attributes": [
|
|
399
|
-
"data-category:primary-cta",
|
|
400
|
-
"data-campaign:summer-sale",
|
|
401
|
-
"aria-label:Sign up for free trial",
|
|
402
|
-
"target:_blank"
|
|
403
|
-
]
|
|
404
|
-
},
|
|
405
|
-
"position": {
|
|
406
|
-
"viewport_offset_pct": 45.2,
|
|
407
|
-
"dom_index": 2
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
```
|
|
288
|
+
### Sessions
|
|
411
289
|
|
|
412
|
-
|
|
290
|
+
- 30-minute inactivity timeout
|
|
291
|
+
- Resets at midnight UTC
|
|
292
|
+
- New session if UTM campaign changes
|
|
413
293
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
clicks: false // Explicitly disabled (also default if omitted)
|
|
419
|
-
});
|
|
420
|
-
```
|
|
294
|
+
### Identity
|
|
295
|
+
|
|
296
|
+
- Anonymous user ID persisted across sessions
|
|
297
|
+
- Stored in `dot_analytics_user_id`
|
|
421
298
|
|
|
422
|
-
##
|
|
299
|
+
## Usage Examples
|
|
423
300
|
|
|
424
|
-
###
|
|
301
|
+
### Automatic Page View Tracking
|
|
425
302
|
|
|
426
|
-
|
|
303
|
+
Add `DotContentAnalytics` to your root layout. No additional code is needed -- page views are tracked on every route change.
|
|
427
304
|
|
|
428
|
-
```
|
|
429
|
-
//
|
|
430
|
-
|
|
431
|
-
|
|
305
|
+
```jsx
|
|
306
|
+
// src/app/layout.js
|
|
307
|
+
import { DotContentAnalytics } from '@dotcms/analytics/react';
|
|
308
|
+
import { analyticsConfig } from '@/config/analytics.config';
|
|
309
|
+
|
|
310
|
+
export default function RootLayout({ children }) {
|
|
311
|
+
return (
|
|
312
|
+
<html lang="en">
|
|
313
|
+
<body>
|
|
314
|
+
<DotContentAnalytics config={analyticsConfig} />
|
|
315
|
+
{children}
|
|
316
|
+
</body>
|
|
317
|
+
</html>
|
|
318
|
+
);
|
|
319
|
+
}
|
|
432
320
|
```
|
|
433
321
|
|
|
434
|
-
|
|
322
|
+
### Manual Page View with Custom Data
|
|
435
323
|
|
|
436
|
-
```
|
|
437
|
-
|
|
438
|
-
// Plus your custom properties are added under 'custom'
|
|
439
|
-
window.dotAnalytics.pageView({
|
|
440
|
-
contentType: 'blog',
|
|
441
|
-
category: 'technology',
|
|
442
|
-
author: 'john-doe',
|
|
443
|
-
wordCount: 1500
|
|
444
|
-
});
|
|
445
|
-
|
|
446
|
-
// The server receives: page + device + utm + context + custom (your data)
|
|
447
|
-
```
|
|
324
|
+
```jsx
|
|
325
|
+
'use client';
|
|
448
326
|
|
|
449
|
-
|
|
327
|
+
import { useEffect } from 'react';
|
|
328
|
+
import { useContentAnalytics } from '@dotcms/analytics/react';
|
|
329
|
+
import { analyticsConfig } from '@/config/analytics.config';
|
|
450
330
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
window.dotAnalytics.track('cta-click', {
|
|
454
|
-
button: 'Buy Now',
|
|
455
|
-
location: 'hero-section'
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
// Track form submission
|
|
459
|
-
window.dotAnalytics.track('form-submit', {
|
|
460
|
-
formName: 'contact-form',
|
|
461
|
-
formType: 'lead-gen'
|
|
462
|
-
});
|
|
463
|
-
|
|
464
|
-
// Track video interaction
|
|
465
|
-
window.dotAnalytics.track('video-play', {
|
|
466
|
-
videoId: 'intro-video',
|
|
467
|
-
duration: 120,
|
|
468
|
-
autoplay: false
|
|
469
|
-
});
|
|
470
|
-
```
|
|
331
|
+
function BlogPost({ post }) {
|
|
332
|
+
const { pageView } = useContentAnalytics(analyticsConfig);
|
|
471
333
|
|
|
472
|
-
|
|
334
|
+
useEffect(() => {
|
|
335
|
+
pageView({
|
|
336
|
+
contentType: 'blog',
|
|
337
|
+
category: post.category,
|
|
338
|
+
author: post.author,
|
|
339
|
+
wordCount: post.wordCount
|
|
340
|
+
});
|
|
341
|
+
}, []);
|
|
473
342
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
siteAuth: 'abc123',
|
|
477
|
-
server: 'https://your-dotcms.com',
|
|
478
|
-
debug: true,
|
|
479
|
-
autoPageView: false
|
|
480
|
-
});
|
|
481
|
-
|
|
482
|
-
// Track custom events with properties
|
|
483
|
-
analytics.track('product-view', {
|
|
484
|
-
productId: 'SKU-12345',
|
|
485
|
-
category: 'Electronics',
|
|
486
|
-
price: 299.99,
|
|
487
|
-
inStock: true
|
|
488
|
-
});
|
|
489
|
-
|
|
490
|
-
// Manual page view with custom data
|
|
491
|
-
// Automatic enrichment (page, device, UTM, context) + your custom data
|
|
492
|
-
analytics.pageView({
|
|
493
|
-
section: 'checkout',
|
|
494
|
-
step: 'payment',
|
|
495
|
-
cartValue: 299.99
|
|
496
|
-
});
|
|
343
|
+
return <article>{/* post content */}</article>;
|
|
344
|
+
}
|
|
497
345
|
```
|
|
498
346
|
|
|
499
|
-
###
|
|
347
|
+
### Custom Event Tracking
|
|
500
348
|
|
|
501
|
-
|
|
349
|
+
```jsx
|
|
350
|
+
'use client';
|
|
502
351
|
|
|
503
|
-
|
|
352
|
+
import { useContentAnalytics } from '@dotcms/analytics/react';
|
|
353
|
+
import { analyticsConfig } from '@/config/analytics.config';
|
|
504
354
|
|
|
505
|
-
|
|
506
|
-
|
|
355
|
+
function CallToAction() {
|
|
356
|
+
const { track } = useContentAnalytics(analyticsConfig);
|
|
507
357
|
|
|
508
|
-
const
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
358
|
+
const handleClick = () => {
|
|
359
|
+
track('cta-click', {
|
|
360
|
+
button: 'Buy Now',
|
|
361
|
+
location: 'hero-section',
|
|
362
|
+
price: 299.99
|
|
363
|
+
});
|
|
364
|
+
};
|
|
513
365
|
|
|
514
|
-
|
|
515
|
-
return <DotContentAnalytics config={config} />;
|
|
366
|
+
return <button onClick={handleClick}>Buy Now</button>;
|
|
516
367
|
}
|
|
517
368
|
```
|
|
518
369
|
|
|
519
|
-
|
|
370
|
+
### Conversion Tracking (Real-World Example)
|
|
371
|
+
|
|
372
|
+
This example is based on the Contact Us form in the [Next.js example app](https://github.com/dotCMS/core/tree/main/examples/nextjs):
|
|
373
|
+
|
|
374
|
+
```jsx
|
|
375
|
+
'use client';
|
|
520
376
|
|
|
521
|
-
|
|
377
|
+
import { useState } from 'react';
|
|
522
378
|
import { useContentAnalytics } from '@dotcms/analytics/react';
|
|
379
|
+
import { analyticsConfig } from '@/config/analytics.config';
|
|
380
|
+
|
|
381
|
+
export default function ContactUs({ description }) {
|
|
382
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
383
|
+
const [isSuccess, setIsSuccess] = useState(false);
|
|
384
|
+
const { conversion } = useContentAnalytics(analyticsConfig);
|
|
385
|
+
|
|
386
|
+
const handleSubmit = (e) => {
|
|
387
|
+
e.preventDefault();
|
|
388
|
+
setIsSubmitting(true);
|
|
389
|
+
|
|
390
|
+
// Simulate form submission
|
|
391
|
+
setTimeout(() => {
|
|
392
|
+
setIsSuccess(true);
|
|
393
|
+
|
|
394
|
+
// Track conversion ONLY after successful submission
|
|
395
|
+
conversion('form-submit', {
|
|
396
|
+
formName: 'contact-us',
|
|
397
|
+
formType: 'lead-gen'
|
|
398
|
+
});
|
|
399
|
+
}, 3000);
|
|
400
|
+
};
|
|
523
401
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
402
|
+
return (
|
|
403
|
+
<form onSubmit={handleSubmit}>
|
|
404
|
+
{/* form fields */}
|
|
405
|
+
<button type="submit" disabled={isSubmitting}>
|
|
406
|
+
{isSubmitting ? 'Submitting...' : 'Submit'}
|
|
407
|
+
</button>
|
|
408
|
+
</form>
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
```
|
|
529
412
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
413
|
+
### E-commerce Purchase Conversion
|
|
414
|
+
|
|
415
|
+
```jsx
|
|
416
|
+
'use client';
|
|
417
|
+
|
|
418
|
+
import { useContentAnalytics } from '@dotcms/analytics/react';
|
|
419
|
+
import { analyticsConfig } from '@/config/analytics.config';
|
|
420
|
+
|
|
421
|
+
function CheckoutButton({ product, quantity }) {
|
|
422
|
+
const { conversion } = useContentAnalytics(analyticsConfig);
|
|
423
|
+
|
|
424
|
+
const handlePurchase = async () => {
|
|
425
|
+
// Process payment...
|
|
426
|
+
const result = await processPayment(product, quantity);
|
|
427
|
+
|
|
428
|
+
if (result.success) {
|
|
429
|
+
// Track conversion ONLY after confirmed payment
|
|
430
|
+
conversion('purchase', {
|
|
431
|
+
value: product.price * quantity,
|
|
432
|
+
currency: 'USD',
|
|
433
|
+
productId: product.sku,
|
|
434
|
+
category: product.category
|
|
435
|
+
});
|
|
436
|
+
}
|
|
533
437
|
};
|
|
534
438
|
|
|
535
|
-
return <button onClick={
|
|
439
|
+
return <button onClick={handlePurchase}>Complete Purchase</button>;
|
|
536
440
|
}
|
|
537
441
|
```
|
|
538
442
|
|
|
539
443
|
## API Reference
|
|
540
444
|
|
|
445
|
+
### `<DotContentAnalytics />`
|
|
446
|
+
|
|
447
|
+
React component for automatic page view tracking on route changes.
|
|
448
|
+
|
|
541
449
|
```typescript
|
|
450
|
+
interface DotContentAnalyticsProps {
|
|
451
|
+
config: DotCMSAnalyticsConfig;
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
Place once in your root layout. Wraps the internal tracker in `<Suspense>` for Next.js App Router compatibility.
|
|
456
|
+
|
|
457
|
+
### `useContentAnalytics(config)`
|
|
458
|
+
|
|
459
|
+
React hook that returns tracking methods. **Always requires config as a parameter.**
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
function useContentAnalytics(config: DotCMSAnalyticsConfig): DotCMSAnalytics;
|
|
463
|
+
|
|
542
464
|
interface DotCMSAnalytics {
|
|
543
|
-
/**
|
|
544
|
-
* Track a page view event with optional custom data
|
|
545
|
-
* @param customData - Optional object with custom properties to attach to the pageview
|
|
546
|
-
*/
|
|
465
|
+
/** Track a page view with optional custom data */
|
|
547
466
|
pageView: (customData?: Record<string, unknown>) => void;
|
|
548
467
|
|
|
549
|
-
/**
|
|
550
|
-
* Track a custom event
|
|
551
|
-
* @param eventName - Name of the custom event (cannot be "pageview" or "conversion")
|
|
552
|
-
* @param properties - Optional object with event-specific properties
|
|
553
|
-
*/
|
|
468
|
+
/** Track a custom event (eventName cannot be "pageview" or "conversion") */
|
|
554
469
|
track: (eventName: string, properties?: Record<string, unknown>) => void;
|
|
555
470
|
|
|
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
|
-
*/
|
|
471
|
+
/** Track a conversion after a successful business action */
|
|
562
472
|
conversion: (name: string, options?: Record<string, unknown>) => void;
|
|
563
473
|
}
|
|
564
474
|
```
|
|
565
475
|
|
|
566
|
-
###
|
|
476
|
+
### `DotCMSAnalyticsConfig`
|
|
567
477
|
|
|
568
|
-
|
|
478
|
+
```typescript
|
|
479
|
+
interface DotCMSAnalyticsConfig {
|
|
480
|
+
server: string;
|
|
481
|
+
siteAuth: string;
|
|
482
|
+
debug?: boolean;
|
|
483
|
+
autoPageView?: boolean;
|
|
484
|
+
queue?: QueueConfig | false;
|
|
485
|
+
impressions?: ImpressionConfig | boolean;
|
|
486
|
+
clicks?: boolean;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
interface QueueConfig {
|
|
490
|
+
eventBatchSize?: number;
|
|
491
|
+
flushInterval?: number;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
interface ImpressionConfig {
|
|
495
|
+
visibilityThreshold?: number;
|
|
496
|
+
dwellMs?: number;
|
|
497
|
+
maxNodes?: number;
|
|
498
|
+
}
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
### Event Payload Structures
|
|
502
|
+
|
|
503
|
+
#### Page View Event
|
|
504
|
+
|
|
505
|
+
When you call `pageView(customData?)`, the SDK sends:
|
|
569
506
|
|
|
570
507
|
```typescript
|
|
571
508
|
{
|
|
572
|
-
context: {
|
|
573
|
-
site_key: string; //
|
|
574
|
-
session_id: string; //
|
|
575
|
-
user_id: string; //
|
|
576
|
-
device: {
|
|
577
|
-
screen_resolution: string;
|
|
578
|
-
language: string;
|
|
579
|
-
viewport_width: string;
|
|
580
|
-
viewport_height: string;
|
|
509
|
+
context: {
|
|
510
|
+
site_key: string; // Your site key
|
|
511
|
+
session_id: string; // Current session ID
|
|
512
|
+
user_id: string; // Anonymous user ID
|
|
513
|
+
device: {
|
|
514
|
+
screen_resolution: string;
|
|
515
|
+
language: string;
|
|
516
|
+
viewport_width: string;
|
|
517
|
+
viewport_height: string;
|
|
581
518
|
}
|
|
582
519
|
},
|
|
583
520
|
events: [{
|
|
584
521
|
event_type: "pageview",
|
|
585
|
-
local_time: string, //
|
|
522
|
+
local_time: string, // ISO 8601 timestamp with timezone
|
|
586
523
|
data: {
|
|
587
|
-
page: { //
|
|
588
|
-
url: string;
|
|
589
|
-
title: string;
|
|
590
|
-
referrer: string;
|
|
591
|
-
path: string;
|
|
592
|
-
doc_host: string;
|
|
593
|
-
doc_protocol: string;
|
|
594
|
-
doc_search: string;
|
|
595
|
-
doc_hash: string;
|
|
596
|
-
doc_encoding: string;
|
|
524
|
+
page: { // Captured automatically
|
|
525
|
+
url: string;
|
|
526
|
+
title: string;
|
|
527
|
+
referrer: string;
|
|
528
|
+
path: string;
|
|
529
|
+
doc_host: string;
|
|
530
|
+
doc_protocol: string;
|
|
531
|
+
doc_search: string;
|
|
532
|
+
doc_hash: string;
|
|
533
|
+
doc_encoding: string;
|
|
597
534
|
},
|
|
598
|
-
utm?: { //
|
|
599
|
-
source: string;
|
|
600
|
-
medium: string;
|
|
601
|
-
campaign: string;
|
|
602
|
-
term: string;
|
|
603
|
-
content: string;
|
|
535
|
+
utm?: { // Captured automatically (if present in URL)
|
|
536
|
+
source: string;
|
|
537
|
+
medium: string;
|
|
538
|
+
campaign: string;
|
|
539
|
+
term: string;
|
|
540
|
+
content: string;
|
|
604
541
|
},
|
|
605
|
-
custom?: { //
|
|
606
|
-
// Any
|
|
607
|
-
contentType?: string;
|
|
608
|
-
category?: string;
|
|
609
|
-
author?: string;
|
|
610
|
-
// ... any other properties
|
|
542
|
+
custom?: { // Your optional data from pageView(customData)
|
|
543
|
+
// Any properties you pass
|
|
611
544
|
}
|
|
612
545
|
}
|
|
613
546
|
}]
|
|
614
547
|
}
|
|
615
548
|
```
|
|
616
549
|
|
|
617
|
-
|
|
550
|
+
#### Custom Event
|
|
618
551
|
|
|
619
|
-
|
|
620
|
-
- 👤 `custom` is where **your optional data** goes
|
|
621
|
-
- All automatic data is always captured, even if you don't pass `customData`
|
|
622
|
-
|
|
623
|
-
### Custom Event Structure
|
|
624
|
-
|
|
625
|
-
When you call `track(eventName, properties)`, the following structure is sent:
|
|
552
|
+
When you call `track(eventName, properties)`:
|
|
626
553
|
|
|
627
554
|
```typescript
|
|
628
555
|
{
|
|
629
|
-
context: {
|
|
630
|
-
site_key: string; // Your site key
|
|
631
|
-
session_id: string; // Current session ID
|
|
632
|
-
user_id: string; // Anonymous user ID
|
|
633
|
-
device: { // 🤖 AUTOMATIC - Device & Browser Info
|
|
634
|
-
screen_resolution: string; // Screen size
|
|
635
|
-
language: string; // Browser language
|
|
636
|
-
viewport_width: string; // Viewport width
|
|
637
|
-
viewport_height: string; // Viewport height
|
|
638
|
-
}
|
|
639
|
-
},
|
|
556
|
+
context: { /* same as above */ },
|
|
640
557
|
events: [{
|
|
641
|
-
event_type: string,
|
|
642
|
-
local_time: string,
|
|
558
|
+
event_type: string, // Your custom event name
|
|
559
|
+
local_time: string,
|
|
643
560
|
data: {
|
|
644
561
|
custom: {
|
|
645
562
|
// Your properties object
|
|
@@ -649,96 +566,139 @@ When you call `track(eventName, properties)`, the following structure is sent:
|
|
|
649
566
|
}
|
|
650
567
|
```
|
|
651
568
|
|
|
652
|
-
|
|
569
|
+
#### Conversion Event
|
|
653
570
|
|
|
654
|
-
When you call `conversion(name, options)
|
|
571
|
+
When you call `conversion(name, options)`:
|
|
655
572
|
|
|
656
573
|
```typescript
|
|
657
574
|
{
|
|
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
|
-
},
|
|
575
|
+
context: { /* same as above */ },
|
|
669
576
|
events: [{
|
|
670
577
|
event_type: "conversion",
|
|
671
|
-
local_time: string,
|
|
578
|
+
local_time: string,
|
|
672
579
|
data: {
|
|
673
|
-
conversion: {
|
|
674
|
-
name: string;
|
|
580
|
+
conversion: {
|
|
581
|
+
name: string; // Your conversion name
|
|
675
582
|
},
|
|
676
|
-
page: {
|
|
677
|
-
url: string;
|
|
678
|
-
title: string;
|
|
583
|
+
page: {
|
|
584
|
+
url: string;
|
|
585
|
+
title: string;
|
|
679
586
|
},
|
|
680
|
-
custom?: {
|
|
681
|
-
// All properties from options
|
|
682
|
-
value?: number;
|
|
683
|
-
currency?: string;
|
|
684
|
-
category?: string;
|
|
685
|
-
// ... any other custom properties
|
|
587
|
+
custom?: { // Your optional data from options parameter
|
|
588
|
+
// All properties from options
|
|
686
589
|
}
|
|
687
590
|
}
|
|
688
591
|
}]
|
|
689
592
|
}
|
|
690
593
|
```
|
|
691
594
|
|
|
692
|
-
|
|
595
|
+
#### Click Event
|
|
693
596
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
597
|
+
When click tracking is enabled and a user clicks on a contentlet element:
|
|
598
|
+
|
|
599
|
+
```json
|
|
600
|
+
{
|
|
601
|
+
"content": {
|
|
602
|
+
"identifier": "abc123",
|
|
603
|
+
"inode": "xyz789",
|
|
604
|
+
"title": "Product Page",
|
|
605
|
+
"content_type": "Page"
|
|
606
|
+
},
|
|
607
|
+
"element": {
|
|
608
|
+
"text": "Start Free Trial",
|
|
609
|
+
"type": "a",
|
|
610
|
+
"id": "cta-signup",
|
|
611
|
+
"class": "btn btn-primary",
|
|
612
|
+
"href": "/signup",
|
|
613
|
+
"attributes": [
|
|
614
|
+
"data-category:primary-cta",
|
|
615
|
+
"data-campaign:summer-sale",
|
|
616
|
+
"aria-label:Sign up for free trial"
|
|
617
|
+
]
|
|
618
|
+
},
|
|
619
|
+
"position": {
|
|
620
|
+
"viewport_offset_pct": 45.2,
|
|
621
|
+
"dom_index": 2
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
```
|
|
697
625
|
|
|
698
626
|
## Under the Hood
|
|
699
627
|
|
|
700
628
|
### Storage Keys
|
|
701
629
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
630
|
+
| Key | Purpose |
|
|
631
|
+
| --- | --- |
|
|
632
|
+
| `dot_analytics_user_id` | Anonymous user identifier (persisted across sessions) |
|
|
633
|
+
| `dot_analytics_session_id` | Current session ID |
|
|
634
|
+
| `dot_analytics_session_utm` | UTM campaign data for the session |
|
|
635
|
+
| `dot_analytics_session_start` | Session start timestamp |
|
|
706
636
|
|
|
707
637
|
### Editor Detection
|
|
708
638
|
|
|
709
|
-
Analytics are disabled when inside the dotCMS editor.
|
|
639
|
+
Analytics are automatically disabled when inside the dotCMS Universal Visual Editor (UVE). No events are sent in editor mode.
|
|
640
|
+
|
|
641
|
+
### Endpoint
|
|
642
|
+
|
|
643
|
+
All events are sent via `POST` to:
|
|
644
|
+
|
|
645
|
+
```
|
|
646
|
+
{server}/api/v1/analytics/content/event
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
Where `{server}` is the `server` value from your config.
|
|
710
650
|
|
|
711
651
|
## Debugging & Troubleshooting
|
|
712
652
|
|
|
713
|
-
|
|
653
|
+
### Enable Debug Mode
|
|
654
|
+
|
|
655
|
+
Set `debug: true` in your config to see verbose logging in the browser console.
|
|
656
|
+
|
|
657
|
+
### Verify Events in the Network Tab
|
|
658
|
+
|
|
659
|
+
1. Open browser DevTools > Network tab
|
|
660
|
+
2. Filter by `/api/v1/analytics/content/event`
|
|
661
|
+
3. Perform actions in your app
|
|
662
|
+
4. Inspect request payloads to see captured data
|
|
663
|
+
|
|
664
|
+
### Check Storage
|
|
665
|
+
|
|
666
|
+
Open browser DevTools > Application > Local Storage and look for:
|
|
667
|
+
|
|
668
|
+
- `dot_analytics_user_id`
|
|
669
|
+
- `dot_analytics_session_id`
|
|
670
|
+
- `dot_analytics_session_utm`
|
|
671
|
+
- `dot_analytics_session_start`
|
|
672
|
+
|
|
673
|
+
### Common Issues
|
|
674
|
+
|
|
675
|
+
**Events not appearing?**
|
|
714
676
|
|
|
715
|
-
-
|
|
716
|
-
- Enable debug
|
|
717
|
-
-
|
|
718
|
-
-
|
|
677
|
+
- Verify `siteAuth` and `server` are correct in your config
|
|
678
|
+
- Enable `debug: true` to see console logs
|
|
679
|
+
- Ensure environment variables are set in `.env.local` (restart dev server after changes)
|
|
680
|
+
- Check that variable names start with `NEXT_PUBLIC_`
|
|
681
|
+
- Analytics are auto-disabled in dotCMS editor mode -- test in preview or published mode
|
|
719
682
|
|
|
720
|
-
|
|
683
|
+
**Queue not flushing?**
|
|
721
684
|
|
|
722
|
-
- `
|
|
723
|
-
- `
|
|
724
|
-
-
|
|
725
|
-
- `data-analytics-debug` (`true` to enable)
|
|
685
|
+
- Check `eventBatchSize` -- the threshold might not be reached yet
|
|
686
|
+
- Verify `flushInterval` is appropriate for your use case
|
|
687
|
+
- Events auto-flush on page navigation/close via `visibilitychange`
|
|
726
688
|
|
|
727
|
-
|
|
689
|
+
**Session not persisting?**
|
|
728
690
|
|
|
729
|
-
-
|
|
730
|
-
-
|
|
731
|
-
- Angular & Vue support
|
|
732
|
-
- Realtime dashboard
|
|
691
|
+
- Check that localStorage is enabled in the browser
|
|
692
|
+
- Verify no browser extensions are blocking storage
|
|
733
693
|
|
|
734
694
|
## Support
|
|
735
695
|
|
|
736
696
|
We offer multiple channels to get help with the dotCMS Analytics SDK:
|
|
737
697
|
|
|
738
|
-
- **GitHub Issues**: For bug reports and feature requests, please [open an issue](https://github.com/dotCMS/core/issues/new/choose) in the GitHub repository
|
|
739
|
-
- **Community Forum**: Join our [community discussions](https://community.dotcms.com/) to ask questions and share solutions
|
|
740
|
-
- **Stack Overflow**: Use the tag `dotcms-analytics` when posting questions
|
|
741
|
-
- **Enterprise Support**: Enterprise customers can access premium support through the [dotCMS Support Portal](https://helpdesk.dotcms.com/support/)
|
|
698
|
+
- **GitHub Issues**: For bug reports and feature requests, please [open an issue](https://github.com/dotCMS/core/issues/new/choose) in the GitHub repository.
|
|
699
|
+
- **Community Forum**: Join our [community discussions](https://community.dotcms.com/) to ask questions and share solutions.
|
|
700
|
+
- **Stack Overflow**: Use the tag `dotcms-analytics` when posting questions.
|
|
701
|
+
- **Enterprise Support**: Enterprise customers can access premium support through the [dotCMS Support Portal](https://helpdesk.dotcms.com/support/).
|
|
742
702
|
|
|
743
703
|
When reporting issues, please include:
|
|
744
704
|
|