@arthurreira/analytics 0.18.0 → 0.20.0
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/dist/af-analytics.umd.js +49 -12
- package/dist/client.js +11 -2
- package/dist/index.d.ts +11 -3
- package/dist/index.js +27 -3
- package/package.json +5 -6
package/dist/af-analytics.umd.js
CHANGED
|
@@ -38,20 +38,47 @@ var AfAnalytics = (() => {
|
|
|
38
38
|
// src/vanilla.ts
|
|
39
39
|
var vanilla_exports = {};
|
|
40
40
|
__export(vanilla_exports, {
|
|
41
|
-
|
|
41
|
+
consent: () => consent,
|
|
42
|
+
init: () => init,
|
|
43
|
+
isOptedOut: () => isOptedOut,
|
|
44
|
+
optIn: () => optIn,
|
|
45
|
+
optOut: () => optOut
|
|
42
46
|
});
|
|
47
|
+
|
|
48
|
+
// src/lib/consent.ts
|
|
49
|
+
var CONSENT_KEY = "af_analytics_opted_out";
|
|
50
|
+
function optOut() {
|
|
51
|
+
if (typeof localStorage === "undefined") return;
|
|
52
|
+
localStorage.setItem(CONSENT_KEY, "1");
|
|
53
|
+
}
|
|
54
|
+
function optIn() {
|
|
55
|
+
if (typeof localStorage === "undefined") return;
|
|
56
|
+
localStorage.removeItem(CONSENT_KEY);
|
|
57
|
+
}
|
|
58
|
+
function isOptedOut() {
|
|
59
|
+
if (typeof localStorage !== "undefined" && localStorage.getItem(CONSENT_KEY) === "1") return true;
|
|
60
|
+
if (typeof navigator !== "undefined" && navigator.doNotTrack === "1") return true;
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
function consent(enabled) {
|
|
64
|
+
if (enabled) optIn();
|
|
65
|
+
else optOut();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// src/vanilla.ts
|
|
43
69
|
var _currentScript = document.currentScript;
|
|
44
70
|
var SESSION_EXPIRY_MS = 30 * 60 * 1e3;
|
|
45
71
|
var IDLE_TOUCH_INTERVAL_MS = 5 * 60 * 1e3;
|
|
46
72
|
var BC_CHANNEL = "af_analytics_session";
|
|
47
73
|
var BC_ADOPT_TIMEOUT_MS = 50;
|
|
48
74
|
function readConfig() {
|
|
49
|
-
var _a, _b, _c, _d;
|
|
75
|
+
var _a, _b, _c, _d, _e, _f;
|
|
50
76
|
const script = _currentScript != null ? _currentScript : document.querySelector("script[data-api-key]");
|
|
51
77
|
const apiKey = (_b = (_a = script == null ? void 0 : script.dataset.apiKey) == null ? void 0 : _a.trim()) != null ? _b : "";
|
|
52
78
|
const apiUrl = ((_d = (_c = script == null ? void 0 : script.dataset.url) == null ? void 0 : _c.trim()) != null ? _d : "").replace(/\/$/, "");
|
|
53
79
|
if (!apiKey || !apiUrl) return null;
|
|
54
|
-
|
|
80
|
+
const wsUrl = (_f = (_e = script == null ? void 0 : script.dataset.wsUrl) == null ? void 0 : _e.trim()) != null ? _f : apiUrl.replace(/^https:\/\//, "wss://").replace(/^http:\/\//, "ws://") + "/realtime";
|
|
81
|
+
return { apiKey, apiUrl, wsUrl };
|
|
55
82
|
}
|
|
56
83
|
function generateId() {
|
|
57
84
|
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
@@ -97,6 +124,7 @@ var AfAnalytics = (() => {
|
|
|
97
124
|
}
|
|
98
125
|
}
|
|
99
126
|
function send(apiUrl, apiKey, payload) {
|
|
127
|
+
if (isOptedOut()) return;
|
|
100
128
|
fetch(`${apiUrl}/events`, {
|
|
101
129
|
method: "POST",
|
|
102
130
|
headers: { "X-API-Key": apiKey, "Content-Type": "application/json" },
|
|
@@ -157,7 +185,7 @@ var AfAnalytics = (() => {
|
|
|
157
185
|
return () => channel.close();
|
|
158
186
|
}
|
|
159
187
|
async function createRemoteSession(apiUrl, apiKey, visitorId) {
|
|
160
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
188
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
|
|
161
189
|
const nav = navigator;
|
|
162
190
|
const conn = (_c = (_b = (_a = nav["connection"]) != null ? _a : nav["mozConnection"]) != null ? _b : nav["webkitConnection"]) != null ? _c : null;
|
|
163
191
|
const params = new URLSearchParams(window.location.search);
|
|
@@ -182,14 +210,22 @@ var AfAnalytics = (() => {
|
|
|
182
210
|
utm_term: params.get("utm_term"),
|
|
183
211
|
utm_content: params.get("utm_content")
|
|
184
212
|
};
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
213
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
214
|
+
try {
|
|
215
|
+
const res = await fetch(`${apiUrl}/sessions`, {
|
|
216
|
+
method: "POST",
|
|
217
|
+
headers: { "X-API-Key": apiKey, "Content-Type": "application/json" },
|
|
218
|
+
body: JSON.stringify(body)
|
|
219
|
+
});
|
|
220
|
+
if (res.ok) {
|
|
221
|
+
const data = await res.json();
|
|
222
|
+
return (_o = (_n = data.session_id) != null ? _n : data.id) != null ? _o : "";
|
|
223
|
+
}
|
|
224
|
+
} catch (e) {
|
|
225
|
+
}
|
|
226
|
+
if (attempt < 2) await new Promise((r) => setTimeout(r, 500 * 2 ** attempt));
|
|
227
|
+
}
|
|
228
|
+
return "";
|
|
193
229
|
}
|
|
194
230
|
async function getOrCreateSession(apiUrl, apiKey) {
|
|
195
231
|
const stored = getStoredSession();
|
|
@@ -235,6 +271,7 @@ var AfAnalytics = (() => {
|
|
|
235
271
|
send(apiUrl, apiKey, __spreadValues(__spreadValues({}, baseFields(sessionId, "js_exception")), fields));
|
|
236
272
|
}
|
|
237
273
|
function init() {
|
|
274
|
+
if (isOptedOut()) return;
|
|
238
275
|
const config = readConfig();
|
|
239
276
|
if (!config) return;
|
|
240
277
|
const { apiKey, apiUrl } = config;
|
package/dist/client.js
CHANGED
|
@@ -8,6 +8,14 @@ import { usePathname } from "next/navigation";
|
|
|
8
8
|
// src/hooks/useAnalytics.ts
|
|
9
9
|
import { useEffect, useRef } from "react";
|
|
10
10
|
|
|
11
|
+
// src/lib/consent.ts
|
|
12
|
+
var CONSENT_KEY = "af_analytics_opted_out";
|
|
13
|
+
function isOptedOut() {
|
|
14
|
+
if (typeof localStorage !== "undefined" && localStorage.getItem(CONSENT_KEY) === "1") return true;
|
|
15
|
+
if (typeof navigator !== "undefined" && navigator.doNotTrack === "1") return true;
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
|
|
11
19
|
// src/lib/api.ts
|
|
12
20
|
var BASE_FIELDS = (sessionId, eventType, path) => ({
|
|
13
21
|
session_id: sessionId,
|
|
@@ -28,6 +36,7 @@ function getGpu() {
|
|
|
28
36
|
}
|
|
29
37
|
}
|
|
30
38
|
async function createSession(apiUrl, apiKey, visitorId) {
|
|
39
|
+
if (isOptedOut()) return null;
|
|
31
40
|
const sessionData = { visitor_id: visitorId };
|
|
32
41
|
if (typeof window !== "undefined") {
|
|
33
42
|
const nav = navigator;
|
|
@@ -77,6 +86,7 @@ async function createSession(apiUrl, apiKey, visitorId) {
|
|
|
77
86
|
}
|
|
78
87
|
}
|
|
79
88
|
async function sendEvent(apiUrl, apiKey, payload) {
|
|
89
|
+
if (isOptedOut()) return;
|
|
80
90
|
await fetch(`${apiUrl}/events`, {
|
|
81
91
|
method: "POST",
|
|
82
92
|
headers: {
|
|
@@ -144,8 +154,7 @@ async function trackCTA(apiUrl, apiKey, sessionId, path, ctaId, ctaVariant) {
|
|
|
144
154
|
}
|
|
145
155
|
|
|
146
156
|
// src/lib/presence.ts
|
|
147
|
-
|
|
148
|
-
function connectPresence(apiKey, sessionId, wsUrl = DEFAULT_WS_URL) {
|
|
157
|
+
function connectPresence(apiKey, sessionId, wsUrl) {
|
|
149
158
|
if (typeof WebSocket === "undefined") {
|
|
150
159
|
return { disconnect: () => {
|
|
151
160
|
} };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
declare function optOut(): void;
|
|
2
|
+
declare function optIn(): void;
|
|
3
|
+
/**
|
|
4
|
+
* Returns true when the user has opted out via localStorage flag OR
|
|
5
|
+
* the browser-level DNT header is set to "1".
|
|
6
|
+
*/
|
|
7
|
+
declare function isOptedOut(): boolean;
|
|
8
|
+
declare function consent(enabled: boolean): void;
|
|
9
|
+
|
|
1
10
|
declare function createSession(apiUrl: string, apiKey: string, visitorId?: string): Promise<string | null>;
|
|
2
11
|
declare function trackPageview(apiUrl: string, apiKey: string, sessionId: string, path: string): Promise<void>;
|
|
3
12
|
declare function trackClick(apiUrl: string, apiKey: string, sessionId: string, path: string, e: MouseEvent, element: HTMLElement): Promise<void>;
|
|
@@ -13,10 +22,9 @@ declare function trackException(apiUrl: string, apiKey: string, sessionId: strin
|
|
|
13
22
|
declare function trackError(apiUrl: string, apiKey: string, sessionId: string, path: string, error: Error): Promise<void>;
|
|
14
23
|
declare function trackCTA(apiUrl: string, apiKey: string, sessionId: string, path: string, ctaId: string, ctaVariant?: string): Promise<void>;
|
|
15
24
|
|
|
16
|
-
declare const DEFAULT_WS_URL = "wss://edge.arthurreira.dev/realtime";
|
|
17
25
|
interface PresenceConnection {
|
|
18
26
|
disconnect: () => void;
|
|
19
27
|
}
|
|
20
|
-
declare function connectPresence(apiKey: string, sessionId: string, wsUrl
|
|
28
|
+
declare function connectPresence(apiKey: string, sessionId: string, wsUrl: string): PresenceConnection;
|
|
21
29
|
|
|
22
|
-
export {
|
|
30
|
+
export { type ExceptionFields, type PresenceConnection, connectPresence, consent, createSession, isOptedOut, optIn, optOut, trackCTA, trackClick, trackCopy, trackError, trackException, trackPageview, trackScroll, trackSearch };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
// src/lib/consent.ts
|
|
2
|
+
var CONSENT_KEY = "af_analytics_opted_out";
|
|
3
|
+
function optOut() {
|
|
4
|
+
if (typeof localStorage === "undefined") return;
|
|
5
|
+
localStorage.setItem(CONSENT_KEY, "1");
|
|
6
|
+
}
|
|
7
|
+
function optIn() {
|
|
8
|
+
if (typeof localStorage === "undefined") return;
|
|
9
|
+
localStorage.removeItem(CONSENT_KEY);
|
|
10
|
+
}
|
|
11
|
+
function isOptedOut() {
|
|
12
|
+
if (typeof localStorage !== "undefined" && localStorage.getItem(CONSENT_KEY) === "1") return true;
|
|
13
|
+
if (typeof navigator !== "undefined" && navigator.doNotTrack === "1") return true;
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
function consent(enabled) {
|
|
17
|
+
if (enabled) optIn();
|
|
18
|
+
else optOut();
|
|
19
|
+
}
|
|
20
|
+
|
|
1
21
|
// src/lib/api.ts
|
|
2
22
|
var BASE_FIELDS = (sessionId, eventType, path) => ({
|
|
3
23
|
session_id: sessionId,
|
|
@@ -18,6 +38,7 @@ function getGpu() {
|
|
|
18
38
|
}
|
|
19
39
|
}
|
|
20
40
|
async function createSession(apiUrl, apiKey, visitorId) {
|
|
41
|
+
if (isOptedOut()) return null;
|
|
21
42
|
const sessionData = { visitor_id: visitorId };
|
|
22
43
|
if (typeof window !== "undefined") {
|
|
23
44
|
const nav = navigator;
|
|
@@ -67,6 +88,7 @@ async function createSession(apiUrl, apiKey, visitorId) {
|
|
|
67
88
|
}
|
|
68
89
|
}
|
|
69
90
|
async function sendEvent(apiUrl, apiKey, payload) {
|
|
91
|
+
if (isOptedOut()) return;
|
|
70
92
|
await fetch(`${apiUrl}/events`, {
|
|
71
93
|
method: "POST",
|
|
72
94
|
headers: {
|
|
@@ -134,8 +156,7 @@ async function trackCTA(apiUrl, apiKey, sessionId, path, ctaId, ctaVariant) {
|
|
|
134
156
|
}
|
|
135
157
|
|
|
136
158
|
// src/lib/presence.ts
|
|
137
|
-
|
|
138
|
-
function connectPresence(apiKey, sessionId, wsUrl = DEFAULT_WS_URL) {
|
|
159
|
+
function connectPresence(apiKey, sessionId, wsUrl) {
|
|
139
160
|
if (typeof WebSocket === "undefined") {
|
|
140
161
|
return { disconnect: () => {
|
|
141
162
|
} };
|
|
@@ -204,9 +225,12 @@ function connectPresence(apiKey, sessionId, wsUrl = DEFAULT_WS_URL) {
|
|
|
204
225
|
};
|
|
205
226
|
}
|
|
206
227
|
export {
|
|
207
|
-
DEFAULT_WS_URL,
|
|
208
228
|
connectPresence,
|
|
229
|
+
consent,
|
|
209
230
|
createSession,
|
|
231
|
+
isOptedOut,
|
|
232
|
+
optIn,
|
|
233
|
+
optOut,
|
|
210
234
|
trackCTA,
|
|
211
235
|
trackClick,
|
|
212
236
|
trackCopy,
|
package/package.json
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arthurreira/analytics",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"scripts": {
|
|
6
|
-
"build": "tsup",
|
|
7
|
-
"prepare": "tsup",
|
|
8
|
-
"dev": "tsup src/index.ts --format esm --dts --watch"
|
|
9
|
-
},
|
|
10
5
|
"exports": {
|
|
11
6
|
".": {
|
|
12
7
|
"types": "./dist/index.d.ts",
|
|
@@ -37,5 +32,9 @@
|
|
|
37
32
|
"peerDependencies": {
|
|
38
33
|
"next": "^14.0.0 || ^15.0.0 || ^16.0.0",
|
|
39
34
|
"react": "^18.0.0 || ^19.0.0"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsup",
|
|
38
|
+
"dev": "tsup src/index.ts --format esm --dts --watch"
|
|
40
39
|
}
|
|
41
40
|
}
|