@dotcms/analytics 1.2.0 → 1.2.1-next.2
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 +314 -9
- package/lib/core/dot-analytics.content.js +84 -0
- package/lib/core/plugin/click/dot-analytics.click-tracker.d.ts +108 -0
- package/lib/core/plugin/click/dot-analytics.click-tracker.js +144 -0
- package/lib/core/plugin/click/dot-analytics.click.plugin.d.ts +36 -0
- package/lib/core/plugin/click/dot-analytics.click.plugin.js +27 -0
- package/lib/core/plugin/click/dot-analytics.click.utils.d.ts +12 -0
- package/lib/core/plugin/click/dot-analytics.click.utils.js +55 -0
- 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/{shared/dot-content-analytics.activity-tracker.d.ts → plugin/identity/dot-analytics.identity.activity-tracker.d.ts} +2 -17
- package/lib/core/{shared/dot-content-analytics.activity-tracker.js → plugin/identity/dot-analytics.identity.activity-tracker.js} +17 -38
- package/lib/core/plugin/identity/dot-analytics.identity.plugin.d.ts +2 -20
- package/lib/core/plugin/identity/dot-analytics.identity.plugin.js +7 -7
- package/lib/core/plugin/identity/dot-analytics.identity.utils.d.ts +0 -16
- package/lib/core/plugin/impression/dot-analytics.impression-tracker.d.ts +62 -0
- package/lib/core/plugin/impression/dot-analytics.impression-tracker.js +202 -0
- package/lib/core/plugin/impression/dot-analytics.impression.plugin.d.ts +40 -0
- package/lib/core/plugin/impression/dot-analytics.impression.plugin.js +27 -0
- package/lib/core/plugin/impression/dot-analytics.impression.utils.d.ts +26 -0
- package/lib/core/plugin/impression/dot-analytics.impression.utils.js +27 -0
- package/lib/core/plugin/impression/index.d.ts +2 -0
- package/lib/core/plugin/main/dot-analytics.plugin.d.ts +46 -0
- package/lib/core/plugin/main/dot-analytics.plugin.js +129 -0
- package/lib/core/shared/constants/{dot-content-analytics.constants.d.ts → dot-analytics.constants.d.ts} +62 -0
- package/lib/core/shared/constants/dot-analytics.constants.js +53 -0
- package/lib/core/shared/constants/index.d.ts +1 -1
- package/lib/core/shared/dot-analytics.logger.d.ts +85 -0
- package/lib/core/shared/dot-analytics.logger.js +90 -0
- package/lib/core/shared/http/dot-analytics.http.d.ts +9 -0
- package/lib/core/shared/http/dot-analytics.http.js +34 -0
- package/lib/core/shared/models/data.model.d.ts +39 -1
- package/lib/core/shared/models/event.model.d.ts +108 -3
- package/lib/core/shared/models/library.model.d.ts +89 -28
- package/lib/core/shared/models/request.model.d.ts +17 -9
- package/lib/core/shared/queue/dot-analytics.queue.utils.js +47 -40
- package/lib/core/shared/{dot-content-analytics.utils.d.ts → utils/dot-analytics.utils.d.ts} +91 -3
- package/lib/core/shared/utils/dot-analytics.utils.js +200 -0
- package/lib/react/hook/useContentAnalytics.js +17 -11
- package/lib/react/hook/useRouterTracker.js +12 -12
- package/lib/react/internal/utils.js +1 -1
- package/package.json +7 -6
- package/uve/src/internal/events.js +30 -31
- package/uve/src/lib/dom/dom.utils.js +46 -52
- package/lib/core/dot-content-analytics.js +0 -46
- package/lib/core/plugin/dot-analytics.plugin.d.ts +0 -33
- package/lib/core/plugin/dot-analytics.plugin.js +0 -42
- package/lib/core/shared/constants/dot-content-analytics.constants.js +0 -34
- package/lib/core/shared/dot-content-analytics.http.d.ts +0 -17
- package/lib/core/shared/dot-content-analytics.http.js +0 -41
- package/lib/core/shared/dot-content-analytics.utils.js +0 -147
- /package/lib/core/{dot-content-analytics.d.ts → dot-analytics.content.d.ts} +0 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { handleContentletClick as c } from "./dot-analytics.click.utils.js";
|
|
2
|
+
import { DEFAULT_CLICK_THROTTLE_MS as d } from "../../shared/constants/dot-analytics.constants.js";
|
|
3
|
+
import { createPluginLogger as h, isBrowser as l, INITIAL_SCAN_DELAY_MS as g, findContentlets as r, createContentletObserver as u } from "../../shared/utils/dot-analytics.utils.js";
|
|
4
|
+
class C {
|
|
5
|
+
constructor(t) {
|
|
6
|
+
this.config = t, this.mutationObserver = null, this.lastClickTime = { value: 0 }, this.subscribers = /* @__PURE__ */ new Set(), this.trackedElements = /* @__PURE__ */ new WeakSet(), this.elementHandlers = /* @__PURE__ */ new WeakMap(), this.logger = h("Click", t);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Subscribe to click events
|
|
10
|
+
* @param callback - Function called when click is detected
|
|
11
|
+
* @returns Subscription object with unsubscribe method
|
|
12
|
+
*/
|
|
13
|
+
onClick(t) {
|
|
14
|
+
return this.subscribers.add(t), {
|
|
15
|
+
unsubscribe: () => {
|
|
16
|
+
this.subscribers.delete(t);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Notifies all subscribers of a click event
|
|
22
|
+
* @param eventName - Name of the event (e.g., 'content_click')
|
|
23
|
+
* @param payload - Click event payload with content and element data
|
|
24
|
+
*/
|
|
25
|
+
notifySubscribers(t, e) {
|
|
26
|
+
this.subscribers.forEach((i) => i(t, e));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Initialize click tracking system
|
|
30
|
+
*
|
|
31
|
+
* Performs the following:
|
|
32
|
+
* - Validates browser environment
|
|
33
|
+
* - Scans for existing contentlets after a delay (100ms)
|
|
34
|
+
* - Sets up MutationObserver for dynamic content
|
|
35
|
+
*
|
|
36
|
+
* The delay allows React/Next.js to finish initial rendering
|
|
37
|
+
* before attaching listeners.
|
|
38
|
+
*/
|
|
39
|
+
initialize() {
|
|
40
|
+
if (!l()) {
|
|
41
|
+
this.logger.warn("No document, skipping");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
this.logger.debug("Plugin initializing"), typeof window < "u" && setTimeout(() => {
|
|
45
|
+
this.logger.debug("Running initial scan after timeout..."), this.findAndAttachListeners();
|
|
46
|
+
}, g), this.initializeMutationObserver(), this.logger.info("Plugin initialized");
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Attach click listener to a contentlet container
|
|
50
|
+
*
|
|
51
|
+
* Skips if element already has a listener attached.
|
|
52
|
+
* The listener delegates to handleContentletClick which:
|
|
53
|
+
* - Finds clicked anchor/button elements
|
|
54
|
+
* - Extracts contentlet and element data
|
|
55
|
+
* - Applies throttling (300ms)
|
|
56
|
+
* - Notifies subscribers
|
|
57
|
+
*
|
|
58
|
+
* @param element - Contentlet container element to track
|
|
59
|
+
*/
|
|
60
|
+
attachClickListener(t) {
|
|
61
|
+
if (this.trackedElements.has(t)) {
|
|
62
|
+
const n = t.dataset.dotAnalyticsIdentifier || "unknown";
|
|
63
|
+
this.logger.debug(`Element ${n} already has listener, skipping`);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (!t.dataset.dotAnalyticsDomIndex) {
|
|
67
|
+
const n = r();
|
|
68
|
+
t.dataset.dotAnalyticsDomIndex = String(n.indexOf(t));
|
|
69
|
+
}
|
|
70
|
+
const e = (n) => {
|
|
71
|
+
this.logger.debug("Click handler triggered on contentlet"), c(
|
|
72
|
+
n,
|
|
73
|
+
t,
|
|
74
|
+
(a, s) => {
|
|
75
|
+
const o = Date.now();
|
|
76
|
+
o - this.lastClickTime.value < d || (this.lastClickTime.value = o, this.notifySubscribers(a, s), this.logger.info(
|
|
77
|
+
`Fired click event for ${s.content.identifier}`,
|
|
78
|
+
s
|
|
79
|
+
));
|
|
80
|
+
},
|
|
81
|
+
this.logger
|
|
82
|
+
);
|
|
83
|
+
};
|
|
84
|
+
t.addEventListener("click", e), this.trackedElements.add(t), this.elementHandlers.set(t, e);
|
|
85
|
+
const i = t.dataset.dotAnalyticsIdentifier || "unknown";
|
|
86
|
+
this.logger.log(`Attached listener to contentlet ${i}`, t);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Find and attach listeners to all contentlet elements in the DOM
|
|
90
|
+
*
|
|
91
|
+
* Scans the entire document for elements with the
|
|
92
|
+
* `.dotcms-analytics-contentlet` class and attaches click
|
|
93
|
+
* listeners if not already tracked.
|
|
94
|
+
*
|
|
95
|
+
* Called during initialization and whenever DOM mutations are detected.
|
|
96
|
+
*/
|
|
97
|
+
findAndAttachListeners() {
|
|
98
|
+
this.logger.debug("findAndAttachListeners called");
|
|
99
|
+
const t = r();
|
|
100
|
+
this.logger.debug(`Scanning... found ${t.length} contentlets`);
|
|
101
|
+
let e = 0;
|
|
102
|
+
t.forEach((i) => {
|
|
103
|
+
const n = !this.trackedElements.has(i);
|
|
104
|
+
this.attachClickListener(i), n && this.trackedElements.has(i) && e++;
|
|
105
|
+
}), e > 0 && this.logger.info(`Attached ${e} new click listeners`);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Initialize MutationObserver to detect new contentlet containers
|
|
109
|
+
* Uses same simple strategy as impression tracker - no complex filtering
|
|
110
|
+
*/
|
|
111
|
+
initializeMutationObserver() {
|
|
112
|
+
l() && (this.mutationObserver = u(() => {
|
|
113
|
+
this.findAndAttachListeners();
|
|
114
|
+
}), this.logger.info("MutationObserver enabled for click tracking"));
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Remove all click listeners from tracked contentlets
|
|
118
|
+
*
|
|
119
|
+
* Iterates through all contentlet elements and removes their
|
|
120
|
+
* click event handlers, cleaning up WeakMap references.
|
|
121
|
+
*/
|
|
122
|
+
removeAllListeners() {
|
|
123
|
+
r().forEach((e) => {
|
|
124
|
+
const i = this.elementHandlers.get(e);
|
|
125
|
+
i && (e.removeEventListener("click", i), this.elementHandlers.delete(e));
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Cleanup all resources used by the click tracker
|
|
130
|
+
*
|
|
131
|
+
* Performs:
|
|
132
|
+
* - Removes all event listeners from contentlets
|
|
133
|
+
* - Disconnects MutationObserver
|
|
134
|
+
* - Clears internal references
|
|
135
|
+
*
|
|
136
|
+
* Should be called when the plugin is disabled or on page unload.
|
|
137
|
+
*/
|
|
138
|
+
cleanup() {
|
|
139
|
+
this.removeAllListeners(), this.mutationObserver && (this.mutationObserver.disconnect(), this.mutationObserver = null), this.logger.info("Click tracking cleaned up");
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
export {
|
|
143
|
+
C as DotCMSClickTracker
|
|
144
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { AnalyticsInstance } from 'analytics';
|
|
2
|
+
import { DotCMSAnalyticsConfig } from '../../shared/models';
|
|
3
|
+
/**
|
|
4
|
+
* Click Plugin for DotAnalytics
|
|
5
|
+
* Handles automatic tracking of clicks on content elements.
|
|
6
|
+
*
|
|
7
|
+
* This plugin initializes the click tracker which:
|
|
8
|
+
* - Uses MutationObserver to detect contentlet containers
|
|
9
|
+
* - Attaches click listeners to each .dotcms-analytics-contentlet element
|
|
10
|
+
* - Filters for clicks on <a> or <button> elements inside tracked contentlets
|
|
11
|
+
* - Extracts contentlet data and element metadata
|
|
12
|
+
* - Throttles clicks to prevent duplicates
|
|
13
|
+
* - Fires 'content_click' events via subscription callback
|
|
14
|
+
*
|
|
15
|
+
* Note: This plugin is only registered if config.clicks is enabled.
|
|
16
|
+
* See getEnhancedTrackingPlugins() for conditional loading logic.
|
|
17
|
+
*
|
|
18
|
+
* @param {DotCMSAnalyticsConfig} config - Configuration with clicks settings
|
|
19
|
+
* @returns {Object} Plugin object with lifecycle methods
|
|
20
|
+
*/
|
|
21
|
+
export declare const dotAnalyticsClickPlugin: (config: DotCMSAnalyticsConfig) => {
|
|
22
|
+
name: string;
|
|
23
|
+
/**
|
|
24
|
+
* Initialize click tracking
|
|
25
|
+
* Called when Analytics.js initializes the plugin with instance context
|
|
26
|
+
* @param instance - Analytics.js instance with track method
|
|
27
|
+
*/
|
|
28
|
+
initialize: ({ instance }: {
|
|
29
|
+
instance: AnalyticsInstance;
|
|
30
|
+
}) => Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Setup cleanup handlers when plugin is loaded
|
|
33
|
+
* Called after Analytics.js completes plugin loading
|
|
34
|
+
*/
|
|
35
|
+
loaded: () => boolean;
|
|
36
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { DotCMSClickTracker as o } from "./dot-analytics.click-tracker.js";
|
|
2
|
+
import { createPluginLogger as u, isBrowser as a, setupPluginCleanup as s } from "../../shared/utils/dot-analytics.utils.js";
|
|
3
|
+
const g = (n) => {
|
|
4
|
+
let i = null, l = null;
|
|
5
|
+
const e = u("Click", n);
|
|
6
|
+
return {
|
|
7
|
+
name: "dot-analytics-click",
|
|
8
|
+
/**
|
|
9
|
+
* Initialize click tracking
|
|
10
|
+
* Called when Analytics.js initializes the plugin with instance context
|
|
11
|
+
* @param instance - Analytics.js instance with track method
|
|
12
|
+
*/
|
|
13
|
+
initialize: ({ instance: r }) => (i = new o(n), l = i.onClick((c, t) => {
|
|
14
|
+
r.track(c, t);
|
|
15
|
+
}), i.initialize(), e.info("Click tracking plugin initialized"), Promise.resolve()),
|
|
16
|
+
/**
|
|
17
|
+
* Setup cleanup handlers when plugin is loaded
|
|
18
|
+
* Called after Analytics.js completes plugin loading
|
|
19
|
+
*/
|
|
20
|
+
loaded: () => (a() && i && s(() => {
|
|
21
|
+
l && (l.unsubscribe(), l = null), i && (i.cleanup(), i = null, e.info("Click tracking cleaned up on page unload"));
|
|
22
|
+
}), !0)
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
export {
|
|
26
|
+
g as dotAnalyticsClickPlugin
|
|
27
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { DotCMSContentClickPayload } from '../../shared/models';
|
|
2
|
+
import { createPluginLogger } from '../../shared/utils/dot-analytics.utils';
|
|
3
|
+
/**
|
|
4
|
+
* Handles click events on elements within a contentlet.
|
|
5
|
+
* The contentlet element is already known since we attach listeners to contentlets.
|
|
6
|
+
*
|
|
7
|
+
* @param event - The mouse event
|
|
8
|
+
* @param contentletElement - The contentlet container element
|
|
9
|
+
* @param trackCallback - Callback to execute if the click is valid
|
|
10
|
+
* @param logger - Logger instance for debug messages
|
|
11
|
+
*/
|
|
12
|
+
export declare const handleContentletClick: (event: MouseEvent, contentletElement: HTMLElement, trackCallback: (eventName: string, payload: DotCMSContentClickPayload) => void, logger: ReturnType<typeof createPluginLogger>) => void;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { CLICKABLE_ELEMENTS_SELECTOR as l, CLICK_EVENT_TYPE as m } from "../../shared/constants/dot-analytics.constants.js";
|
|
2
|
+
import { extractContentletData as p } from "../../shared/utils/dot-analytics.utils.js";
|
|
3
|
+
import { getViewportMetrics as b } from "../impression/dot-analytics.impression.utils.js";
|
|
4
|
+
const _ = (r, o, c, e) => {
|
|
5
|
+
const a = r.target;
|
|
6
|
+
e.debug("Click detected on:", a);
|
|
7
|
+
const t = a.closest(l);
|
|
8
|
+
if (!t) {
|
|
9
|
+
e.debug("No <a> or <button> found in click path");
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (!o.contains(t)) {
|
|
13
|
+
e.debug("Click was outside contentlet boundary");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
e.debug("Found clickable element:", t);
|
|
17
|
+
const n = p(o);
|
|
18
|
+
if (!n.identifier) {
|
|
19
|
+
e.debug("Contentlet has no identifier");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
e.debug("Contentlet data:", n);
|
|
23
|
+
const d = b(o), s = [];
|
|
24
|
+
for (const i of t.attributes)
|
|
25
|
+
!i.name.startsWith("data-dot-analytics") && i.name !== "class" && i.name !== "id" && i.name !== "href" && s.push(`${i.name}:${i.value}`);
|
|
26
|
+
const f = parseInt(o.dataset.dotAnalyticsDomIndex || "-1", 10), u = {
|
|
27
|
+
content: {
|
|
28
|
+
identifier: n.identifier,
|
|
29
|
+
inode: n.inode,
|
|
30
|
+
title: n.title,
|
|
31
|
+
content_type: n.contentType
|
|
32
|
+
},
|
|
33
|
+
position: {
|
|
34
|
+
viewport_offset_pct: d.offsetPercentage,
|
|
35
|
+
dom_index: f
|
|
36
|
+
},
|
|
37
|
+
element: {
|
|
38
|
+
text: (t.innerText || t.textContent || "").trim().substring(0, 100),
|
|
39
|
+
// Limit length
|
|
40
|
+
type: t.tagName.toLowerCase(),
|
|
41
|
+
id: t.id || "",
|
|
42
|
+
// Required by backend, empty string if not present
|
|
43
|
+
class: t.className || "",
|
|
44
|
+
// Required by backend, empty string if not present
|
|
45
|
+
href: t.getAttribute("href") || "",
|
|
46
|
+
// Path as written in HTML (relative), empty string for buttons
|
|
47
|
+
attributes: s
|
|
48
|
+
// Additional attributes (data-*, aria-*, target, etc.)
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
c(m, u);
|
|
52
|
+
};
|
|
53
|
+
export {
|
|
54
|
+
_ as handleContentletClick
|
|
55
|
+
};
|
|
@@ -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 content 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 r } from "../../shared/constants/dot-analytics.constants.js";
|
|
2
|
+
import { getLocalTime as i, enrichPagePayloadOptimized as o } from "../../shared/utils/dot-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: e
|
|
12
12
|
}) => {
|
|
13
|
-
const
|
|
14
|
-
if (!t)
|
|
13
|
+
const t = o(e);
|
|
14
|
+
if (!t.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 t;
|
|
30
17
|
},
|
|
31
18
|
/**
|
|
32
19
|
* TRACK EVENT ENRICHMENT - Runs after identity context injection
|
|
33
|
-
*
|
|
34
|
-
*
|
|
20
|
+
* Adds page data and timestamp for predefined content 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: e
|
|
38
27
|
}) => {
|
|
39
|
-
const { event:
|
|
40
|
-
return {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
]
|
|
28
|
+
const { event: t } = e, n = i();
|
|
29
|
+
return t === r.CONTENT_IMPRESSION || t === r.CONTENT_CLICK || t === r.CONVERSION ? {
|
|
30
|
+
...e,
|
|
31
|
+
page: {
|
|
32
|
+
title: document.title,
|
|
33
|
+
url: window.location.href
|
|
34
|
+
},
|
|
35
|
+
local_time: n
|
|
36
|
+
} : {
|
|
37
|
+
...e,
|
|
38
|
+
local_time: n
|
|
51
39
|
};
|
|
52
40
|
}
|
|
53
41
|
});
|
|
54
42
|
export {
|
|
55
|
-
|
|
43
|
+
l as dotAnalyticsEnricherPlugin
|
|
56
44
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ANALYTICS_WINDOWS_ACTIVE_KEY, ANALYTICS_WINDOWS_CLEANUP_KEY } from '
|
|
2
|
-
import { DotCMSAnalyticsConfig } from '
|
|
1
|
+
import { ANALYTICS_WINDOWS_ACTIVE_KEY, ANALYTICS_WINDOWS_CLEANUP_KEY } from '../../../../../../uve/src/internal.ts';
|
|
2
|
+
import { DotCMSAnalyticsConfig } from '../../shared/models';
|
|
3
3
|
declare global {
|
|
4
4
|
interface Window {
|
|
5
5
|
[ANALYTICS_WINDOWS_CLEANUP_KEY]?: () => void;
|
|
@@ -10,13 +10,6 @@ declare global {
|
|
|
10
10
|
* Updates session activity with throttling
|
|
11
11
|
*/
|
|
12
12
|
export declare const updateSessionActivity: () => void;
|
|
13
|
-
/**
|
|
14
|
-
* Gets session information for debugging
|
|
15
|
-
*/
|
|
16
|
-
export declare const getSessionInfo: () => {
|
|
17
|
-
lastActivity: number;
|
|
18
|
-
isActive: boolean;
|
|
19
|
-
};
|
|
20
13
|
/**
|
|
21
14
|
* Initializes activity tracking
|
|
22
15
|
*/
|
|
@@ -25,11 +18,3 @@ export declare const initializeActivityTracking: (config: DotCMSAnalyticsConfig)
|
|
|
25
18
|
* Cleans up activity tracking listeners and resets analytics state
|
|
26
19
|
*/
|
|
27
20
|
export declare const cleanupActivityTracking: () => void;
|
|
28
|
-
/**
|
|
29
|
-
* Checks if user has been inactive
|
|
30
|
-
*/
|
|
31
|
-
export declare const isUserInactive: () => boolean;
|
|
32
|
-
/**
|
|
33
|
-
* Gets last activity time
|
|
34
|
-
*/
|
|
35
|
-
export declare const getLastActivity: () => number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ANALYTICS_WINDOWS_ACTIVE_KEY as
|
|
2
|
-
import { DEFAULT_SESSION_TIMEOUT_MINUTES as
|
|
3
|
-
class
|
|
1
|
+
import { ANALYTICS_WINDOWS_ACTIVE_KEY as a, ANALYTICS_WINDOWS_CLEANUP_KEY as o } from "../../../../uve/src/internal/constants.js";
|
|
2
|
+
import { DEFAULT_SESSION_TIMEOUT_MINUTES as r, ACTIVITY_EVENTS as l } from "../../shared/constants/dot-analytics.constants.js";
|
|
3
|
+
class v {
|
|
4
4
|
constructor() {
|
|
5
5
|
this.activityListeners = [], this.lastActivityTime = Date.now(), this.inactivityTimer = null, this.isThrottled = !1, this.config = null, this.ACTIVITY_THROTTLE_MS = 1e3;
|
|
6
6
|
}
|
|
@@ -11,25 +11,11 @@ class l {
|
|
|
11
11
|
updateActivityTime() {
|
|
12
12
|
this.lastActivityTime = Date.now(), this.inactivityTimer && clearTimeout(this.inactivityTimer), this.inactivityTimer = setTimeout(
|
|
13
13
|
() => {
|
|
14
|
-
|
|
15
|
-
(i = this.config) != null && i.debug && console.warn("DotCMS Analytics: User became inactive after timeout"), this.inactivityTimer = null;
|
|
14
|
+
this.config?.debug && console.warn("DotCMS Analytics [Activity]: User became inactive after timeout"), this.inactivityTimer = null;
|
|
16
15
|
},
|
|
17
|
-
|
|
16
|
+
r * 60 * 1e3
|
|
18
17
|
);
|
|
19
18
|
}
|
|
20
|
-
/**
|
|
21
|
-
* Checks if user has been inactive
|
|
22
|
-
*/
|
|
23
|
-
isUserInactive() {
|
|
24
|
-
const i = c * 60 * 1e3;
|
|
25
|
-
return Date.now() - this.lastActivityTime > i;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Gets last activity time
|
|
29
|
-
*/
|
|
30
|
-
getLastActivity() {
|
|
31
|
-
return this.lastActivityTime;
|
|
32
|
-
}
|
|
33
19
|
/**
|
|
34
20
|
* Updates session activity with throttling
|
|
35
21
|
*/
|
|
@@ -45,17 +31,19 @@ class l {
|
|
|
45
31
|
if (this.cleanup(), this.config = i, typeof window > "u")
|
|
46
32
|
return;
|
|
47
33
|
const s = () => this.updateSessionActivity();
|
|
48
|
-
|
|
49
|
-
window.addEventListener(
|
|
50
|
-
() => window.removeEventListener(
|
|
34
|
+
l.forEach((c) => {
|
|
35
|
+
window.addEventListener(c, s, { passive: !0 }), this.activityListeners.push(
|
|
36
|
+
() => window.removeEventListener(c, s)
|
|
51
37
|
);
|
|
52
38
|
});
|
|
53
39
|
const n = () => {
|
|
54
|
-
document.visibilityState === "visible" && (this.updateSessionActivity(), i.debug && console.warn(
|
|
40
|
+
document.visibilityState === "visible" && (this.updateSessionActivity(), i.debug && console.warn(
|
|
41
|
+
"DotCMS Analytics [Activity]: User returned to tab, session reactivated"
|
|
42
|
+
));
|
|
55
43
|
};
|
|
56
44
|
document.addEventListener("visibilitychange", n), this.activityListeners.push(
|
|
57
45
|
() => document.removeEventListener("visibilitychange", n)
|
|
58
|
-
), this.updateActivityTime(), i.debug && console.warn("DotCMS Analytics: Activity tracking initialized");
|
|
46
|
+
), this.updateActivityTime(), i.debug && console.warn("DotCMS Analytics [Activity]: Activity tracking initialized");
|
|
59
47
|
}
|
|
60
48
|
/**
|
|
61
49
|
* Cleans up all activity tracking listeners
|
|
@@ -63,25 +51,16 @@ class l {
|
|
|
63
51
|
cleanup() {
|
|
64
52
|
this.activityListeners.forEach((i) => i()), this.activityListeners = [], this.inactivityTimer && (clearTimeout(this.inactivityTimer), this.inactivityTimer = null), this.config = null;
|
|
65
53
|
}
|
|
66
|
-
/**
|
|
67
|
-
* Gets session information for debugging
|
|
68
|
-
*/
|
|
69
|
-
getSessionInfo() {
|
|
70
|
-
return {
|
|
71
|
-
lastActivity: this.getLastActivity(),
|
|
72
|
-
isActive: !this.isUserInactive()
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
54
|
}
|
|
76
|
-
const t = new
|
|
55
|
+
const t = new v(), d = () => {
|
|
77
56
|
t.updateSessionActivity();
|
|
78
|
-
},
|
|
57
|
+
}, u = (e) => {
|
|
79
58
|
t.initialize(e);
|
|
80
59
|
}, y = () => {
|
|
81
|
-
t.cleanup(), typeof window < "u" && (window[
|
|
60
|
+
t.cleanup(), typeof window < "u" && (window[a] = !1, window[o] = void 0, window.dispatchEvent(new CustomEvent("dotcms:analytics:cleanup")));
|
|
82
61
|
};
|
|
83
62
|
export {
|
|
84
63
|
y as cleanupActivityTracking,
|
|
85
|
-
|
|
86
|
-
|
|
64
|
+
u as initializeActivityTracking,
|
|
65
|
+
d as updateSessionActivity
|
|
87
66
|
};
|
|
@@ -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;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { cleanupActivityTracking as n, updateSessionActivity as r, initializeActivityTracking as a } from "./dot-analytics.identity.activity-tracker.js";
|
|
2
|
+
import { getAnalyticsContext as o } from "../../shared/utils/dot-analytics.utils.js";
|
|
3
3
|
const s = (t) => ({
|
|
4
4
|
name: "dot-analytics-identity",
|
|
5
5
|
/**
|
|
@@ -12,8 +12,8 @@ const s = (t) => ({
|
|
|
12
12
|
* This runs BEFORE the enricher plugin
|
|
13
13
|
*/
|
|
14
14
|
pageStart: ({ payload: e }) => {
|
|
15
|
-
|
|
16
|
-
const i =
|
|
15
|
+
r();
|
|
16
|
+
const i = o(t);
|
|
17
17
|
return {
|
|
18
18
|
...e,
|
|
19
19
|
context: i
|
|
@@ -24,8 +24,8 @@ const s = (t) => ({
|
|
|
24
24
|
* This runs BEFORE the enricher plugin
|
|
25
25
|
*/
|
|
26
26
|
trackStart: ({ payload: e }) => {
|
|
27
|
-
|
|
28
|
-
const i =
|
|
27
|
+
r();
|
|
28
|
+
const i = o(t);
|
|
29
29
|
return {
|
|
30
30
|
...e,
|
|
31
31
|
context: i
|
|
@@ -35,7 +35,7 @@ const s = (t) => ({
|
|
|
35
35
|
* Clean up on plugin unload
|
|
36
36
|
* Sets up cleanup handlers for activity tracking
|
|
37
37
|
*/
|
|
38
|
-
loaded: () => (typeof window < "u" && (window.addEventListener("beforeunload",
|
|
38
|
+
loaded: () => (typeof window < "u" && (window.addEventListener("beforeunload", n), window.addEventListener("pagehide", n)), !0)
|
|
39
39
|
});
|
|
40
40
|
export {
|
|
41
41
|
s as dotAnalyticsIdentityPlugin
|
|
@@ -1,20 +1,4 @@
|
|
|
1
1
|
import { DotCMSEventUtmData } from '../../shared/models';
|
|
2
|
-
/**
|
|
3
|
-
* Updates activity timestamp
|
|
4
|
-
*/
|
|
5
|
-
export declare const updateActivityTime: () => void;
|
|
6
|
-
/**
|
|
7
|
-
* Checks if user has been inactive
|
|
8
|
-
*/
|
|
9
|
-
export declare const isUserInactive: () => boolean;
|
|
10
|
-
/**
|
|
11
|
-
* Checks if a new day has started since session creation
|
|
12
|
-
*/
|
|
13
|
-
export declare const hasPassedMidnight: (sessionStartTime: number) => boolean;
|
|
14
|
-
/**
|
|
15
|
-
* Gets the last activity time
|
|
16
|
-
*/
|
|
17
|
-
export declare const getLastActivityTime: () => number;
|
|
18
2
|
/**
|
|
19
3
|
* Compares UTM parameters to detect campaign changes.
|
|
20
4
|
* Only checks significant parameters: source, medium, and campaign.
|