@dotcms/analytics 26.9.18-1 → 26.9.18-1-next.2741
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/MIGRATION.md +42 -0
- package/README.md +10 -1
- package/index.d.ts +1 -1
- package/index.js +4 -4
- package/lib/core/dot-analytics.content.js +10 -11
- package/lib/core/plugin/identity/dot-analytics.identity.plugin.d.ts +4 -4
- package/lib/core/plugin/impression/dot-analytics.impression-tracker.js +13 -13
- package/lib/core/public-api.d.ts +12 -0
- package/lib/core/shared/constants/dot-analytics.constants.js +24 -23
- package/lib/core/shared/http/dot-analytics.http.js +3 -3
- package/lib/core/shared/queue/dot-analytics.queue.utils.js +13 -13
- package/lib/core/shared/utils/dot-analytics.utils.js +223 -153
- package/lib/react/hook/useContentAnalytics.js +6 -7
- package/package.json +19 -7
- package/types/src/lib/editor/public.js +2 -3
- package/uve/src/lib/core/core.utils.js +2 -3
- package/types/src/lib/events/internal.js +0 -4
- package/uve/src/internal/constants.js +0 -7
- package/uve/src/internal/contentlet-sentinel.constants.js +0 -5
- package/uve/src/internal/events.js +0 -196
- package/uve/src/lib/dom/dom.utils.js +0 -103
package/MIGRATION.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Migration guide
|
|
2
|
+
|
|
3
|
+
## The package root is now framework-neutral
|
|
4
|
+
|
|
5
|
+
**Affects:** anyone importing React APIs from `@dotcms/analytics` directly.
|
|
6
|
+
|
|
7
|
+
Previously `@dotcms/analytics` and `@dotcms/analytics/react` resolved to exactly the same module — the package root was a single re-export of the React bindings:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
// src/index.ts, before
|
|
11
|
+
export * from './lib/react';
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
That meant importing the package at all pulled in `react`, `next/navigation` and `@dotcms/uve`, even for a consumer that only wanted to initialize tracking. It also left the framework-neutral analytics engine — `initializeContentAnalytics`, the plugins, the queue and the trackers — with no entrypoint of its own.
|
|
15
|
+
|
|
16
|
+
The root now exports only the framework-neutral API. The React bindings stay exactly where they already were, behind the explicit `./react` subpath.
|
|
17
|
+
|
|
18
|
+
### What to change
|
|
19
|
+
|
|
20
|
+
If you import `useContentAnalytics` or `DotContentAnalytics` from the package root, add `/react` to the specifier:
|
|
21
|
+
|
|
22
|
+
```diff
|
|
23
|
+
- import { useContentAnalytics, DotContentAnalytics } from '@dotcms/analytics';
|
|
24
|
+
+ import { useContentAnalytics, DotContentAnalytics } from '@dotcms/analytics/react';
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Nothing else changes: the components, hooks and their signatures are untouched, and `@dotcms/analytics/react` already worked before this release, so you can make the change ahead of upgrading.
|
|
28
|
+
|
|
29
|
+
### What you get for it
|
|
30
|
+
|
|
31
|
+
A non-React consumer can now use analytics without React in the bundle at all:
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { initializeContentAnalytics } from '@dotcms/analytics';
|
|
35
|
+
|
|
36
|
+
const analytics = initializeContentAnalytics({ siteAuth: '…', server: '…' });
|
|
37
|
+
analytics?.pageView();
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Also in this release
|
|
41
|
+
|
|
42
|
+
`next` is now declared as an optional peer dependency. The `./react` entry has always imported `next/navigation` (through `useRouterTracker`), but never said so, which left package managers unable to warn about a missing or mismatched Next.js version. It is marked optional because the neutral root does not need it.
|
package/README.md
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
# @dotcms/analytics
|
|
2
2
|
|
|
3
|
-
Content Analytics SDK for tracking content-aware events in dotCMS-powered
|
|
3
|
+
Content Analytics SDK for tracking content-aware events in dotCMS-powered applications.
|
|
4
|
+
|
|
5
|
+
## Entrypoints
|
|
6
|
+
|
|
7
|
+
| Import | Contains | Use it when |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| `@dotcms/analytics` | The framework-neutral engine: `initializeContentAnalytics`, `getAnalyticsConfig`, and the shared types. No React, no Next.js. | You are not using React, or you want to drive analytics yourself. |
|
|
10
|
+
| `@dotcms/analytics/react` | `DotContentAnalytics` and `useContentAnalytics`, including the Next.js App Router integration. | You are using React. This is what the rest of this guide uses. |
|
|
11
|
+
|
|
12
|
+
> **Upgrading?** The package root used to re-export the React bindings, so `@dotcms/analytics` and `@dotcms/analytics/react` resolved to the same module. The root is now framework-neutral. If you imported `useContentAnalytics` or `DotContentAnalytics` from the root, add `/react` to the specifier — see [MIGRATION.md](./MIGRATION.md).
|
|
4
13
|
|
|
5
14
|
## Which SDK Version Should I Use?
|
|
6
15
|
|
package/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './lib/
|
|
1
|
+
export * from './lib/core/public-api';
|
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { getAnalyticsConfig as n } from "./lib/core/shared/utils/dot-analytics.utils.js";
|
|
2
|
+
import { initializeContentAnalytics as e } from "./lib/core/dot-analytics.content.js";
|
|
3
3
|
export {
|
|
4
|
-
n as
|
|
5
|
-
|
|
4
|
+
n as getAnalyticsConfig,
|
|
5
|
+
e as initializeContentAnalytics
|
|
6
6
|
};
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { Analytics as l } from "analytics";
|
|
2
2
|
import { getUVEState as d } from "../../uve/src/lib/core/core.utils.js";
|
|
3
|
-
import "../../uve/src/internal/constants.js";
|
|
4
3
|
import { dotAnalyticsClickPlugin as y } from "./plugin/click/dot-analytics.click.plugin.js";
|
|
5
|
-
import { dotAnalyticsEnricherPlugin as
|
|
6
|
-
import { dotAnalyticsIdentityPlugin as
|
|
4
|
+
import { dotAnalyticsEnricherPlugin as u } from "./plugin/enricher/dot-analytics.enricher.plugin.js";
|
|
5
|
+
import { dotAnalyticsIdentityPlugin as m } from "./plugin/identity/dot-analytics.identity.plugin.js";
|
|
7
6
|
import { dotAnalyticsImpressionPlugin as A } from "./plugin/impression/dot-analytics.impression.plugin.js";
|
|
8
|
-
import { dotAnalytics as
|
|
9
|
-
import { ANALYTICS_WINDOWS_ACTIVE_KEY as e, ANALYTICS_WINDOWS_CLEANUP_KEY as
|
|
7
|
+
import { dotAnalytics as f } from "./plugin/main/dot-analytics.plugin.js";
|
|
8
|
+
import { ANALYTICS_WINDOWS_ACTIVE_KEY as e, ANALYTICS_WINDOWS_CLEANUP_KEY as p, DotCMSPredefinedEventType as w } from "./shared/constants/dot-analytics.constants.js";
|
|
10
9
|
import { validateAnalyticsConfig as C, isBrowser as g, getEnhancedTrackingPlugins as E } from "./shared/utils/dot-analytics.utils.js";
|
|
11
10
|
import { cleanupActivityTracking as S } from "./plugin/identity/dot-analytics.identity.activity-tracker.js";
|
|
12
|
-
const
|
|
11
|
+
const h = (t) => {
|
|
13
12
|
const r = C(t);
|
|
14
13
|
if (r)
|
|
15
14
|
return console.error(
|
|
@@ -25,17 +24,17 @@ const O = (t) => {
|
|
|
25
24
|
app: "dotAnalytics",
|
|
26
25
|
debug: t.debug,
|
|
27
26
|
plugins: [
|
|
28
|
-
|
|
27
|
+
m(t),
|
|
29
28
|
// Inject identity context
|
|
30
29
|
...s,
|
|
31
30
|
//Track content impressions & clicks (conditionally loaded)
|
|
32
|
-
|
|
31
|
+
u(),
|
|
33
32
|
// Enrich and clean payload with page, device, utm data and custom data
|
|
34
|
-
|
|
33
|
+
f(t)
|
|
35
34
|
// Send events to server
|
|
36
35
|
]
|
|
37
36
|
}), a = () => S();
|
|
38
|
-
return typeof window < "u" && (window.addEventListener("beforeunload", a), window[
|
|
37
|
+
return typeof window < "u" && (window.addEventListener("beforeunload", a), window[p] = a, window[e] = !0, window.dispatchEvent(new CustomEvent("dotcms:analytics:ready"))), {
|
|
39
38
|
/**
|
|
40
39
|
* Track a page view.
|
|
41
40
|
* Session activity is automatically updated by the identity plugin.
|
|
@@ -83,5 +82,5 @@ const O = (t) => {
|
|
|
83
82
|
};
|
|
84
83
|
};
|
|
85
84
|
export {
|
|
86
|
-
|
|
85
|
+
h as initializeContentAnalytics
|
|
87
86
|
};
|
|
@@ -24,8 +24,8 @@ export declare const dotAnalyticsIdentityPlugin: (config: DotCMSAnalyticsConfig)
|
|
|
24
24
|
* This runs BEFORE the enricher plugin
|
|
25
25
|
*/
|
|
26
26
|
pageStart: ({ payload }: AnalyticsBaseParams) => {
|
|
27
|
-
context: import('../../
|
|
28
|
-
type: "
|
|
27
|
+
context: import('../../public-api').DotCMSAnalyticsEventContext;
|
|
28
|
+
type: "track" | "page";
|
|
29
29
|
properties: Record<string, unknown>;
|
|
30
30
|
options: Record<string, unknown>;
|
|
31
31
|
userId: string;
|
|
@@ -41,8 +41,8 @@ export declare const dotAnalyticsIdentityPlugin: (config: DotCMSAnalyticsConfig)
|
|
|
41
41
|
* This runs BEFORE the enricher plugin
|
|
42
42
|
*/
|
|
43
43
|
trackStart: ({ payload }: AnalyticsBaseParams) => {
|
|
44
|
-
context: import('../../
|
|
45
|
-
type: "
|
|
44
|
+
context: import('../../public-api').DotCMSAnalyticsEventContext;
|
|
45
|
+
type: "track" | "page";
|
|
46
46
|
properties: Record<string, unknown>;
|
|
47
47
|
options: Record<string, unknown>;
|
|
48
48
|
userId: string;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { getViewportMetrics as m, isElementMeetingVisibilityThreshold as d } from "./dot-analytics.impression.utils.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { createPluginLogger as u, isBrowser as l, INITIAL_SCAN_DELAY_MS as g, findContentlets as p, extractContentletIdentifier as a, createContentletObserver as b, extractContentletData as f } from "../../shared/utils/dot-analytics.utils.js";
|
|
3
|
+
import { DEFAULT_IMPRESSION_CONFIG as c, IMPRESSION_EVENT_TYPE as v } from "../../shared/constants/dot-analytics.constants.js";
|
|
4
4
|
class T {
|
|
5
5
|
constructor(e) {
|
|
6
|
-
this.observer = null, this.mutationObserver = null, this.elementImpressionStates = /* @__PURE__ */ new Map(), this.sessionTrackedImpressions = /* @__PURE__ */ new Set(), this.currentPagePath = "", this.subscribers = /* @__PURE__ */ new Set(), this.logger =
|
|
6
|
+
this.observer = null, this.mutationObserver = null, this.elementImpressionStates = /* @__PURE__ */ new Map(), this.sessionTrackedImpressions = /* @__PURE__ */ new Set(), this.currentPagePath = "", this.subscribers = /* @__PURE__ */ new Set(), this.logger = u("Impression", e), this.impressionConfig = this.resolveImpressionConfig(e.impressions);
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* Subscribe to impression events
|
|
@@ -29,16 +29,16 @@ class T {
|
|
|
29
29
|
}
|
|
30
30
|
/** Merges user config with defaults */
|
|
31
31
|
resolveImpressionConfig(e) {
|
|
32
|
-
return typeof e != "object" || e === null ? { ...
|
|
33
|
-
...
|
|
32
|
+
return typeof e != "object" || e === null ? { ...c } : {
|
|
33
|
+
...c,
|
|
34
34
|
...e
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
37
|
/** Initializes tracking: sets up observers, finds contentlets, handles visibility/navigation */
|
|
38
38
|
initialize() {
|
|
39
|
-
|
|
39
|
+
l() && (this.initializeIntersectionObserver(), typeof window < "u" && setTimeout(() => {
|
|
40
40
|
this.logger.debug("Running initial scan after timeout..."), this.findAndObserveContentletElements();
|
|
41
|
-
},
|
|
41
|
+
}, g), this.initializeDynamicContentDetector(), this.initializePageVisibilityHandler(), this.initializePageNavigationHandler(), this.logger.info("Impression tracking initialized with config:", this.impressionConfig));
|
|
42
42
|
}
|
|
43
43
|
/** Sets up IntersectionObserver with configured visibility threshold */
|
|
44
44
|
initializeIntersectionObserver() {
|
|
@@ -55,7 +55,7 @@ class T {
|
|
|
55
55
|
/** Finds contentlets in DOM, validates them, and starts observing (respects maxNodes limit) */
|
|
56
56
|
findAndObserveContentletElements() {
|
|
57
57
|
if (!this.observer) return;
|
|
58
|
-
const e =
|
|
58
|
+
const e = p();
|
|
59
59
|
if (e.length === 0) {
|
|
60
60
|
this.logger.warn("No contentlets found to track");
|
|
61
61
|
return;
|
|
@@ -63,7 +63,7 @@ class T {
|
|
|
63
63
|
const i = Math.min(e.length, this.impressionConfig.maxNodes);
|
|
64
64
|
let t = 0;
|
|
65
65
|
for (let s = 0; s < i; s++) {
|
|
66
|
-
const n = e[s], r =
|
|
66
|
+
const n = e[s], r = a(n);
|
|
67
67
|
if (r) {
|
|
68
68
|
const o = this.shouldSkipElement(n);
|
|
69
69
|
if (o) {
|
|
@@ -84,7 +84,7 @@ class T {
|
|
|
84
84
|
}
|
|
85
85
|
/** Watches for new contentlets added to DOM (debounced for performance) */
|
|
86
86
|
initializeDynamicContentDetector() {
|
|
87
|
-
|
|
87
|
+
l() && (this.mutationObserver = b(() => {
|
|
88
88
|
this.findAndObserveContentletElements();
|
|
89
89
|
}), this.logger.info("MutationObserver enabled for dynamic content detection"));
|
|
90
90
|
}
|
|
@@ -118,7 +118,7 @@ class T {
|
|
|
118
118
|
/** Handles visibility changes: starts timer on enter, cancels on exit */
|
|
119
119
|
processIntersectionChanges(e) {
|
|
120
120
|
document.visibilityState === "visible" && e.forEach((i) => {
|
|
121
|
-
const t = i.target, s =
|
|
121
|
+
const t = i.target, s = a(t);
|
|
122
122
|
s && (i.isIntersecting ? this.startImpressionDwellTimer(s, t) : this.cancelImpressionDwellTimer(s));
|
|
123
123
|
});
|
|
124
124
|
}
|
|
@@ -142,7 +142,7 @@ class T {
|
|
|
142
142
|
trackAndSendImpression(e, i) {
|
|
143
143
|
const t = this.elementImpressionStates.get(e);
|
|
144
144
|
if (!t) return;
|
|
145
|
-
const s = t.visibleSince ? Date.now() - t.visibleSince : 0, n =
|
|
145
|
+
const s = t.visibleSince ? Date.now() - t.visibleSince : 0, n = f(i), r = m(i), o = parseInt(i.dataset.dotDomIndex || "-1", 10), h = {
|
|
146
146
|
content: {
|
|
147
147
|
identifier: n.identifier,
|
|
148
148
|
inode: n.inode,
|
|
@@ -154,7 +154,7 @@ class T {
|
|
|
154
154
|
dom_index: o
|
|
155
155
|
}
|
|
156
156
|
};
|
|
157
|
-
this.notifySubscribers(
|
|
157
|
+
this.notifySubscribers(v, h), this.markImpressionAsTracked(e), t.timer = null, t.visibleSince = null, t.tracked = !0, this.observer && this.observer.unobserve(i), this.logger.info(
|
|
158
158
|
`Fired impression for ${e} (dwell: ${s}ms) - element unobserved`,
|
|
159
159
|
n
|
|
160
160
|
);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-neutral public API for `@dotcms/analytics`.
|
|
3
|
+
*
|
|
4
|
+
* This is the package root (`@dotcms/analytics`). It contains no React and no Next.js: the
|
|
5
|
+
* React bindings — `DotContentAnalytics` and `useContentAnalytics`, which depend on
|
|
6
|
+
* `react` and `next/navigation` — live behind the explicit `@dotcms/analytics/react`
|
|
7
|
+
* subpath so a Vue, Angular, Astro or plain-JS consumer never pulls them in.
|
|
8
|
+
*/
|
|
9
|
+
export { initializeContentAnalytics } from './dot-analytics.content';
|
|
10
|
+
export { getAnalyticsConfig } from './shared/utils/dot-analytics.utils';
|
|
11
|
+
export type { DotCMSAnalytics, DotCMSAnalyticsConfig, DotCMSAnalyticsParams, ContentletData, ImpressionConfig, QueueConfig } from './shared/models';
|
|
12
|
+
export type { DotCMSAnalyticsEventContext, DotCMSEventPageData, DotCMSImpressionEventData } from './shared/models';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const S = "/api/v1/analytics/content/event", c = {
|
|
2
2
|
PAGEVIEW: "pageview",
|
|
3
3
|
CONTENT_IMPRESSION: "content_impression",
|
|
4
4
|
CONTENT_CLICK: "content_click",
|
|
@@ -9,12 +9,12 @@ const c = "/api/v1/analytics/content/event", o = {
|
|
|
9
9
|
"utm_campaign",
|
|
10
10
|
"utm_term",
|
|
11
11
|
"utm_content"
|
|
12
|
-
],
|
|
12
|
+
], o = 30, e = "dot_analytics_session_id", N = "dot_analytics_user_id", _ = 15, E = 5e3, A = ["click"], L = {
|
|
13
13
|
eventBatchSize: _,
|
|
14
14
|
// Max events per batch - auto-sends when reached
|
|
15
15
|
flushInterval: E
|
|
16
16
|
// Time between flushes - sends whatever is queued
|
|
17
|
-
},
|
|
17
|
+
}, O = "ca.min.js", i = [
|
|
18
18
|
"title",
|
|
19
19
|
"url",
|
|
20
20
|
"path",
|
|
@@ -23,36 +23,37 @@ const c = "/api/v1/analytics/content/event", o = {
|
|
|
23
23
|
"width",
|
|
24
24
|
"height",
|
|
25
25
|
"referrer"
|
|
26
|
-
], t = 0.5, n = 750, T = 100,
|
|
26
|
+
], t = 0.5, n = 750, T = 100, I = 100, C = 250, U = {
|
|
27
27
|
visibilityThreshold: t,
|
|
28
28
|
dwellMs: n,
|
|
29
29
|
maxNodes: T,
|
|
30
|
-
throttleMs:
|
|
31
|
-
},
|
|
30
|
+
throttleMs: I
|
|
31
|
+
}, a = "content_impression", M = "content_click", D = 300, R = "a, button", l = "__dotAnalyticsActive__", F = "__dotAnalyticsCleanup__", P = "dotcms-contentlet", d = "dot_analytics_tab_id", r = "dot_analytics_queue", Y = 1440 * 60 * 1e3;
|
|
32
32
|
export {
|
|
33
33
|
A as ACTIVITY_EVENTS,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
l as
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
34
|
+
S as ANALYTICS_ENDPOINT,
|
|
35
|
+
i as ANALYTICS_JS_DEFAULT_PROPERTIES,
|
|
36
|
+
O as ANALYTICS_MINIFIED_SCRIPT_NAME,
|
|
37
|
+
l as ANALYTICS_WINDOWS_ACTIVE_KEY,
|
|
38
|
+
F as ANALYTICS_WINDOWS_CLEANUP_KEY,
|
|
39
|
+
R as CLICKABLE_ELEMENTS_SELECTOR,
|
|
40
|
+
M as CLICK_EVENT_TYPE,
|
|
41
|
+
P as CONTENTLET_CLASS,
|
|
41
42
|
D as DEFAULT_CLICK_THROTTLE_MS,
|
|
42
|
-
|
|
43
|
+
U as DEFAULT_IMPRESSION_CONFIG,
|
|
43
44
|
n as DEFAULT_IMPRESSION_DWELL_MS,
|
|
44
45
|
T as DEFAULT_IMPRESSION_MAX_NODES,
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
C as DEFAULT_IMPRESSION_MUTATION_OBSERVER_DEBOUNCE_MS,
|
|
47
|
+
I as DEFAULT_IMPRESSION_THROTTLE_MS,
|
|
47
48
|
t as DEFAULT_IMPRESSION_VISIBILITY_THRESHOLD,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
L as DEFAULT_QUEUE_CONFIG,
|
|
50
|
+
o as DEFAULT_SESSION_TIMEOUT_MINUTES,
|
|
51
|
+
c as DotCMSPredefinedEventType,
|
|
51
52
|
s as EXPECTED_UTM_KEYS,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
a as IMPRESSION_EVENT_TYPE,
|
|
54
|
+
Y as MAX_EVENT_AGE_MS,
|
|
55
|
+
r as QUEUE_STORAGE_KEY_PREFIX,
|
|
55
56
|
e as SESSION_STORAGE_KEY,
|
|
56
|
-
|
|
57
|
+
d as TAB_ID_STORAGE_KEY,
|
|
57
58
|
N as USER_ID_KEY
|
|
58
59
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { createPluginLogger as p } from "../utils/dot-analytics.utils.js";
|
|
2
|
+
import { ANALYTICS_ENDPOINT as l } from "../constants/dot-analytics.constants.js";
|
|
3
3
|
const m = async (n, i, c = !1) => {
|
|
4
|
-
const e =
|
|
4
|
+
const e = p("HTTP", i), f = `${i.server}${l}`, g = JSON.stringify(n);
|
|
5
5
|
e.info(`Sending ${n.events.length} event(s)${c ? " (keepalive)" : ""}`, {
|
|
6
6
|
payload: n
|
|
7
7
|
});
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import q from "@analytics/queue-utils";
|
|
2
2
|
import F from "@analytics/router-utils";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { sendAnalyticsEvent as I } from "../http/dot-analytics.http.js";
|
|
4
|
+
import { createPluginLogger as x, safeSessionStorage as d, generateSecureId as z, getAnalyticsContext as P } from "../utils/dot-analytics.utils.js";
|
|
5
|
+
import { DEFAULT_QUEUE_CONFIG as T, TAB_ID_STORAGE_KEY as w, MAX_EVENT_AGE_MS as U, QUEUE_STORAGE_KEY_PREFIX as D } from "../constants/dot-analytics.constants.js";
|
|
6
6
|
const R = (l) => {
|
|
7
|
-
const n =
|
|
7
|
+
const n = x("Queue", l);
|
|
8
8
|
let i = null, c = null, f = !1, m = !1, v = typeof window < "u" ? window.location.pathname : "", o = "", a = [];
|
|
9
9
|
const y = {
|
|
10
|
-
...
|
|
10
|
+
...T,
|
|
11
11
|
...typeof l.queue == "object" ? l.queue : {}
|
|
12
|
-
}, g = () => `${
|
|
12
|
+
}, g = () => `${D}_${o}`, E = (e) => {
|
|
13
13
|
const t = e;
|
|
14
14
|
if (!t || typeof t != "object" || Array.isArray(t))
|
|
15
15
|
return null;
|
|
@@ -32,7 +32,7 @@ const R = (l) => {
|
|
|
32
32
|
if (!r)
|
|
33
33
|
return d.removeItem(e), null;
|
|
34
34
|
const u = Date.now() - r.timestamp;
|
|
35
|
-
return u >
|
|
35
|
+
return u > U ? (n.warn(
|
|
36
36
|
`Persisted events too old (${Math.round(u / 1e3 / 60 / 60)}h), discarding`
|
|
37
37
|
), d.removeItem(e), null) : (n.info(
|
|
38
38
|
`Loaded ${r.events.length} persisted event(s) from storage (age: ${Math.round(u / 1e3)}s)`
|
|
@@ -63,14 +63,14 @@ const R = (l) => {
|
|
|
63
63
|
if (e.length === 0)
|
|
64
64
|
return !0;
|
|
65
65
|
n.info(`Sending ${e.length} persisted event(s) immediately`);
|
|
66
|
-
const r = { context:
|
|
67
|
-
return
|
|
66
|
+
const r = { context: P(l), events: e };
|
|
67
|
+
return I(r, l, t);
|
|
68
68
|
}, $ = (e, t) => {
|
|
69
69
|
if (!c) return;
|
|
70
70
|
n.debug(`Sending batch of ${e.length} event(s)`, {
|
|
71
71
|
events: e,
|
|
72
72
|
keepalive: f
|
|
73
|
-
}),
|
|
73
|
+
}), I({ context: c, events: e }, l, f), a = a.filter(
|
|
74
74
|
(r) => !e.some((u) => u === r)
|
|
75
75
|
), a.length === 0 ? b() : h();
|
|
76
76
|
}, p = () => {
|
|
@@ -90,13 +90,13 @@ const R = (l) => {
|
|
|
90
90
|
*/
|
|
91
91
|
initialize: () => {
|
|
92
92
|
if (typeof window < "u") {
|
|
93
|
-
const t = d.getItem(
|
|
93
|
+
const t = d.getItem(w);
|
|
94
94
|
if (t)
|
|
95
95
|
o = t, n.debug(`Reusing Tab ID: ${o}`);
|
|
96
96
|
else {
|
|
97
|
-
typeof crypto < "u" && typeof crypto.randomUUID == "function" ? o = crypto.randomUUID() : (o =
|
|
97
|
+
typeof crypto < "u" && typeof crypto.randomUUID == "function" ? o = crypto.randomUUID() : (o = z("tab"), n.debug("crypto.randomUUID not available, using fallback generator"));
|
|
98
98
|
try {
|
|
99
|
-
d.setItem(
|
|
99
|
+
d.setItem(w, o);
|
|
100
100
|
} catch {
|
|
101
101
|
}
|
|
102
102
|
n.debug(`Generated new Tab ID: ${o}`);
|