@stacksee/analytics 0.9.2 → 0.9.5
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 +4 -0
- package/dist/providers/client.js +213 -196
- package/dist/providers/server.js +150 -121
- package/package.json +1 -1
- package/readme.md +28 -39
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,96 +24,119 @@ class b extends d {
|
|
|
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
|
-
const
|
|
41
|
-
|
|
42
|
-
this.scriptLoaded = !0,
|
|
43
|
-
},
|
|
44
|
-
|
|
45
|
-
}, document.head.appendChild(
|
|
40
|
+
const t = document.createElement("script");
|
|
41
|
+
t.src = `https://fast.bentonow.com?site_uuid=${this.config.siteUuid}`, t.async = !0, t.defer = !0, t.onload = () => {
|
|
42
|
+
this.scriptLoaded = !0, e();
|
|
43
|
+
}, t.onerror = () => {
|
|
44
|
+
i(new Error("Failed to load Bento script"));
|
|
45
|
+
}, document.head.appendChild(t);
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
|
-
async waitForBento(
|
|
49
|
-
for (let
|
|
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((
|
|
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
|
|
59
|
-
if (this.bento.identify(
|
|
60
|
-
const
|
|
61
|
-
delete
|
|
58
|
+
const s = (i == null ? void 0 : i.email) || e;
|
|
59
|
+
if (this.bento.identify(s), i) {
|
|
60
|
+
const t = { ...i };
|
|
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
|
|
65
|
+
track(e, i) {
|
|
66
|
+
var t, n, l;
|
|
67
67
|
if (!this.isEnabled() || !this.initialized || !this.bento) return;
|
|
68
|
-
const
|
|
69
|
-
...
|
|
70
|
-
category:
|
|
71
|
-
timestamp:
|
|
72
|
-
...
|
|
73
|
-
...
|
|
74
|
-
...(
|
|
68
|
+
const s = {
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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 }
|
|
79
83
|
}
|
|
80
84
|
},
|
|
81
|
-
...(
|
|
82
|
-
...(
|
|
85
|
+
...(i == null ? void 0 : i.device) && { device: i.device },
|
|
86
|
+
...(i == null ? void 0 : i.utm) && { utm: i.utm },
|
|
83
87
|
// Include user email and traits as regular event properties
|
|
84
|
-
...((
|
|
85
|
-
...((n =
|
|
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 }
|
|
86
91
|
};
|
|
87
|
-
this.bento.track(
|
|
92
|
+
this.bento.track(e.action, s), this.log("Tracked event", { event: e, context: i });
|
|
88
93
|
}
|
|
89
|
-
pageView(
|
|
94
|
+
pageView(e, i) {
|
|
95
|
+
var s;
|
|
90
96
|
if (!(!this.isEnabled() || !this.initialized || !this.bento || !a())) {
|
|
91
|
-
if (this.bento.view(),
|
|
97
|
+
if (this.bento.view(), e || i != null && i.page) {
|
|
92
98
|
const t = {
|
|
93
|
-
...
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
...e,
|
|
100
|
+
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
101
|
+
...(i == null ? void 0 : i.page) && {
|
|
102
|
+
page: {
|
|
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
|
+
}
|
|
111
|
+
},
|
|
112
|
+
...((s = i == null ? void 0 : i.user) == null ? void 0 : s.userId) && { visitor: i.user.userId }
|
|
99
113
|
};
|
|
100
114
|
this.bento.track("$view", t);
|
|
101
115
|
}
|
|
102
|
-
this.log("Tracked page view", { properties:
|
|
116
|
+
this.log("Tracked page view", { properties: e, context: i });
|
|
103
117
|
}
|
|
104
118
|
}
|
|
105
|
-
pageLeave(
|
|
119
|
+
pageLeave(e, i) {
|
|
120
|
+
var t;
|
|
106
121
|
if (!this.isEnabled() || !this.initialized || !this.bento || !a())
|
|
107
122
|
return;
|
|
108
|
-
const
|
|
109
|
-
...
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
123
|
+
const s = {
|
|
124
|
+
...e,
|
|
125
|
+
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
126
|
+
...(i == null ? void 0 : i.page) && {
|
|
127
|
+
page: {
|
|
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
|
+
}
|
|
136
|
+
},
|
|
137
|
+
...((t = i == null ? void 0 : i.user) == null ? void 0 : t.userId) && { visitor: i.user.userId }
|
|
115
138
|
};
|
|
116
|
-
this.bento.track("$pageleave",
|
|
139
|
+
this.bento.track("$pageleave", s), this.log("Tracked page leave", { properties: e, context: i });
|
|
117
140
|
}
|
|
118
141
|
reset() {
|
|
119
142
|
!this.isEnabled() || !this.initialized || !this.bento || !a() || this.log("Reset user session - Note: Bento doesn't have a native reset method");
|
|
@@ -130,8 +153,8 @@ class b extends d {
|
|
|
130
153
|
* bentoProvider.tag('beta_tester');
|
|
131
154
|
* ```
|
|
132
155
|
*/
|
|
133
|
-
tag(
|
|
134
|
-
!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 }));
|
|
135
158
|
}
|
|
136
159
|
/**
|
|
137
160
|
* Get the current user's email address
|
|
@@ -183,8 +206,8 @@ class b extends d {
|
|
|
183
206
|
* }
|
|
184
207
|
* ```
|
|
185
208
|
*/
|
|
186
|
-
showSurveyForm(
|
|
187
|
-
!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 }));
|
|
188
211
|
}
|
|
189
212
|
/**
|
|
190
213
|
* Validate an email address using Bento's spam check
|
|
@@ -200,14 +223,14 @@ class b extends d {
|
|
|
200
223
|
* }
|
|
201
224
|
* ```
|
|
202
225
|
*/
|
|
203
|
-
async spamCheck(
|
|
226
|
+
async spamCheck(e) {
|
|
204
227
|
if (!this.isEnabled() || !this.initialized || !this.bento || !a())
|
|
205
228
|
return !1;
|
|
206
229
|
try {
|
|
207
|
-
const
|
|
208
|
-
return this.log("Spam check completed", { email:
|
|
209
|
-
} catch (
|
|
210
|
-
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;
|
|
211
234
|
}
|
|
212
235
|
}
|
|
213
236
|
// ============================================================================
|
|
@@ -253,14 +276,14 @@ class b extends d {
|
|
|
253
276
|
));
|
|
254
277
|
}
|
|
255
278
|
}
|
|
256
|
-
class
|
|
257
|
-
constructor(
|
|
258
|
-
super({ debug:
|
|
279
|
+
class m extends u {
|
|
280
|
+
constructor(e) {
|
|
281
|
+
super({ debug: e.debug, enabled: e.enabled });
|
|
259
282
|
r(this, "name", "Pirsch-Client");
|
|
260
283
|
r(this, "client");
|
|
261
284
|
r(this, "initialized", !1);
|
|
262
285
|
r(this, "config");
|
|
263
|
-
this.config =
|
|
286
|
+
this.config = e;
|
|
264
287
|
}
|
|
265
288
|
async initialize() {
|
|
266
289
|
if (this.isEnabled() && !this.initialized) {
|
|
@@ -271,98 +294,92 @@ class w extends d {
|
|
|
271
294
|
if (!this.config.identificationCode || typeof this.config.identificationCode != "string")
|
|
272
295
|
throw new Error("Pirsch requires an identificationCode");
|
|
273
296
|
try {
|
|
274
|
-
const { Pirsch:
|
|
275
|
-
this.client = new
|
|
297
|
+
const { Pirsch: e } = await import("../web-imCcOhDC.js").then((i) => i.w);
|
|
298
|
+
this.client = new e({
|
|
276
299
|
identificationCode: this.config.identificationCode,
|
|
277
300
|
...this.config.hostname && { hostname: this.config.hostname }
|
|
278
301
|
}), this.initialized = !0, this.log("Initialized successfully", this.config);
|
|
279
|
-
} catch (
|
|
302
|
+
} catch (e) {
|
|
280
303
|
throw console.error(
|
|
281
304
|
"[Pirsch-Client] Failed to initialize. Make sure pirsch-sdk is installed:",
|
|
282
|
-
|
|
283
|
-
),
|
|
305
|
+
e
|
|
306
|
+
), e;
|
|
284
307
|
}
|
|
285
308
|
}
|
|
286
309
|
}
|
|
287
|
-
identify(
|
|
310
|
+
identify(e, i) {
|
|
288
311
|
!this.isEnabled() || !this.initialized || !this.client || (this.client.event("user_identified", 0, {
|
|
289
|
-
userId:
|
|
290
|
-
...
|
|
291
|
-
}).catch((
|
|
292
|
-
console.error("[Pirsch-Client] Failed to track identify event:",
|
|
293
|
-
}), this.log("Identified user via event", { userId:
|
|
294
|
-
}
|
|
295
|
-
async track(
|
|
296
|
-
var
|
|
312
|
+
userId: e,
|
|
313
|
+
...i
|
|
314
|
+
}).catch((s) => {
|
|
315
|
+
console.error("[Pirsch-Client] Failed to track identify event:", s);
|
|
316
|
+
}), this.log("Identified user via event", { userId: e, traits: i }));
|
|
317
|
+
}
|
|
318
|
+
async track(e, i) {
|
|
319
|
+
var t, n;
|
|
297
320
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
298
|
-
const
|
|
299
|
-
...
|
|
300
|
-
category:
|
|
301
|
-
...
|
|
302
|
-
...
|
|
303
|
-
...(
|
|
304
|
-
page_path:
|
|
305
|
-
page_title:
|
|
306
|
-
page_referrer:
|
|
321
|
+
const s = {
|
|
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
|
|
307
330
|
},
|
|
308
|
-
...(
|
|
309
|
-
...(
|
|
310
|
-
...((
|
|
311
|
-
...((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 }
|
|
312
335
|
};
|
|
313
336
|
try {
|
|
314
|
-
await this.client.event(
|
|
315
|
-
} catch (
|
|
316
|
-
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);
|
|
317
340
|
}
|
|
318
341
|
}
|
|
319
|
-
pageView(
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
this.log("Tracked page view", { properties: i, context: e });
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
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) {
|
|
343
360
|
if (!this.isEnabled() || !this.initialized || !this.client || !a())
|
|
344
361
|
return;
|
|
345
|
-
const
|
|
346
|
-
...
|
|
347
|
-
...(
|
|
348
|
-
path:
|
|
349
|
-
title:
|
|
362
|
+
const s = {
|
|
363
|
+
...e,
|
|
364
|
+
...(i == null ? void 0 : i.page) && {
|
|
365
|
+
path: i.page.path,
|
|
366
|
+
title: i.page.title
|
|
350
367
|
}
|
|
351
368
|
};
|
|
352
|
-
this.client.event("page_leave", 0,
|
|
353
|
-
console.error("[Pirsch-Client] Failed to track page leave:",
|
|
354
|
-
}), this.log("Tracked page leave", { properties:
|
|
369
|
+
this.client.event("page_leave", 0, s).catch((t) => {
|
|
370
|
+
console.error("[Pirsch-Client] Failed to track page leave:", t);
|
|
371
|
+
}), this.log("Tracked page leave", { properties: e, context: i });
|
|
355
372
|
}
|
|
356
373
|
reset() {
|
|
357
|
-
!this.isEnabled() || !this.initialized || !this.client || !a() || (this.client.event("session_reset", 0, {}).catch((
|
|
358
|
-
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);
|
|
359
376
|
}), this.log("Reset user session"));
|
|
360
377
|
}
|
|
361
378
|
}
|
|
362
|
-
class
|
|
363
|
-
constructor(
|
|
364
|
-
var
|
|
365
|
-
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 });
|
|
366
383
|
r(this, "name", "Proxy");
|
|
367
384
|
r(this, "config");
|
|
368
385
|
r(this, "queue", []);
|
|
@@ -372,7 +389,7 @@ class y extends d {
|
|
|
372
389
|
r(this, "retryAttempts");
|
|
373
390
|
r(this, "retryBackoff");
|
|
374
391
|
r(this, "retryInitialDelay");
|
|
375
|
-
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", () => {
|
|
376
393
|
this.flush(!0);
|
|
377
394
|
}), document.addEventListener("visibilitychange", () => {
|
|
378
395
|
document.visibilityState === "hidden" && this.flush(!0);
|
|
@@ -381,26 +398,26 @@ class y extends d {
|
|
|
381
398
|
async initialize() {
|
|
382
399
|
this.isEnabled() && this.log("Initialized successfully", { endpoint: this.config.endpoint });
|
|
383
400
|
}
|
|
384
|
-
identify(
|
|
401
|
+
identify(e, i) {
|
|
385
402
|
this.isEnabled() && (this.queueEvent({
|
|
386
403
|
type: "identify",
|
|
387
|
-
userId:
|
|
388
|
-
traits:
|
|
389
|
-
}), this.log("Queued identify event", { userId:
|
|
404
|
+
userId: e,
|
|
405
|
+
traits: i
|
|
406
|
+
}), this.log("Queued identify event", { userId: e, traits: i }));
|
|
390
407
|
}
|
|
391
|
-
async track(
|
|
408
|
+
async track(e, i) {
|
|
392
409
|
this.isEnabled() && (this.queueEvent({
|
|
393
410
|
type: "track",
|
|
394
|
-
event:
|
|
395
|
-
context: this.enrichContext(
|
|
396
|
-
}), this.log("Queued track event", { event:
|
|
411
|
+
event: e,
|
|
412
|
+
context: this.enrichContext(i)
|
|
413
|
+
}), this.log("Queued track event", { event: e, context: i }));
|
|
397
414
|
}
|
|
398
|
-
pageView(
|
|
415
|
+
pageView(e, i) {
|
|
399
416
|
this.isEnabled() && (this.queueEvent({
|
|
400
417
|
type: "pageView",
|
|
401
|
-
properties:
|
|
402
|
-
context: this.enrichContext(
|
|
403
|
-
}), 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 }));
|
|
404
421
|
}
|
|
405
422
|
async reset() {
|
|
406
423
|
this.isEnabled() && (this.queueEvent({
|
|
@@ -413,76 +430,76 @@ class y extends d {
|
|
|
413
430
|
/**
|
|
414
431
|
* Manually flush all queued events
|
|
415
432
|
*/
|
|
416
|
-
async flush(
|
|
433
|
+
async flush(e = !1) {
|
|
417
434
|
if (this.queue.length === 0) return;
|
|
418
|
-
const
|
|
419
|
-
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);
|
|
420
437
|
}
|
|
421
|
-
queueEvent(
|
|
422
|
-
if (this.queue.push(
|
|
423
|
-
this.flush().catch((
|
|
424
|
-
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);
|
|
425
442
|
});
|
|
426
443
|
return;
|
|
427
444
|
}
|
|
428
445
|
this.flushTimer || (this.flushTimer = setTimeout(() => {
|
|
429
|
-
this.flush().catch((
|
|
430
|
-
console.error("[Proxy] Failed to flush events:",
|
|
446
|
+
this.flush().catch((i) => {
|
|
447
|
+
console.error("[Proxy] Failed to flush events:", i);
|
|
431
448
|
});
|
|
432
449
|
}, this.batchInterval));
|
|
433
450
|
}
|
|
434
|
-
async sendEvents(
|
|
435
|
-
const
|
|
436
|
-
if (
|
|
437
|
-
const
|
|
451
|
+
async sendEvents(e, i = !1) {
|
|
452
|
+
const s = { events: e };
|
|
453
|
+
if (i && typeof navigator < "u" && navigator.sendBeacon) {
|
|
454
|
+
const t = new Blob([JSON.stringify(s)], {
|
|
438
455
|
type: "application/json"
|
|
439
456
|
});
|
|
440
|
-
navigator.sendBeacon(this.config.endpoint,
|
|
457
|
+
navigator.sendBeacon(this.config.endpoint, t) || console.warn("[Proxy] Failed to send events via beacon");
|
|
441
458
|
return;
|
|
442
459
|
}
|
|
443
|
-
await this.sendWithRetry(
|
|
460
|
+
await this.sendWithRetry(s);
|
|
444
461
|
}
|
|
445
|
-
async sendWithRetry(
|
|
462
|
+
async sendWithRetry(e, i = 0) {
|
|
446
463
|
try {
|
|
447
|
-
const
|
|
464
|
+
const s = await fetch(this.config.endpoint, {
|
|
448
465
|
method: "POST",
|
|
449
466
|
headers: {
|
|
450
467
|
"Content-Type": "application/json",
|
|
451
468
|
...this.config.headers
|
|
452
469
|
},
|
|
453
|
-
body: JSON.stringify(
|
|
470
|
+
body: JSON.stringify(e),
|
|
454
471
|
// Don't include credentials by default
|
|
455
472
|
credentials: "same-origin"
|
|
456
473
|
});
|
|
457
|
-
if (!
|
|
458
|
-
throw new Error(`HTTP ${
|
|
459
|
-
this.log(`Sent ${
|
|
460
|
-
} catch (
|
|
461
|
-
if (
|
|
462
|
-
const
|
|
463
|
-
return this.log(`Retry attempt ${
|
|
474
|
+
if (!s.ok)
|
|
475
|
+
throw new Error(`HTTP ${s.status}: ${s.statusText}`);
|
|
476
|
+
this.log(`Sent ${e.events.length} events successfully`);
|
|
477
|
+
} catch (s) {
|
|
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);
|
|
464
481
|
}
|
|
465
|
-
throw console.error("[Proxy] Failed to send events after retries:",
|
|
482
|
+
throw console.error("[Proxy] Failed to send events after retries:", s), s;
|
|
466
483
|
}
|
|
467
484
|
}
|
|
468
|
-
calculateRetryDelay(
|
|
469
|
-
return this.retryBackoff === "exponential" ? this.retryInitialDelay * 2 **
|
|
485
|
+
calculateRetryDelay(e) {
|
|
486
|
+
return this.retryBackoff === "exponential" ? this.retryInitialDelay * 2 ** e : this.retryInitialDelay * (e + 1);
|
|
470
487
|
}
|
|
471
|
-
enrichContext(
|
|
472
|
-
return typeof window > "u" ?
|
|
473
|
-
...
|
|
488
|
+
enrichContext(e) {
|
|
489
|
+
return typeof window > "u" ? e || {} : {
|
|
490
|
+
...e,
|
|
474
491
|
page: {
|
|
475
492
|
path: window.location.pathname,
|
|
476
493
|
title: document.title,
|
|
477
494
|
referrer: document.referrer,
|
|
478
|
-
...
|
|
495
|
+
...e == null ? void 0 : e.page,
|
|
479
496
|
url: window.location.href
|
|
480
497
|
},
|
|
481
498
|
user: {
|
|
482
|
-
...
|
|
499
|
+
...e == null ? void 0 : e.user
|
|
483
500
|
},
|
|
484
501
|
device: {
|
|
485
|
-
...
|
|
502
|
+
...e == null ? void 0 : e.device,
|
|
486
503
|
userAgent: navigator.userAgent,
|
|
487
504
|
language: navigator.language,
|
|
488
505
|
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
@@ -499,9 +516,9 @@ class y extends d {
|
|
|
499
516
|
}
|
|
500
517
|
}
|
|
501
518
|
export {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
519
|
+
u as BaseAnalyticsProvider,
|
|
520
|
+
w as BentoClientProvider,
|
|
521
|
+
m as PirschClientProvider,
|
|
522
|
+
z as PostHogClientProvider,
|
|
523
|
+
v as ProxyProvider
|
|
507
524
|
};
|
package/dist/providers/server.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { B as
|
|
5
|
-
import { P as
|
|
6
|
-
class
|
|
1
|
+
var P = Object.defineProperty;
|
|
2
|
+
var z = (n, t, i) => t in n ? P(n, t, { enumerable: !0, configurable: !0, writable: !0, value: i }) : n[t] = i;
|
|
3
|
+
var p = (n, t, i) => z(n, typeof t != "symbol" ? t + "" : t, i);
|
|
4
|
+
import { B as I } from "../base.provider-AfFL5W_P.js";
|
|
5
|
+
import { P as _ } from "../server-DjEk1fUD.js";
|
|
6
|
+
class A extends I {
|
|
7
7
|
constructor(i) {
|
|
8
8
|
super({ debug: i.debug, enabled: i.enabled });
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
p(this, "name", "Bento-Server");
|
|
10
|
+
p(this, "client");
|
|
11
|
+
p(this, "initialized", !1);
|
|
12
|
+
p(this, "config");
|
|
13
|
+
p(this, "currentUserEmail");
|
|
14
14
|
this.config = i;
|
|
15
15
|
}
|
|
16
16
|
async initialize() {
|
|
@@ -23,77 +23,110 @@ class v extends p {
|
|
|
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:
|
|
27
|
-
this.client = new
|
|
26
|
+
const { Analytics: r } = await import("../bento-node-sdk.esm-CWEAoj97.js"), { debug: s, enabled: a, ...o } = this.config;
|
|
27
|
+
this.client = new r(o), this.initialized = !0, this.log("Initialized successfully", {
|
|
28
28
|
siteUuid: this.config.siteUuid
|
|
29
29
|
});
|
|
30
|
-
} catch (
|
|
30
|
+
} catch (r) {
|
|
31
31
|
throw console.error(
|
|
32
32
|
"[Bento-Server] Failed to initialize. Make sure @bentonow/bento-node-sdk is installed:",
|
|
33
|
-
|
|
34
|
-
),
|
|
33
|
+
r
|
|
34
|
+
), r;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
identify(i, e) {
|
|
39
39
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
const r = (e == null ? void 0 : e.email) || i;
|
|
41
|
+
if (!r || !r.includes("@")) {
|
|
42
|
+
this.log("Skipping identify - invalid or missing email", { userId: i, traits: e });
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
this.currentUserEmail = r;
|
|
46
|
+
const s = e ? { ...e } : {};
|
|
47
|
+
delete s.email, this.client.V1.addSubscriber({
|
|
48
|
+
email: r,
|
|
49
|
+
fields: s
|
|
50
|
+
}).catch((a) => {
|
|
51
|
+
console.error("[Bento-Server] Failed to identify user:", a);
|
|
52
|
+
}), this.log("Identified user", { userId: i, email: r, traits: e });
|
|
49
53
|
}
|
|
50
54
|
async track(i, e) {
|
|
51
|
-
var o,
|
|
55
|
+
var o, l, h, d;
|
|
52
56
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
53
|
-
const
|
|
57
|
+
const r = ((o = e == null ? void 0 : e.user) == null ? void 0 : o.email) || this.currentUserEmail || ((l = e == null ? void 0 : e.user) == null ? void 0 : l.userId) || i.userId;
|
|
58
|
+
if (!r || !r.includes("@")) {
|
|
59
|
+
console.warn(
|
|
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
|
+
);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const s = {
|
|
54
65
|
...i.properties,
|
|
55
66
|
category: i.category,
|
|
56
67
|
timestamp: i.timestamp || Date.now(),
|
|
57
68
|
...i.sessionId && { sessionId: i.sessionId },
|
|
58
69
|
...(e == null ? void 0 : e.page) && {
|
|
59
70
|
page: {
|
|
71
|
+
url: e.page.url,
|
|
72
|
+
host: e.page.host,
|
|
60
73
|
path: e.page.path,
|
|
61
74
|
title: e.page.title,
|
|
62
|
-
|
|
75
|
+
protocol: e.page.protocol,
|
|
76
|
+
referrer: e.page.referrer,
|
|
77
|
+
...e.page.search && { search: e.page.search }
|
|
63
78
|
}
|
|
64
79
|
},
|
|
65
80
|
...(e == null ? void 0 : e.device) && { device: e.device },
|
|
66
|
-
...(e == null ? void 0 : e.utm) && { utm: e.utm }
|
|
67
|
-
|
|
81
|
+
...(e == null ? void 0 : e.utm) && { utm: e.utm },
|
|
82
|
+
site: this.config.siteUuid,
|
|
83
|
+
...((h = e == null ? void 0 : e.user) == null ? void 0 : h.userId) && { visitor: e.user.userId }
|
|
84
|
+
}, a = ((d = e == null ? void 0 : e.user) == null ? void 0 : d.traits) || {};
|
|
68
85
|
try {
|
|
69
86
|
await this.client.V1.track({
|
|
70
|
-
email:
|
|
87
|
+
email: r,
|
|
71
88
|
type: `$${i.action}`,
|
|
72
|
-
details:
|
|
73
|
-
fields:
|
|
89
|
+
details: s,
|
|
90
|
+
fields: a
|
|
74
91
|
}), this.log("Tracked event", { event: i, context: e });
|
|
75
|
-
} catch (
|
|
76
|
-
console.error("[Bento-Server] Failed to track event:",
|
|
92
|
+
} catch (g) {
|
|
93
|
+
console.error("[Bento-Server] Failed to track event:", g);
|
|
77
94
|
}
|
|
78
95
|
}
|
|
79
96
|
pageView(i, e) {
|
|
80
|
-
var o,
|
|
97
|
+
var o, l, h;
|
|
81
98
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
82
|
-
const
|
|
99
|
+
const r = ((o = e == null ? void 0 : e.user) == null ? void 0 : o.email) || this.currentUserEmail;
|
|
100
|
+
if (!r || !r.includes("@")) {
|
|
101
|
+
console.warn(
|
|
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
|
+
);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const s = {
|
|
83
107
|
...i,
|
|
108
|
+
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
84
109
|
...(e == null ? void 0 : e.page) && {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
110
|
+
page: {
|
|
111
|
+
url: e.page.url,
|
|
112
|
+
host: e.page.host,
|
|
113
|
+
path: e.page.path,
|
|
114
|
+
title: e.page.title,
|
|
115
|
+
protocol: e.page.protocol,
|
|
116
|
+
referrer: e.page.referrer,
|
|
117
|
+
...e.page.search && { search: e.page.search }
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
site: this.config.siteUuid,
|
|
121
|
+
...((l = e == null ? void 0 : e.user) == null ? void 0 : l.userId) && { visitor: e.user.userId }
|
|
122
|
+
}, a = ((h = e == null ? void 0 : e.user) == null ? void 0 : h.traits) || {};
|
|
90
123
|
this.client.V1.track({
|
|
91
|
-
email:
|
|
124
|
+
email: r,
|
|
92
125
|
type: "$view",
|
|
93
|
-
details:
|
|
94
|
-
fields:
|
|
95
|
-
}).catch((
|
|
96
|
-
console.error("[Bento-Server] Failed to track page view:",
|
|
126
|
+
details: s,
|
|
127
|
+
fields: a
|
|
128
|
+
}).catch((d) => {
|
|
129
|
+
console.error("[Bento-Server] Failed to track page view:", d);
|
|
97
130
|
}), this.log("Tracked page view", { properties: i, context: e });
|
|
98
131
|
}
|
|
99
132
|
async reset() {
|
|
@@ -103,13 +136,13 @@ class v extends p {
|
|
|
103
136
|
this.client = void 0, this.initialized = !1, this.log("Shutdown complete");
|
|
104
137
|
}
|
|
105
138
|
}
|
|
106
|
-
class
|
|
139
|
+
class K extends I {
|
|
107
140
|
constructor(i) {
|
|
108
141
|
super({ debug: i.debug, enabled: i.enabled });
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
142
|
+
p(this, "name", "Pirsch-Server");
|
|
143
|
+
p(this, "client");
|
|
144
|
+
p(this, "initialized", !1);
|
|
145
|
+
p(this, "config");
|
|
113
146
|
this.config = i;
|
|
114
147
|
}
|
|
115
148
|
async initialize() {
|
|
@@ -119,8 +152,8 @@ class E extends p {
|
|
|
119
152
|
if (!this.config.clientSecret || typeof this.config.clientSecret != "string")
|
|
120
153
|
throw new Error("Pirsch requires a clientSecret (or access key)");
|
|
121
154
|
try {
|
|
122
|
-
const { Pirsch: i } = await import("../index-zS7gy63J.js").then((
|
|
123
|
-
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", {
|
|
124
157
|
hostname: this.config.hostname
|
|
125
158
|
});
|
|
126
159
|
} catch (i) {
|
|
@@ -133,72 +166,68 @@ class E extends p {
|
|
|
133
166
|
}
|
|
134
167
|
identify(i, e) {
|
|
135
168
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
136
|
-
const
|
|
169
|
+
const r = {
|
|
137
170
|
url: "https://identify",
|
|
138
171
|
ip: "0.0.0.0",
|
|
139
172
|
user_agent: "analytics-library"
|
|
140
|
-
},
|
|
173
|
+
}, s = {
|
|
141
174
|
userId: i,
|
|
142
175
|
...e && Object.fromEntries(
|
|
143
176
|
Object.entries(e).filter(
|
|
144
|
-
([,
|
|
177
|
+
([, a]) => typeof a == "string" || typeof a == "number" || typeof a == "boolean"
|
|
145
178
|
)
|
|
146
179
|
)
|
|
147
180
|
};
|
|
148
|
-
this.client.event("user_identified",
|
|
149
|
-
console.error("[Pirsch-Server] Failed to track identify event:",
|
|
181
|
+
this.client.event("user_identified", r, 0, s).catch((a) => {
|
|
182
|
+
console.error("[Pirsch-Server] Failed to track identify event:", a);
|
|
150
183
|
}), this.log("Identified user via event", { userId: i, traits: e });
|
|
151
184
|
}
|
|
152
185
|
async track(i, e) {
|
|
153
|
-
var
|
|
186
|
+
var g, f, y, c, m, v, b, w, u, S, E;
|
|
154
187
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
155
|
-
const s = {
|
|
156
|
-
url: ((
|
|
157
|
-
ip:
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
...((h = e == null ? void 0 : e.page) == null ? void 0 : h.referrer) && { referrer: e.page.referrer }
|
|
163
|
-
}, t = {
|
|
188
|
+
const r = e, s = ((g = r == null ? void 0 : r.device) == null ? void 0 : g.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: ((c = e == null ? void 0 : e.page) == null ? void 0 : c.url) || ((m = e == null ? void 0 : e.page) != null && m.protocol && ((v = e == null ? void 0 : e.page) != null && v.host) && ((b = e == null ? void 0 : e.page) != null && b.path) ? `${e.page.protocol}://${e.page.host}${e.page.path}` : (w = e == null ? void 0 : e.page) != null && w.path ? `https://${this.config.hostname}${e.page.path}` : "https://event"),
|
|
190
|
+
ip: s,
|
|
191
|
+
user_agent: a,
|
|
192
|
+
...((u = e == null ? void 0 : e.page) == null ? void 0 : u.title) && { title: e.page.title },
|
|
193
|
+
...((S = e == null ? void 0 : e.page) == null ? void 0 : S.referrer) && { referrer: e.page.referrer }
|
|
194
|
+
}, d = {
|
|
164
195
|
...Object.fromEntries(
|
|
165
196
|
Object.entries(i.properties).filter(
|
|
166
|
-
([,
|
|
197
|
+
([, k]) => typeof k == "string" || typeof k == "number" || typeof k == "boolean"
|
|
167
198
|
)
|
|
168
199
|
),
|
|
169
200
|
category: i.category,
|
|
170
201
|
timestamp: String(i.timestamp || Date.now()),
|
|
171
202
|
...i.userId && { userId: i.userId },
|
|
172
203
|
...i.sessionId && { sessionId: i.sessionId },
|
|
173
|
-
...((
|
|
204
|
+
...((E = e == null ? void 0 : e.user) == null ? void 0 : E.email) && { user_email: e.user.email }
|
|
174
205
|
};
|
|
175
206
|
try {
|
|
176
|
-
await this.client.event(i.action,
|
|
177
|
-
} catch (
|
|
178
|
-
console.error("[Pirsch-Server] Failed to track event:",
|
|
207
|
+
await this.client.event(i.action, l, 0, d), this.log("Tracked event", { event: i, context: e });
|
|
208
|
+
} catch (k) {
|
|
209
|
+
console.error("[Pirsch-Server] Failed to track event:", k);
|
|
179
210
|
}
|
|
180
211
|
}
|
|
181
212
|
pageView(i, e) {
|
|
182
|
-
var
|
|
213
|
+
var h, d, g, f, y, c, m, v, b, w;
|
|
183
214
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
184
|
-
const s = {
|
|
185
|
-
url: ((
|
|
186
|
-
ip:
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
...((t = e == null ? void 0 : e.page) == null ? void 0 : t.title) && { title: e.page.title },
|
|
191
|
-
...((o = e == null ? void 0 : e.page) == null ? void 0 : o.referrer) && { referrer: e.page.referrer },
|
|
215
|
+
const r = e, s = ((h = r == null ? void 0 : r.device) == null ? void 0 : h.ip) || "0.0.0.0", a = ((d = r == null ? void 0 : r.server) == null ? void 0 : d.userAgent) || ((g = r == null ? void 0 : r.device) == null ? void 0 : g.userAgent) || "unknown", l = {
|
|
216
|
+
url: ((f = e == null ? void 0 : e.page) == null ? void 0 : f.url) || ((y = e == null ? void 0 : e.page) != null && y.protocol && ((c = e == null ? void 0 : e.page) != null && c.host) && ((m = e == null ? void 0 : e.page) != null && m.path) ? `${e.page.protocol}://${e.page.host}${e.page.path}` : (v = e == null ? void 0 : e.page) != null && v.path ? `https://${this.config.hostname}${e.page.path}` : "https://pageview"),
|
|
217
|
+
ip: s,
|
|
218
|
+
user_agent: a,
|
|
219
|
+
...((b = e == null ? void 0 : e.page) == null ? void 0 : b.title) && { title: e.page.title },
|
|
220
|
+
...((w = e == null ? void 0 : e.page) == null ? void 0 : w.referrer) && { referrer: e.page.referrer },
|
|
192
221
|
...i && {
|
|
193
222
|
tags: Object.fromEntries(
|
|
194
223
|
Object.entries(i).filter(
|
|
195
|
-
([,
|
|
224
|
+
([, u]) => typeof u == "string" || typeof u == "number" || typeof u == "boolean"
|
|
196
225
|
)
|
|
197
226
|
)
|
|
198
227
|
}
|
|
199
228
|
};
|
|
200
|
-
this.client.hit(
|
|
201
|
-
console.error("[Pirsch-Server] Failed to track page view:",
|
|
229
|
+
this.client.hit(l).catch((u) => {
|
|
230
|
+
console.error("[Pirsch-Server] Failed to track page view:", u);
|
|
202
231
|
}), this.log("Tracked page view", { properties: i, context: e });
|
|
203
232
|
}
|
|
204
233
|
async reset() {
|
|
@@ -216,68 +245,68 @@ class E extends p {
|
|
|
216
245
|
this.client = void 0, this.initialized = !1, this.log("Shutdown complete");
|
|
217
246
|
}
|
|
218
247
|
}
|
|
219
|
-
async function
|
|
220
|
-
var e,
|
|
248
|
+
async function B(n, t, i) {
|
|
249
|
+
var e, r;
|
|
221
250
|
try {
|
|
222
|
-
const
|
|
223
|
-
if (!
|
|
251
|
+
const s = await n.json();
|
|
252
|
+
if (!s.events || !Array.isArray(s.events))
|
|
224
253
|
throw new Error("Invalid payload: missing events array");
|
|
225
|
-
const
|
|
226
|
-
for (const
|
|
254
|
+
const a = i != null && i.extractIp ? i.extractIp(n) : F(n), o = i != null && i.enrichContext ? i.enrichContext(n) : {};
|
|
255
|
+
for (const l of s.events)
|
|
227
256
|
try {
|
|
228
|
-
switch (
|
|
257
|
+
switch (l.type) {
|
|
229
258
|
case "track": {
|
|
230
259
|
const h = {
|
|
231
|
-
...
|
|
260
|
+
...l.context,
|
|
232
261
|
...o,
|
|
233
262
|
device: {
|
|
234
|
-
...(e =
|
|
263
|
+
...(e = l.context) == null ? void 0 : e.device,
|
|
235
264
|
// Add IP (using type assertion for extended fields)
|
|
236
265
|
// biome-ignore lint/suspicious/noExplicitAny: IP field not in base device type
|
|
237
|
-
...
|
|
266
|
+
...a ? { ip: a } : {}
|
|
238
267
|
}
|
|
239
268
|
};
|
|
240
|
-
await
|
|
241
|
-
userId:
|
|
242
|
-
sessionId:
|
|
269
|
+
await t.track(l.event.action, l.event.properties, {
|
|
270
|
+
userId: l.event.userId,
|
|
271
|
+
sessionId: l.event.sessionId,
|
|
243
272
|
// biome-ignore lint/suspicious/noExplicitAny: Generic context forwarding requires type assertion
|
|
244
273
|
context: h
|
|
245
274
|
});
|
|
246
275
|
break;
|
|
247
276
|
}
|
|
248
277
|
case "identify": {
|
|
249
|
-
|
|
278
|
+
t.identify(l.userId, l.traits);
|
|
250
279
|
break;
|
|
251
280
|
}
|
|
252
281
|
case "pageView": {
|
|
253
282
|
const h = {
|
|
254
|
-
...
|
|
283
|
+
...l.context,
|
|
255
284
|
...o,
|
|
256
285
|
device: {
|
|
257
|
-
...(
|
|
286
|
+
...(r = l.context) == null ? void 0 : r.device,
|
|
258
287
|
// biome-ignore lint/suspicious/noExplicitAny: IP field not in base device type
|
|
259
288
|
// Add IP (using type assertion for extended fields)
|
|
260
|
-
...
|
|
289
|
+
...a ? { ip: a } : {}
|
|
261
290
|
}
|
|
262
291
|
};
|
|
263
|
-
|
|
292
|
+
t.pageView(l.properties, h);
|
|
264
293
|
break;
|
|
265
294
|
}
|
|
266
295
|
case "reset":
|
|
267
296
|
break;
|
|
268
297
|
default:
|
|
269
|
-
console.warn("[Proxy] Unknown event type:",
|
|
298
|
+
console.warn("[Proxy] Unknown event type:", l);
|
|
270
299
|
}
|
|
271
300
|
} catch (h) {
|
|
272
301
|
i != null && i.onError ? i.onError(h) : console.error("[Proxy] Failed to process event:", h);
|
|
273
302
|
}
|
|
274
|
-
} catch (
|
|
275
|
-
throw i != null && i.onError ? i.onError(
|
|
303
|
+
} catch (s) {
|
|
304
|
+
throw i != null && i.onError ? i.onError(s) : console.error("[Proxy] Failed to ingest events:", s), s;
|
|
276
305
|
}
|
|
277
306
|
}
|
|
278
|
-
function
|
|
307
|
+
function F(n) {
|
|
279
308
|
var i;
|
|
280
|
-
const
|
|
309
|
+
const t = [
|
|
281
310
|
"x-forwarded-for",
|
|
282
311
|
"x-real-ip",
|
|
283
312
|
"cf-connecting-ip",
|
|
@@ -285,26 +314,26 @@ function m(l) {
|
|
|
285
314
|
"x-client-ip",
|
|
286
315
|
"x-cluster-client-ip"
|
|
287
316
|
];
|
|
288
|
-
for (const e of
|
|
289
|
-
const
|
|
290
|
-
if (
|
|
291
|
-
return (i =
|
|
317
|
+
for (const e of t) {
|
|
318
|
+
const r = n.headers.get(e);
|
|
319
|
+
if (r)
|
|
320
|
+
return (i = r.split(",")[0]) == null ? void 0 : i.trim();
|
|
292
321
|
}
|
|
293
322
|
}
|
|
294
|
-
function
|
|
323
|
+
function O(n, t) {
|
|
295
324
|
return async (i) => {
|
|
296
325
|
try {
|
|
297
|
-
return await
|
|
326
|
+
return await B(i, n, t), new Response("OK", { status: 200 });
|
|
298
327
|
} catch (e) {
|
|
299
328
|
return console.error("[Proxy] Handler error:", e), new Response("Internal Server Error", { status: 500 });
|
|
300
329
|
}
|
|
301
330
|
};
|
|
302
331
|
}
|
|
303
332
|
export {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
333
|
+
I as BaseAnalyticsProvider,
|
|
334
|
+
A as BentoServerProvider,
|
|
335
|
+
K as PirschServerProvider,
|
|
336
|
+
_ as PostHogServerProvider,
|
|
337
|
+
O as createProxyHandler,
|
|
338
|
+
B as ingestProxyEvents
|
|
310
339
|
};
|
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.
|