@stacksee/analytics 0.9.4 → 0.9.6
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/core/events/types.d.ts +11 -0
- package/dist/providers/client.js +180 -186
- package/dist/providers/server.js +115 -105
- package/package.json +1 -1
- package/readme.md +28 -39
|
@@ -28,6 +28,17 @@ export interface EventContext<TTraits extends Record<string, unknown> = Record<s
|
|
|
28
28
|
type?: string;
|
|
29
29
|
os?: string;
|
|
30
30
|
browser?: string;
|
|
31
|
+
userAgent?: string;
|
|
32
|
+
language?: string;
|
|
33
|
+
timezone?: string;
|
|
34
|
+
screen?: {
|
|
35
|
+
width?: number;
|
|
36
|
+
height?: number;
|
|
37
|
+
};
|
|
38
|
+
viewport?: {
|
|
39
|
+
width?: number;
|
|
40
|
+
height?: number;
|
|
41
|
+
};
|
|
31
42
|
};
|
|
32
43
|
utm?: {
|
|
33
44
|
source?: string;
|
package/dist/providers/client.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var r = (
|
|
4
|
-
import { B as
|
|
1
|
+
var f = Object.defineProperty;
|
|
2
|
+
var p = (d, h, e) => h in d ? f(d, h, { enumerable: !0, configurable: !0, writable: !0, value: e }) : d[h] = e;
|
|
3
|
+
var r = (d, h, e) => p(d, typeof h != "symbol" ? h + "" : h, e);
|
|
4
|
+
import { B as u } from "../base.provider-AfFL5W_P.js";
|
|
5
5
|
import { i as a } from "../client-DTHZYkxx.js";
|
|
6
|
-
import { P as
|
|
7
|
-
class
|
|
8
|
-
constructor(
|
|
9
|
-
super({ debug:
|
|
6
|
+
import { P as z } from "../client-DTHZYkxx.js";
|
|
7
|
+
class w extends u {
|
|
8
|
+
constructor(e) {
|
|
9
|
+
super({ debug: e.debug, enabled: e.enabled });
|
|
10
10
|
r(this, "name", "Bento-Client");
|
|
11
11
|
r(this, "bento");
|
|
12
12
|
r(this, "initialized", !1);
|
|
13
13
|
r(this, "config");
|
|
14
14
|
r(this, "scriptLoaded", !1);
|
|
15
|
-
this.config =
|
|
15
|
+
this.config = e;
|
|
16
16
|
}
|
|
17
17
|
async initialize() {
|
|
18
18
|
if (this.isEnabled() && !this.initialized) {
|
|
@@ -24,119 +24,119 @@ class b extends o {
|
|
|
24
24
|
throw new Error("Bento requires a siteUuid");
|
|
25
25
|
try {
|
|
26
26
|
this.scriptLoaded || await this.loadBentoScript(), await this.waitForBento(), this.bento = window.bento, this.initialized = !0, this.log("Initialized successfully", this.config);
|
|
27
|
-
} catch (
|
|
28
|
-
throw console.error("[Bento-Client] Failed to initialize:",
|
|
27
|
+
} catch (e) {
|
|
28
|
+
throw console.error("[Bento-Client] Failed to initialize:", e), e;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
async loadBentoScript() {
|
|
33
|
-
return new Promise((
|
|
33
|
+
return new Promise((e, i) => {
|
|
34
34
|
if (document.querySelector(
|
|
35
35
|
'script[src*="bentonow.com"]'
|
|
36
36
|
)) {
|
|
37
|
-
this.scriptLoaded = !0,
|
|
37
|
+
this.scriptLoaded = !0, e();
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
40
|
const t = document.createElement("script");
|
|
41
41
|
t.src = `https://fast.bentonow.com?site_uuid=${this.config.siteUuid}`, t.async = !0, t.defer = !0, t.onload = () => {
|
|
42
|
-
this.scriptLoaded = !0,
|
|
42
|
+
this.scriptLoaded = !0, e();
|
|
43
43
|
}, t.onerror = () => {
|
|
44
|
-
|
|
44
|
+
i(new Error("Failed to load Bento script"));
|
|
45
45
|
}, document.head.appendChild(t);
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
|
-
async waitForBento(
|
|
49
|
-
for (let s = 0; s <
|
|
48
|
+
async waitForBento(e = 50, i = 100) {
|
|
49
|
+
for (let s = 0; s < e; s++) {
|
|
50
50
|
if (window.bento)
|
|
51
51
|
return;
|
|
52
|
-
await new Promise((t) => setTimeout(t,
|
|
52
|
+
await new Promise((t) => setTimeout(t, i));
|
|
53
53
|
}
|
|
54
54
|
throw new Error("Bento SDK not available after loading script");
|
|
55
55
|
}
|
|
56
|
-
identify(
|
|
56
|
+
identify(e, i) {
|
|
57
57
|
if (!this.isEnabled() || !this.initialized || !this.bento) return;
|
|
58
|
-
const s = (
|
|
59
|
-
if (this.bento.identify(s),
|
|
60
|
-
const t = { ...
|
|
58
|
+
const s = (i == null ? void 0 : i.email) || e;
|
|
59
|
+
if (this.bento.identify(s), i) {
|
|
60
|
+
const t = { ...i };
|
|
61
61
|
delete t.email, Object.keys(t).length > 0 && this.bento.updateFields(t);
|
|
62
62
|
}
|
|
63
|
-
this.log("Identified user", { userId:
|
|
63
|
+
this.log("Identified user", { userId: e, email: s, traits: i });
|
|
64
64
|
}
|
|
65
|
-
track(
|
|
66
|
-
var t, n,
|
|
65
|
+
track(e, i) {
|
|
66
|
+
var t, n, l;
|
|
67
67
|
if (!this.isEnabled() || !this.initialized || !this.bento) return;
|
|
68
68
|
const s = {
|
|
69
|
-
...
|
|
70
|
-
category:
|
|
71
|
-
timestamp:
|
|
72
|
-
...
|
|
73
|
-
...
|
|
74
|
-
...(
|
|
69
|
+
...e.properties,
|
|
70
|
+
category: e.category,
|
|
71
|
+
timestamp: e.timestamp || Date.now(),
|
|
72
|
+
...e.userId && { userId: e.userId },
|
|
73
|
+
...e.sessionId && { sessionId: e.sessionId },
|
|
74
|
+
...(i == null ? void 0 : i.page) && {
|
|
75
75
|
page: {
|
|
76
|
-
url:
|
|
77
|
-
host:
|
|
78
|
-
path:
|
|
79
|
-
title:
|
|
80
|
-
protocol:
|
|
81
|
-
referrer:
|
|
82
|
-
...
|
|
76
|
+
url: i.page.url,
|
|
77
|
+
host: i.page.host,
|
|
78
|
+
path: i.page.path,
|
|
79
|
+
title: i.page.title,
|
|
80
|
+
protocol: i.page.protocol,
|
|
81
|
+
referrer: i.page.referrer,
|
|
82
|
+
...i.page.search && { search: i.page.search }
|
|
83
83
|
}
|
|
84
84
|
},
|
|
85
|
-
...(
|
|
86
|
-
...(
|
|
85
|
+
...(i == null ? void 0 : i.device) && { device: i.device },
|
|
86
|
+
...(i == null ? void 0 : i.utm) && { utm: i.utm },
|
|
87
87
|
// Include user email and traits as regular event properties
|
|
88
|
-
...((t =
|
|
89
|
-
...((n =
|
|
90
|
-
...((
|
|
88
|
+
...((t = i == null ? void 0 : i.user) == null ? void 0 : t.email) && { user_email: i.user.email },
|
|
89
|
+
...((n = i == null ? void 0 : i.user) == null ? void 0 : n.traits) && { user_traits: i.user.traits },
|
|
90
|
+
...((l = i == null ? void 0 : i.user) == null ? void 0 : l.userId) && { visitor: i.user.userId }
|
|
91
91
|
};
|
|
92
|
-
this.bento.track(
|
|
92
|
+
this.bento.track(e.action, s), this.log("Tracked event", { event: e, context: i });
|
|
93
93
|
}
|
|
94
|
-
pageView(
|
|
94
|
+
pageView(e, i) {
|
|
95
95
|
var s;
|
|
96
96
|
if (!(!this.isEnabled() || !this.initialized || !this.bento || !a())) {
|
|
97
|
-
if (this.bento.view(),
|
|
97
|
+
if (this.bento.view(), e || i != null && i.page) {
|
|
98
98
|
const t = {
|
|
99
|
-
...
|
|
99
|
+
...e,
|
|
100
100
|
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
101
|
-
...(
|
|
101
|
+
...(i == null ? void 0 : i.page) && {
|
|
102
102
|
page: {
|
|
103
|
-
url:
|
|
104
|
-
host:
|
|
105
|
-
path:
|
|
106
|
-
title:
|
|
107
|
-
protocol:
|
|
108
|
-
referrer:
|
|
109
|
-
...
|
|
103
|
+
url: i.page.url,
|
|
104
|
+
host: i.page.host,
|
|
105
|
+
path: i.page.path,
|
|
106
|
+
title: i.page.title,
|
|
107
|
+
protocol: i.page.protocol,
|
|
108
|
+
referrer: i.page.referrer,
|
|
109
|
+
...i.page.search && { search: i.page.search }
|
|
110
110
|
}
|
|
111
111
|
},
|
|
112
|
-
...((s =
|
|
112
|
+
...((s = i == null ? void 0 : i.user) == null ? void 0 : s.userId) && { visitor: i.user.userId }
|
|
113
113
|
};
|
|
114
114
|
this.bento.track("$view", t);
|
|
115
115
|
}
|
|
116
|
-
this.log("Tracked page view", { properties:
|
|
116
|
+
this.log("Tracked page view", { properties: e, context: i });
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
|
-
pageLeave(
|
|
119
|
+
pageLeave(e, i) {
|
|
120
120
|
var t;
|
|
121
121
|
if (!this.isEnabled() || !this.initialized || !this.bento || !a())
|
|
122
122
|
return;
|
|
123
123
|
const s = {
|
|
124
|
-
...
|
|
124
|
+
...e,
|
|
125
125
|
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
126
|
-
...(
|
|
126
|
+
...(i == null ? void 0 : i.page) && {
|
|
127
127
|
page: {
|
|
128
|
-
url:
|
|
129
|
-
host:
|
|
130
|
-
path:
|
|
131
|
-
title:
|
|
132
|
-
protocol:
|
|
133
|
-
referrer:
|
|
134
|
-
...
|
|
128
|
+
url: i.page.url,
|
|
129
|
+
host: i.page.host,
|
|
130
|
+
path: i.page.path,
|
|
131
|
+
title: i.page.title,
|
|
132
|
+
protocol: i.page.protocol,
|
|
133
|
+
referrer: i.page.referrer,
|
|
134
|
+
...i.page.search && { search: i.page.search }
|
|
135
135
|
}
|
|
136
136
|
},
|
|
137
|
-
...((t =
|
|
137
|
+
...((t = i == null ? void 0 : i.user) == null ? void 0 : t.userId) && { visitor: i.user.userId }
|
|
138
138
|
};
|
|
139
|
-
this.bento.track("$pageleave", s), this.log("Tracked page leave", { properties:
|
|
139
|
+
this.bento.track("$pageleave", s), this.log("Tracked page leave", { properties: e, context: i });
|
|
140
140
|
}
|
|
141
141
|
reset() {
|
|
142
142
|
!this.isEnabled() || !this.initialized || !this.bento || !a() || this.log("Reset user session - Note: Bento doesn't have a native reset method");
|
|
@@ -153,8 +153,8 @@ class b extends o {
|
|
|
153
153
|
* bentoProvider.tag('beta_tester');
|
|
154
154
|
* ```
|
|
155
155
|
*/
|
|
156
|
-
tag(
|
|
157
|
-
!this.isEnabled() || !this.initialized || !this.bento || !a() || (this.bento.tag(
|
|
156
|
+
tag(e) {
|
|
157
|
+
!this.isEnabled() || !this.initialized || !this.bento || !a() || (this.bento.tag(e), this.log("Added tag to user", { tag: e }));
|
|
158
158
|
}
|
|
159
159
|
/**
|
|
160
160
|
* Get the current user's email address
|
|
@@ -206,8 +206,8 @@ class b extends o {
|
|
|
206
206
|
* }
|
|
207
207
|
* ```
|
|
208
208
|
*/
|
|
209
|
-
showSurveyForm(
|
|
210
|
-
!this.isEnabled() || !this.initialized || !this.bento || !a() || (this.bento.showSurveyForm(
|
|
209
|
+
showSurveyForm(e, i, s = "popup") {
|
|
210
|
+
!this.isEnabled() || !this.initialized || !this.bento || !a() || (this.bento.showSurveyForm(e, i, s), this.log("Showed survey form", { surveyId: i, type: s }));
|
|
211
211
|
}
|
|
212
212
|
/**
|
|
213
213
|
* Validate an email address using Bento's spam check
|
|
@@ -223,14 +223,14 @@ class b extends o {
|
|
|
223
223
|
* }
|
|
224
224
|
* ```
|
|
225
225
|
*/
|
|
226
|
-
async spamCheck(
|
|
226
|
+
async spamCheck(e) {
|
|
227
227
|
if (!this.isEnabled() || !this.initialized || !this.bento || !a())
|
|
228
228
|
return !1;
|
|
229
229
|
try {
|
|
230
|
-
const
|
|
231
|
-
return this.log("Spam check completed", { email:
|
|
232
|
-
} catch (
|
|
233
|
-
return console.error("[Bento-Client] Spam check failed:",
|
|
230
|
+
const i = await this.bento.spamCheck(e);
|
|
231
|
+
return this.log("Spam check completed", { email: e, result: i }), i;
|
|
232
|
+
} catch (i) {
|
|
233
|
+
return console.error("[Bento-Client] Spam check failed:", i), !1;
|
|
234
234
|
}
|
|
235
235
|
}
|
|
236
236
|
// ============================================================================
|
|
@@ -276,14 +276,14 @@ class b extends o {
|
|
|
276
276
|
));
|
|
277
277
|
}
|
|
278
278
|
}
|
|
279
|
-
class
|
|
280
|
-
constructor(
|
|
281
|
-
super({ debug:
|
|
279
|
+
class m extends u {
|
|
280
|
+
constructor(e) {
|
|
281
|
+
super({ debug: e.debug, enabled: e.enabled });
|
|
282
282
|
r(this, "name", "Pirsch-Client");
|
|
283
283
|
r(this, "client");
|
|
284
284
|
r(this, "initialized", !1);
|
|
285
285
|
r(this, "config");
|
|
286
|
-
this.config =
|
|
286
|
+
this.config = e;
|
|
287
287
|
}
|
|
288
288
|
async initialize() {
|
|
289
289
|
if (this.isEnabled() && !this.initialized) {
|
|
@@ -294,98 +294,92 @@ class w extends o {
|
|
|
294
294
|
if (!this.config.identificationCode || typeof this.config.identificationCode != "string")
|
|
295
295
|
throw new Error("Pirsch requires an identificationCode");
|
|
296
296
|
try {
|
|
297
|
-
const { Pirsch:
|
|
298
|
-
this.client = new
|
|
297
|
+
const { Pirsch: e } = await import("../web-imCcOhDC.js").then((i) => i.w);
|
|
298
|
+
this.client = new e({
|
|
299
299
|
identificationCode: this.config.identificationCode,
|
|
300
300
|
...this.config.hostname && { hostname: this.config.hostname }
|
|
301
301
|
}), this.initialized = !0, this.log("Initialized successfully", this.config);
|
|
302
|
-
} catch (
|
|
302
|
+
} catch (e) {
|
|
303
303
|
throw console.error(
|
|
304
304
|
"[Pirsch-Client] Failed to initialize. Make sure pirsch-sdk is installed:",
|
|
305
|
-
|
|
306
|
-
),
|
|
305
|
+
e
|
|
306
|
+
), e;
|
|
307
307
|
}
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
|
-
identify(
|
|
310
|
+
identify(e, i) {
|
|
311
311
|
!this.isEnabled() || !this.initialized || !this.client || (this.client.event("user_identified", 0, {
|
|
312
|
-
userId:
|
|
313
|
-
...
|
|
312
|
+
userId: e,
|
|
313
|
+
...i
|
|
314
314
|
}).catch((s) => {
|
|
315
315
|
console.error("[Pirsch-Client] Failed to track identify event:", s);
|
|
316
|
-
}), this.log("Identified user via event", { userId:
|
|
316
|
+
}), this.log("Identified user via event", { userId: e, traits: i }));
|
|
317
317
|
}
|
|
318
|
-
async track(
|
|
318
|
+
async track(e, i) {
|
|
319
319
|
var t, n;
|
|
320
320
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
321
321
|
const s = {
|
|
322
|
-
...
|
|
323
|
-
category:
|
|
324
|
-
...
|
|
325
|
-
...
|
|
326
|
-
...(
|
|
327
|
-
page_path:
|
|
328
|
-
page_title:
|
|
329
|
-
page_referrer:
|
|
322
|
+
...e.properties,
|
|
323
|
+
category: e.category,
|
|
324
|
+
...e.userId && { userId: e.userId },
|
|
325
|
+
...e.sessionId && { sessionId: e.sessionId },
|
|
326
|
+
...(i == null ? void 0 : i.page) && {
|
|
327
|
+
page_path: i.page.path,
|
|
328
|
+
page_title: i.page.title,
|
|
329
|
+
page_referrer: i.page.referrer
|
|
330
330
|
},
|
|
331
|
-
...(
|
|
332
|
-
...(
|
|
333
|
-
...((t =
|
|
334
|
-
...((n =
|
|
331
|
+
...(i == null ? void 0 : i.device) && { device: i.device },
|
|
332
|
+
...(i == null ? void 0 : i.utm) && { utm: i.utm },
|
|
333
|
+
...((t = i == null ? void 0 : i.user) == null ? void 0 : t.email) && { user_email: i.user.email },
|
|
334
|
+
...((n = i == null ? void 0 : i.user) == null ? void 0 : n.traits) && { user_traits: i.user.traits }
|
|
335
335
|
};
|
|
336
336
|
try {
|
|
337
|
-
await this.client.event(
|
|
338
|
-
} catch (
|
|
339
|
-
console.error("[Pirsch-Client] Failed to track event:",
|
|
337
|
+
await this.client.event(e.action, 0, s), this.log("Tracked event", { event: e, context: i });
|
|
338
|
+
} catch (l) {
|
|
339
|
+
console.error("[Pirsch-Client] Failed to track event:", l);
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
|
-
pageView(
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
this.log("Tracked page view", { properties: i, context: e });
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
pageLeave(i, e) {
|
|
342
|
+
pageView(e, i) {
|
|
343
|
+
var l, g;
|
|
344
|
+
if (!this.isEnabled() || !this.initialized || !this.client || !a())
|
|
345
|
+
return;
|
|
346
|
+
const s = e && Object.keys(e).length > 0 ? Object.fromEntries(
|
|
347
|
+
Object.entries(e).filter(
|
|
348
|
+
([, o]) => typeof o == "string" || typeof o == "number" || typeof o == "boolean"
|
|
349
|
+
)
|
|
350
|
+
) : void 0, t = {
|
|
351
|
+
...((l = i == null ? void 0 : i.page) == null ? void 0 : l.url) && { url: i.page.url },
|
|
352
|
+
...((g = i == null ? void 0 : i.page) == null ? void 0 : g.title) && { title: i.page.title },
|
|
353
|
+
...s && { tags: s }
|
|
354
|
+
}, n = Object.keys(t).length > 0 ? t : void 0;
|
|
355
|
+
this.client.hit(n).catch((o) => {
|
|
356
|
+
console.error("[Pirsch-Client] Failed to track page view:", o);
|
|
357
|
+
}), this.log("Tracked page view", { properties: e, context: i });
|
|
358
|
+
}
|
|
359
|
+
pageLeave(e, i) {
|
|
366
360
|
if (!this.isEnabled() || !this.initialized || !this.client || !a())
|
|
367
361
|
return;
|
|
368
362
|
const s = {
|
|
369
|
-
...
|
|
370
|
-
...(
|
|
371
|
-
path:
|
|
372
|
-
title:
|
|
363
|
+
...e,
|
|
364
|
+
...(i == null ? void 0 : i.page) && {
|
|
365
|
+
path: i.page.path,
|
|
366
|
+
title: i.page.title
|
|
373
367
|
}
|
|
374
368
|
};
|
|
375
369
|
this.client.event("page_leave", 0, s).catch((t) => {
|
|
376
370
|
console.error("[Pirsch-Client] Failed to track page leave:", t);
|
|
377
|
-
}), this.log("Tracked page leave", { properties:
|
|
371
|
+
}), this.log("Tracked page leave", { properties: e, context: i });
|
|
378
372
|
}
|
|
379
373
|
reset() {
|
|
380
|
-
!this.isEnabled() || !this.initialized || !this.client || !a() || (this.client.event("session_reset", 0, {}).catch((
|
|
381
|
-
console.error("[Pirsch-Client] Failed to track session reset:",
|
|
374
|
+
!this.isEnabled() || !this.initialized || !this.client || !a() || (this.client.event("session_reset", 0, {}).catch((e) => {
|
|
375
|
+
console.error("[Pirsch-Client] Failed to track session reset:", e);
|
|
382
376
|
}), this.log("Reset user session"));
|
|
383
377
|
}
|
|
384
378
|
}
|
|
385
|
-
class
|
|
386
|
-
constructor(
|
|
387
|
-
var
|
|
388
|
-
super({ debug:
|
|
379
|
+
class v extends u {
|
|
380
|
+
constructor(e) {
|
|
381
|
+
var i, s, t, n, l;
|
|
382
|
+
super({ debug: e.debug, enabled: e.enabled });
|
|
389
383
|
r(this, "name", "Proxy");
|
|
390
384
|
r(this, "config");
|
|
391
385
|
r(this, "queue", []);
|
|
@@ -395,7 +389,7 @@ class y extends o {
|
|
|
395
389
|
r(this, "retryAttempts");
|
|
396
390
|
r(this, "retryBackoff");
|
|
397
391
|
r(this, "retryInitialDelay");
|
|
398
|
-
this.config =
|
|
392
|
+
this.config = e, this.batchSize = ((i = e.batch) == null ? void 0 : i.size) ?? 10, this.batchInterval = ((s = e.batch) == null ? void 0 : s.interval) ?? 5e3, this.retryAttempts = ((t = e.retry) == null ? void 0 : t.attempts) ?? 3, this.retryBackoff = ((n = e.retry) == null ? void 0 : n.backoff) ?? "exponential", this.retryInitialDelay = ((l = e.retry) == null ? void 0 : l.initialDelay) ?? 1e3, typeof window < "u" && (window.addEventListener("beforeunload", () => {
|
|
399
393
|
this.flush(!0);
|
|
400
394
|
}), document.addEventListener("visibilitychange", () => {
|
|
401
395
|
document.visibilityState === "hidden" && this.flush(!0);
|
|
@@ -404,26 +398,26 @@ class y extends o {
|
|
|
404
398
|
async initialize() {
|
|
405
399
|
this.isEnabled() && this.log("Initialized successfully", { endpoint: this.config.endpoint });
|
|
406
400
|
}
|
|
407
|
-
identify(
|
|
401
|
+
identify(e, i) {
|
|
408
402
|
this.isEnabled() && (this.queueEvent({
|
|
409
403
|
type: "identify",
|
|
410
|
-
userId:
|
|
411
|
-
traits:
|
|
412
|
-
}), this.log("Queued identify event", { userId:
|
|
404
|
+
userId: e,
|
|
405
|
+
traits: i
|
|
406
|
+
}), this.log("Queued identify event", { userId: e, traits: i }));
|
|
413
407
|
}
|
|
414
|
-
async track(
|
|
408
|
+
async track(e, i) {
|
|
415
409
|
this.isEnabled() && (this.queueEvent({
|
|
416
410
|
type: "track",
|
|
417
|
-
event:
|
|
418
|
-
context: this.enrichContext(
|
|
419
|
-
}), this.log("Queued track event", { event:
|
|
411
|
+
event: e,
|
|
412
|
+
context: this.enrichContext(i)
|
|
413
|
+
}), this.log("Queued track event", { event: e, context: i }));
|
|
420
414
|
}
|
|
421
|
-
pageView(
|
|
415
|
+
pageView(e, i) {
|
|
422
416
|
this.isEnabled() && (this.queueEvent({
|
|
423
417
|
type: "pageView",
|
|
424
|
-
properties:
|
|
425
|
-
context: this.enrichContext(
|
|
426
|
-
}), this.log("Queued page view event", { properties:
|
|
418
|
+
properties: e,
|
|
419
|
+
context: this.enrichContext(i)
|
|
420
|
+
}), this.log("Queued page view event", { properties: e, context: i }));
|
|
427
421
|
}
|
|
428
422
|
async reset() {
|
|
429
423
|
this.isEnabled() && (this.queueEvent({
|
|
@@ -436,27 +430,27 @@ class y extends o {
|
|
|
436
430
|
/**
|
|
437
431
|
* Manually flush all queued events
|
|
438
432
|
*/
|
|
439
|
-
async flush(
|
|
433
|
+
async flush(e = !1) {
|
|
440
434
|
if (this.queue.length === 0) return;
|
|
441
|
-
const
|
|
442
|
-
this.queue = [], this.flushTimer && (clearTimeout(this.flushTimer), this.flushTimer = void 0), await this.sendEvents(
|
|
435
|
+
const i = [...this.queue];
|
|
436
|
+
this.queue = [], this.flushTimer && (clearTimeout(this.flushTimer), this.flushTimer = void 0), await this.sendEvents(i, e);
|
|
443
437
|
}
|
|
444
|
-
queueEvent(
|
|
445
|
-
if (this.queue.push(
|
|
446
|
-
this.flush().catch((
|
|
447
|
-
console.error("[Proxy] Failed to flush events:",
|
|
438
|
+
queueEvent(e) {
|
|
439
|
+
if (this.queue.push(e), this.queue.length >= this.batchSize) {
|
|
440
|
+
this.flush().catch((i) => {
|
|
441
|
+
console.error("[Proxy] Failed to flush events:", i);
|
|
448
442
|
});
|
|
449
443
|
return;
|
|
450
444
|
}
|
|
451
445
|
this.flushTimer || (this.flushTimer = setTimeout(() => {
|
|
452
|
-
this.flush().catch((
|
|
453
|
-
console.error("[Proxy] Failed to flush events:",
|
|
446
|
+
this.flush().catch((i) => {
|
|
447
|
+
console.error("[Proxy] Failed to flush events:", i);
|
|
454
448
|
});
|
|
455
449
|
}, this.batchInterval));
|
|
456
450
|
}
|
|
457
|
-
async sendEvents(
|
|
458
|
-
const s = { events:
|
|
459
|
-
if (
|
|
451
|
+
async sendEvents(e, i = !1) {
|
|
452
|
+
const s = { events: e };
|
|
453
|
+
if (i && typeof navigator < "u" && navigator.sendBeacon) {
|
|
460
454
|
const t = new Blob([JSON.stringify(s)], {
|
|
461
455
|
type: "application/json"
|
|
462
456
|
});
|
|
@@ -465,7 +459,7 @@ class y extends o {
|
|
|
465
459
|
}
|
|
466
460
|
await this.sendWithRetry(s);
|
|
467
461
|
}
|
|
468
|
-
async sendWithRetry(
|
|
462
|
+
async sendWithRetry(e, i = 0) {
|
|
469
463
|
try {
|
|
470
464
|
const s = await fetch(this.config.endpoint, {
|
|
471
465
|
method: "POST",
|
|
@@ -473,39 +467,39 @@ class y extends o {
|
|
|
473
467
|
"Content-Type": "application/json",
|
|
474
468
|
...this.config.headers
|
|
475
469
|
},
|
|
476
|
-
body: JSON.stringify(
|
|
470
|
+
body: JSON.stringify(e),
|
|
477
471
|
// Don't include credentials by default
|
|
478
472
|
credentials: "same-origin"
|
|
479
473
|
});
|
|
480
474
|
if (!s.ok)
|
|
481
475
|
throw new Error(`HTTP ${s.status}: ${s.statusText}`);
|
|
482
|
-
this.log(`Sent ${
|
|
476
|
+
this.log(`Sent ${e.events.length} events successfully`);
|
|
483
477
|
} catch (s) {
|
|
484
|
-
if (
|
|
485
|
-
const t = this.calculateRetryDelay(
|
|
486
|
-
return this.log(`Retry attempt ${
|
|
478
|
+
if (i < this.retryAttempts) {
|
|
479
|
+
const t = this.calculateRetryDelay(i);
|
|
480
|
+
return this.log(`Retry attempt ${i + 1} after ${t}ms`, { error: s }), await new Promise((n) => setTimeout(n, t)), this.sendWithRetry(e, i + 1);
|
|
487
481
|
}
|
|
488
482
|
throw console.error("[Proxy] Failed to send events after retries:", s), s;
|
|
489
483
|
}
|
|
490
484
|
}
|
|
491
|
-
calculateRetryDelay(
|
|
492
|
-
return this.retryBackoff === "exponential" ? this.retryInitialDelay * 2 **
|
|
485
|
+
calculateRetryDelay(e) {
|
|
486
|
+
return this.retryBackoff === "exponential" ? this.retryInitialDelay * 2 ** e : this.retryInitialDelay * (e + 1);
|
|
493
487
|
}
|
|
494
|
-
enrichContext(
|
|
495
|
-
return typeof window > "u" ?
|
|
496
|
-
...
|
|
488
|
+
enrichContext(e) {
|
|
489
|
+
return typeof window > "u" ? e || {} : {
|
|
490
|
+
...e,
|
|
497
491
|
page: {
|
|
498
492
|
path: window.location.pathname,
|
|
499
493
|
title: document.title,
|
|
500
494
|
referrer: document.referrer,
|
|
501
|
-
...
|
|
495
|
+
...e == null ? void 0 : e.page,
|
|
502
496
|
url: window.location.href
|
|
503
497
|
},
|
|
504
498
|
user: {
|
|
505
|
-
...
|
|
499
|
+
...e == null ? void 0 : e.user
|
|
506
500
|
},
|
|
507
501
|
device: {
|
|
508
|
-
...
|
|
502
|
+
...e == null ? void 0 : e.device,
|
|
509
503
|
userAgent: navigator.userAgent,
|
|
510
504
|
language: navigator.language,
|
|
511
505
|
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
@@ -522,9 +516,9 @@ class y extends o {
|
|
|
522
516
|
}
|
|
523
517
|
}
|
|
524
518
|
export {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
519
|
+
u as BaseAnalyticsProvider,
|
|
520
|
+
w as BentoClientProvider,
|
|
521
|
+
m as PirschClientProvider,
|
|
522
|
+
z as PostHogClientProvider,
|
|
523
|
+
v as ProxyProvider
|
|
530
524
|
};
|
package/dist/providers/server.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { B as
|
|
5
|
-
import { P } from "../server-DjEk1fUD.js";
|
|
6
|
-
class
|
|
1
|
+
var j = Object.defineProperty;
|
|
2
|
+
var q = (d, h, i) => h in d ? j(d, h, { enumerable: !0, configurable: !0, writable: !0, value: i }) : d[h] = i;
|
|
3
|
+
var g = (d, h, i) => q(d, typeof h != "symbol" ? h + "" : h, i);
|
|
4
|
+
import { B as V } from "../base.provider-AfFL5W_P.js";
|
|
5
|
+
import { P as Q } from "../server-DjEk1fUD.js";
|
|
6
|
+
class M extends V {
|
|
7
7
|
constructor(i) {
|
|
8
8
|
super({ debug: i.debug, enabled: i.enabled });
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
g(this, "name", "Bento-Server");
|
|
10
|
+
g(this, "client");
|
|
11
|
+
g(this, "initialized", !1);
|
|
12
|
+
g(this, "config");
|
|
13
|
+
g(this, "currentUserEmail");
|
|
14
14
|
this.config = i;
|
|
15
15
|
}
|
|
16
16
|
async initialize() {
|
|
@@ -23,8 +23,8 @@ class w extends c {
|
|
|
23
23
|
if (!((e = this.config.authentication) != null && e.secretKey) || typeof this.config.authentication.secretKey != "string")
|
|
24
24
|
throw new Error("Bento requires authentication.secretKey");
|
|
25
25
|
try {
|
|
26
|
-
const { Analytics: r } = await import("../bento-node-sdk.esm-CWEAoj97.js"), { debug:
|
|
27
|
-
this.client = new r(
|
|
26
|
+
const { Analytics: r } = await import("../bento-node-sdk.esm-CWEAoj97.js"), { debug: s, enabled: a, ...u } = this.config;
|
|
27
|
+
this.client = new r(u), this.initialized = !0, this.log("Initialized successfully", {
|
|
28
28
|
siteUuid: this.config.siteUuid
|
|
29
29
|
});
|
|
30
30
|
} catch (r) {
|
|
@@ -43,25 +43,25 @@ class w extends c {
|
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
this.currentUserEmail = r;
|
|
46
|
-
const
|
|
47
|
-
delete
|
|
46
|
+
const s = e ? { ...e } : {};
|
|
47
|
+
delete s.email, this.client.V1.addSubscriber({
|
|
48
48
|
email: r,
|
|
49
|
-
fields:
|
|
49
|
+
fields: s
|
|
50
50
|
}).catch((a) => {
|
|
51
51
|
console.error("[Bento-Server] Failed to identify user:", a);
|
|
52
52
|
}), this.log("Identified user", { userId: i, email: r, traits: e });
|
|
53
53
|
}
|
|
54
54
|
async track(i, e) {
|
|
55
|
-
var
|
|
55
|
+
var u, l, p, n;
|
|
56
56
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
57
|
-
const r = ((
|
|
57
|
+
const r = ((u = e == null ? void 0 : e.user) == null ? void 0 : u.email) || this.currentUserEmail || ((l = e == null ? void 0 : e.user) == null ? void 0 : l.userId) || i.userId;
|
|
58
58
|
if (!r || !r.includes("@")) {
|
|
59
59
|
console.warn(
|
|
60
60
|
"[Bento-Server] Skipping event - Bento requires an email address. Anonymous events are not currently supported by the Bento Node SDK. For now, use the Bento client provider for anonymous tracking. If you're using a proxy, use the hybrid pattern as described in the docs. For identified users, call identify() with a valid email before tracking events."
|
|
61
61
|
);
|
|
62
62
|
return;
|
|
63
63
|
}
|
|
64
|
-
const
|
|
64
|
+
const s = {
|
|
65
65
|
...i.properties,
|
|
66
66
|
category: i.category,
|
|
67
67
|
timestamp: i.timestamp || Date.now(),
|
|
@@ -80,30 +80,30 @@ class w extends c {
|
|
|
80
80
|
...(e == null ? void 0 : e.device) && { device: e.device },
|
|
81
81
|
...(e == null ? void 0 : e.utm) && { utm: e.utm },
|
|
82
82
|
site: this.config.siteUuid,
|
|
83
|
-
...((
|
|
84
|
-
}, a = ((
|
|
83
|
+
...((p = e == null ? void 0 : e.user) == null ? void 0 : p.userId) && { visitor: e.user.userId }
|
|
84
|
+
}, a = ((n = e == null ? void 0 : e.user) == null ? void 0 : n.traits) || {};
|
|
85
85
|
try {
|
|
86
86
|
await this.client.V1.track({
|
|
87
87
|
email: r,
|
|
88
88
|
type: `$${i.action}`,
|
|
89
|
-
details:
|
|
89
|
+
details: s,
|
|
90
90
|
fields: a
|
|
91
91
|
}), this.log("Tracked event", { event: i, context: e });
|
|
92
|
-
} catch (
|
|
93
|
-
console.error("[Bento-Server] Failed to track event:",
|
|
92
|
+
} catch (v) {
|
|
93
|
+
console.error("[Bento-Server] Failed to track event:", v);
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
pageView(i, e) {
|
|
97
|
-
var
|
|
97
|
+
var u, l, p;
|
|
98
98
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
99
|
-
const r = ((
|
|
99
|
+
const r = ((u = e == null ? void 0 : e.user) == null ? void 0 : u.email) || this.currentUserEmail;
|
|
100
100
|
if (!r || !r.includes("@")) {
|
|
101
101
|
console.warn(
|
|
102
102
|
"[Bento-Server] Skipping pageView - Bento requires an email address. Anonymous events are not currently supported by the Bento Node SDK. For now, use the Bento client provider for anonymous tracking. If you're using a proxy, use the hybrid pattern as described in the docs. For identified users, call identify() with a valid email before tracking events."
|
|
103
103
|
);
|
|
104
104
|
return;
|
|
105
105
|
}
|
|
106
|
-
const
|
|
106
|
+
const s = {
|
|
107
107
|
...i,
|
|
108
108
|
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
109
109
|
...(e == null ? void 0 : e.page) && {
|
|
@@ -118,15 +118,15 @@ class w extends c {
|
|
|
118
118
|
}
|
|
119
119
|
},
|
|
120
120
|
site: this.config.siteUuid,
|
|
121
|
-
...((
|
|
122
|
-
}, a = ((
|
|
121
|
+
...((l = e == null ? void 0 : e.user) == null ? void 0 : l.userId) && { visitor: e.user.userId }
|
|
122
|
+
}, a = ((p = e == null ? void 0 : e.user) == null ? void 0 : p.traits) || {};
|
|
123
123
|
this.client.V1.track({
|
|
124
124
|
email: r,
|
|
125
125
|
type: "$view",
|
|
126
|
-
details:
|
|
126
|
+
details: s,
|
|
127
127
|
fields: a
|
|
128
|
-
}).catch((
|
|
129
|
-
console.error("[Bento-Server] Failed to track page view:",
|
|
128
|
+
}).catch((n) => {
|
|
129
|
+
console.error("[Bento-Server] Failed to track page view:", n);
|
|
130
130
|
}), this.log("Tracked page view", { properties: i, context: e });
|
|
131
131
|
}
|
|
132
132
|
async reset() {
|
|
@@ -136,13 +136,13 @@ class w extends c {
|
|
|
136
136
|
this.client = void 0, this.initialized = !1, this.log("Shutdown complete");
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
|
-
class
|
|
139
|
+
class N extends V {
|
|
140
140
|
constructor(i) {
|
|
141
141
|
super({ debug: i.debug, enabled: i.enabled });
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
142
|
+
g(this, "name", "Pirsch-Server");
|
|
143
|
+
g(this, "client");
|
|
144
|
+
g(this, "initialized", !1);
|
|
145
|
+
g(this, "config");
|
|
146
146
|
this.config = i;
|
|
147
147
|
}
|
|
148
148
|
async initialize() {
|
|
@@ -152,8 +152,8 @@ class k extends c {
|
|
|
152
152
|
if (!this.config.clientSecret || typeof this.config.clientSecret != "string")
|
|
153
153
|
throw new Error("Pirsch requires a clientSecret (or access key)");
|
|
154
154
|
try {
|
|
155
|
-
const { Pirsch: i } = await import("../index-zS7gy63J.js").then((a) => a.i), { debug: e, enabled: r, ...
|
|
156
|
-
this.client = new i(
|
|
155
|
+
const { Pirsch: i } = await import("../index-zS7gy63J.js").then((a) => a.i), { debug: e, enabled: r, ...s } = this.config;
|
|
156
|
+
this.client = new i(s), this.initialized = !0, this.log("Initialized successfully", {
|
|
157
157
|
hostname: this.config.hostname
|
|
158
158
|
});
|
|
159
159
|
} catch (i) {
|
|
@@ -170,7 +170,7 @@ class k extends c {
|
|
|
170
170
|
url: "https://identify",
|
|
171
171
|
ip: "0.0.0.0",
|
|
172
172
|
user_agent: "analytics-library"
|
|
173
|
-
},
|
|
173
|
+
}, s = {
|
|
174
174
|
userId: i,
|
|
175
175
|
...e && Object.fromEntries(
|
|
176
176
|
Object.entries(e).filter(
|
|
@@ -178,60 +178,70 @@ class k extends c {
|
|
|
178
178
|
)
|
|
179
179
|
)
|
|
180
180
|
};
|
|
181
|
-
this.client.event("user_identified", r, 0,
|
|
181
|
+
this.client.event("user_identified", r, 0, s).catch((a) => {
|
|
182
182
|
console.error("[Pirsch-Server] Failed to track identify event:", a);
|
|
183
183
|
}), this.log("Identified user via event", { userId: i, traits: e });
|
|
184
184
|
}
|
|
185
185
|
async track(i, e) {
|
|
186
|
-
var o,
|
|
186
|
+
var v, f, y, t, w, m, b, c, k, S, _, E, I, z, P, B, F, o, $, A, K, O;
|
|
187
187
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
188
|
-
const r = {
|
|
189
|
-
url: ((
|
|
190
|
-
ip:
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
...((
|
|
195
|
-
...((
|
|
196
|
-
|
|
188
|
+
const r = e, s = ((v = r == null ? void 0 : r.device) == null ? void 0 : v.ip) || "0.0.0.0", a = ((f = r == null ? void 0 : r.server) == null ? void 0 : f.userAgent) || ((y = r == null ? void 0 : r.device) == null ? void 0 : y.userAgent) || "unknown", l = {
|
|
189
|
+
url: ((t = e == null ? void 0 : e.page) == null ? void 0 : t.url) || ((w = e == null ? void 0 : e.page) != null && w.protocol && ((m = e == null ? void 0 : e.page) != null && m.host) && ((b = e == null ? void 0 : e.page) != null && b.path) ? `${e.page.protocol}://${e.page.host}${e.page.path}` : (c = e == null ? void 0 : e.page) != null && c.path ? `https://${this.config.hostname}${e.page.path}` : "https://event"),
|
|
190
|
+
ip: s,
|
|
191
|
+
user_agent: a,
|
|
192
|
+
...((k = e == null ? void 0 : e.page) == null ? void 0 : k.title) && { title: e.page.title },
|
|
193
|
+
...((S = e == null ? void 0 : e.page) == null ? void 0 : S.referrer) && { referrer: e.page.referrer },
|
|
194
|
+
...((E = (_ = e == null ? void 0 : e.device) == null ? void 0 : _.screen) == null ? void 0 : E.width) && { screen_width: e.device.screen.width },
|
|
195
|
+
...((z = (I = e == null ? void 0 : e.device) == null ? void 0 : I.screen) == null ? void 0 : z.height) && { screen_height: e.device.screen.height },
|
|
196
|
+
...((B = (P = e == null ? void 0 : e.device) == null ? void 0 : P.viewport) == null ? void 0 : B.width) && { sec_ch_viewport_width: String(e.device.viewport.width) },
|
|
197
|
+
...((F = e == null ? void 0 : e.device) == null ? void 0 : F.language) && { accept_language: e.device.language },
|
|
198
|
+
...((o = e == null ? void 0 : e.device) == null ? void 0 : o.type) && { sec_ch_ua_mobile: e.device.type === "mobile" || e.device.type === "tablet" ? "?1" : "?0" },
|
|
199
|
+
...(($ = e == null ? void 0 : e.device) == null ? void 0 : $.os) && { sec_ch_ua_platform: e.device.os }
|
|
200
|
+
}, n = {
|
|
197
201
|
...Object.fromEntries(
|
|
198
202
|
Object.entries(i.properties).filter(
|
|
199
|
-
([,
|
|
203
|
+
([, U]) => typeof U == "string" || typeof U == "number" || typeof U == "boolean"
|
|
200
204
|
)
|
|
201
205
|
),
|
|
202
206
|
category: i.category,
|
|
203
207
|
timestamp: String(i.timestamp || Date.now()),
|
|
204
208
|
...i.userId && { userId: i.userId },
|
|
205
209
|
...i.sessionId && { sessionId: i.sessionId },
|
|
206
|
-
...((
|
|
210
|
+
...((A = e == null ? void 0 : e.user) == null ? void 0 : A.email) && { user_email: e.user.email },
|
|
211
|
+
...((K = e == null ? void 0 : e.device) == null ? void 0 : K.timezone) && { timezone: e.device.timezone },
|
|
212
|
+
...((O = e == null ? void 0 : e.device) == null ? void 0 : O.browser) && { browser: e.device.browser }
|
|
207
213
|
};
|
|
208
214
|
try {
|
|
209
|
-
await this.client.event(i.action,
|
|
210
|
-
} catch (
|
|
211
|
-
console.error("[Pirsch-Server] Failed to track event:",
|
|
215
|
+
await this.client.event(i.action, l, 0, n), this.log("Tracked event", { event: i, context: e });
|
|
216
|
+
} catch (U) {
|
|
217
|
+
console.error("[Pirsch-Server] Failed to track event:", U);
|
|
212
218
|
}
|
|
213
219
|
}
|
|
214
220
|
pageView(i, e) {
|
|
215
|
-
var t,
|
|
221
|
+
var p, n, v, f, y, t, w, m, b, c, k, S, _, E, I, z, P, B, F;
|
|
216
222
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
217
|
-
const r = {
|
|
218
|
-
url: ((
|
|
219
|
-
ip:
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
...((
|
|
224
|
-
...((
|
|
223
|
+
const r = e, s = ((p = r == null ? void 0 : r.device) == null ? void 0 : p.ip) || "0.0.0.0", a = ((n = r == null ? void 0 : r.server) == null ? void 0 : n.userAgent) || ((v = r == null ? void 0 : r.device) == null ? void 0 : v.userAgent) || "unknown", l = {
|
|
224
|
+
url: ((f = e == null ? void 0 : e.page) == null ? void 0 : f.url) || ((y = e == null ? void 0 : e.page) != null && y.protocol && ((t = e == null ? void 0 : e.page) != null && t.host) && ((w = e == null ? void 0 : e.page) != null && w.path) ? `${e.page.protocol}://${e.page.host}${e.page.path}` : (m = e == null ? void 0 : e.page) != null && m.path ? `https://${this.config.hostname}${e.page.path}` : "https://pageview"),
|
|
225
|
+
ip: s,
|
|
226
|
+
user_agent: a,
|
|
227
|
+
...((b = e == null ? void 0 : e.page) == null ? void 0 : b.title) && { title: e.page.title },
|
|
228
|
+
...((c = e == null ? void 0 : e.page) == null ? void 0 : c.referrer) && { referrer: e.page.referrer },
|
|
229
|
+
...((S = (k = e == null ? void 0 : e.device) == null ? void 0 : k.screen) == null ? void 0 : S.width) && { screen_width: e.device.screen.width },
|
|
230
|
+
...((E = (_ = e == null ? void 0 : e.device) == null ? void 0 : _.screen) == null ? void 0 : E.height) && { screen_height: e.device.screen.height },
|
|
231
|
+
...((z = (I = e == null ? void 0 : e.device) == null ? void 0 : I.viewport) == null ? void 0 : z.width) && { sec_ch_viewport_width: String(e.device.viewport.width) },
|
|
232
|
+
...((P = e == null ? void 0 : e.device) == null ? void 0 : P.language) && { accept_language: e.device.language },
|
|
233
|
+
...((B = e == null ? void 0 : e.device) == null ? void 0 : B.type) && { sec_ch_ua_mobile: e.device.type === "mobile" || e.device.type === "tablet" ? "?1" : "?0" },
|
|
234
|
+
...((F = e == null ? void 0 : e.device) == null ? void 0 : F.os) && { sec_ch_ua_platform: e.device.os },
|
|
225
235
|
...i && {
|
|
226
236
|
tags: Object.fromEntries(
|
|
227
237
|
Object.entries(i).filter(
|
|
228
|
-
([,
|
|
238
|
+
([, o]) => typeof o == "string" || typeof o == "number" || typeof o == "boolean"
|
|
229
239
|
)
|
|
230
240
|
)
|
|
231
241
|
}
|
|
232
242
|
};
|
|
233
|
-
this.client.hit(
|
|
234
|
-
console.error("[Pirsch-Server] Failed to track page view:",
|
|
243
|
+
this.client.hit(l).catch((o) => {
|
|
244
|
+
console.error("[Pirsch-Server] Failed to track page view:", o);
|
|
235
245
|
}), this.log("Tracked page view", { properties: i, context: e });
|
|
236
246
|
}
|
|
237
247
|
async reset() {
|
|
@@ -249,68 +259,68 @@ class k extends c {
|
|
|
249
259
|
this.client = void 0, this.initialized = !1, this.log("Shutdown complete");
|
|
250
260
|
}
|
|
251
261
|
}
|
|
252
|
-
async function
|
|
262
|
+
async function D(d, h, i) {
|
|
253
263
|
var e, r;
|
|
254
264
|
try {
|
|
255
|
-
const
|
|
256
|
-
if (!
|
|
265
|
+
const s = await d.json();
|
|
266
|
+
if (!s.events || !Array.isArray(s.events))
|
|
257
267
|
throw new Error("Invalid payload: missing events array");
|
|
258
|
-
const a = i != null && i.extractIp ? i.extractIp(
|
|
259
|
-
for (const
|
|
268
|
+
const a = i != null && i.extractIp ? i.extractIp(d) : R(d), u = i != null && i.enrichContext ? i.enrichContext(d) : {};
|
|
269
|
+
for (const l of s.events)
|
|
260
270
|
try {
|
|
261
|
-
switch (
|
|
271
|
+
switch (l.type) {
|
|
262
272
|
case "track": {
|
|
263
|
-
const
|
|
264
|
-
...
|
|
265
|
-
...
|
|
273
|
+
const p = {
|
|
274
|
+
...l.context,
|
|
275
|
+
...u,
|
|
266
276
|
device: {
|
|
267
|
-
...(e =
|
|
277
|
+
...(e = l.context) == null ? void 0 : e.device,
|
|
268
278
|
// Add IP (using type assertion for extended fields)
|
|
269
279
|
// biome-ignore lint/suspicious/noExplicitAny: IP field not in base device type
|
|
270
280
|
...a ? { ip: a } : {}
|
|
271
281
|
}
|
|
272
282
|
};
|
|
273
|
-
await
|
|
274
|
-
userId:
|
|
275
|
-
sessionId:
|
|
283
|
+
await h.track(l.event.action, l.event.properties, {
|
|
284
|
+
userId: l.event.userId,
|
|
285
|
+
sessionId: l.event.sessionId,
|
|
276
286
|
// biome-ignore lint/suspicious/noExplicitAny: Generic context forwarding requires type assertion
|
|
277
|
-
context:
|
|
287
|
+
context: p
|
|
278
288
|
});
|
|
279
289
|
break;
|
|
280
290
|
}
|
|
281
291
|
case "identify": {
|
|
282
|
-
|
|
292
|
+
h.identify(l.userId, l.traits);
|
|
283
293
|
break;
|
|
284
294
|
}
|
|
285
295
|
case "pageView": {
|
|
286
|
-
const
|
|
287
|
-
...
|
|
288
|
-
...
|
|
296
|
+
const p = {
|
|
297
|
+
...l.context,
|
|
298
|
+
...u,
|
|
289
299
|
device: {
|
|
290
|
-
...(r =
|
|
300
|
+
...(r = l.context) == null ? void 0 : r.device,
|
|
291
301
|
// biome-ignore lint/suspicious/noExplicitAny: IP field not in base device type
|
|
292
302
|
// Add IP (using type assertion for extended fields)
|
|
293
303
|
...a ? { ip: a } : {}
|
|
294
304
|
}
|
|
295
305
|
};
|
|
296
|
-
|
|
306
|
+
h.pageView(l.properties, p);
|
|
297
307
|
break;
|
|
298
308
|
}
|
|
299
309
|
case "reset":
|
|
300
310
|
break;
|
|
301
311
|
default:
|
|
302
|
-
console.warn("[Proxy] Unknown event type:",
|
|
312
|
+
console.warn("[Proxy] Unknown event type:", l);
|
|
303
313
|
}
|
|
304
|
-
} catch (
|
|
305
|
-
i != null && i.onError ? i.onError(
|
|
314
|
+
} catch (p) {
|
|
315
|
+
i != null && i.onError ? i.onError(p) : console.error("[Proxy] Failed to process event:", p);
|
|
306
316
|
}
|
|
307
|
-
} catch (
|
|
308
|
-
throw i != null && i.onError ? i.onError(
|
|
317
|
+
} catch (s) {
|
|
318
|
+
throw i != null && i.onError ? i.onError(s) : console.error("[Proxy] Failed to ingest events:", s), s;
|
|
309
319
|
}
|
|
310
320
|
}
|
|
311
|
-
function
|
|
321
|
+
function R(d) {
|
|
312
322
|
var i;
|
|
313
|
-
const
|
|
323
|
+
const h = [
|
|
314
324
|
"x-forwarded-for",
|
|
315
325
|
"x-real-ip",
|
|
316
326
|
"cf-connecting-ip",
|
|
@@ -318,26 +328,26 @@ function b(l) {
|
|
|
318
328
|
"x-client-ip",
|
|
319
329
|
"x-cluster-client-ip"
|
|
320
330
|
];
|
|
321
|
-
for (const e of
|
|
322
|
-
const r =
|
|
331
|
+
for (const e of h) {
|
|
332
|
+
const r = d.headers.get(e);
|
|
323
333
|
if (r)
|
|
324
334
|
return (i = r.split(",")[0]) == null ? void 0 : i.trim();
|
|
325
335
|
}
|
|
326
336
|
}
|
|
327
|
-
function
|
|
337
|
+
function G(d, h) {
|
|
328
338
|
return async (i) => {
|
|
329
339
|
try {
|
|
330
|
-
return await
|
|
340
|
+
return await D(i, d, h), new Response("OK", { status: 200 });
|
|
331
341
|
} catch (e) {
|
|
332
342
|
return console.error("[Proxy] Handler error:", e), new Response("Internal Server Error", { status: 500 });
|
|
333
343
|
}
|
|
334
344
|
};
|
|
335
345
|
}
|
|
336
346
|
export {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
347
|
+
V as BaseAnalyticsProvider,
|
|
348
|
+
M as BentoServerProvider,
|
|
349
|
+
N as PirschServerProvider,
|
|
350
|
+
Q as PostHogServerProvider,
|
|
351
|
+
G as createProxyHandler,
|
|
352
|
+
D as ingestProxyEvents
|
|
343
353
|
};
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -2,38 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
A highly typed, zero-dependency, provider-agnostic analytics library for TypeScript applications. Works seamlessly on both client and server sides with full type safety for your custom events.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- [
|
|
10
|
-
- [Quick Start](
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- [3. Server-Side Usage](#3-server-side-usage)
|
|
14
|
-
- [Async Tracking](#async-tracking-when-to-await-vs-fire-and-forget)
|
|
15
|
-
- [Fire-and-forget (Client-side typical usage)](#fire-and-forget-client-side-typical-usage)
|
|
16
|
-
- [Await for critical events (Server-side typical usage)](#await-for-critical-events-server-side-typical-usage)
|
|
17
|
-
- [Error handling](#error-handling)
|
|
18
|
-
- [Best practices](#best-practices)
|
|
19
|
-
- [A complete example](#a-complete-example)
|
|
20
|
-
- [Advanced Usage](#advanced-usage)
|
|
21
|
-
- [Creating a Typed Analytics Service](#creating-a-typed-analytics-service)
|
|
22
|
-
- [Event Categories](#event-categories)
|
|
23
|
-
- [Adding Custom Providers](#adding-custom-providers)
|
|
24
|
-
- [Client-Only and Server-Only Providers](#client-only-and-server-only-providers)
|
|
25
|
-
- [Using Multiple Providers](#using-multiple-providers)
|
|
26
|
-
- [Server Deployments and waitUntil](#server-deployments-and-waituntil)
|
|
27
|
-
- [Vercel Functions](#vercel-functions)
|
|
28
|
-
- [Cloudflare Workers](#cloudflare-workers)
|
|
29
|
-
- [Netlify Functions](#netlify-functions)
|
|
30
|
-
- [API Reference](#api-reference)
|
|
31
|
-
- [Client API](#client-api)
|
|
32
|
-
- [Server API](#server-api)
|
|
33
|
-
- [Type Helpers](#type-helpers)
|
|
34
|
-
- [Best Practices](#best-practices)
|
|
35
|
-
- [Contributing](#contributing)
|
|
36
|
-
- [License](#license)
|
|
5
|
+
> **📚 [Full Documentation](https://stacksee-analytics.vercel.app)** - For complete guides, examples, and API reference, visit our documentation site.
|
|
6
|
+
|
|
7
|
+
## Quick Links
|
|
8
|
+
|
|
9
|
+
- 📖 [Documentation](https://stacksee-analytics.vercel.app)
|
|
10
|
+
- 🚀 [Quick Start](https://stacksee-analytics.vercel.app/docs/quick-start)
|
|
11
|
+
- 🔌 [Providers](https://stacksee-analytics.vercel.app/docs/providers)
|
|
12
|
+
- 💡 [Core Concepts](https://stacksee-analytics.vercel.app/docs/core-concepts)
|
|
37
13
|
|
|
38
14
|
## Features
|
|
39
15
|
|
|
@@ -53,15 +29,15 @@ The library includes built-in support for popular analytics services, with more
|
|
|
53
29
|
|
|
54
30
|
| Provider | Type | Documentation |
|
|
55
31
|
|----------|------|---------------|
|
|
56
|
-
| **PostHog** | Product Analytics | [
|
|
57
|
-
| **Bento** | Email Marketing & Events | [
|
|
58
|
-
| **Pirsch** | Privacy-Focused Web Analytics | [
|
|
32
|
+
| **PostHog** | Product Analytics | [View Docs](https://stacksee-analytics.vercel.app/docs/providers/posthog) |
|
|
33
|
+
| **Bento** | Email Marketing & Events | [View Docs](https://stacksee-analytics.vercel.app/docs/providers/bento) |
|
|
34
|
+
| **Pirsch** | Privacy-Focused Web Analytics | [View Docs](https://stacksee-analytics.vercel.app/docs/providers/pirsch) |
|
|
59
35
|
|
|
60
36
|
### Community & Custom Providers
|
|
61
37
|
|
|
62
38
|
Want to use a different analytics service? Check out our guide:
|
|
63
39
|
|
|
64
|
-
**[Creating Custom Providers →](
|
|
40
|
+
**[Creating Custom Providers →](https://stacksee-analytics.vercel.app/docs/providers/custom)**
|
|
65
41
|
|
|
66
42
|
You can easily create providers for:
|
|
67
43
|
- Google Analytics
|
|
@@ -72,7 +48,7 @@ You can easily create providers for:
|
|
|
72
48
|
- Loops
|
|
73
49
|
- Any analytics service with a JavaScript SDK
|
|
74
50
|
|
|
75
|
-
**[View all provider documentation →](
|
|
51
|
+
**[View all provider documentation →](https://stacksee-analytics.vercel.app/docs/providers)**
|
|
76
52
|
|
|
77
53
|
## Installation
|
|
78
54
|
|
|
@@ -89,7 +65,7 @@ pnpm install @bentonow/bento-node-sdk
|
|
|
89
65
|
pnpm install pirsch-sdk
|
|
90
66
|
```
|
|
91
67
|
|
|
92
|
-
> **See also:** [Provider Documentation](
|
|
68
|
+
> **See also:** [Provider Documentation](https://stacksee-analytics.vercel.app/docs/providers) for detailed setup guides for each provider.
|
|
93
69
|
|
|
94
70
|
## Quick Start
|
|
95
71
|
|
|
@@ -745,7 +721,7 @@ export const appEvents = {
|
|
|
745
721
|
|
|
746
722
|
Want to integrate with a different analytics service? See our comprehensive guide:
|
|
747
723
|
|
|
748
|
-
**[Creating Custom Providers →](
|
|
724
|
+
**[Creating Custom Providers →](https://stacksee-analytics.vercel.app/docs/providers/custom)**
|
|
749
725
|
|
|
750
726
|
Quick example:
|
|
751
727
|
|
|
@@ -1064,6 +1040,19 @@ const analytics = createServerAnalytics<AppEvents>({
|
|
|
1064
1040
|
7. **Document events** - Add comments to explain when each event should be fired
|
|
1065
1041
|
8. **Create provider instances once** - Reuse provider instances across your app
|
|
1066
1042
|
|
|
1043
|
+
---
|
|
1044
|
+
|
|
1045
|
+
## Learn More
|
|
1046
|
+
|
|
1047
|
+
This README provides a quick overview. For comprehensive documentation, guides, and examples:
|
|
1048
|
+
|
|
1049
|
+
**📚 [Visit the Full Documentation](https://stacksee-analytics.vercel.app)**
|
|
1050
|
+
|
|
1051
|
+
- [Quick Start Guide](https://stacksee-analytics.vercel.app/docs/quick-start)
|
|
1052
|
+
- [Core Concepts](https://stacksee-analytics.vercel.app/docs/core-concepts)
|
|
1053
|
+
- [Provider Setup Guides](https://stacksee-analytics.vercel.app/docs/providers)
|
|
1054
|
+
- [API Reference](https://stacksee-analytics.vercel.app/docs/api-reference)
|
|
1055
|
+
|
|
1067
1056
|
## Contributing
|
|
1068
1057
|
|
|
1069
1058
|
Contributions are welcome! Please read our contributing guidelines before submitting PRs.
|