@stacksee/analytics 0.13.1 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/server/server-analytics.d.ts +2 -2
- package/dist/providers/bento/server.d.ts +2 -2
- package/dist/providers/client.d.ts +2 -0
- package/dist/providers/client.js +159 -45
- package/dist/providers/emitkit/server.d.ts +2 -2
- package/dist/providers/pirsch/server.d.ts +2 -2
- package/dist/providers/server.js +128 -124
- package/dist/providers/visitors/client.d.ts +67 -0
- package/dist/server.js +41 -38
- package/package.json +7 -2
|
@@ -130,7 +130,7 @@ export declare class ServerAnalytics<TEventMap extends Record<string, Record<str
|
|
|
130
130
|
* }
|
|
131
131
|
* ```
|
|
132
132
|
*/
|
|
133
|
-
identify(userId: string, traits?: Record<string, unknown>): void
|
|
133
|
+
identify(userId: string, traits?: Record<string, unknown>): Promise<void>;
|
|
134
134
|
/**
|
|
135
135
|
* Tracks a custom event with properties and optional context.
|
|
136
136
|
*
|
|
@@ -320,7 +320,7 @@ export declare class ServerAnalytics<TEventMap extends Record<string, Record<str
|
|
|
320
320
|
*/
|
|
321
321
|
pageView(properties?: Record<string, unknown>, options?: {
|
|
322
322
|
context?: EventContext<TUserTraits>;
|
|
323
|
-
}): void
|
|
323
|
+
}): Promise<void>;
|
|
324
324
|
/**
|
|
325
325
|
* Tracks when a user leaves a page from the server side.
|
|
326
326
|
*
|
|
@@ -50,9 +50,9 @@ export declare class BentoServerProvider extends BaseAnalyticsProvider {
|
|
|
50
50
|
private currentUserEmail?;
|
|
51
51
|
constructor(config: BentoServerConfig);
|
|
52
52
|
initialize(): Promise<void>;
|
|
53
|
-
identify(userId: string, traits?: Record<string, unknown>): void
|
|
53
|
+
identify(userId: string, traits?: Record<string, unknown>): Promise<void>;
|
|
54
54
|
track(event: BaseEvent, context?: EventContext): Promise<void>;
|
|
55
|
-
pageView(properties?: Record<string, unknown>, context?: EventContext): void
|
|
55
|
+
pageView(properties?: Record<string, unknown>, context?: EventContext): Promise<void>;
|
|
56
56
|
reset(): Promise<void>;
|
|
57
57
|
shutdown(): Promise<void>;
|
|
58
58
|
}
|
|
@@ -5,6 +5,8 @@ export { BentoClientProvider } from './bento/client.js';
|
|
|
5
5
|
export type { BentoClientConfig } from './bento/client.js';
|
|
6
6
|
export { PirschClientProvider } from './pirsch/client.js';
|
|
7
7
|
export type { PirschClientConfig } from './pirsch/client.js';
|
|
8
|
+
export { VisitorsClientProvider } from './visitors/client.js';
|
|
9
|
+
export type { VisitorsClientConfig } from './visitors/client.js';
|
|
8
10
|
export { ProxyProvider } from './proxy/client.js';
|
|
9
11
|
export type { ProxyProviderConfig } from './proxy/client.js';
|
|
10
12
|
export type { ProxyBatchConfig, ProxyRetryConfig, ProxyEvent, ProxyPayload, ProxyTrackEvent, ProxyIdentifyEvent, ProxyPageViewEvent, ProxyResetEvent, } from './proxy/types.js';
|
package/dist/providers/client.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
var
|
|
2
|
-
var p = (o,
|
|
3
|
-
var r = (o,
|
|
4
|
-
import { B as
|
|
5
|
-
import { i as
|
|
6
|
-
import { P as
|
|
7
|
-
class w extends
|
|
1
|
+
var g = Object.defineProperty;
|
|
2
|
+
var p = (o, l, e) => l in o ? g(o, l, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[l] = e;
|
|
3
|
+
var r = (o, l, e) => p(o, typeof l != "symbol" ? l + "" : l, e);
|
|
4
|
+
import { B as f } from "../base.provider-AfFL5W_P.js";
|
|
5
|
+
import { i as n } from "../client-DTHZYkxx.js";
|
|
6
|
+
import { P as C } from "../client-DTHZYkxx.js";
|
|
7
|
+
class w extends f {
|
|
8
8
|
constructor(e) {
|
|
9
9
|
super({ debug: e.debug, enabled: e.enabled });
|
|
10
10
|
r(this, "name", "Bento-Client");
|
|
@@ -16,7 +16,7 @@ class w extends u {
|
|
|
16
16
|
}
|
|
17
17
|
async initialize() {
|
|
18
18
|
if (this.isEnabled() && !this.initialized) {
|
|
19
|
-
if (!
|
|
19
|
+
if (!n()) {
|
|
20
20
|
this.log("Skipping initialization - not in browser environment");
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
@@ -63,7 +63,7 @@ class w extends u {
|
|
|
63
63
|
this.log("Identified user", { userId: e, email: s, traits: i });
|
|
64
64
|
}
|
|
65
65
|
track(e, i) {
|
|
66
|
-
var t,
|
|
66
|
+
var t, a, h;
|
|
67
67
|
if (!this.isEnabled() || !this.initialized || !this.bento) return;
|
|
68
68
|
const s = {
|
|
69
69
|
...e.properties,
|
|
@@ -86,14 +86,14 @@ class w extends u {
|
|
|
86
86
|
...(i == null ? void 0 : i.utm) && { utm: i.utm },
|
|
87
87
|
// Include user email and traits as regular event properties
|
|
88
88
|
...((t = i == null ? void 0 : i.user) == null ? void 0 : t.email) && { user_email: i.user.email },
|
|
89
|
-
...((
|
|
90
|
-
...((
|
|
89
|
+
...((a = i == null ? void 0 : i.user) == null ? void 0 : a.traits) && { user_traits: i.user.traits },
|
|
90
|
+
...((h = i == null ? void 0 : i.user) == null ? void 0 : h.userId) && { visitor: i.user.userId }
|
|
91
91
|
};
|
|
92
92
|
this.bento.track(e.action, s), this.log("Tracked event", { event: e, context: i });
|
|
93
93
|
}
|
|
94
94
|
pageView(e, i) {
|
|
95
95
|
var s;
|
|
96
|
-
if (!(!this.isEnabled() || !this.initialized || !this.bento || !
|
|
96
|
+
if (!(!this.isEnabled() || !this.initialized || !this.bento || !n())) {
|
|
97
97
|
if (this.bento.view(), e || i != null && i.page) {
|
|
98
98
|
const t = {
|
|
99
99
|
...e,
|
|
@@ -118,7 +118,7 @@ class w extends u {
|
|
|
118
118
|
}
|
|
119
119
|
pageLeave(e, i) {
|
|
120
120
|
var t;
|
|
121
|
-
if (!this.isEnabled() || !this.initialized || !this.bento || !
|
|
121
|
+
if (!this.isEnabled() || !this.initialized || !this.bento || !n())
|
|
122
122
|
return;
|
|
123
123
|
const s = {
|
|
124
124
|
...e,
|
|
@@ -139,7 +139,7 @@ class w extends u {
|
|
|
139
139
|
this.bento.track("$pageleave", s), this.log("Tracked page leave", { properties: e, context: i });
|
|
140
140
|
}
|
|
141
141
|
reset() {
|
|
142
|
-
!this.isEnabled() || !this.initialized || !this.bento || !
|
|
142
|
+
!this.isEnabled() || !this.initialized || !this.bento || !n() || this.log(
|
|
143
143
|
"Reset user session - Note: Bento doesn't have a native reset method"
|
|
144
144
|
);
|
|
145
145
|
}
|
|
@@ -156,7 +156,7 @@ class w extends u {
|
|
|
156
156
|
* ```
|
|
157
157
|
*/
|
|
158
158
|
tag(e) {
|
|
159
|
-
!this.isEnabled() || !this.initialized || !this.bento || !
|
|
159
|
+
!this.isEnabled() || !this.initialized || !this.bento || !n() || (this.bento.tag(e), this.log("Added tag to user", { tag: e }));
|
|
160
160
|
}
|
|
161
161
|
/**
|
|
162
162
|
* Get the current user's email address
|
|
@@ -172,7 +172,7 @@ class w extends u {
|
|
|
172
172
|
* ```
|
|
173
173
|
*/
|
|
174
174
|
getEmail() {
|
|
175
|
-
return !this.isEnabled() || !this.initialized || !this.bento || !
|
|
175
|
+
return !this.isEnabled() || !this.initialized || !this.bento || !n() ? null : this.bento.getEmail();
|
|
176
176
|
}
|
|
177
177
|
/**
|
|
178
178
|
* Get the current user's name
|
|
@@ -188,7 +188,7 @@ class w extends u {
|
|
|
188
188
|
* ```
|
|
189
189
|
*/
|
|
190
190
|
getName() {
|
|
191
|
-
return !this.isEnabled() || !this.initialized || !this.bento || !
|
|
191
|
+
return !this.isEnabled() || !this.initialized || !this.bento || !n() ? null : this.bento.getName();
|
|
192
192
|
}
|
|
193
193
|
// ============================================================================
|
|
194
194
|
// Survey Methods
|
|
@@ -209,7 +209,7 @@ class w extends u {
|
|
|
209
209
|
* ```
|
|
210
210
|
*/
|
|
211
211
|
showSurveyForm(e, i, s = "popup") {
|
|
212
|
-
!this.isEnabled() || !this.initialized || !this.bento || !
|
|
212
|
+
!this.isEnabled() || !this.initialized || !this.bento || !n() || (this.bento.showSurveyForm(e, i, s), this.log("Showed survey form", { surveyId: i, type: s }));
|
|
213
213
|
}
|
|
214
214
|
/**
|
|
215
215
|
* Validate an email address using Bento's spam check
|
|
@@ -226,7 +226,7 @@ class w extends u {
|
|
|
226
226
|
* ```
|
|
227
227
|
*/
|
|
228
228
|
async spamCheck(e) {
|
|
229
|
-
if (!this.isEnabled() || !this.initialized || !this.bento || !
|
|
229
|
+
if (!this.isEnabled() || !this.initialized || !this.bento || !n())
|
|
230
230
|
return !1;
|
|
231
231
|
try {
|
|
232
232
|
const i = await this.bento.spamCheck(e);
|
|
@@ -247,7 +247,7 @@ class w extends u {
|
|
|
247
247
|
* ```
|
|
248
248
|
*/
|
|
249
249
|
showChat() {
|
|
250
|
-
!this.isEnabled() || !this.initialized || !this.bento || !
|
|
250
|
+
!this.isEnabled() || !this.initialized || !this.bento || !n() || (this.bento.showChat ? (this.bento.showChat(), this.log("Showed chat widget")) : console.warn(
|
|
251
251
|
"[Bento-Client] Chat not available. Make sure chat is enabled in your Bento settings."
|
|
252
252
|
));
|
|
253
253
|
}
|
|
@@ -260,7 +260,7 @@ class w extends u {
|
|
|
260
260
|
* ```
|
|
261
261
|
*/
|
|
262
262
|
hideChat() {
|
|
263
|
-
!this.isEnabled() || !this.initialized || !this.bento || !
|
|
263
|
+
!this.isEnabled() || !this.initialized || !this.bento || !n() || (this.bento.hideChat ? (this.bento.hideChat(), this.log("Hid chat widget")) : console.warn(
|
|
264
264
|
"[Bento-Client] Chat not available. Make sure chat is enabled in your Bento settings."
|
|
265
265
|
));
|
|
266
266
|
}
|
|
@@ -273,12 +273,12 @@ class w extends u {
|
|
|
273
273
|
* ```
|
|
274
274
|
*/
|
|
275
275
|
openChat() {
|
|
276
|
-
!this.isEnabled() || !this.initialized || !this.bento || !
|
|
276
|
+
!this.isEnabled() || !this.initialized || !this.bento || !n() || (this.bento.openChat ? (this.bento.openChat(), this.log("Opened chat widget")) : console.warn(
|
|
277
277
|
"[Bento-Client] Chat not available. Make sure chat is enabled in your Bento settings."
|
|
278
278
|
));
|
|
279
279
|
}
|
|
280
280
|
}
|
|
281
|
-
class m extends
|
|
281
|
+
class m extends f {
|
|
282
282
|
constructor(e) {
|
|
283
283
|
super({ debug: e.debug, enabled: e.enabled });
|
|
284
284
|
r(this, "name", "Pirsch-Client");
|
|
@@ -289,7 +289,7 @@ class m extends u {
|
|
|
289
289
|
}
|
|
290
290
|
async initialize() {
|
|
291
291
|
if (this.isEnabled() && !this.initialized) {
|
|
292
|
-
if (!
|
|
292
|
+
if (!n()) {
|
|
293
293
|
this.log("Skipping initialization - not in browser environment");
|
|
294
294
|
return;
|
|
295
295
|
}
|
|
@@ -319,7 +319,7 @@ class m extends u {
|
|
|
319
319
|
}), this.log("Identified user via event", { userId: e, traits: i }));
|
|
320
320
|
}
|
|
321
321
|
async track(e, i) {
|
|
322
|
-
var t,
|
|
322
|
+
var t, a;
|
|
323
323
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
324
324
|
const s = {
|
|
325
325
|
...e.properties,
|
|
@@ -334,33 +334,33 @@ class m extends u {
|
|
|
334
334
|
...(i == null ? void 0 : i.device) && { device: i.device },
|
|
335
335
|
...(i == null ? void 0 : i.utm) && { utm: i.utm },
|
|
336
336
|
...((t = i == null ? void 0 : i.user) == null ? void 0 : t.email) && { user_email: i.user.email },
|
|
337
|
-
...((
|
|
337
|
+
...((a = i == null ? void 0 : i.user) == null ? void 0 : a.traits) && { user_traits: i.user.traits }
|
|
338
338
|
};
|
|
339
339
|
try {
|
|
340
340
|
await this.client.event(e.action, 0, s), this.log("Tracked event", { event: e, context: i });
|
|
341
|
-
} catch (
|
|
342
|
-
console.error("[Pirsch-Client] Failed to track event:",
|
|
341
|
+
} catch (h) {
|
|
342
|
+
console.error("[Pirsch-Client] Failed to track event:", h);
|
|
343
343
|
}
|
|
344
344
|
}
|
|
345
345
|
pageView(e, i) {
|
|
346
|
-
var
|
|
347
|
-
if (!this.isEnabled() || !this.initialized || !this.client || !
|
|
346
|
+
var h, d;
|
|
347
|
+
if (!this.isEnabled() || !this.initialized || !this.client || !n())
|
|
348
348
|
return;
|
|
349
349
|
const s = e && Object.keys(e).length > 0 ? Object.fromEntries(
|
|
350
350
|
Object.entries(e).filter(
|
|
351
|
-
([,
|
|
351
|
+
([, u]) => typeof u == "string" || typeof u == "number" || typeof u == "boolean"
|
|
352
352
|
)
|
|
353
353
|
) : void 0, t = {
|
|
354
|
-
...((
|
|
355
|
-
...((
|
|
354
|
+
...((h = i == null ? void 0 : i.page) == null ? void 0 : h.url) && { url: i.page.url },
|
|
355
|
+
...((d = i == null ? void 0 : i.page) == null ? void 0 : d.title) && { title: i.page.title },
|
|
356
356
|
...s && { tags: s }
|
|
357
|
-
},
|
|
358
|
-
this.client.hit(
|
|
359
|
-
console.error("[Pirsch-Client] Failed to track page view:",
|
|
357
|
+
}, a = Object.keys(t).length > 0 ? t : void 0;
|
|
358
|
+
this.client.hit(a).catch((u) => {
|
|
359
|
+
console.error("[Pirsch-Client] Failed to track page view:", u);
|
|
360
360
|
}), this.log("Tracked page view", { properties: e, context: i });
|
|
361
361
|
}
|
|
362
362
|
pageLeave(e, i) {
|
|
363
|
-
if (!this.isEnabled() || !this.initialized || !this.client || !
|
|
363
|
+
if (!this.isEnabled() || !this.initialized || !this.client || !n())
|
|
364
364
|
return;
|
|
365
365
|
const s = {
|
|
366
366
|
...e,
|
|
@@ -374,14 +374,127 @@ class m extends u {
|
|
|
374
374
|
}), this.log("Tracked page leave", { properties: e, context: i });
|
|
375
375
|
}
|
|
376
376
|
reset() {
|
|
377
|
-
!this.isEnabled() || !this.initialized || !this.client || !
|
|
377
|
+
!this.isEnabled() || !this.initialized || !this.client || !n() || (this.client.event("session_reset", 0, {}).catch((e) => {
|
|
378
378
|
console.error("[Pirsch-Client] Failed to track session reset:", e);
|
|
379
379
|
}), this.log("Reset user session"));
|
|
380
380
|
}
|
|
381
381
|
}
|
|
382
|
-
class v extends
|
|
382
|
+
class v extends f {
|
|
383
383
|
constructor(e) {
|
|
384
|
-
|
|
384
|
+
super({ debug: e.debug, enabled: e.enabled });
|
|
385
|
+
r(this, "name", "Visitors-Client");
|
|
386
|
+
r(this, "visitors");
|
|
387
|
+
r(this, "initialized", !1);
|
|
388
|
+
r(this, "config");
|
|
389
|
+
r(this, "scriptLoaded", !1);
|
|
390
|
+
this.config = e;
|
|
391
|
+
}
|
|
392
|
+
async initialize() {
|
|
393
|
+
if (this.isEnabled() && !this.initialized) {
|
|
394
|
+
if (!n()) {
|
|
395
|
+
this.log("Skipping initialization - not in browser environment");
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
if (!this.config.token || typeof this.config.token != "string")
|
|
399
|
+
throw new Error("Visitors requires a token");
|
|
400
|
+
try {
|
|
401
|
+
this.scriptLoaded || await this.loadScript(), await this.waitForVisitors(), this.visitors = window.visitors, this.initialized = !0, this.log("Initialized successfully", this.config);
|
|
402
|
+
} catch (e) {
|
|
403
|
+
throw console.error("[Visitors-Client] Failed to initialize:", e), e;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
async loadScript() {
|
|
408
|
+
return new Promise((e, i) => {
|
|
409
|
+
if (document.querySelector(
|
|
410
|
+
'script[src*="cdn.visitors.now"]'
|
|
411
|
+
)) {
|
|
412
|
+
this.scriptLoaded = !0, e();
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
const t = document.createElement("script");
|
|
416
|
+
t.src = "https://cdn.visitors.now/v.js", t.setAttribute("data-token", this.config.token), t.async = !0, t.defer = !0, t.onload = () => {
|
|
417
|
+
this.scriptLoaded = !0, e();
|
|
418
|
+
}, t.onerror = () => {
|
|
419
|
+
i(new Error("Failed to load Visitors script"));
|
|
420
|
+
}, document.head.appendChild(t);
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
async waitForVisitors(e = 50, i = 100) {
|
|
424
|
+
for (let s = 0; s < e; s++) {
|
|
425
|
+
if (window.visitors)
|
|
426
|
+
return;
|
|
427
|
+
await new Promise((t) => setTimeout(t, i));
|
|
428
|
+
}
|
|
429
|
+
throw new Error("Visitors SDK not available after loading script");
|
|
430
|
+
}
|
|
431
|
+
identify(e, i) {
|
|
432
|
+
if (!this.isEnabled() || !this.initialized || !this.visitors) return;
|
|
433
|
+
const s = { id: e };
|
|
434
|
+
if (i)
|
|
435
|
+
for (const [t, a] of Object.entries(i))
|
|
436
|
+
(typeof a == "string" || typeof a == "number") && (s[t] = a);
|
|
437
|
+
this.visitors.identify(s), this.log("Identified user", { userId: e, traits: i });
|
|
438
|
+
}
|
|
439
|
+
track(e, i) {
|
|
440
|
+
var t, a;
|
|
441
|
+
if (!this.isEnabled() || !this.initialized || !this.visitors) return;
|
|
442
|
+
const s = {};
|
|
443
|
+
if (e.properties)
|
|
444
|
+
for (const [h, d] of Object.entries(e.properties))
|
|
445
|
+
(typeof d == "string" || typeof d == "number") && (s[h] = d);
|
|
446
|
+
e.category && (s.category = e.category), (t = i == null ? void 0 : i.page) != null && t.path && (s.page_path = i.page.path), (a = i == null ? void 0 : i.page) != null && a.title && (s.page_title = i.page.title), this.visitors.track(e.action, s), this.log("Tracked event", { event: e, context: i });
|
|
447
|
+
}
|
|
448
|
+
pageView(e, i) {
|
|
449
|
+
this.log("Page view - handled automatically by Visitors script", {
|
|
450
|
+
properties: e,
|
|
451
|
+
context: i
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
pageLeave(e, i) {
|
|
455
|
+
var t;
|
|
456
|
+
if (!this.isEnabled() || !this.initialized || !this.visitors || !n())
|
|
457
|
+
return;
|
|
458
|
+
const s = {};
|
|
459
|
+
if ((t = i == null ? void 0 : i.page) != null && t.path && (s.page_path = i.page.path), e)
|
|
460
|
+
for (const [a, h] of Object.entries(e))
|
|
461
|
+
(typeof h == "string" || typeof h == "number") && (s[a] = h);
|
|
462
|
+
this.visitors.track("page_leave", s), this.log("Tracked page leave", { properties: e, context: i });
|
|
463
|
+
}
|
|
464
|
+
reset() {
|
|
465
|
+
!this.isEnabled() || !this.initialized || !this.visitors || !n() || this.log("Reset user session - Note: Visitors does not have a native reset method");
|
|
466
|
+
}
|
|
467
|
+
// ============================================================================
|
|
468
|
+
// Stripe Revenue Attribution
|
|
469
|
+
// ============================================================================
|
|
470
|
+
/**
|
|
471
|
+
* Returns the current visitor ID from the `visitor` cookie set by the
|
|
472
|
+
* visitors.now script. Pass this value in your Stripe checkout session
|
|
473
|
+
* metadata so revenue is attributed to the correct visitor.
|
|
474
|
+
*
|
|
475
|
+
* Requires persist mode to be enabled in your visitors.now project settings.
|
|
476
|
+
*
|
|
477
|
+
* @example Server-side Stripe checkout creation:
|
|
478
|
+
* ```typescript
|
|
479
|
+
* // Client-side: get visitor ID and send to your server
|
|
480
|
+
* const visitorId = visitorsProvider.getVisitorId();
|
|
481
|
+
*
|
|
482
|
+
* // Server-side: include in Stripe checkout session
|
|
483
|
+
* const session = await stripe.checkout.sessions.create({
|
|
484
|
+
* // ...
|
|
485
|
+
* metadata: { visitor: visitorId },
|
|
486
|
+
* });
|
|
487
|
+
* ```
|
|
488
|
+
*/
|
|
489
|
+
getVisitorId() {
|
|
490
|
+
if (!n()) return null;
|
|
491
|
+
const e = document.cookie.split("; ").find((i) => i.startsWith("visitor="));
|
|
492
|
+
return e ? decodeURIComponent(e.split("=")[1]) : null;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
class k extends f {
|
|
496
|
+
constructor(e) {
|
|
497
|
+
var i, s, t, a, h;
|
|
385
498
|
super({ debug: e.debug, enabled: e.enabled });
|
|
386
499
|
r(this, "name", "Proxy");
|
|
387
500
|
r(this, "config");
|
|
@@ -392,7 +505,7 @@ class v extends u {
|
|
|
392
505
|
r(this, "retryAttempts");
|
|
393
506
|
r(this, "retryBackoff");
|
|
394
507
|
r(this, "retryInitialDelay");
|
|
395
|
-
this.config = e, this.batchSize = ((i = e.batch) == null ? void 0 : i.size) ?? 10, this.batchInterval = ((s = e.batch) == null ? void 0 : s.interval) ?? 2e3, this.retryAttempts = ((t = e.retry) == null ? void 0 : t.attempts) ?? 3, this.retryBackoff = ((
|
|
508
|
+
this.config = e, this.batchSize = ((i = e.batch) == null ? void 0 : i.size) ?? 10, this.batchInterval = ((s = e.batch) == null ? void 0 : s.interval) ?? 2e3, this.retryAttempts = ((t = e.retry) == null ? void 0 : t.attempts) ?? 3, this.retryBackoff = ((a = e.retry) == null ? void 0 : a.backoff) ?? "exponential", this.retryInitialDelay = ((h = e.retry) == null ? void 0 : h.initialDelay) ?? 1e3, typeof window < "u" && (window.addEventListener("beforeunload", () => {
|
|
396
509
|
this.flush(!0);
|
|
397
510
|
}), document.addEventListener("visibilitychange", () => {
|
|
398
511
|
document.visibilityState === "hidden" && this.flush(!0);
|
|
@@ -480,7 +593,7 @@ class v extends u {
|
|
|
480
593
|
} catch (s) {
|
|
481
594
|
if (i < this.retryAttempts) {
|
|
482
595
|
const t = this.calculateRetryDelay(i);
|
|
483
|
-
return this.log(`Retry attempt ${i + 1} after ${t}ms`, { error: s }), await new Promise((
|
|
596
|
+
return this.log(`Retry attempt ${i + 1} after ${t}ms`, { error: s }), await new Promise((a) => setTimeout(a, t)), this.sendWithRetry(e, i + 1);
|
|
484
597
|
}
|
|
485
598
|
throw console.error("[Proxy] Failed to send events after retries:", s), s;
|
|
486
599
|
}
|
|
@@ -519,9 +632,10 @@ class v extends u {
|
|
|
519
632
|
}
|
|
520
633
|
}
|
|
521
634
|
export {
|
|
522
|
-
|
|
635
|
+
f as BaseAnalyticsProvider,
|
|
523
636
|
w as BentoClientProvider,
|
|
524
637
|
m as PirschClientProvider,
|
|
525
|
-
|
|
526
|
-
|
|
638
|
+
C as PostHogClientProvider,
|
|
639
|
+
k as ProxyProvider,
|
|
640
|
+
v as VisitorsClientProvider
|
|
527
641
|
};
|
|
@@ -66,9 +66,9 @@ export declare class EmitKitServerProvider extends BaseAnalyticsProvider {
|
|
|
66
66
|
private currentUserEmail?;
|
|
67
67
|
constructor(config: EmitKitServerConfig);
|
|
68
68
|
initialize(): Promise<void>;
|
|
69
|
-
identify(userId: string, traits?: Record<string, unknown>): void
|
|
69
|
+
identify(userId: string, traits?: Record<string, unknown>): Promise<void>;
|
|
70
70
|
track(event: BaseEvent, context?: EventContext): Promise<void>;
|
|
71
|
-
pageView(properties?: Record<string, unknown>, context?: EventContext): void
|
|
71
|
+
pageView(properties?: Record<string, unknown>, context?: EventContext): Promise<void>;
|
|
72
72
|
reset(): Promise<void>;
|
|
73
73
|
shutdown(): Promise<void>;
|
|
74
74
|
/**
|
|
@@ -74,9 +74,9 @@ export declare class PirschServerProvider extends BaseAnalyticsProvider {
|
|
|
74
74
|
* Build a Pirsch hit from context
|
|
75
75
|
*/
|
|
76
76
|
private buildHit;
|
|
77
|
-
identify(userId: string, traits?: Record<string, unknown>): void
|
|
77
|
+
identify(userId: string, traits?: Record<string, unknown>): Promise<void>;
|
|
78
78
|
track(event: BaseEvent, context?: EventContext): Promise<void>;
|
|
79
|
-
pageView(properties?: Record<string, unknown>, context?: EventContext): void
|
|
79
|
+
pageView(properties?: Record<string, unknown>, context?: EventContext): Promise<void>;
|
|
80
80
|
reset(): Promise<void>;
|
|
81
81
|
shutdown(): Promise<void>;
|
|
82
82
|
}
|
package/dist/providers/server.js
CHANGED
|
@@ -23,8 +23,8 @@ class O extends y {
|
|
|
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-CT4oS3Kp.js"), { debug: s, enabled:
|
|
27
|
-
this.client = new r(
|
|
26
|
+
const { Analytics: r } = await import("../bento-node-sdk.esm-CT4oS3Kp.js"), { debug: s, enabled: n, ...a } = this.config;
|
|
27
|
+
this.client = new r(a), this.initialized = !0, this.log("Initialized successfully", {
|
|
28
28
|
siteUuid: this.config.siteUuid
|
|
29
29
|
});
|
|
30
30
|
} catch (r) {
|
|
@@ -35,7 +35,7 @@ class O extends y {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
identify(i, e) {
|
|
38
|
+
async identify(i, e) {
|
|
39
39
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
40
40
|
const r = (e == null ? void 0 : e.email) || i;
|
|
41
41
|
if (!r || !r.includes("@")) {
|
|
@@ -47,17 +47,17 @@ class O extends y {
|
|
|
47
47
|
}
|
|
48
48
|
this.currentUserEmail = r;
|
|
49
49
|
const s = e ? { ...e } : {};
|
|
50
|
-
s.email = void 0
|
|
51
|
-
|
|
52
|
-
fields: s
|
|
53
|
-
}
|
|
54
|
-
console.error("[Bento-Server] Failed to identify user:",
|
|
55
|
-
}
|
|
50
|
+
s.email = void 0;
|
|
51
|
+
try {
|
|
52
|
+
await this.client.V1.addSubscriber({ email: r, fields: s }), this.log("Identified user", { userId: i, email: r, traits: e });
|
|
53
|
+
} catch (n) {
|
|
54
|
+
console.error("[Bento-Server] Failed to identify user:", n);
|
|
55
|
+
}
|
|
56
56
|
}
|
|
57
57
|
async track(i, e) {
|
|
58
|
-
var
|
|
58
|
+
var a, h, l, o;
|
|
59
59
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
60
|
-
const r = ((
|
|
60
|
+
const r = ((a = e == null ? void 0 : e.user) == null ? void 0 : a.email) || this.currentUserEmail || ((h = e == null ? void 0 : e.user) == null ? void 0 : h.userId) || i.userId;
|
|
61
61
|
if (!r || !r.includes("@")) {
|
|
62
62
|
console.warn(
|
|
63
63
|
"[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."
|
|
@@ -84,22 +84,22 @@ class O extends y {
|
|
|
84
84
|
...(e == null ? void 0 : e.utm) && { utm: e.utm },
|
|
85
85
|
site: this.config.siteUuid,
|
|
86
86
|
...((l = e == null ? void 0 : e.user) == null ? void 0 : l.userId) && { visitor: e.user.userId }
|
|
87
|
-
},
|
|
87
|
+
}, n = ((o = e == null ? void 0 : e.user) == null ? void 0 : o.traits) || {};
|
|
88
88
|
try {
|
|
89
89
|
await this.client.V1.track({
|
|
90
90
|
email: r,
|
|
91
91
|
type: `$${i.action}`,
|
|
92
92
|
details: s,
|
|
93
|
-
fields:
|
|
93
|
+
fields: n
|
|
94
94
|
}), this.log("Tracked event", { event: i, context: e });
|
|
95
|
-
} catch (
|
|
96
|
-
console.error("[Bento-Server] Failed to track event:",
|
|
95
|
+
} catch (t) {
|
|
96
|
+
console.error("[Bento-Server] Failed to track event:", t);
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
|
-
pageView(i, e) {
|
|
100
|
-
var
|
|
99
|
+
async pageView(i, e) {
|
|
100
|
+
var a, h, l;
|
|
101
101
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
102
|
-
const r = ((
|
|
102
|
+
const r = ((a = e == null ? void 0 : e.user) == null ? void 0 : a.email) || this.currentUserEmail;
|
|
103
103
|
if (!r || !r.includes("@")) {
|
|
104
104
|
console.warn(
|
|
105
105
|
"[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."
|
|
@@ -122,15 +122,12 @@ class O extends y {
|
|
|
122
122
|
},
|
|
123
123
|
site: this.config.siteUuid,
|
|
124
124
|
...((h = e == null ? void 0 : e.user) == null ? void 0 : h.userId) && { visitor: e.user.userId }
|
|
125
|
-
},
|
|
126
|
-
|
|
127
|
-
email: r,
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}).catch((n) => {
|
|
132
|
-
console.error("[Bento-Server] Failed to track page view:", n);
|
|
133
|
-
}), this.log("Tracked page view", { properties: i, context: e });
|
|
125
|
+
}, n = ((l = e == null ? void 0 : e.user) == null ? void 0 : l.traits) || {};
|
|
126
|
+
try {
|
|
127
|
+
await this.client.V1.track({ email: r, type: "$view", details: s, fields: n }), this.log("Tracked page view", { properties: i, context: e });
|
|
128
|
+
} catch (o) {
|
|
129
|
+
console.error("[Bento-Server] Failed to track page view:", o);
|
|
130
|
+
}
|
|
134
131
|
}
|
|
135
132
|
async reset() {
|
|
136
133
|
!this.isEnabled() || !this.initialized || !this.client || (this.currentUserEmail = void 0, this.log("Reset user session"));
|
|
@@ -171,14 +168,14 @@ class j extends y {
|
|
|
171
168
|
* Fetch with timeout using AbortController
|
|
172
169
|
*/
|
|
173
170
|
async fetchWithTimeout(i, e, r) {
|
|
174
|
-
const s = new AbortController(),
|
|
171
|
+
const s = new AbortController(), n = r ?? this.config.timeout ?? K, a = setTimeout(() => s.abort(), n);
|
|
175
172
|
try {
|
|
176
173
|
return await fetch(i, {
|
|
177
174
|
...e,
|
|
178
175
|
signal: s.signal
|
|
179
176
|
});
|
|
180
177
|
} finally {
|
|
181
|
-
clearTimeout(
|
|
178
|
+
clearTimeout(a);
|
|
182
179
|
}
|
|
183
180
|
}
|
|
184
181
|
/**
|
|
@@ -217,7 +214,7 @@ class j extends y {
|
|
|
217
214
|
async request(i, e, r = !0) {
|
|
218
215
|
const s = await this.ensureToken();
|
|
219
216
|
try {
|
|
220
|
-
const
|
|
217
|
+
const n = await this.fetchWithTimeout(
|
|
221
218
|
`${T}${i}`,
|
|
222
219
|
{
|
|
223
220
|
method: "POST",
|
|
@@ -228,16 +225,16 @@ class j extends y {
|
|
|
228
225
|
body: JSON.stringify(e)
|
|
229
226
|
}
|
|
230
227
|
);
|
|
231
|
-
if (
|
|
228
|
+
if (n.status === 401 && r && !this.isAccessKey)
|
|
232
229
|
return this.accessToken = "", this.tokenExpiresAt = null, this.request(i, e, !1);
|
|
233
|
-
if (!
|
|
234
|
-
const
|
|
235
|
-
throw new Error(`Pirsch API error: ${
|
|
230
|
+
if (!n.ok) {
|
|
231
|
+
const a = await n.text();
|
|
232
|
+
throw new Error(`Pirsch API error: ${n.status} ${a}`);
|
|
236
233
|
}
|
|
237
|
-
} catch (
|
|
238
|
-
throw
|
|
234
|
+
} catch (n) {
|
|
235
|
+
throw n instanceof Error && n.name === "AbortError" ? new Error(
|
|
239
236
|
`Pirsch request timeout after ${this.config.timeout ?? K}ms`
|
|
240
|
-
) :
|
|
237
|
+
) : n;
|
|
241
238
|
}
|
|
242
239
|
}
|
|
243
240
|
/**
|
|
@@ -265,10 +262,10 @@ class j extends y {
|
|
|
265
262
|
* Build a Pirsch hit from context
|
|
266
263
|
*/
|
|
267
264
|
buildHit(i) {
|
|
268
|
-
var
|
|
269
|
-
const e = i, r = ((
|
|
265
|
+
var a, h, l, o, t, p, g, f, m, v, w, b, k, E, _, S, I, A, z, P;
|
|
266
|
+
const e = i, r = ((a = e == null ? void 0 : e.device) == null ? void 0 : a.ip) || ((h = e == null ? void 0 : e.server) == null ? void 0 : h.ip), s = ((l = e == null ? void 0 : e.server) == null ? void 0 : l.userAgent) || ((o = e == null ? void 0 : e.device) == null ? void 0 : o.userAgent);
|
|
270
267
|
return !r || !s ? null : {
|
|
271
|
-
url: ((
|
|
268
|
+
url: ((t = i == null ? void 0 : i.page) == null ? void 0 : t.url) || ((p = i == null ? void 0 : i.page) != null && p.protocol && ((g = i == null ? void 0 : i.page) != null && g.host) && ((f = i == null ? void 0 : i.page) != null && f.path) ? `${i.page.protocol}://${i.page.host}${i.page.path}` : (m = i == null ? void 0 : i.page) != null && m.path ? `https://${this.config.hostname}${i.page.path}` : `https://${this.config.hostname}`),
|
|
272
269
|
ip: r,
|
|
273
270
|
user_agent: s,
|
|
274
271
|
...((v = i == null ? void 0 : i.page) == null ? void 0 : v.title) && { title: i.page.title },
|
|
@@ -292,7 +289,7 @@ class j extends y {
|
|
|
292
289
|
...this.config.disableBotFilter && { disable_bot_filter: !0 }
|
|
293
290
|
};
|
|
294
291
|
}
|
|
295
|
-
identify(i, e) {
|
|
292
|
+
async identify(i, e) {
|
|
296
293
|
if (!this.isEnabled() || !this.initialized) return;
|
|
297
294
|
const r = {
|
|
298
295
|
url: `https://${this.config.hostname}/identify`,
|
|
@@ -302,7 +299,7 @@ class j extends y {
|
|
|
302
299
|
}, s = this.toStringRecord({
|
|
303
300
|
userId: i,
|
|
304
301
|
...e
|
|
305
|
-
}),
|
|
302
|
+
}), n = {
|
|
306
303
|
...r,
|
|
307
304
|
event_name: "user_identified",
|
|
308
305
|
event_duration: 0,
|
|
@@ -310,12 +307,14 @@ class j extends y {
|
|
|
310
307
|
non_interactive: !0
|
|
311
308
|
// Synthetic event shouldn't affect bounce rate
|
|
312
309
|
};
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
}
|
|
310
|
+
try {
|
|
311
|
+
await this.request("/api/v1/event", n), this.log("Identified user via event", { userId: i, traits: e });
|
|
312
|
+
} catch (a) {
|
|
313
|
+
console.error("[Pirsch-Server] Failed to track identify event:", a);
|
|
314
|
+
}
|
|
316
315
|
}
|
|
317
316
|
async track(i, e) {
|
|
318
|
-
var h, l,
|
|
317
|
+
var h, l, o, t;
|
|
319
318
|
if (!this.isEnabled() || !this.initialized) return;
|
|
320
319
|
const r = this.buildHit(e);
|
|
321
320
|
if (!r) {
|
|
@@ -332,21 +331,21 @@ class j extends y {
|
|
|
332
331
|
...i.sessionId && { sessionId: i.sessionId },
|
|
333
332
|
...((h = e == null ? void 0 : e.user) == null ? void 0 : h.email) && { user_email: e.user.email },
|
|
334
333
|
...((l = e == null ? void 0 : e.device) == null ? void 0 : l.timezone) && { timezone: e.device.timezone },
|
|
335
|
-
...((
|
|
336
|
-
}),
|
|
334
|
+
...((o = e == null ? void 0 : e.device) == null ? void 0 : o.browser) && { browser: e.device.browser }
|
|
335
|
+
}), n = ((t = i.properties) == null ? void 0 : t.non_interactive) === !0, a = {
|
|
337
336
|
...r,
|
|
338
337
|
event_name: i.action,
|
|
339
338
|
event_duration: 0,
|
|
340
339
|
event_meta: s,
|
|
341
|
-
...
|
|
340
|
+
...n && { non_interactive: !0 }
|
|
342
341
|
};
|
|
343
342
|
try {
|
|
344
|
-
await this.request("/api/v1/event",
|
|
343
|
+
await this.request("/api/v1/event", a), this.log("Tracked event", { event: i.action });
|
|
345
344
|
} catch (p) {
|
|
346
345
|
console.error("[Pirsch-Server] Failed to track event:", p);
|
|
347
346
|
}
|
|
348
347
|
}
|
|
349
|
-
pageView(i, e) {
|
|
348
|
+
async pageView(i, e) {
|
|
350
349
|
var s;
|
|
351
350
|
if (!this.isEnabled() || !this.initialized) return;
|
|
352
351
|
const r = this.buildHit(e);
|
|
@@ -354,9 +353,12 @@ class j extends y {
|
|
|
354
353
|
this.log("Skipping pageView - missing required IP or user-agent");
|
|
355
354
|
return;
|
|
356
355
|
}
|
|
357
|
-
i && Object.keys(i).length > 0 && (r.tags = this.filterScalars(i))
|
|
358
|
-
|
|
359
|
-
|
|
356
|
+
i && Object.keys(i).length > 0 && (r.tags = this.filterScalars(i));
|
|
357
|
+
try {
|
|
358
|
+
await this.request("/api/v1/hit", r), this.log("Tracked page view", { path: (s = e == null ? void 0 : e.page) == null ? void 0 : s.path });
|
|
359
|
+
} catch (n) {
|
|
360
|
+
console.error("[Pirsch-Server] Failed to track page view:", n);
|
|
361
|
+
}
|
|
360
362
|
}
|
|
361
363
|
async reset() {
|
|
362
364
|
if (!this.isEnabled() || !this.initialized) return;
|
|
@@ -412,37 +414,39 @@ class N extends y {
|
|
|
412
414
|
}
|
|
413
415
|
}
|
|
414
416
|
}
|
|
415
|
-
identify(i, e) {
|
|
417
|
+
async identify(i, e) {
|
|
418
|
+
var n, a, h, l, o;
|
|
416
419
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
417
420
|
this.currentUserId = i;
|
|
418
421
|
const r = (e == null ? void 0 : e.email) || i;
|
|
419
422
|
r != null && r.includes("@") && (this.currentUserEmail = r);
|
|
420
423
|
const s = [];
|
|
421
|
-
i && s.push(i), r && r !== i && s.push(r), e != null && e.username && typeof e.username == "string" && s.push(e.username)
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
424
|
+
i && s.push(i), r && r !== i && s.push(r), e != null && e.username && typeof e.username == "string" && s.push(e.username);
|
|
425
|
+
try {
|
|
426
|
+
const t = await this.client.identify({
|
|
427
|
+
user_id: i,
|
|
428
|
+
properties: e || {},
|
|
429
|
+
aliases: s.length > 0 ? s : void 0
|
|
430
|
+
});
|
|
427
431
|
this.log("Identified user", {
|
|
428
432
|
userId: i,
|
|
429
433
|
email: r,
|
|
430
|
-
identityId:
|
|
431
|
-
aliasesCreated: ((
|
|
432
|
-
aliasesFailed: ((
|
|
433
|
-
}), (o =
|
|
434
|
+
identityId: t.data.id,
|
|
435
|
+
aliasesCreated: ((a = (n = t.data.aliases) == null ? void 0 : n.created) == null ? void 0 : a.length) || 0,
|
|
436
|
+
aliasesFailed: ((l = (h = t.data.aliases) == null ? void 0 : h.failed) == null ? void 0 : l.length) || 0
|
|
437
|
+
}), (o = t.data.aliases) != null && o.failed && t.data.aliases.failed.length > 0 && console.warn(
|
|
434
438
|
"[EmitKit-Server] Some aliases failed to create:",
|
|
435
|
-
|
|
439
|
+
t.data.aliases.failed
|
|
436
440
|
);
|
|
437
|
-
}
|
|
438
|
-
console.error("[EmitKit-Server] Failed to identify user:",
|
|
439
|
-
}
|
|
441
|
+
} catch (t) {
|
|
442
|
+
console.error("[EmitKit-Server] Failed to identify user:", t);
|
|
443
|
+
}
|
|
440
444
|
}
|
|
441
445
|
async track(i, e) {
|
|
442
|
-
var
|
|
446
|
+
var t, p;
|
|
443
447
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
444
|
-
const r = ((
|
|
445
|
-
...
|
|
448
|
+
const r = ((t = e == null ? void 0 : e.user) == null ? void 0 : t.email) || ((p = e == null ? void 0 : e.user) == null ? void 0 : p.userId) || i.userId || this.currentUserEmail || this.currentUserId, s = this.formatEventTitle(i.action), { __emitkit_channel: n, ...a } = i.properties || {}, h = {
|
|
449
|
+
...a,
|
|
446
450
|
category: i.category,
|
|
447
451
|
timestamp: i.timestamp || Date.now(),
|
|
448
452
|
...i.sessionId && { sessionId: i.sessionId },
|
|
@@ -461,11 +465,11 @@ class N extends y {
|
|
|
461
465
|
...(e == null ? void 0 : e.utm) && { utm: e.utm },
|
|
462
466
|
...(e == null ? void 0 : e.server) && { server: e.server }
|
|
463
467
|
}, l = [];
|
|
464
|
-
i.category && l.push(i.category),
|
|
465
|
-
const
|
|
468
|
+
i.category && l.push(i.category), a != null && a.tags && Array.isArray(a.tags) && a.tags.every((g) => typeof g == "string") && l.push(...a.tags);
|
|
469
|
+
const o = this.resolveChannelName(i);
|
|
466
470
|
try {
|
|
467
471
|
const g = await this.client.events.create({
|
|
468
|
-
channelName:
|
|
472
|
+
channelName: o,
|
|
469
473
|
title: s,
|
|
470
474
|
description: this.getEventDescription(i, e),
|
|
471
475
|
icon: this.getEventIcon(i.category),
|
|
@@ -480,17 +484,17 @@ class N extends y {
|
|
|
480
484
|
eventId: g.data.id,
|
|
481
485
|
action: i.action,
|
|
482
486
|
userId: r,
|
|
483
|
-
channelName:
|
|
487
|
+
channelName: o
|
|
484
488
|
});
|
|
485
489
|
} catch (g) {
|
|
486
490
|
throw console.error("[EmitKit-Server] Failed to track event:", g), g;
|
|
487
491
|
}
|
|
488
492
|
}
|
|
489
|
-
pageView(i, e) {
|
|
490
|
-
var
|
|
493
|
+
async pageView(i, e) {
|
|
494
|
+
var o, t, p, g;
|
|
491
495
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
492
|
-
const r = ((
|
|
493
|
-
...
|
|
496
|
+
const r = ((o = e == null ? void 0 : e.user) == null ? void 0 : o.email) || ((t = e == null ? void 0 : e.user) == null ? void 0 : t.userId) || this.currentUserEmail || this.currentUserId, { __emitkit_channel: s, ...n } = i || {}, a = {
|
|
497
|
+
...n,
|
|
494
498
|
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
495
499
|
...(e == null ? void 0 : e.page) && {
|
|
496
500
|
page: {
|
|
@@ -511,29 +515,29 @@ class N extends y {
|
|
|
511
515
|
category: "navigation",
|
|
512
516
|
properties: i || {}
|
|
513
517
|
}, l = this.resolveChannelName(h);
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
518
|
+
try {
|
|
519
|
+
const f = await this.client.events.create({
|
|
520
|
+
channelName: l,
|
|
521
|
+
title: "Page View",
|
|
522
|
+
description: ((p = e == null ? void 0 : e.page) == null ? void 0 : p.path) || "User viewed a page",
|
|
523
|
+
icon: "👁️",
|
|
524
|
+
tags: ["page_view", "navigation"],
|
|
525
|
+
metadata: a,
|
|
526
|
+
userId: r || null,
|
|
527
|
+
notify: !1,
|
|
528
|
+
// Don't notify for page views by default
|
|
529
|
+
displayAs: "message",
|
|
530
|
+
source: "stacksee-analytics"
|
|
531
|
+
});
|
|
528
532
|
this.log("Tracked page view", {
|
|
529
|
-
eventId:
|
|
530
|
-
path: (
|
|
533
|
+
eventId: f.data.id,
|
|
534
|
+
path: (g = e == null ? void 0 : e.page) == null ? void 0 : g.path,
|
|
531
535
|
userId: r,
|
|
532
536
|
channelName: l
|
|
533
537
|
});
|
|
534
|
-
}
|
|
535
|
-
console.error("[EmitKit-Server] Failed to track page view:",
|
|
536
|
-
}
|
|
538
|
+
} catch (f) {
|
|
539
|
+
console.error("[EmitKit-Server] Failed to track page view:", f);
|
|
540
|
+
}
|
|
537
541
|
}
|
|
538
542
|
async reset() {
|
|
539
543
|
!this.isEnabled() || !this.initialized || !this.client || (this.currentUserId = void 0, this.currentUserEmail = void 0, this.log("Reset user session"));
|
|
@@ -597,60 +601,60 @@ class N extends y {
|
|
|
597
601
|
}
|
|
598
602
|
}
|
|
599
603
|
async function B(d, u, i) {
|
|
600
|
-
var e, r, s,
|
|
604
|
+
var e, r, s, n;
|
|
601
605
|
try {
|
|
602
|
-
const
|
|
603
|
-
if (!
|
|
606
|
+
const a = await d.json();
|
|
607
|
+
if (!a.events || !Array.isArray(a.events))
|
|
604
608
|
throw new Error("Invalid payload: missing events array");
|
|
605
|
-
const h = i != null && i.extractIp ? i.extractIp(d) : $(d), l = d.headers.get("user-agent"),
|
|
606
|
-
for (const
|
|
609
|
+
const h = i != null && i.extractIp ? i.extractIp(d) : $(d), l = d.headers.get("user-agent"), o = i != null && i.enrichContext ? i.enrichContext(d) : {};
|
|
610
|
+
for (const t of a.events)
|
|
607
611
|
try {
|
|
608
|
-
switch (
|
|
612
|
+
switch (t.type) {
|
|
609
613
|
case "track": {
|
|
610
614
|
const p = {
|
|
611
|
-
...
|
|
612
|
-
...
|
|
615
|
+
...t.context,
|
|
616
|
+
...o,
|
|
613
617
|
server: {
|
|
614
|
-
...(e =
|
|
615
|
-
...typeof (
|
|
618
|
+
...(e = t.context) == null ? void 0 : e.server,
|
|
619
|
+
...typeof (o == null ? void 0 : o.server) == "object" && o.server !== null ? o.server : {},
|
|
616
620
|
...l ? { userAgent: l } : {}
|
|
617
621
|
},
|
|
618
622
|
device: {
|
|
619
|
-
...(r =
|
|
623
|
+
...(r = t.context) == null ? void 0 : r.device,
|
|
620
624
|
...h ? { ip: h } : {}
|
|
621
625
|
}
|
|
622
626
|
};
|
|
623
627
|
await u.track(
|
|
624
|
-
|
|
628
|
+
t.event.action,
|
|
625
629
|
// biome-ignore lint/suspicious/noExplicitAny: Properties from JSON cannot be type-checked against TEventMap at compile time
|
|
626
|
-
|
|
630
|
+
t.event.properties,
|
|
627
631
|
{
|
|
628
|
-
userId:
|
|
629
|
-
sessionId:
|
|
632
|
+
userId: t.event.userId,
|
|
633
|
+
sessionId: t.event.sessionId,
|
|
630
634
|
context: p
|
|
631
635
|
}
|
|
632
636
|
);
|
|
633
637
|
break;
|
|
634
638
|
}
|
|
635
639
|
case "identify": {
|
|
636
|
-
u.identify(
|
|
640
|
+
await u.identify(t.userId, t.traits);
|
|
637
641
|
break;
|
|
638
642
|
}
|
|
639
643
|
case "pageView": {
|
|
640
644
|
const p = {
|
|
641
|
-
...
|
|
642
|
-
...
|
|
645
|
+
...t.context,
|
|
646
|
+
...o,
|
|
643
647
|
server: {
|
|
644
|
-
...(s =
|
|
645
|
-
...typeof (
|
|
648
|
+
...(s = t.context) == null ? void 0 : s.server,
|
|
649
|
+
...typeof (o == null ? void 0 : o.server) == "object" && o.server !== null ? o.server : {},
|
|
646
650
|
...l ? { userAgent: l } : {}
|
|
647
651
|
},
|
|
648
652
|
device: {
|
|
649
|
-
...(
|
|
653
|
+
...(n = t.context) == null ? void 0 : n.device,
|
|
650
654
|
...h ? { ip: h } : {}
|
|
651
655
|
}
|
|
652
656
|
};
|
|
653
|
-
u.pageView(
|
|
657
|
+
await u.pageView(t.properties, {
|
|
654
658
|
context: p
|
|
655
659
|
});
|
|
656
660
|
break;
|
|
@@ -658,13 +662,13 @@ async function B(d, u, i) {
|
|
|
658
662
|
case "reset":
|
|
659
663
|
break;
|
|
660
664
|
default:
|
|
661
|
-
console.warn("[Proxy] Unknown event type:",
|
|
665
|
+
console.warn("[Proxy] Unknown event type:", t);
|
|
662
666
|
}
|
|
663
667
|
} catch (p) {
|
|
664
668
|
i != null && i.onError ? i.onError(p) : console.error("[Proxy] Failed to process event:", p);
|
|
665
669
|
}
|
|
666
|
-
} catch (
|
|
667
|
-
throw i != null && i.onError ? i.onError(
|
|
670
|
+
} catch (a) {
|
|
671
|
+
throw i != null && i.onError ? i.onError(a) : console.error("[Proxy] Failed to ingest events:", a), a;
|
|
668
672
|
}
|
|
669
673
|
}
|
|
670
674
|
function $(d) {
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { BaseEvent, EventContext } from '../../core/events/types.js';
|
|
2
|
+
import { BaseAnalyticsProvider } from '../base.provider.js';
|
|
3
|
+
interface VisitorsClient {
|
|
4
|
+
track(event: string, properties?: Record<string, string | number>): void;
|
|
5
|
+
identify(traits: {
|
|
6
|
+
id: string;
|
|
7
|
+
email?: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
[key: string]: string | number | undefined;
|
|
10
|
+
}): void;
|
|
11
|
+
}
|
|
12
|
+
export interface VisitorsClientConfig {
|
|
13
|
+
/**
|
|
14
|
+
* Your Visitors project token from the dashboard
|
|
15
|
+
*/
|
|
16
|
+
token: string;
|
|
17
|
+
/**
|
|
18
|
+
* Enable debug logging
|
|
19
|
+
*/
|
|
20
|
+
debug?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Enable/disable the provider
|
|
23
|
+
*/
|
|
24
|
+
enabled?: boolean;
|
|
25
|
+
}
|
|
26
|
+
declare global {
|
|
27
|
+
interface Window {
|
|
28
|
+
visitors?: VisitorsClient;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export declare class VisitorsClientProvider extends BaseAnalyticsProvider {
|
|
32
|
+
name: string;
|
|
33
|
+
private visitors?;
|
|
34
|
+
private initialized;
|
|
35
|
+
private config;
|
|
36
|
+
private scriptLoaded;
|
|
37
|
+
constructor(config: VisitorsClientConfig);
|
|
38
|
+
initialize(): Promise<void>;
|
|
39
|
+
private loadScript;
|
|
40
|
+
private waitForVisitors;
|
|
41
|
+
identify(userId: string, traits?: Record<string, unknown>): void;
|
|
42
|
+
track(event: BaseEvent, context?: EventContext): void;
|
|
43
|
+
pageView(properties?: Record<string, unknown>, context?: EventContext): void;
|
|
44
|
+
pageLeave(properties?: Record<string, unknown>, context?: EventContext): void;
|
|
45
|
+
reset(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Returns the current visitor ID from the `visitor` cookie set by the
|
|
48
|
+
* visitors.now script. Pass this value in your Stripe checkout session
|
|
49
|
+
* metadata so revenue is attributed to the correct visitor.
|
|
50
|
+
*
|
|
51
|
+
* Requires persist mode to be enabled in your visitors.now project settings.
|
|
52
|
+
*
|
|
53
|
+
* @example Server-side Stripe checkout creation:
|
|
54
|
+
* ```typescript
|
|
55
|
+
* // Client-side: get visitor ID and send to your server
|
|
56
|
+
* const visitorId = visitorsProvider.getVisitorId();
|
|
57
|
+
*
|
|
58
|
+
* // Server-side: include in Stripe checkout session
|
|
59
|
+
* const session = await stripe.checkout.sessions.create({
|
|
60
|
+
* // ...
|
|
61
|
+
* metadata: { visitor: visitorId },
|
|
62
|
+
* });
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
getVisitorId(): string | null;
|
|
66
|
+
}
|
|
67
|
+
export {};
|
package/dist/server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
var u = Object.defineProperty;
|
|
2
|
-
var h = (
|
|
3
|
-
var c = (
|
|
2
|
+
var h = (a, e, t) => e in a ? u(a, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : a[e] = t;
|
|
3
|
+
var c = (a, e, t) => h(a, typeof e != "symbol" ? e + "" : e, t);
|
|
4
4
|
import { P as w } from "./server-DjEk1fUD.js";
|
|
5
5
|
import { B as y } from "./base.provider-AfFL5W_P.js";
|
|
6
6
|
class f {
|
|
@@ -68,25 +68,25 @@ class f {
|
|
|
68
68
|
), r.excludeEvents && r.eventPatterns && console.warn(
|
|
69
69
|
`[Analytics] Provider ${r.provider.name} has both 'excludeEvents' and 'eventPatterns' specified. Using 'eventPatterns' and ignoring 'excludeEvents'.`
|
|
70
70
|
);
|
|
71
|
-
let
|
|
72
|
-
r.methods ?
|
|
71
|
+
let i;
|
|
72
|
+
r.methods ? i = new Set(r.methods) : r.exclude ? i = new Set(
|
|
73
73
|
t.filter(
|
|
74
|
-
(
|
|
74
|
+
(o) => {
|
|
75
75
|
var v;
|
|
76
|
-
return !((v = r.exclude) != null && v.includes(
|
|
76
|
+
return !((v = r.exclude) != null && v.includes(o));
|
|
77
77
|
}
|
|
78
78
|
)
|
|
79
|
-
) :
|
|
80
|
-
let
|
|
81
|
-
return r.events && r.events.length > 0 ?
|
|
82
|
-
const v =
|
|
79
|
+
) : i = new Set(t);
|
|
80
|
+
let s, l, d;
|
|
81
|
+
return r.events && r.events.length > 0 ? s = new Set(r.events) : r.eventPatterns && r.eventPatterns.length > 0 ? d = r.eventPatterns.map((o) => {
|
|
82
|
+
const v = o.replace(/\*/g, ".*");
|
|
83
83
|
return new RegExp(`^${v}$`);
|
|
84
|
-
}) : r.excludeEvents && r.excludeEvents.length > 0 && (
|
|
84
|
+
}) : r.excludeEvents && r.excludeEvents.length > 0 && (l = new Set(r.excludeEvents)), {
|
|
85
85
|
provider: r.provider,
|
|
86
|
-
enabledMethods:
|
|
87
|
-
enabledEvents:
|
|
88
|
-
excludedEvents:
|
|
89
|
-
eventPatterns:
|
|
86
|
+
enabledMethods: i,
|
|
87
|
+
enabledEvents: s,
|
|
88
|
+
excludedEvents: l,
|
|
89
|
+
eventPatterns: d
|
|
90
90
|
};
|
|
91
91
|
});
|
|
92
92
|
}
|
|
@@ -191,9 +191,11 @@ class f {
|
|
|
191
191
|
* }
|
|
192
192
|
* ```
|
|
193
193
|
*/
|
|
194
|
-
identify(e, t) {
|
|
195
|
-
|
|
196
|
-
|
|
194
|
+
async identify(e, t) {
|
|
195
|
+
const n = this.providerConfigs.filter((i) => this.shouldCallMethod(i, "identify")).map((i) => i.provider.identify(e, t)), r = await Promise.allSettled(n);
|
|
196
|
+
for (const i of r)
|
|
197
|
+
if (i.status === "rejected")
|
|
198
|
+
throw i.reason;
|
|
197
199
|
}
|
|
198
200
|
/**
|
|
199
201
|
* Tracks a custom event with properties and optional context.
|
|
@@ -317,7 +319,7 @@ class f {
|
|
|
317
319
|
* ```
|
|
318
320
|
*/
|
|
319
321
|
async track(e, t, n) {
|
|
320
|
-
var
|
|
322
|
+
var l;
|
|
321
323
|
if (!this.initialized) {
|
|
322
324
|
console.warn("[Analytics] Not initialized. Call initialize() first.");
|
|
323
325
|
return;
|
|
@@ -329,23 +331,23 @@ class f {
|
|
|
329
331
|
timestamp: Date.now(),
|
|
330
332
|
userId: n == null ? void 0 : n.userId,
|
|
331
333
|
sessionId: n == null ? void 0 : n.sessionId
|
|
332
|
-
},
|
|
334
|
+
}, i = {
|
|
333
335
|
...this.config.defaultContext,
|
|
334
336
|
...n == null ? void 0 : n.context,
|
|
335
|
-
user: (n == null ? void 0 : n.user) || ((
|
|
336
|
-
},
|
|
337
|
-
(
|
|
338
|
-
).map(async (
|
|
337
|
+
user: (n == null ? void 0 : n.user) || ((l = n == null ? void 0 : n.context) == null ? void 0 : l.user)
|
|
338
|
+
}, s = this.providerConfigs.filter(
|
|
339
|
+
(d) => this.shouldCallMethod(d, "track") && this.shouldTrackEvent(d, e)
|
|
340
|
+
).map(async (d) => {
|
|
339
341
|
try {
|
|
340
|
-
await
|
|
341
|
-
} catch (
|
|
342
|
+
await d.provider.track(r, i);
|
|
343
|
+
} catch (o) {
|
|
342
344
|
console.error(
|
|
343
|
-
`[Analytics] Provider ${
|
|
344
|
-
|
|
345
|
+
`[Analytics] Provider ${d.provider.name} failed to track event:`,
|
|
346
|
+
o
|
|
345
347
|
);
|
|
346
348
|
}
|
|
347
349
|
});
|
|
348
|
-
await Promise.all(
|
|
350
|
+
await Promise.all(s);
|
|
349
351
|
}
|
|
350
352
|
/**
|
|
351
353
|
* Tracks a page view event from the server side.
|
|
@@ -407,14 +409,15 @@ class f {
|
|
|
407
409
|
* }
|
|
408
410
|
* ```
|
|
409
411
|
*/
|
|
410
|
-
pageView(e, t) {
|
|
412
|
+
async pageView(e, t) {
|
|
411
413
|
if (!this.initialized) return;
|
|
412
414
|
const n = {
|
|
413
415
|
...this.config.defaultContext,
|
|
414
416
|
...t == null ? void 0 : t.context
|
|
415
|
-
};
|
|
416
|
-
for (const
|
|
417
|
-
|
|
417
|
+
}, r = this.providerConfigs.filter((s) => this.shouldCallMethod(s, "pageView")).map((s) => s.provider.pageView(e, n)), i = await Promise.allSettled(r);
|
|
418
|
+
for (const s of i)
|
|
419
|
+
if (s.status === "rejected")
|
|
420
|
+
throw s.reason;
|
|
418
421
|
}
|
|
419
422
|
/**
|
|
420
423
|
* Tracks when a user leaves a page from the server side.
|
|
@@ -577,11 +580,11 @@ class f {
|
|
|
577
580
|
return t.length > 1 && t[0] ? t[0] : "engagement";
|
|
578
581
|
}
|
|
579
582
|
}
|
|
580
|
-
function
|
|
583
|
+
function m(a) {
|
|
581
584
|
const e = {
|
|
582
|
-
providers:
|
|
583
|
-
debug:
|
|
584
|
-
enabled:
|
|
585
|
+
providers: a.providers || [],
|
|
586
|
+
debug: a.debug,
|
|
587
|
+
enabled: a.enabled
|
|
585
588
|
}, t = new f(e);
|
|
586
589
|
return t.initialize(), t;
|
|
587
590
|
}
|
|
@@ -589,5 +592,5 @@ export {
|
|
|
589
592
|
y as BaseAnalyticsProvider,
|
|
590
593
|
w as PostHogServerProvider,
|
|
591
594
|
f as ServerAnalytics,
|
|
592
|
-
|
|
595
|
+
m as createServerAnalytics
|
|
593
596
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksee/analytics",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "A highly typed, provider-agnostic analytics library for TypeScript applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"@vitest/coverage-v8": "3.1.4",
|
|
57
57
|
"globals": "^15.8.0",
|
|
58
58
|
"jsdom": "^26.1.0",
|
|
59
|
+
"playwright": "^1.58.2",
|
|
59
60
|
"prettier": "^3.3.3",
|
|
60
61
|
"typescript": "~5.5.3",
|
|
61
62
|
"vite": "^6.3.5",
|
|
@@ -76,12 +77,16 @@
|
|
|
76
77
|
"scripts": {
|
|
77
78
|
"test": "vitest run",
|
|
78
79
|
"test:watch": "vitest",
|
|
80
|
+
"test:e2e": "node e2e/pirsch.test.js",
|
|
81
|
+
"test:e2e:server": "node e2e/test-app/server.js",
|
|
82
|
+
"test:e2e:visitors": "node e2e/visitors.test.js",
|
|
83
|
+
"test:e2e:visitors:server": "node e2e/visitors-test-app/server.js",
|
|
79
84
|
"build": "vite build",
|
|
80
85
|
"dev": "pnpm --filter @stacksee/docs dev",
|
|
81
86
|
"build:docs": "pnpm --filter @stacksee/docs build",
|
|
82
87
|
"deploy": "npm publish",
|
|
83
88
|
"typecheck": "tsc --noEmit",
|
|
84
|
-
"ci:publish": "pnpm build && changeset publish",
|
|
89
|
+
"ci:publish": "pnpm build && changeset publish --provenance",
|
|
85
90
|
"lint": "biome lint .",
|
|
86
91
|
"format": "biome format --write .",
|
|
87
92
|
"biome": "biome"
|