@dotcms/analytics 0.0.1-beta.41 → 0.0.1-beta.43

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.
Files changed (28) hide show
  1. package/lib/dotAnalytics/dot-content-analytics.d.ts +5 -5
  2. package/lib/dotAnalytics/dot-content-analytics.js +28 -9
  3. package/lib/dotAnalytics/plugin/dot-analytics.plugin.d.ts +9 -7
  4. package/lib/dotAnalytics/plugin/dot-analytics.plugin.js +30 -31
  5. package/lib/dotAnalytics/plugin/enricher/dot-analytics.enricher.plugin.d.ts +46 -0
  6. package/lib/dotAnalytics/plugin/enricher/dot-analytics.enricher.plugin.js +33 -0
  7. package/lib/dotAnalytics/plugin/identity/dot-analytics.identity.plugin.d.ts +80 -0
  8. package/lib/dotAnalytics/plugin/identity/dot-analytics.identity.plugin.js +40 -0
  9. package/lib/dotAnalytics/plugin/identity/dot-analytics.identity.utils.d.ts +24 -0
  10. package/lib/dotAnalytics/shared/dot-content-analytics.activity-tracker.d.ts +29 -0
  11. package/lib/dotAnalytics/shared/dot-content-analytics.activity-tracker.js +86 -0
  12. package/lib/dotAnalytics/shared/dot-content-analytics.constants.d.ts +16 -7
  13. package/lib/dotAnalytics/shared/dot-content-analytics.constants.js +8 -8
  14. package/lib/dotAnalytics/shared/dot-content-analytics.http.d.ts +2 -2
  15. package/lib/dotAnalytics/shared/dot-content-analytics.http.js +2 -8
  16. package/lib/dotAnalytics/shared/dot-content-analytics.model.d.ts +263 -89
  17. package/lib/dotAnalytics/shared/dot-content-analytics.utils.d.ts +91 -28
  18. package/lib/dotAnalytics/shared/dot-content-analytics.utils.js +125 -40
  19. package/lib/react/components/DotContentAnalyticsProvider.d.ts +4 -4
  20. package/lib/react/components/DotContentAnalyticsProvider.js +5 -2
  21. package/lib/react/contexts/DotContentAnalyticsContext.d.ts +3 -3
  22. package/lib/react/hook/useContentAnalytics.d.ts +36 -6
  23. package/lib/react/hook/useContentAnalytics.js +25 -25
  24. package/lib/react/hook/useRouterTracker.d.ts +3 -3
  25. package/lib/standalone.d.ts +2 -2
  26. package/package.json +4 -4
  27. package/lib/dotAnalytics/plugin/dot-analytics.enricher.plugin.d.ts +0 -31
  28. package/lib/dotAnalytics/plugin/dot-analytics.enricher.plugin.js +0 -28
@@ -1,46 +1,131 @@
1
- import i from "analytics";
2
- import { EXPECTED_UTM_KEYS as a } from "./dot-content-analytics.constants.js";
3
- import { dotAnalyticsEnricherPlugin as s } from "../plugin/dot-analytics.enricher.plugin.js";
4
- import { dotAnalytics as c } from "../plugin/dot-analytics.plugin.js";
5
- const h = (e) => ({
6
- utc_time: (/* @__PURE__ */ new Date()).toISOString(),
7
- local_tz_offset: (/* @__PURE__ */ new Date()).getTimezoneOffset(),
8
- screen_resolution: `${window.screen.width}x${window.screen.height}`,
9
- vp_size: `${window.innerWidth}x${window.innerHeight}`,
10
- userAgent: navigator.userAgent,
11
- user_language: navigator.language,
12
- doc_encoding: document.characterSet,
13
- doc_path: e.pathname,
14
- doc_host: e.hostname,
15
- doc_protocol: e.protocol,
16
- doc_hash: e.hash,
17
- doc_search: e.search,
18
- referrer: document.referrer,
19
- page_title: document.title,
20
- utm: u(window.location)
21
- }), u = (e) => {
22
- const o = new URLSearchParams(e.search);
23
- return a.reduce(
24
- (t, r) => {
25
- const n = o.get(r);
26
- return n !== null && (t[r.replace("utm_", "")] = n), t;
27
- },
28
- {}
29
- );
30
- }, m = () => {
1
+ import { SESSION_STORAGE_KEY as l, DEFAULT_SESSION_TIMEOUT_MINUTES as S, USER_ID_KEY as h } from "./dot-content-analytics.constants.js";
2
+ let g = null;
3
+ const u = (t) => {
4
+ const e = Date.now(), n = Math.random().toString(36).substr(2, 9), o = Math.random().toString(36).substr(2, 9);
5
+ return `${t}_${e}_${n}${o}`;
6
+ }, m = {
7
+ getItem: (t) => {
8
+ try {
9
+ return localStorage.getItem(t);
10
+ } catch {
11
+ return null;
12
+ }
13
+ },
14
+ setItem: (t, e) => {
15
+ try {
16
+ localStorage.setItem(t, e);
17
+ } catch {
18
+ console.warn(`DotAnalytics: Could not save ${t} to localStorage`);
19
+ }
20
+ }
21
+ }, f = () => {
22
+ let t = m.getItem(h);
23
+ return t || (t = u("user"), m.setItem(h, t)), t;
24
+ }, w = (t) => {
25
+ const e = new Date(t), n = /* @__PURE__ */ new Date(), o = new Date(
26
+ e.getUTCFullYear(),
27
+ e.getUTCMonth(),
28
+ e.getUTCDate()
29
+ ), s = new Date(n.getUTCFullYear(), n.getUTCMonth(), n.getUTCDate());
30
+ return o.getTime() !== s.getTime();
31
+ }, p = () => {
32
+ const t = Date.now();
33
+ if (typeof window > "u")
34
+ return u("session_fallback");
31
35
  try {
32
- return typeof window > "u" || !window.parent ? !1 : window.parent !== window;
36
+ const e = sessionStorage.getItem(l);
37
+ if (e) {
38
+ const { sessionId: s, startTime: i, lastActivity: c } = JSON.parse(e), d = !w(i), r = t - c < S * 60 * 1e3;
39
+ if (d && r)
40
+ return sessionStorage.setItem(
41
+ l,
42
+ JSON.stringify({
43
+ sessionId: s,
44
+ startTime: i,
45
+ lastActivity: t
46
+ })
47
+ ), s;
48
+ }
49
+ const n = u("session"), o = {
50
+ sessionId: n,
51
+ startTime: t,
52
+ lastActivity: t
53
+ };
54
+ return sessionStorage.setItem(l, JSON.stringify(o)), n;
55
+ } catch {
56
+ return u("session_fallback");
57
+ }
58
+ }, T = (t) => {
59
+ const e = p(), n = f();
60
+ return t.debug && console.warn("DotAnalytics Identity Context:", {
61
+ sessionId: e,
62
+ userId: n
63
+ }), {
64
+ site_key: t.siteKey,
65
+ session_id: e,
66
+ user_id: n
67
+ };
68
+ }, I = () => g || (g = {
69
+ user_language: navigator.language || void 0,
70
+ doc_encoding: document.characterSet || document.charset || void 0,
71
+ screen_resolution: typeof screen < "u" && screen.width && screen.height ? `${screen.width}x${screen.height}` : void 0
72
+ }, g), $ = () => {
73
+ if (typeof window > "u")
74
+ return !1;
75
+ try {
76
+ const t = window.self !== window.top, e = window.location.href.includes("mode=EDIT_MODE"), n = window.location.href.includes("/vtl/");
77
+ return t || e || n;
33
78
  } catch {
34
79
  return !1;
35
80
  }
36
- }, p = (e) => e.apiKey ? e.server ? i({
37
- app: "dotAnalytics",
38
- debug: e.debug,
39
- plugins: [s, c(e)]
40
- }) : (console.error('DotContentAnalytics: Missing "server" in configuration'), null) : (console.error('DotContentAnalytics: Missing "apiKey" in configuration'), null);
81
+ }, D = () => {
82
+ try {
83
+ const t = (/* @__PURE__ */ new Date()).getTimezoneOffset(), e = t > 0 ? "-" : "+", n = Math.abs(t), o = Math.floor(n / 60), s = n % 60;
84
+ return `${e}${o.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
85
+ } catch {
86
+ return "+00:00";
87
+ }
88
+ }, y = () => {
89
+ try {
90
+ const t = /* @__PURE__ */ new Date(), e = D(), n = t.getFullYear(), o = (t.getMonth() + 1).toString().padStart(2, "0"), s = t.getDate().toString().padStart(2, "0"), i = t.getHours().toString().padStart(2, "0"), c = t.getMinutes().toString().padStart(2, "0"), d = t.getSeconds().toString().padStart(2, "0"), r = t.getMilliseconds().toString().padStart(3, "0");
91
+ return `${n}-${o}-${s}T${i}:${c}:${d}.${r}${e}`;
92
+ } catch {
93
+ return (/* @__PURE__ */ new Date()).toISOString();
94
+ }
95
+ }, v = (t, e = typeof window < "u" ? window.location : {}) => {
96
+ const n = y(), o = I(), { properties: s } = t, { utm: i } = s, c = {
97
+ url: s.url ?? e.href,
98
+ path: s.path ?? e.pathname,
99
+ hash: s.hash ?? e.hash ?? "",
100
+ search: s.search ?? e.search ?? "",
101
+ title: s.title ?? (document == null ? void 0 : document.title),
102
+ width: String(s.width),
103
+ height: String(s.height),
104
+ referrer: s.referrer ?? (document == null ? void 0 : document.referrer)
105
+ }, d = {
106
+ screen_resolution: o.screen_resolution,
107
+ language: o.user_language,
108
+ viewport_width: String(s.width),
109
+ viewport_height: String(s.height)
110
+ }, r = {};
111
+ if (i && typeof i == "object") {
112
+ const a = i;
113
+ a.medium && (r.medium = a.medium), a.source && (r.source = a.source), a.campaign && (r.campaign = a.campaign), a.term && (r.term = a.term), a.content && (r.content = a.content);
114
+ }
115
+ return {
116
+ ...t,
117
+ page: c,
118
+ device: d,
119
+ ...Object.keys(r).length > 0 && { utm: r },
120
+ local_time: n
121
+ };
122
+ };
41
123
  export {
42
- p as createAnalyticsInstance,
43
- u as extractUTMParameters,
44
- h as getBrowserEventData,
45
- m as isInsideEditor
124
+ v as enrichPagePayloadOptimized,
125
+ u as generateSecureId,
126
+ T as getAnalyticsContext,
127
+ y as getLocalTime,
128
+ p as getSessionId,
129
+ f as getUserId,
130
+ $ as isInsideEditor
46
131
  };
@@ -1,15 +1,15 @@
1
- import { DotContentAnalyticsConfig } from '../../dotAnalytics/shared/dot-content-analytics.model';
1
+ import { DotCMSAnalyticsConfig } from '../../dotAnalytics/shared/dot-content-analytics.model';
2
2
  import { ReactElement, ReactNode } from 'react';
3
3
 
4
4
  interface DotContentAnalyticsProviderProps {
5
5
  children?: ReactNode;
6
- config: DotContentAnalyticsConfig;
6
+ config: DotCMSAnalyticsConfig;
7
7
  }
8
8
  /**
9
- * Provider component that initializes and manages DotContentAnalytics instance.
9
+ * Provider component that initializes and manages DotCMSAnalytics instance.
10
10
  * It makes the analytics functionality available to all child components through React Context.
11
11
  * This component is responsible for:
12
- * - Initializing the DotContentAnalytics singleton instance with the provided config
12
+ * - Initializing the DotCMSAnalytics singleton instance with the provided config
13
13
  * - Making the instance accessible via useContext hook to child components
14
14
  * - Managing the lifecycle of the analytics instance
15
15
  *
@@ -7,8 +7,11 @@ const f = ({
7
7
  children: r,
8
8
  config: t
9
9
  }) => {
10
- const o = i(() => n(t), [t]);
11
- return t.autoPageView !== !1 && m(o), /* @__PURE__ */ e(a.Provider, { value: o, children: r });
10
+ const o = i(
11
+ () => n(t),
12
+ [t]
13
+ );
14
+ return t.autoPageView !== !1 && o && m(o), /* @__PURE__ */ e(a.Provider, { value: o, children: r });
12
15
  };
13
16
  export {
14
17
  f as DotContentAnalyticsProvider
@@ -1,13 +1,13 @@
1
- import { DotAnalytics } from '../../dotAnalytics/shared/dot-content-analytics.model';
1
+ import { DotCMSAnalytics } from '../../dotAnalytics/shared/dot-content-analytics.model';
2
2
 
3
3
  /**
4
4
  * `DotContentAnalyticsContext` is a React context that is designed to provide an instance of
5
- * `DotContentAnalytics` to all of the components within its tree that are Consumers of this context.
5
+ * `DotCMSAnalytics` to all of the components within its tree that are Consumers of this context.
6
6
  *
7
7
  * The context is created with a default value of `null`. It is meant to be provided a real value
8
8
  * using the `DotContentAnalyticsProvider` component.
9
9
  *
10
10
  * @see {@link https://reactjs.org/docs/context.html|React Context}
11
11
  */
12
- declare const DotContentAnalyticsContext: import('react').Context<DotAnalytics | null>;
12
+ declare const DotContentAnalyticsContext: import('react').Context<DotCMSAnalytics | null>;
13
13
  export default DotContentAnalyticsContext;
@@ -1,15 +1,14 @@
1
- import { DotAnalytics } from '../../dotAnalytics/shared/dot-content-analytics.model';
1
+ import { DotCMSAnalytics } from '../../dotAnalytics/shared/dot-content-analytics.model';
2
2
 
3
3
  /**
4
- * Custom hook that handles analytics page view tracking.
4
+ * Custom hook that handles analytics tracking for anonymous users.
5
5
  *
6
6
  * @example
7
7
  * ```tsx
8
8
  * function Button({ title, urlTitle }) {
9
9
  * const { track } = useContentAnalytics();
10
10
  *
11
- * // First parameter: custom event name to identify the action
12
- * // Second parameter: object with properties you want to track
11
+ * // Track button click with custom properties
13
12
  * return (
14
13
  * <button onClick={() => track('btn-click', { title, urlTitle })}>
15
14
  * See Details →
@@ -17,6 +16,37 @@ import { DotAnalytics } from '../../dotAnalytics/shared/dot-content-analytics.mo
17
16
  * );
18
17
  * }
19
18
  * ```
20
- * @returns {DotContentAnalyticsCustomHook} - The analytics instance used to track page views
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * // Session debugging example
23
+ * function AnalyticsDebugComponent() {
24
+ * const { getAnonymousUserId, getSessionInfo, updateSessionActivity } = useContentAnalytics();
25
+ *
26
+ * const handleManualActivity = () => {
27
+ * updateSessionActivity();
28
+ * // Manual activity updated
29
+ * };
30
+ *
31
+ * // Debug session info in development
32
+ * const debugInfo = () => {
33
+ * if (process.env.NODE_ENV === 'development') {
34
+ * console.log('Anonymous ID:', getAnonymousUserId());
35
+ * console.log('Session info:', getSessionInfo());
36
+ * }
37
+ * };
38
+ *
39
+ * return (
40
+ * <div>
41
+ * <button onClick={handleManualActivity}>Update Activity</button>
42
+ * <button onClick={debugInfo}>Debug Session</button>
43
+ * <p>User ID: {getAnonymousUserId()}</p>
44
+ * </div>
45
+ * );
46
+ * }
47
+ * ```
48
+ *
49
+ * @returns {DotCMSAnalytics} - The analytics instance with tracking capabilities for anonymous users
50
+ * @throws {Error} - Throws error if used outside of DotContentAnalyticsProvider or if analytics failed to initialize
21
51
  */
22
- export declare const useContentAnalytics: () => DotAnalytics;
52
+ export declare const useContentAnalytics: () => DotCMSAnalytics;
@@ -1,34 +1,34 @@
1
- import { useContext as i, useRef as s } from "react";
2
- import { isInsideEditor as r } from "../../dotAnalytics/shared/dot-content-analytics.utils.js";
3
- import a from "../contexts/DotContentAnalyticsContext.js";
4
- const f = () => {
5
- const t = i(a), o = s(null);
1
+ import { useContext as c, useRef as u, useCallback as o } from "react";
2
+ import { isInsideEditor as s } from "../../dotAnalytics/shared/dot-content-analytics.utils.js";
3
+ import l from "../contexts/DotContentAnalyticsContext.js";
4
+ const w = () => {
5
+ const t = c(l), i = u(null);
6
6
  if (!t)
7
- throw new Error("useContentAnalytics must be used within a DotContentAnalyticsProvider");
8
- return {
9
- /**
10
- * Track a custom event.
11
- * @param {string} eventName - The name of the event to track.
12
- * @param {Record<string, unknown>} payload - The payload to track.
13
- */
14
- track: (n, e = {}) => {
15
- r() || t == null || t.track(n, {
16
- ...e,
7
+ throw new Error(
8
+ "useContentAnalytics must be used within a DotContentAnalyticsProvider and analytics must be successfully initialized"
9
+ );
10
+ const r = o(
11
+ (e, n = {}) => {
12
+ s() || t.track(e, {
13
+ ...n,
17
14
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
18
15
  });
19
16
  },
20
- /**
21
- * Track a page view.
22
- * @param {Record<string, unknown>} payload - The payload to track.
23
- */
24
- pageView: (n = {}) => {
25
- if (!r()) {
26
- const e = window.location.pathname;
27
- e !== o.current && (o.current = e, t.pageView(n));
17
+ [t]
18
+ ), a = o(
19
+ (e = {}) => {
20
+ if (!s()) {
21
+ const n = window.location.pathname;
22
+ n !== i.current && (i.current = n, t.pageView(e));
28
23
  }
29
- }
24
+ },
25
+ [t]
26
+ );
27
+ return {
28
+ track: r,
29
+ pageView: a
30
30
  };
31
31
  };
32
32
  export {
33
- f as useContentAnalytics
33
+ w as useContentAnalytics
34
34
  };
@@ -1,10 +1,10 @@
1
- import { DotAnalytics } from '../../dotAnalytics/shared/dot-content-analytics.model';
1
+ import { DotCMSAnalytics } from '../../dotAnalytics/shared/dot-content-analytics.model';
2
2
 
3
3
  /**
4
4
  * Internal custom hook that handles analytics page view tracking.
5
5
  *
6
- * @param {DotContentAnalytics | null} instance - The analytics instance used to track page views
6
+ * @param {DotCMSAnalytics | null} instance - The analytics instance used to track page views
7
7
  * @returns {void}
8
8
  *
9
9
  */
10
- export declare function useRouterTracker(analytics: DotAnalytics | null): void;
10
+ export declare function useRouterTracker(analytics: DotCMSAnalytics | null): void;
@@ -1,8 +1,8 @@
1
- import { DotAnalytics } from './dotAnalytics/shared/dot-content-analytics.model';
1
+ import { DotCMSAnalytics } from './dotAnalytics/shared/dot-content-analytics.model';
2
2
  import { ANALYTICS_WINDOWS_KEY } from './dotAnalytics/shared/dot-content-analytics.constants';
3
3
 
4
4
  declare global {
5
5
  interface Window {
6
- [ANALYTICS_WINDOWS_KEY]: DotAnalytics;
6
+ [ANALYTICS_WINDOWS_KEY]: DotCMSAnalytics | null;
7
7
  }
8
8
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotcms/analytics",
3
- "version": "0.0.1-beta.41",
3
+ "version": "0.0.1-beta.43",
4
4
  "description": "Official JavaScript library for Content Analytics with DotCMS.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -23,12 +23,12 @@
23
23
  "analytics": "^0.8.14"
24
24
  },
25
25
  "peerDependencies": {
26
- "react": "^18.2.0"
26
+ "react": "19.1.0"
27
27
  },
28
28
  "devDependencies": {
29
- "vite": "~5.0.0",
30
29
  "@testing-library/jest-dom": "^6.1.6",
31
- "@testing-library/react": "^14.0.0"
30
+ "@testing-library/react": "^14.0.0",
31
+ "vite": "~5.0.0"
32
32
  },
33
33
  "main": "./index.cjs.js",
34
34
  "module": "./index.esm.js",
@@ -1,31 +0,0 @@
1
- import { DotAnalyticsPayload, PageViewEvent, TrackEvent } from '../shared/dot-content-analytics.model';
2
-
3
- /**
4
- * Plugin that enriches the analytics payload data based on the event type.
5
- * For page view events, it adds browser data like viewport size, user agent, etc.
6
- * For track events, it adds custom event properties and standardizes the event format.
7
- * All events are enriched with source type and anonymous ID if available.
8
- */
9
- export declare const dotAnalyticsEnricherPlugin: {
10
- name: string;
11
- 'page:dot-analytics': ({ payload }: {
12
- payload: DotAnalyticsPayload;
13
- }) => {
14
- properties: PageViewEvent;
15
- type: string;
16
- event: string;
17
- options: Record<string, unknown>;
18
- userId: string | null;
19
- anonymousId: string | null;
20
- };
21
- 'track:dot-analytics': ({ payload }: {
22
- payload: DotAnalyticsPayload;
23
- }) => {
24
- properties: TrackEvent;
25
- type: string;
26
- event: string;
27
- options: Record<string, unknown>;
28
- userId: string | null;
29
- anonymousId: string | null;
30
- };
31
- };
@@ -1,28 +0,0 @@
1
- import { EventType as n, ANALYTICS_SOURCE_TYPE as r, ANALYTICS_PAGEVIEW_EVENT as o } from "../shared/dot-content-analytics.constants.js";
2
- import { getBrowserEventData as i } from "../shared/dot-content-analytics.utils.js";
3
- const p = {
4
- name: "enrich-dot-analytics",
5
- "page:dot-analytics": ({ payload: e }) => {
6
- const t = {
7
- ...i(window.location),
8
- ...e.properties,
9
- event_type: o,
10
- anonymousId: e.anonymousId || void 0,
11
- src: r
12
- };
13
- return { ...e, properties: t };
14
- },
15
- "track:dot-analytics": ({ payload: e }) => {
16
- const t = {
17
- ...e.properties,
18
- custom_event: e.event,
19
- event_type: n.Track,
20
- anonymousId: e.anonymousId || void 0,
21
- src: r
22
- };
23
- return { ...e, properties: t };
24
- }
25
- };
26
- export {
27
- p as dotAnalyticsEnricherPlugin
28
- };