@dotcms/analytics 1.1.1-next.6 → 1.1.1-next.8
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 +8 -8
- package/lib/core/dot-content-analytics.d.ts +7 -0
- package/lib/core/dot-content-analytics.js +23 -22
- package/lib/core/shared/dot-content-analytics.activity-tracker.d.ts +8 -1
- package/lib/core/shared/dot-content-analytics.activity-tracker.js +11 -10
- package/lib/core/shared/dot-content-analytics.utils.d.ts +15 -0
- package/lib/core/shared/dot-content-analytics.utils.js +27 -20
- package/lib/core/shared/models/index.d.ts +0 -5
- package/package.json +1 -1
- package/uve/src/internal/constants.js +8 -3
package/README.md
CHANGED
|
@@ -426,14 +426,14 @@ Standalone attributes to verify:
|
|
|
426
426
|
- Angular & Vue support
|
|
427
427
|
- Realtime dashboard
|
|
428
428
|
|
|
429
|
-
##
|
|
429
|
+
## Support
|
|
430
430
|
|
|
431
431
|
We offer multiple channels to get help with the dotCMS Analytics SDK:
|
|
432
432
|
|
|
433
|
-
- **GitHub Issues**: For bug reports and feature requests, please [open an issue](https://github.com/dotCMS/core/issues/new/choose) in the GitHub repository
|
|
434
|
-
- **Community Forum**: Join our [community discussions](https://community.dotcms.com/) to ask questions and share solutions
|
|
435
|
-
- **Stack Overflow**: Use the tag `dotcms-analytics` when posting questions
|
|
436
|
-
- **Enterprise Support**: Enterprise customers can access premium support through the [dotCMS Support Portal](https://helpdesk.dotcms.com/support/)
|
|
433
|
+
- **GitHub Issues**: For bug reports and feature requests, please [open an issue](https://github.com/dotCMS/core/issues/new/choose) in the GitHub repository
|
|
434
|
+
- **Community Forum**: Join our [community discussions](https://community.dotcms.com/) to ask questions and share solutions
|
|
435
|
+
- **Stack Overflow**: Use the tag `dotcms-analytics` when posting questions
|
|
436
|
+
- **Enterprise Support**: Enterprise customers can access premium support through the [dotCMS Support Portal](https://helpdesk.dotcms.com/support/)
|
|
437
437
|
|
|
438
438
|
When reporting issues, please include:
|
|
439
439
|
|
|
@@ -442,9 +442,9 @@ When reporting issues, please include:
|
|
|
442
442
|
- Minimal reproduction steps
|
|
443
443
|
- Expected vs. actual behavior
|
|
444
444
|
|
|
445
|
-
##
|
|
445
|
+
## Contributing
|
|
446
446
|
|
|
447
|
-
GitHub pull requests are the preferred method to contribute code to dotCMS. We welcome contributions to the
|
|
447
|
+
GitHub pull requests are the preferred method to contribute code to dotCMS. We welcome contributions to the dotCMS Analytics SDK! If you'd like to contribute, please follow these steps:
|
|
448
448
|
|
|
449
449
|
1. Fork the repository [dotCMS/core](https://github.com/dotCMS/core)
|
|
450
450
|
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
@@ -454,7 +454,7 @@ GitHub pull requests are the preferred method to contribute code to dotCMS. We w
|
|
|
454
454
|
|
|
455
455
|
Please ensure your code follows the existing style and includes appropriate tests.
|
|
456
456
|
|
|
457
|
-
## Licensing
|
|
457
|
+
## Licensing
|
|
458
458
|
|
|
459
459
|
dotCMS comes in multiple editions and as such is dual-licensed. The dotCMS Community Edition is licensed under the GPL 3.0 and is freely available for download, customization, and deployment for use within organizations of all stripes. dotCMS Enterprise Editions (EE) adds several enterprise features and is available via a supported, indemnified commercial license from dotCMS. For the differences between the editions, see [the feature page](http://www.dotcms.com/cms-platform/features).
|
|
460
460
|
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
+
import { ANALYTICS_WINDOWS_ACTIVE_KEY, ANALYTICS_WINDOWS_CLEANUP_KEY } from '../../../../uve/src/internal.ts';
|
|
1
2
|
import { DotCMSAnalytics, DotCMSAnalyticsConfig } from './shared/models';
|
|
3
|
+
declare global {
|
|
4
|
+
interface Window {
|
|
5
|
+
[ANALYTICS_WINDOWS_ACTIVE_KEY]?: boolean;
|
|
6
|
+
[ANALYTICS_WINDOWS_CLEANUP_KEY]?: () => void;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
2
9
|
/**
|
|
3
10
|
* Creates an analytics instance for content analytics tracking.
|
|
4
11
|
*
|
|
@@ -1,33 +1,34 @@
|
|
|
1
|
-
import { Analytics as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import { Analytics as a } from "analytics";
|
|
2
|
+
import { ANALYTICS_WINDOWS_ACTIVE_KEY as r, ANALYTICS_WINDOWS_CLEANUP_KEY as s } from "../../uve/src/internal/constants.js";
|
|
3
|
+
import { dotAnalytics as l } from "./plugin/dot-analytics.plugin.js";
|
|
4
|
+
import { dotAnalyticsEnricherPlugin as c } from "./plugin/enricher/dot-analytics.enricher.plugin.js";
|
|
5
|
+
import { dotAnalyticsIdentityPlugin as p } from "./plugin/identity/dot-analytics.identity.plugin.js";
|
|
6
|
+
import { validateAnalyticsConfig as m } from "./shared/dot-content-analytics.utils.js";
|
|
7
|
+
import { cleanupActivityTracking as u } from "./shared/dot-content-analytics.activity-tracker.js";
|
|
8
|
+
const I = (n) => {
|
|
9
|
+
const o = m(n);
|
|
10
|
+
if (o)
|
|
11
|
+
return console.error(`DotCMS Analytics: Missing ${o.join(" and ")} in configuration`), typeof window < "u" && (window[r] = !1), null;
|
|
12
|
+
const i = a({
|
|
12
13
|
app: "dotAnalytics",
|
|
13
|
-
debug:
|
|
14
|
+
debug: n.debug,
|
|
14
15
|
plugins: [
|
|
15
|
-
|
|
16
|
+
p(n),
|
|
16
17
|
// Inject identity context (user_id, session_id, local_tz)
|
|
17
|
-
|
|
18
|
+
c(),
|
|
18
19
|
// Enrich and clean payload with page, device, utm data and custom data
|
|
19
|
-
|
|
20
|
+
l(n)
|
|
20
21
|
// Send events to server
|
|
21
22
|
]
|
|
22
|
-
}),
|
|
23
|
-
return typeof window < "u" && (window.addEventListener("beforeunload",
|
|
23
|
+
}), e = () => u();
|
|
24
|
+
return typeof window < "u" && (window.addEventListener("beforeunload", e), window[s] = e, window[r] = !0, window.dispatchEvent(new CustomEvent("dotcms:analytics:ready"))), {
|
|
24
25
|
/**
|
|
25
26
|
* Track a page view.
|
|
26
27
|
* Session activity is automatically updated by the identity plugin.
|
|
27
28
|
* @param payload - Optional custom data to include with the page view (any valid JSON object)
|
|
28
29
|
*/
|
|
29
|
-
pageView: (
|
|
30
|
-
|
|
30
|
+
pageView: (t = {}) => {
|
|
31
|
+
i == null || i.page(t);
|
|
31
32
|
},
|
|
32
33
|
/**
|
|
33
34
|
* Track a custom event.
|
|
@@ -35,11 +36,11 @@ const f = (i) => {
|
|
|
35
36
|
* @param eventName - The name of the event to track
|
|
36
37
|
* @param payload - Custom data to include with the event (any valid JSON object)
|
|
37
38
|
*/
|
|
38
|
-
track: (
|
|
39
|
-
|
|
39
|
+
track: (t, d = {}) => {
|
|
40
|
+
i == null || i.track(t, d);
|
|
40
41
|
}
|
|
41
42
|
};
|
|
42
43
|
};
|
|
43
44
|
export {
|
|
44
|
-
|
|
45
|
+
I as initializeContentAnalytics
|
|
45
46
|
};
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
+
import { ANALYTICS_WINDOWS_ACTIVE_KEY, ANALYTICS_WINDOWS_CLEANUP_KEY } from '../../../../../uve/src/internal.ts';
|
|
1
2
|
import { DotCMSAnalyticsConfig } from './models';
|
|
3
|
+
declare global {
|
|
4
|
+
interface Window {
|
|
5
|
+
[ANALYTICS_WINDOWS_CLEANUP_KEY]?: () => void;
|
|
6
|
+
[ANALYTICS_WINDOWS_ACTIVE_KEY]?: boolean;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
2
9
|
/**
|
|
3
10
|
* Updates session activity with throttling
|
|
4
11
|
*/
|
|
@@ -15,7 +22,7 @@ export declare const getSessionInfo: () => {
|
|
|
15
22
|
*/
|
|
16
23
|
export declare const initializeActivityTracking: (config: DotCMSAnalyticsConfig) => void;
|
|
17
24
|
/**
|
|
18
|
-
* Cleans up activity tracking listeners
|
|
25
|
+
* Cleans up activity tracking listeners and resets analytics state
|
|
19
26
|
*/
|
|
20
27
|
export declare const cleanupActivityTracking: () => void;
|
|
21
28
|
/**
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { ANALYTICS_WINDOWS_ACTIVE_KEY as o, ANALYTICS_WINDOWS_CLEANUP_KEY as r } from "../../../uve/src/internal/constants.js";
|
|
2
|
+
import { DEFAULT_SESSION_TIMEOUT_MINUTES as c, ACTIVITY_EVENTS as v } from "./constants/dot-content-analytics.constants.js";
|
|
3
|
+
class l {
|
|
3
4
|
constructor() {
|
|
4
5
|
this.activityListeners = [], this.lastActivityTime = Date.now(), this.inactivityTimer = null, this.isThrottled = !1, this.config = null, this.ACTIVITY_THROTTLE_MS = 1e3;
|
|
5
6
|
}
|
|
@@ -44,7 +45,7 @@ class o {
|
|
|
44
45
|
if (this.cleanup(), this.config = i, typeof window > "u")
|
|
45
46
|
return;
|
|
46
47
|
const s = () => this.updateSessionActivity();
|
|
47
|
-
|
|
48
|
+
v.forEach((a) => {
|
|
48
49
|
window.addEventListener(a, s, { passive: !0 }), this.activityListeners.push(
|
|
49
50
|
() => window.removeEventListener(a, s)
|
|
50
51
|
);
|
|
@@ -72,15 +73,15 @@ class o {
|
|
|
72
73
|
};
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
|
-
const t = new
|
|
76
|
+
const t = new l(), u = () => {
|
|
76
77
|
t.updateSessionActivity();
|
|
77
|
-
},
|
|
78
|
+
}, d = (e) => {
|
|
78
79
|
t.initialize(e);
|
|
79
|
-
},
|
|
80
|
-
t.cleanup();
|
|
80
|
+
}, y = () => {
|
|
81
|
+
t.cleanup(), typeof window < "u" && (window[o] = !1, window[r] = void 0, window.dispatchEvent(new CustomEvent("dotcms:analytics:cleanup")));
|
|
81
82
|
};
|
|
82
83
|
export {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
y as cleanupActivityTracking,
|
|
85
|
+
d as initializeActivityTracking,
|
|
86
|
+
u as updateSessionActivity
|
|
86
87
|
};
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import { PageData } from 'analytics';
|
|
2
2
|
import { AnalyticsBasePayloadWithContext, DotCMSAnalyticsConfig, DotCMSAnalyticsEventContext, DotCMSBrowserData, DotCMSEventDeviceData, DotCMSEventUtmData, EnrichedAnalyticsPayload } from './models';
|
|
3
3
|
export { cleanupActivityTracking, getLastActivity, getSessionInfo, initializeActivityTracking, isUserInactive, updateSessionActivity } from './dot-content-analytics.activity-tracker';
|
|
4
|
+
/**
|
|
5
|
+
* Validates required configuration fields for Analytics initialization.
|
|
6
|
+
*
|
|
7
|
+
* @param config - The analytics configuration to validate
|
|
8
|
+
* @returns Array of missing field names, or null if all required fields are present
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const missing = validateAnalyticsConfig(config);
|
|
13
|
+
* if (missing) {
|
|
14
|
+
* console.error(`Missing: ${missing.join(' and ')}`);
|
|
15
|
+
* }
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function validateAnalyticsConfig(config: DotCMSAnalyticsConfig): string[] | null;
|
|
4
19
|
/**
|
|
5
20
|
* Generates a cryptographically secure random ID.
|
|
6
21
|
* @internal This function is for internal use only and should not be used outside of the SDK.
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import { ANALYTICS_JS_DEFAULT_PROPERTIES as
|
|
2
|
-
|
|
1
|
+
import { ANALYTICS_JS_DEFAULT_PROPERTIES as f, SESSION_STORAGE_KEY as h, DEFAULT_SESSION_TIMEOUT_MINUTES as w, USER_ID_KEY as l, EXPECTED_UTM_KEYS as _ } from "./constants/dot-content-analytics.constants.js";
|
|
2
|
+
import "../../../uve/src/internal/constants.js";
|
|
3
|
+
function U(t) {
|
|
4
|
+
var n, s;
|
|
5
|
+
const e = [];
|
|
6
|
+
return (n = t.siteAuth) != null && n.trim() || e.push('"siteAuth"'), (s = t.server) != null && s.trim() || e.push('"server"'), e.length > 0 ? e : null;
|
|
7
|
+
}
|
|
8
|
+
let u = null, g = null;
|
|
3
9
|
const d = (t) => {
|
|
4
10
|
const e = Date.now(), n = Math.random().toString(36).substr(2, 9), s = Math.random().toString(36).substr(2, 9);
|
|
5
11
|
return `${t}_${e}_${n}${s}`;
|
|
6
|
-
},
|
|
12
|
+
}, m = {
|
|
7
13
|
getItem: (t) => {
|
|
8
14
|
try {
|
|
9
15
|
return localStorage.getItem(t);
|
|
@@ -19,8 +25,8 @@ const d = (t) => {
|
|
|
19
25
|
}
|
|
20
26
|
}
|
|
21
27
|
}, p = () => {
|
|
22
|
-
let t =
|
|
23
|
-
return t || (t = d("user"),
|
|
28
|
+
let t = m.getItem(l);
|
|
29
|
+
return t || (t = d("user"), m.setItem(l, t)), t;
|
|
24
30
|
}, D = (t) => {
|
|
25
31
|
const e = new Date(t), n = /* @__PURE__ */ new Date(), s = new Date(
|
|
26
32
|
e.getUTCFullYear(),
|
|
@@ -35,7 +41,7 @@ const d = (t) => {
|
|
|
35
41
|
try {
|
|
36
42
|
const e = sessionStorage.getItem(h);
|
|
37
43
|
if (e) {
|
|
38
|
-
const { sessionId: o, startTime: r, lastActivity: a } = JSON.parse(e), c = !D(r), i = t - a <
|
|
44
|
+
const { sessionId: o, startTime: r, lastActivity: a } = JSON.parse(e), c = !D(r), i = t - a < w * 60 * 1e3;
|
|
39
45
|
if (c && i)
|
|
40
46
|
return sessionStorage.setItem(
|
|
41
47
|
h,
|
|
@@ -55,7 +61,7 @@ const d = (t) => {
|
|
|
55
61
|
} catch {
|
|
56
62
|
return d("session_fallback");
|
|
57
63
|
}
|
|
58
|
-
},
|
|
64
|
+
}, $ = (t) => {
|
|
59
65
|
const e = T(), n = p(), s = I();
|
|
60
66
|
return t.debug && console.warn("DotCMS Analytics Identity Context:", {
|
|
61
67
|
sessionId: e,
|
|
@@ -66,12 +72,12 @@ const d = (t) => {
|
|
|
66
72
|
user_id: n,
|
|
67
73
|
device: s
|
|
68
74
|
};
|
|
69
|
-
},
|
|
75
|
+
}, S = () => u || (u = {
|
|
70
76
|
user_language: navigator.language,
|
|
71
77
|
doc_encoding: document.characterSet || document.charset,
|
|
72
78
|
screen_resolution: typeof screen < "u" && screen.width && screen.height ? `${screen.width}x${screen.height}` : ""
|
|
73
|
-
},
|
|
74
|
-
const t =
|
|
79
|
+
}, u), I = () => {
|
|
80
|
+
const t = S(), e = window.innerWidth || document.documentElement.clientWidth || 0, n = window.innerHeight || document.documentElement.clientHeight || 0;
|
|
75
81
|
return {
|
|
76
82
|
screen_resolution: t.screen_resolution ?? "",
|
|
77
83
|
language: t.user_language ?? "",
|
|
@@ -80,16 +86,16 @@ const d = (t) => {
|
|
|
80
86
|
};
|
|
81
87
|
}, y = (t) => {
|
|
82
88
|
const e = t.search;
|
|
83
|
-
if (
|
|
84
|
-
return
|
|
89
|
+
if (g && g.search === e)
|
|
90
|
+
return g.params;
|
|
85
91
|
const n = new URLSearchParams(e), s = {};
|
|
86
|
-
return
|
|
92
|
+
return _.forEach((o) => {
|
|
87
93
|
const r = n.get(o);
|
|
88
94
|
if (r) {
|
|
89
95
|
const a = o.replace("utm_", "");
|
|
90
96
|
s[a] = r;
|
|
91
97
|
}
|
|
92
|
-
}),
|
|
98
|
+
}), g = { search: e, params: s }, s;
|
|
93
99
|
}, E = () => {
|
|
94
100
|
try {
|
|
95
101
|
const t = (/* @__PURE__ */ new Date()).getTimezoneOffset(), e = t > 0 ? "-" : "+", n = Math.abs(t), s = Math.floor(n / 60), o = n % 60;
|
|
@@ -104,10 +110,10 @@ const d = (t) => {
|
|
|
104
110
|
} catch {
|
|
105
111
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
106
112
|
}
|
|
107
|
-
},
|
|
108
|
-
const n = C(), s =
|
|
113
|
+
}, A = (t, e = typeof window < "u" ? window.location : {}) => {
|
|
114
|
+
const n = C(), s = S(), { properties: o } = t, r = {};
|
|
109
115
|
Object.keys(o).forEach((i) => {
|
|
110
|
-
|
|
116
|
+
f.includes(i) || (r[i] = o[i]);
|
|
111
117
|
});
|
|
112
118
|
const a = {
|
|
113
119
|
url: e.href,
|
|
@@ -129,12 +135,13 @@ const d = (t) => {
|
|
|
129
135
|
};
|
|
130
136
|
};
|
|
131
137
|
export {
|
|
132
|
-
|
|
138
|
+
A as enrichPagePayloadOptimized,
|
|
133
139
|
y as extractUTMParameters,
|
|
134
140
|
d as generateSecureId,
|
|
135
|
-
|
|
141
|
+
$ as getAnalyticsContext,
|
|
136
142
|
I as getDeviceDataForContext,
|
|
137
143
|
C as getLocalTime,
|
|
138
144
|
T as getSessionId,
|
|
139
|
-
p as getUserId
|
|
145
|
+
p as getUserId,
|
|
146
|
+
U as validateAnalyticsConfig
|
|
140
147
|
};
|
package/package.json
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
-
import { UVEEventType as
|
|
2
|
-
import { onContentletHovered as
|
|
3
|
-
|
|
1
|
+
import { UVEEventType as t } from "../../../types/src/lib/editor/public.js";
|
|
2
|
+
import { onContentletHovered as e, onIframeScroll as o, onRequestBounds as r, onPageReload as E, onContentChanges as _ } from "./events.js";
|
|
3
|
+
t.CONTENT_CHANGES + "", t.PAGE_RELOAD + "", t.REQUEST_BOUNDS + "", t.IFRAME_SCROLL + "", t.CONTENTLET_HOVERED + "";
|
|
4
|
+
const N = "__dotAnalyticsActive__", T = "__dotAnalyticsCleanup";
|
|
5
|
+
export {
|
|
6
|
+
N as ANALYTICS_WINDOWS_ACTIVE_KEY,
|
|
7
|
+
T as ANALYTICS_WINDOWS_CLEANUP_KEY
|
|
8
|
+
};
|