@dotcms/analytics 1.2.0-next.3 → 1.2.0-next.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 +59 -0
- package/lib/core/dot-content-analytics.js +31 -21
- package/lib/core/plugin/dot-analytics.plugin.d.ts +21 -9
- package/lib/core/plugin/dot-analytics.plugin.js +79 -24
- package/lib/core/plugin/enricher/dot-analytics.enricher.plugin.d.ts +14 -10
- package/lib/core/plugin/enricher/dot-analytics.enricher.plugin.js +26 -38
- package/lib/core/plugin/identity/dot-analytics.identity.plugin.d.ts +2 -20
- package/lib/core/plugin/impression/dot-analytics.impression.plugin.d.ts +38 -0
- package/lib/core/plugin/impression/dot-analytics.impression.plugin.js +35 -0
- package/lib/core/plugin/impression/dot-analytics.impression.utils.d.ts +51 -0
- package/lib/core/plugin/impression/dot-analytics.impression.utils.js +50 -0
- package/lib/core/plugin/impression/index.d.ts +2 -0
- package/lib/core/shared/constants/dot-content-analytics.constants.d.ts +46 -0
- package/lib/core/shared/constants/dot-content-analytics.constants.js +30 -16
- package/lib/core/shared/dot-content-analytics.http.d.ts +2 -2
- package/lib/core/shared/dot-content-analytics.impression-tracker.d.ts +62 -0
- package/lib/core/shared/dot-content-analytics.impression-tracker.js +218 -0
- package/lib/core/shared/dot-content-analytics.utils.d.ts +20 -0
- package/lib/core/shared/models/data.model.d.ts +39 -1
- package/lib/core/shared/models/event.model.d.ts +40 -2
- package/lib/core/shared/models/library.model.d.ts +60 -25
- package/lib/core/shared/models/request.model.d.ts +17 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -115,6 +115,7 @@ track(eventName: string, properties?: Record<string, unknown>): void
|
|
|
115
115
|
| `debug` | `boolean` | ❌ | `false` | Enable verbose logging |
|
|
116
116
|
| `autoPageView` | `boolean` | ❌ | React: `true` / Standalone: `false` | Auto track page views on route changes |
|
|
117
117
|
| `queueConfig` | `QueueConfig` | ❌ | See below | Event batching configuration |
|
|
118
|
+
| `impressions` | `ImpressionConfig\|boolean` | ❌ | `false` | Content impression tracking (disabled by default) |
|
|
118
119
|
|
|
119
120
|
### Queue Configuration
|
|
120
121
|
|
|
@@ -168,6 +169,64 @@ const analytics = initializeContentAnalytics({
|
|
|
168
169
|
});
|
|
169
170
|
```
|
|
170
171
|
|
|
172
|
+
### Impression Tracking Configuration
|
|
173
|
+
|
|
174
|
+
The `impressions` option controls automatic tracking of content visibility:
|
|
175
|
+
|
|
176
|
+
- **`false` or `undefined` (default)**: Impression tracking disabled
|
|
177
|
+
- **`true`**: Enable tracking with default settings
|
|
178
|
+
- **`ImpressionConfig` object**: Enable tracking with custom settings
|
|
179
|
+
|
|
180
|
+
| Option | Type | Default | Description |
|
|
181
|
+
| --------------------- | -------- | ------- | ------------------------------------------------ |
|
|
182
|
+
| `visibilityThreshold` | `number` | `0.5` | Min percentage visible (0.0 to 1.0) |
|
|
183
|
+
| `dwellMs` | `number` | `750` | Min time visible in milliseconds |
|
|
184
|
+
| `maxNodes` | `number` | `1000` | Max elements to track (performance limit) |
|
|
185
|
+
|
|
186
|
+
**How it works:**
|
|
187
|
+
|
|
188
|
+
- ✅ Tracks contentlets marked with `dotcms-analytics-contentlet` class and `data-dot-analytics-*` attributes
|
|
189
|
+
- ✅ Uses Intersection Observer API for high performance and battery efficiency
|
|
190
|
+
- ✅ Only fires when element is ≥50% visible for ≥750ms (configurable)
|
|
191
|
+
- ✅ Only tracks during active tab (respects page visibility)
|
|
192
|
+
- ✅ One impression per contentlet per session (no duplicates)
|
|
193
|
+
- ✅ Respects user consent settings
|
|
194
|
+
- ✅ Automatically disabled in dotCMS editor mode
|
|
195
|
+
|
|
196
|
+
**Example: Enable with defaults**
|
|
197
|
+
|
|
198
|
+
```javascript
|
|
199
|
+
const analytics = initializeContentAnalytics({
|
|
200
|
+
siteAuth: 'abc123',
|
|
201
|
+
server: 'https://your-dotcms.com',
|
|
202
|
+
impressions: true // 50% visible, 750ms dwell, 1000 max nodes
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Example: Custom thresholds**
|
|
207
|
+
|
|
208
|
+
```javascript
|
|
209
|
+
const analytics = initializeContentAnalytics({
|
|
210
|
+
siteAuth: 'abc123',
|
|
211
|
+
server: 'https://your-dotcms.com',
|
|
212
|
+
impressions: {
|
|
213
|
+
visibilityThreshold: 0.7, // Require 70% visible
|
|
214
|
+
dwellMs: 1000, // Must be visible for 1 second
|
|
215
|
+
maxNodes: 500 // Track max 500 elements
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Example: Disable tracking**
|
|
221
|
+
|
|
222
|
+
```javascript
|
|
223
|
+
const analytics = initializeContentAnalytics({
|
|
224
|
+
siteAuth: 'abc123',
|
|
225
|
+
server: 'https://your-dotcms.com',
|
|
226
|
+
impressions: false // Explicitly disabled (also default if omitted)
|
|
227
|
+
});
|
|
228
|
+
```
|
|
229
|
+
|
|
171
230
|
## 🛠️ Usage Examples
|
|
172
231
|
|
|
173
232
|
### Vanilla JavaScript
|
|
@@ -1,46 +1,56 @@
|
|
|
1
|
-
import { Analytics as
|
|
2
|
-
import { ANALYTICS_WINDOWS_ACTIVE_KEY as
|
|
3
|
-
import { dotAnalytics as
|
|
4
|
-
import { dotAnalyticsEnricherPlugin as
|
|
5
|
-
import { dotAnalyticsIdentityPlugin as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { Analytics as s } from "analytics";
|
|
2
|
+
import { ANALYTICS_WINDOWS_ACTIVE_KEY as a, ANALYTICS_WINDOWS_CLEANUP_KEY as l } from "../../uve/src/internal/constants.js";
|
|
3
|
+
import { dotAnalytics as c } from "./plugin/dot-analytics.plugin.js";
|
|
4
|
+
import { dotAnalyticsEnricherPlugin as d } from "./plugin/enricher/dot-analytics.enricher.plugin.js";
|
|
5
|
+
import { dotAnalyticsIdentityPlugin as m } from "./plugin/identity/dot-analytics.identity.plugin.js";
|
|
6
|
+
import { dotAnalyticsImpressionPlugin as p } from "./plugin/impression/dot-analytics.impression.plugin.js";
|
|
7
|
+
import { validateAnalyticsConfig as y } from "./shared/dot-content-analytics.utils.js";
|
|
8
|
+
import { cleanupActivityTracking as A } from "./shared/dot-content-analytics.activity-tracker.js";
|
|
9
|
+
const _ = (n) => {
|
|
10
|
+
const o = y(n);
|
|
10
11
|
if (o)
|
|
11
|
-
return console.error(`DotCMS Analytics: Missing ${o.join(" and ")} in configuration`), typeof window < "u" && (window[
|
|
12
|
-
const i =
|
|
12
|
+
return console.error(`DotCMS Analytics: Missing ${o.join(" and ")} in configuration`), typeof window < "u" && (window[a] = !1), null;
|
|
13
|
+
const i = s({
|
|
13
14
|
app: "dotAnalytics",
|
|
14
15
|
debug: n.debug,
|
|
15
16
|
plugins: [
|
|
17
|
+
m(n),
|
|
18
|
+
// Inject identity context
|
|
16
19
|
p(n),
|
|
17
|
-
//
|
|
18
|
-
|
|
20
|
+
// Track content impressions
|
|
21
|
+
d(),
|
|
19
22
|
// Enrich and clean payload with page, device, utm data and custom data
|
|
20
|
-
|
|
23
|
+
c(n)
|
|
21
24
|
// Send events to server
|
|
22
25
|
]
|
|
23
|
-
}), e = () =>
|
|
24
|
-
return typeof window < "u" && (window.addEventListener("beforeunload", e), window[
|
|
26
|
+
}), e = () => A();
|
|
27
|
+
return typeof window < "u" && (window.addEventListener("beforeunload", e), window[l] = e, window[a] = !0, window.dispatchEvent(new CustomEvent("dotcms:analytics:ready"))), {
|
|
25
28
|
/**
|
|
26
29
|
* Track a page view.
|
|
27
30
|
* Session activity is automatically updated by the identity plugin.
|
|
28
31
|
* @param payload - Optional custom data to include with the page view (any valid JSON object)
|
|
29
32
|
*/
|
|
30
33
|
pageView: (t = {}) => {
|
|
31
|
-
|
|
34
|
+
if (!i) {
|
|
35
|
+
console.warn("DotCMS Analytics: Analytics instance not initialized");
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
i.page(t);
|
|
32
39
|
},
|
|
33
40
|
/**
|
|
34
41
|
* Track a custom event.
|
|
35
|
-
* Session activity is automatically updated by the identity plugin.
|
|
36
42
|
* @param eventName - The name of the event to track
|
|
37
43
|
* @param payload - Custom data to include with the event (any valid JSON object)
|
|
38
44
|
*/
|
|
39
|
-
track: (t,
|
|
40
|
-
|
|
45
|
+
track: (t, r = {}) => {
|
|
46
|
+
if (!i) {
|
|
47
|
+
console.warn("DotCMS Analytics: Analytics instance not initialized");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
i.track(t, r);
|
|
41
51
|
}
|
|
42
52
|
};
|
|
43
53
|
};
|
|
44
54
|
export {
|
|
45
|
-
|
|
55
|
+
_ as initializeContentAnalytics
|
|
46
56
|
};
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { DotCMSAnalyticsConfig,
|
|
1
|
+
import { DotCMSAnalyticsConfig, EnrichedAnalyticsPayload, EnrichedTrackPayload } from '../shared/models';
|
|
2
2
|
/**
|
|
3
3
|
* Analytics plugin for tracking page views and custom events in DotCMS applications.
|
|
4
|
-
* This plugin handles
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* This plugin handles:
|
|
5
|
+
* 1. Event structuring (deciding between predefined and custom events)
|
|
6
|
+
* 2. Building complete request bodies
|
|
7
|
+
* 3. Sending analytics data to the DotCMS server
|
|
8
|
+
* 4. Managing initialization and queue management
|
|
9
|
+
*
|
|
10
|
+
* The enricher plugin runs BEFORE this plugin and adds page/utm/custom data.
|
|
11
|
+
* This plugin receives enriched payloads and structures them into proper events.
|
|
7
12
|
*
|
|
8
13
|
* @param {DotCMSAnalyticsConfig} config - Configuration object containing API key, server URL,
|
|
9
14
|
* debug mode, auto page view settings, and queue config
|
|
@@ -18,14 +23,21 @@ export declare const dotAnalytics: (config: DotCMSAnalyticsConfig) => {
|
|
|
18
23
|
initialize: () => Promise<void>;
|
|
19
24
|
/**
|
|
20
25
|
* Track a page view event
|
|
21
|
-
*
|
|
26
|
+
* Receives enriched payload from the enricher plugin and structures it into a pageview event
|
|
22
27
|
*/
|
|
23
|
-
page: (
|
|
28
|
+
page: ({ payload }: {
|
|
29
|
+
payload: EnrichedAnalyticsPayload;
|
|
30
|
+
}) => void;
|
|
24
31
|
/**
|
|
25
|
-
* Track a custom event
|
|
26
|
-
*
|
|
32
|
+
* Track a custom or predefined event
|
|
33
|
+
* Receives enriched payload from enricher plugin and structures it into proper event format.
|
|
34
|
+
*
|
|
35
|
+
* - content_impression → extracts from properties, combines with enriched page data
|
|
36
|
+
* - custom events → wraps properties in custom object
|
|
27
37
|
*/
|
|
28
|
-
track: (
|
|
38
|
+
track: ({ payload }: {
|
|
39
|
+
payload: EnrichedTrackPayload;
|
|
40
|
+
}) => void;
|
|
29
41
|
/**
|
|
30
42
|
* Check if the plugin is loaded
|
|
31
43
|
*/
|
|
@@ -1,42 +1,97 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const a = l.events[0], s = l.context;
|
|
12
|
-
i && e ? e.enqueue(a, s) : u({
|
|
13
|
-
context: s,
|
|
14
|
-
events: [a]
|
|
15
|
-
}, c);
|
|
1
|
+
import { DotCMSPredefinedEventType as l } from "../shared/constants/dot-content-analytics.constants.js";
|
|
2
|
+
import { sendAnalyticsEvent as f } from "../shared/dot-content-analytics.http.js";
|
|
3
|
+
import { createAnalyticsQueue as w } from "../shared/queue/dot-analytics.queue.utils.js";
|
|
4
|
+
const P = (s) => {
|
|
5
|
+
let a = !1;
|
|
6
|
+
const u = s.queue !== !1;
|
|
7
|
+
let r = null;
|
|
8
|
+
const d = (e) => {
|
|
9
|
+
const n = e.events[0], t = e.context;
|
|
10
|
+
u && r ? r.enqueue(n, t) : f(e, s);
|
|
16
11
|
};
|
|
17
12
|
return {
|
|
18
13
|
name: "dot-analytics",
|
|
19
|
-
config:
|
|
14
|
+
config: s,
|
|
20
15
|
/**
|
|
21
16
|
* Initialize the plugin with optional queue management
|
|
22
17
|
*/
|
|
23
|
-
initialize: () => (
|
|
18
|
+
initialize: () => (a = !0, u && (r = w(s), r.initialize()), Promise.resolve()),
|
|
24
19
|
/**
|
|
25
20
|
* Track a page view event
|
|
26
|
-
*
|
|
21
|
+
* Receives enriched payload from the enricher plugin and structures it into a pageview event
|
|
27
22
|
*/
|
|
28
|
-
page:
|
|
23
|
+
page: ({ payload: e }) => {
|
|
24
|
+
if (!a)
|
|
25
|
+
throw new Error("DotCMS Analytics: Plugin not initialized");
|
|
26
|
+
const { context: n, page: t, utm: c, custom: i, local_time: o } = e;
|
|
27
|
+
if (!t)
|
|
28
|
+
throw new Error("DotCMS Analytics: Missing required page data");
|
|
29
|
+
const p = {
|
|
30
|
+
context: n,
|
|
31
|
+
events: [
|
|
32
|
+
{
|
|
33
|
+
event_type: l.PAGEVIEW,
|
|
34
|
+
local_time: o,
|
|
35
|
+
data: {
|
|
36
|
+
page: t,
|
|
37
|
+
...c && { utm: c },
|
|
38
|
+
...i && { custom: i }
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
};
|
|
43
|
+
d(p);
|
|
44
|
+
},
|
|
29
45
|
/**
|
|
30
|
-
* Track a custom event
|
|
31
|
-
*
|
|
46
|
+
* Track a custom or predefined event
|
|
47
|
+
* Receives enriched payload from enricher plugin and structures it into proper event format.
|
|
48
|
+
*
|
|
49
|
+
* - content_impression → extracts from properties, combines with enriched page data
|
|
50
|
+
* - custom events → wraps properties in custom object
|
|
32
51
|
*/
|
|
33
|
-
track:
|
|
52
|
+
track: ({ payload: e }) => {
|
|
53
|
+
if (!a)
|
|
54
|
+
throw new Error("DotCMS Analytics: Plugin not initialized");
|
|
55
|
+
const { event: n, properties: t, context: c, local_time: i } = e;
|
|
56
|
+
let o;
|
|
57
|
+
switch (n) {
|
|
58
|
+
case l.CONTENT_IMPRESSION: {
|
|
59
|
+
const v = t, { content: m, position: y } = v, { page: E } = e;
|
|
60
|
+
if (!m || !y || !E)
|
|
61
|
+
throw new Error("DotCMS Analytics: Missing required impression data");
|
|
62
|
+
o = {
|
|
63
|
+
event_type: l.CONTENT_IMPRESSION,
|
|
64
|
+
local_time: i,
|
|
65
|
+
data: {
|
|
66
|
+
content: m,
|
|
67
|
+
position: y,
|
|
68
|
+
page: E
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
default: {
|
|
74
|
+
o = {
|
|
75
|
+
event_type: n,
|
|
76
|
+
local_time: i,
|
|
77
|
+
data: {
|
|
78
|
+
custom: t
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
d({
|
|
85
|
+
context: c,
|
|
86
|
+
events: [o]
|
|
87
|
+
});
|
|
88
|
+
},
|
|
34
89
|
/**
|
|
35
90
|
* Check if the plugin is loaded
|
|
36
91
|
*/
|
|
37
|
-
loaded: () =>
|
|
92
|
+
loaded: () => a
|
|
38
93
|
};
|
|
39
94
|
};
|
|
40
95
|
export {
|
|
41
|
-
|
|
96
|
+
P as dotAnalytics
|
|
42
97
|
};
|
|
@@ -1,28 +1,32 @@
|
|
|
1
|
-
import { AnalyticsBasePayloadWithContext, AnalyticsTrackPayloadWithContext,
|
|
1
|
+
import { AnalyticsBasePayloadWithContext, AnalyticsTrackPayloadWithContext, EnrichedAnalyticsPayload, EnrichedTrackPayload } from '../../shared/models';
|
|
2
2
|
/**
|
|
3
|
-
* Plugin that enriches the analytics payload data
|
|
4
|
-
* Uses Analytics.js lifecycle events to inject
|
|
3
|
+
* Plugin that enriches the analytics payload data with page, UTM, and custom data.
|
|
4
|
+
* Uses Analytics.js lifecycle events to inject enriched data before the main plugin processes it.
|
|
5
|
+
*
|
|
5
6
|
* The identity plugin runs FIRST to inject context: { session_id, site_auth, user_id, device }
|
|
6
7
|
* This enricher plugin runs SECOND to add page/utm/custom data.
|
|
8
|
+
* The main plugin runs THIRD to structure events and send to server.
|
|
7
9
|
*
|
|
8
|
-
*
|
|
10
|
+
* This plugin is ONLY responsible for data enrichment - NOT for event structuring or business logic.
|
|
9
11
|
*/
|
|
10
12
|
export declare const dotAnalyticsEnricherPlugin: () => {
|
|
11
13
|
name: string;
|
|
12
14
|
/**
|
|
13
15
|
* PAGE VIEW ENRICHMENT - Runs after identity context injection
|
|
14
|
-
* Returns
|
|
15
|
-
* @returns {
|
|
16
|
+
* Returns enriched payload with page, utm, and custom data added
|
|
17
|
+
* @returns {EnrichedAnalyticsPayload} Enriched payload ready for event creation
|
|
16
18
|
*/
|
|
17
19
|
'page:dot-analytics': ({ payload }: {
|
|
18
20
|
payload: AnalyticsBasePayloadWithContext;
|
|
19
|
-
}) =>
|
|
21
|
+
}) => EnrichedAnalyticsPayload;
|
|
20
22
|
/**
|
|
21
23
|
* TRACK EVENT ENRICHMENT - Runs after identity context injection
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
+
* Adds page data and timestamp for predefined events.
|
|
25
|
+
* For custom events, only adds timestamp.
|
|
26
|
+
*
|
|
27
|
+
* @returns {EnrichedTrackPayload} Enriched payload ready for event structuring
|
|
24
28
|
*/
|
|
25
29
|
'track:dot-analytics': ({ payload }: {
|
|
26
30
|
payload: AnalyticsTrackPayloadWithContext;
|
|
27
|
-
}) =>
|
|
31
|
+
}) => EnrichedTrackPayload;
|
|
28
32
|
};
|
|
@@ -1,56 +1,44 @@
|
|
|
1
|
-
import { DotCMSPredefinedEventType as
|
|
2
|
-
import { getLocalTime as
|
|
3
|
-
const
|
|
1
|
+
import { DotCMSPredefinedEventType as n } from "../../shared/constants/dot-content-analytics.constants.js";
|
|
2
|
+
import { getLocalTime as i, enrichPagePayloadOptimized as o } 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
|
-
* Returns
|
|
8
|
-
* @returns {
|
|
7
|
+
* Returns enriched payload with page, utm, and custom data added
|
|
8
|
+
* @returns {EnrichedAnalyticsPayload} Enriched payload ready for event creation
|
|
9
9
|
*/
|
|
10
10
|
"page:dot-analytics": ({
|
|
11
|
-
payload:
|
|
11
|
+
payload: t
|
|
12
12
|
}) => {
|
|
13
|
-
const
|
|
14
|
-
if (!
|
|
13
|
+
const e = o(t);
|
|
14
|
+
if (!e.page)
|
|
15
15
|
throw new Error("DotCMS Analytics: Missing required page data");
|
|
16
|
-
return
|
|
17
|
-
context: a,
|
|
18
|
-
events: [
|
|
19
|
-
{
|
|
20
|
-
event_type: i.PAGEVIEW,
|
|
21
|
-
local_time: r,
|
|
22
|
-
data: {
|
|
23
|
-
page: t,
|
|
24
|
-
...e && { utm: e },
|
|
25
|
-
...n && { custom: n }
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
]
|
|
29
|
-
};
|
|
16
|
+
return e;
|
|
30
17
|
},
|
|
31
18
|
/**
|
|
32
19
|
* TRACK EVENT ENRICHMENT - Runs after identity context injection
|
|
33
|
-
*
|
|
34
|
-
*
|
|
20
|
+
* Adds page data and timestamp for predefined events.
|
|
21
|
+
* For custom events, only adds timestamp.
|
|
22
|
+
*
|
|
23
|
+
* @returns {EnrichedTrackPayload} Enriched payload ready for event structuring
|
|
35
24
|
*/
|
|
36
25
|
"track:dot-analytics": ({
|
|
37
|
-
payload:
|
|
26
|
+
payload: t
|
|
38
27
|
}) => {
|
|
39
|
-
const { event:
|
|
40
|
-
return {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
]
|
|
28
|
+
const { event: e } = t, r = i();
|
|
29
|
+
return e === n.CONTENT_IMPRESSION ? {
|
|
30
|
+
...t,
|
|
31
|
+
page: {
|
|
32
|
+
title: document.title,
|
|
33
|
+
url: window.location.href
|
|
34
|
+
},
|
|
35
|
+
local_time: r
|
|
36
|
+
} : {
|
|
37
|
+
...t,
|
|
38
|
+
local_time: r
|
|
51
39
|
};
|
|
52
40
|
}
|
|
53
41
|
});
|
|
54
42
|
export {
|
|
55
|
-
|
|
43
|
+
l as dotAnalyticsEnricherPlugin
|
|
56
44
|
};
|
|
@@ -26,16 +26,7 @@ export declare const dotAnalyticsIdentityPlugin: (config: DotCMSAnalyticsConfig)
|
|
|
26
26
|
pageStart: ({ payload }: AnalyticsBaseParams) => {
|
|
27
27
|
context: import('../../shared/models').DotCMSAnalyticsEventContext;
|
|
28
28
|
type: "page" | "track";
|
|
29
|
-
properties:
|
|
30
|
-
title: string;
|
|
31
|
-
url: string;
|
|
32
|
-
path: string;
|
|
33
|
-
hash: string;
|
|
34
|
-
search: string;
|
|
35
|
-
width: number;
|
|
36
|
-
height: number;
|
|
37
|
-
referrer?: string;
|
|
38
|
-
};
|
|
29
|
+
properties: Record<string, unknown>;
|
|
39
30
|
options: Record<string, unknown>;
|
|
40
31
|
userId: string;
|
|
41
32
|
anonymousId: string;
|
|
@@ -52,16 +43,7 @@ export declare const dotAnalyticsIdentityPlugin: (config: DotCMSAnalyticsConfig)
|
|
|
52
43
|
trackStart: ({ payload }: AnalyticsBaseParams) => {
|
|
53
44
|
context: import('../../shared/models').DotCMSAnalyticsEventContext;
|
|
54
45
|
type: "page" | "track";
|
|
55
|
-
properties:
|
|
56
|
-
title: string;
|
|
57
|
-
url: string;
|
|
58
|
-
path: string;
|
|
59
|
-
hash: string;
|
|
60
|
-
search: string;
|
|
61
|
-
width: number;
|
|
62
|
-
height: number;
|
|
63
|
-
referrer?: string;
|
|
64
|
-
};
|
|
46
|
+
properties: Record<string, unknown>;
|
|
65
47
|
options: Record<string, unknown>;
|
|
66
48
|
userId: string;
|
|
67
49
|
anonymousId: string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { AnalyticsInstance } from 'analytics';
|
|
2
|
+
import { DotCMSAnalyticsConfig } from '../../shared/models';
|
|
3
|
+
/**
|
|
4
|
+
* Impression Plugin for DotAnalytics
|
|
5
|
+
* Handles automatic tracking of content visibility and impressions.
|
|
6
|
+
* Only activates when config.impressions is enabled (true or config object).
|
|
7
|
+
*
|
|
8
|
+
* This plugin initializes the impression tracker which:
|
|
9
|
+
* - Uses IntersectionObserver to detect when contentlets are visible
|
|
10
|
+
* - Tracks dwell time (how long elements are visible)
|
|
11
|
+
* - Fires 'content-impression' events via instance.track()
|
|
12
|
+
* - Deduplicates impressions per session
|
|
13
|
+
*
|
|
14
|
+
* Plugin execution in Analytics.js pipeline:
|
|
15
|
+
* 1. Identity Plugin - Injects context
|
|
16
|
+
* 2. Enricher Plugin - Enriches event data
|
|
17
|
+
* 3. Main Plugin - Sends to queue/server
|
|
18
|
+
* 4. Impression Plugin - Runs independently, fires events via instance.track()
|
|
19
|
+
*
|
|
20
|
+
* @param {DotCMSAnalyticsConfig} config - Configuration with impressions settings
|
|
21
|
+
* @returns {Object} Plugin object with lifecycle methods
|
|
22
|
+
*/
|
|
23
|
+
export declare const dotAnalyticsImpressionPlugin: (config: DotCMSAnalyticsConfig) => {
|
|
24
|
+
name: string;
|
|
25
|
+
/**
|
|
26
|
+
* Initialize impression tracking if enabled
|
|
27
|
+
* Called when Analytics.js initializes the plugin with instance context
|
|
28
|
+
* @param instance - Analytics.js instance with track method
|
|
29
|
+
*/
|
|
30
|
+
initialize: ({ instance }: {
|
|
31
|
+
instance: AnalyticsInstance;
|
|
32
|
+
}) => Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Setup cleanup handlers when plugin is loaded
|
|
35
|
+
* Called after Analytics.js completes plugin loading
|
|
36
|
+
*/
|
|
37
|
+
loaded: () => boolean;
|
|
38
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { DotCMSImpressionTracker as t } from "../../shared/dot-content-analytics.impression-tracker.js";
|
|
2
|
+
const a = (n) => {
|
|
3
|
+
let e = null, i = null;
|
|
4
|
+
return {
|
|
5
|
+
name: "dot-analytics-impression",
|
|
6
|
+
/**
|
|
7
|
+
* Initialize impression tracking if enabled
|
|
8
|
+
* Called when Analytics.js initializes the plugin with instance context
|
|
9
|
+
* @param instance - Analytics.js instance with track method
|
|
10
|
+
*/
|
|
11
|
+
initialize: ({ instance: s }) => (n.impressions ? (e = new t(n), e.initialize(), i = e.onImpression((o, r) => {
|
|
12
|
+
s.track(o, r);
|
|
13
|
+
}), n.debug && console.warn("DotCMS Analytics: Impression tracking plugin initialized")) : n.debug && console.warn(
|
|
14
|
+
"DotCMS Analytics: Impression tracking disabled (config.impressions not set)"
|
|
15
|
+
), Promise.resolve()),
|
|
16
|
+
/**
|
|
17
|
+
* Setup cleanup handlers when plugin is loaded
|
|
18
|
+
* Called after Analytics.js completes plugin loading
|
|
19
|
+
*/
|
|
20
|
+
loaded: () => {
|
|
21
|
+
if (typeof window < "u" && e) {
|
|
22
|
+
const s = () => {
|
|
23
|
+
i && (i.unsubscribe(), i = null), e && (e.cleanup(), e = null, n.debug && console.warn(
|
|
24
|
+
"DotCMS Analytics: Impression tracking cleaned up on page unload"
|
|
25
|
+
));
|
|
26
|
+
};
|
|
27
|
+
window.addEventListener("beforeunload", s), window.addEventListener("pagehide", s);
|
|
28
|
+
}
|
|
29
|
+
return !0;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
export {
|
|
34
|
+
a as dotAnalyticsImpressionPlugin
|
|
35
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ViewportMetrics } from '../../shared/models';
|
|
2
|
+
/**
|
|
3
|
+
* Calculates the visibility ratio of an element in the viewport
|
|
4
|
+
* @param element - The HTML element to check
|
|
5
|
+
* @returns A number between 0 and 1 representing the visible percentage
|
|
6
|
+
*/
|
|
7
|
+
export declare function calculateElementVisibilityRatio(element: HTMLElement): number;
|
|
8
|
+
/**
|
|
9
|
+
* Calculates the offset percentage of an element from the top of the viewport
|
|
10
|
+
* @param element - The HTML element to check
|
|
11
|
+
* @returns Percentage value (can be negative if above viewport)
|
|
12
|
+
*/
|
|
13
|
+
export declare function calculateViewportOffset(element: HTMLElement): number;
|
|
14
|
+
/**
|
|
15
|
+
* Checks if an element meets a specific visibility threshold
|
|
16
|
+
* @param element - The HTML element to check
|
|
17
|
+
* @param threshold - The required visibility ratio (0.0 to 1.0)
|
|
18
|
+
* @returns True if the element meets or exceeds the threshold
|
|
19
|
+
*/
|
|
20
|
+
export declare function isElementMeetingVisibilityThreshold(element: HTMLElement, threshold: number): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Gets comprehensive viewport metrics for an element
|
|
23
|
+
* @param element - The HTML element to analyze
|
|
24
|
+
* @returns Object containing offset percentage and visibility ratio
|
|
25
|
+
*/
|
|
26
|
+
export declare function getViewportMetrics(element: HTMLElement): ViewportMetrics;
|
|
27
|
+
/**
|
|
28
|
+
* Creates a debounced version of a callback function
|
|
29
|
+
* @param callback - The function to debounce
|
|
30
|
+
* @param delayMs - The delay in milliseconds
|
|
31
|
+
* @returns A debounced function that shares the same timer reference
|
|
32
|
+
*/
|
|
33
|
+
export declare function createDebounce(callback: () => void, delayMs: number): () => void;
|
|
34
|
+
/**
|
|
35
|
+
* Extracts the contentlet identifier from a DOM element
|
|
36
|
+
* @param element - The HTML element containing data attributes
|
|
37
|
+
* @returns The contentlet identifier or null if not found
|
|
38
|
+
*/
|
|
39
|
+
export declare function extractContentletIdentifier(element: HTMLElement): string | null;
|
|
40
|
+
/**
|
|
41
|
+
* Extracts all contentlet data from a DOM element's data attributes
|
|
42
|
+
* @param element - The HTML element containing data attributes
|
|
43
|
+
* @returns Complete contentlet data object
|
|
44
|
+
*/
|
|
45
|
+
export declare function extractContentletData(element: HTMLElement): {
|
|
46
|
+
identifier: string;
|
|
47
|
+
inode: string;
|
|
48
|
+
contentType: string;
|
|
49
|
+
title: string;
|
|
50
|
+
baseType: string;
|
|
51
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
function r(t) {
|
|
2
|
+
const e = t.getBoundingClientRect(), i = window.innerHeight || document.documentElement.clientHeight, n = window.innerWidth || document.documentElement.clientWidth, o = Math.min(e.bottom, i) - Math.max(e.top, 0), c = Math.min(e.right, n) - Math.max(e.left, 0);
|
|
3
|
+
if (o <= 0 || c <= 0)
|
|
4
|
+
return 0;
|
|
5
|
+
const s = o * c, a = e.height * e.width;
|
|
6
|
+
return a > 0 ? s / a : 0;
|
|
7
|
+
}
|
|
8
|
+
function l(t) {
|
|
9
|
+
const e = t.getBoundingClientRect(), i = window.innerHeight || document.documentElement.clientHeight, n = e.top / i * 100;
|
|
10
|
+
return Math.round(n * 100) / 100;
|
|
11
|
+
}
|
|
12
|
+
function d(t, e) {
|
|
13
|
+
return r(t) >= e;
|
|
14
|
+
}
|
|
15
|
+
function u(t) {
|
|
16
|
+
const e = r(t);
|
|
17
|
+
return {
|
|
18
|
+
offsetPercentage: l(t),
|
|
19
|
+
visibilityRatio: e
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function f(t, e) {
|
|
23
|
+
let i = null;
|
|
24
|
+
return () => {
|
|
25
|
+
i !== null && window.clearTimeout(i), i = window.setTimeout(() => {
|
|
26
|
+
t(), i = null;
|
|
27
|
+
}, e);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function h(t) {
|
|
31
|
+
return t.dataset.dotAnalyticsIdentifier || null;
|
|
32
|
+
}
|
|
33
|
+
function g(t) {
|
|
34
|
+
return {
|
|
35
|
+
identifier: t.dataset.dotAnalyticsIdentifier || "",
|
|
36
|
+
inode: t.dataset.dotAnalyticsInode || "",
|
|
37
|
+
contentType: t.dataset.dotAnalyticsContenttype || "",
|
|
38
|
+
title: t.dataset.dotAnalyticsTitle || "",
|
|
39
|
+
baseType: t.dataset.dotAnalyticsBasetype || ""
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export {
|
|
43
|
+
r as calculateElementVisibilityRatio,
|
|
44
|
+
l as calculateViewportOffset,
|
|
45
|
+
f as createDebounce,
|
|
46
|
+
g as extractContentletData,
|
|
47
|
+
h as extractContentletIdentifier,
|
|
48
|
+
u as getViewportMetrics,
|
|
49
|
+
d as isElementMeetingVisibilityThreshold
|
|
50
|
+
};
|