@stacksee/analytics 0.5.0 → 0.8.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/_commonjsHelpers-B4e78b8K.js +28 -0
- package/dist/axios-gULqh8dv.js +1820 -0
- package/dist/bento-node-sdk.esm-C4HG7SVz.js +1711 -0
- package/dist/index-bgxxv-IJ.js +829 -0
- package/dist/providers/bento/client.d.ts +47 -0
- package/dist/providers/bento/server.d.ts +58 -0
- package/dist/providers/client.d.ts +7 -0
- package/dist/providers/client.js +371 -4
- package/dist/providers/pirsch/client.d.ts +34 -0
- package/dist/providers/pirsch/server.d.ts +49 -0
- package/dist/providers/proxy/client.d.ts +56 -0
- package/dist/providers/proxy/server.d.ts +55 -0
- package/dist/providers/proxy/types.d.ts +64 -0
- package/dist/providers/server.d.ts +6 -0
- package/dist/providers/server.js +305 -4
- package/dist/web-CvEQewPd.js +220 -0
- package/package.json +3 -1
- package/readme.md +48 -21
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { BaseEvent, EventContext } from '../../core/events/types.js';
|
|
2
|
+
import { BaseAnalyticsProvider } from '../base.provider.js';
|
|
3
|
+
interface BentoClient {
|
|
4
|
+
view(): void;
|
|
5
|
+
identify(email: string): void;
|
|
6
|
+
track(event: string, data?: Record<string, unknown>): void;
|
|
7
|
+
tag(tag: string): void;
|
|
8
|
+
updateFields(fields: Record<string, unknown>): void;
|
|
9
|
+
getEmail(): string | null;
|
|
10
|
+
getName(): string | null;
|
|
11
|
+
}
|
|
12
|
+
export interface BentoClientConfig {
|
|
13
|
+
/**
|
|
14
|
+
* Your Bento Site UUID from Account Settings
|
|
15
|
+
*/
|
|
16
|
+
siteUuid: 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
|
+
bento?: BentoClient;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export declare class BentoClientProvider extends BaseAnalyticsProvider {
|
|
32
|
+
name: string;
|
|
33
|
+
private bento?;
|
|
34
|
+
private initialized;
|
|
35
|
+
private config;
|
|
36
|
+
private scriptLoaded;
|
|
37
|
+
constructor(config: BentoClientConfig);
|
|
38
|
+
initialize(): Promise<void>;
|
|
39
|
+
private loadBentoScript;
|
|
40
|
+
private waitForBento;
|
|
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
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { BaseEvent, EventContext } from '../../core/events/types.js';
|
|
2
|
+
import { BaseAnalyticsProvider } from '../base.provider.js';
|
|
3
|
+
export interface BentoAnalyticsOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Your Bento Site UUID from Team Settings
|
|
6
|
+
*/
|
|
7
|
+
siteUuid: string;
|
|
8
|
+
/**
|
|
9
|
+
* Authentication credentials
|
|
10
|
+
*/
|
|
11
|
+
authentication: {
|
|
12
|
+
/**
|
|
13
|
+
* Your Bento Publishable Key from Team Settings
|
|
14
|
+
*/
|
|
15
|
+
publishableKey: string;
|
|
16
|
+
/**
|
|
17
|
+
* Your Bento Secret Key from Team Settings
|
|
18
|
+
*/
|
|
19
|
+
secretKey: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Optional client configuration
|
|
23
|
+
*/
|
|
24
|
+
clientOptions?: {
|
|
25
|
+
/**
|
|
26
|
+
* Base URL for the Bento API (optional)
|
|
27
|
+
*/
|
|
28
|
+
baseUrl?: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Whether to log errors (optional)
|
|
32
|
+
*/
|
|
33
|
+
logErrors?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface BentoServerConfig extends BentoAnalyticsOptions {
|
|
36
|
+
/**
|
|
37
|
+
* Enable debug logging
|
|
38
|
+
*/
|
|
39
|
+
debug?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Enable/disable the provider
|
|
42
|
+
*/
|
|
43
|
+
enabled?: boolean;
|
|
44
|
+
}
|
|
45
|
+
export declare class BentoServerProvider extends BaseAnalyticsProvider {
|
|
46
|
+
name: string;
|
|
47
|
+
private client?;
|
|
48
|
+
private initialized;
|
|
49
|
+
private config;
|
|
50
|
+
private currentUserEmail?;
|
|
51
|
+
constructor(config: BentoServerConfig);
|
|
52
|
+
initialize(): Promise<void>;
|
|
53
|
+
identify(userId: string, traits?: Record<string, unknown>): void;
|
|
54
|
+
track(event: BaseEvent, context?: EventContext): Promise<void>;
|
|
55
|
+
pageView(properties?: Record<string, unknown>, context?: EventContext): void;
|
|
56
|
+
reset(): Promise<void>;
|
|
57
|
+
shutdown(): Promise<void>;
|
|
58
|
+
}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
export { BaseAnalyticsProvider } from './base.provider.js';
|
|
2
2
|
export { PostHogClientProvider } from './posthog/client.js';
|
|
3
3
|
export type { PostHogConfig } from 'posthog-js';
|
|
4
|
+
export { BentoClientProvider } from './bento/client.js';
|
|
5
|
+
export type { BentoClientConfig } from './bento/client.js';
|
|
6
|
+
export { PirschClientProvider } from './pirsch/client.js';
|
|
7
|
+
export type { PirschClientConfig } from './pirsch/client.js';
|
|
8
|
+
export { ProxyProvider } from './proxy/client.js';
|
|
9
|
+
export type { ProxyProviderConfig } from './proxy/client.js';
|
|
10
|
+
export type { ProxyBatchConfig, ProxyRetryConfig, ProxyEvent, ProxyPayload, ProxyTrackEvent, ProxyIdentifyEvent, ProxyPageViewEvent, ProxyResetEvent, } from './proxy/types.js';
|
package/dist/providers/client.js
CHANGED
|
@@ -1,6 +1,373 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
var u = Object.defineProperty;
|
|
2
|
+
var f = (h, n, i) => n in h ? u(h, n, { enumerable: !0, configurable: !0, writable: !0, value: i }) : h[n] = i;
|
|
3
|
+
var r = (h, n, i) => f(h, typeof n != "symbol" ? n + "" : n, i);
|
|
4
|
+
import { B as o } from "../base.provider-AfFL5W_P.js";
|
|
5
|
+
import { i as l } from "../client-DTHZYkxx.js";
|
|
6
|
+
import { P as E } from "../client-DTHZYkxx.js";
|
|
7
|
+
class y extends o {
|
|
8
|
+
constructor(i) {
|
|
9
|
+
super({ debug: i.debug, enabled: i.enabled });
|
|
10
|
+
r(this, "name", "Bento-Client");
|
|
11
|
+
r(this, "bento");
|
|
12
|
+
r(this, "initialized", !1);
|
|
13
|
+
r(this, "config");
|
|
14
|
+
r(this, "scriptLoaded", !1);
|
|
15
|
+
this.config = i;
|
|
16
|
+
}
|
|
17
|
+
async initialize() {
|
|
18
|
+
if (this.isEnabled() && !this.initialized) {
|
|
19
|
+
if (!l()) {
|
|
20
|
+
this.log("Skipping initialization - not in browser environment");
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (!this.config.siteUuid || typeof this.config.siteUuid != "string")
|
|
24
|
+
throw new Error("Bento requires a siteUuid");
|
|
25
|
+
try {
|
|
26
|
+
this.scriptLoaded || await this.loadBentoScript(), await this.waitForBento(), this.bento = window.bento, this.initialized = !0, this.log("Initialized successfully", this.config);
|
|
27
|
+
} catch (i) {
|
|
28
|
+
throw console.error("[Bento-Client] Failed to initialize:", i), i;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async loadBentoScript() {
|
|
33
|
+
return new Promise((i, e) => {
|
|
34
|
+
if (document.querySelector(
|
|
35
|
+
'script[src*="bentonow.com"]'
|
|
36
|
+
)) {
|
|
37
|
+
this.scriptLoaded = !0, i();
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const t = document.createElement("script");
|
|
41
|
+
t.src = `https://cdn.bentonow.com/v1/${this.config.siteUuid}/bento.js`, t.async = !0, t.onload = () => {
|
|
42
|
+
this.scriptLoaded = !0, i();
|
|
43
|
+
}, t.onerror = () => {
|
|
44
|
+
e(new Error("Failed to load Bento script"));
|
|
45
|
+
}, document.head.appendChild(t);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async waitForBento(i = 50, e = 100) {
|
|
49
|
+
for (let s = 0; s < i; s++) {
|
|
50
|
+
if (window.bento)
|
|
51
|
+
return;
|
|
52
|
+
await new Promise((t) => setTimeout(t, e));
|
|
53
|
+
}
|
|
54
|
+
throw new Error("Bento SDK not available after loading script");
|
|
55
|
+
}
|
|
56
|
+
identify(i, e) {
|
|
57
|
+
if (!this.isEnabled() || !this.initialized || !this.bento) return;
|
|
58
|
+
const s = (e == null ? void 0 : e.email) || i;
|
|
59
|
+
if (this.bento.identify(s), e) {
|
|
60
|
+
const t = { ...e };
|
|
61
|
+
delete t.email, Object.keys(t).length > 0 && this.bento.updateFields(t);
|
|
62
|
+
}
|
|
63
|
+
this.log("Identified user", { userId: i, email: s, traits: e });
|
|
64
|
+
}
|
|
65
|
+
track(i, e) {
|
|
66
|
+
var t, a;
|
|
67
|
+
if (!this.isEnabled() || !this.initialized || !this.bento) return;
|
|
68
|
+
const s = {
|
|
69
|
+
...i.properties,
|
|
70
|
+
category: i.category,
|
|
71
|
+
timestamp: i.timestamp || Date.now(),
|
|
72
|
+
...i.userId && { userId: i.userId },
|
|
73
|
+
...i.sessionId && { sessionId: i.sessionId },
|
|
74
|
+
...(e == null ? void 0 : e.page) && {
|
|
75
|
+
page: {
|
|
76
|
+
path: e.page.path,
|
|
77
|
+
title: e.page.title,
|
|
78
|
+
referrer: e.page.referrer
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
...(e == null ? void 0 : e.device) && { device: e.device },
|
|
82
|
+
...(e == null ? void 0 : e.utm) && { utm: e.utm },
|
|
83
|
+
// Include user email and traits as regular event properties
|
|
84
|
+
...((t = e == null ? void 0 : e.user) == null ? void 0 : t.email) && { user_email: e.user.email },
|
|
85
|
+
...((a = e == null ? void 0 : e.user) == null ? void 0 : a.traits) && { user_traits: e.user.traits }
|
|
86
|
+
};
|
|
87
|
+
this.bento.track(i.action, s), this.log("Tracked event", { event: i, context: e });
|
|
88
|
+
}
|
|
89
|
+
pageView(i, e) {
|
|
90
|
+
if (!(!this.isEnabled() || !this.initialized || !this.bento || !l())) {
|
|
91
|
+
if (this.bento.view(), i || e != null && e.page) {
|
|
92
|
+
const s = {
|
|
93
|
+
...i,
|
|
94
|
+
...(e == null ? void 0 : e.page) && {
|
|
95
|
+
path: e.page.path,
|
|
96
|
+
title: e.page.title,
|
|
97
|
+
referrer: e.page.referrer
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
this.bento.track("$pageview", s);
|
|
101
|
+
}
|
|
102
|
+
this.log("Tracked page view", { properties: i, context: e });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
pageLeave(i, e) {
|
|
106
|
+
if (!this.isEnabled() || !this.initialized || !this.bento || !l())
|
|
107
|
+
return;
|
|
108
|
+
const s = {
|
|
109
|
+
...i,
|
|
110
|
+
...(e == null ? void 0 : e.page) && {
|
|
111
|
+
path: e.page.path,
|
|
112
|
+
title: e.page.title,
|
|
113
|
+
referrer: e.page.referrer
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
this.bento.track("$pageleave", s), this.log("Tracked page leave", { properties: i, context: e });
|
|
117
|
+
}
|
|
118
|
+
reset() {
|
|
119
|
+
!this.isEnabled() || !this.initialized || !this.bento || !l() || this.log("Reset user session - Note: Bento doesn't have a native reset method");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
class w extends o {
|
|
123
|
+
constructor(i) {
|
|
124
|
+
super({ debug: i.debug, enabled: i.enabled });
|
|
125
|
+
r(this, "name", "Pirsch-Client");
|
|
126
|
+
r(this, "client");
|
|
127
|
+
r(this, "initialized", !1);
|
|
128
|
+
r(this, "config");
|
|
129
|
+
this.config = i;
|
|
130
|
+
}
|
|
131
|
+
async initialize() {
|
|
132
|
+
if (this.isEnabled() && !this.initialized) {
|
|
133
|
+
if (!l()) {
|
|
134
|
+
this.log("Skipping initialization - not in browser environment");
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (!this.config.identificationCode || typeof this.config.identificationCode != "string")
|
|
138
|
+
throw new Error("Pirsch requires an identificationCode");
|
|
139
|
+
try {
|
|
140
|
+
const { Pirsch: i } = await import("../web-CvEQewPd.js").then((e) => e.w);
|
|
141
|
+
this.client = new i({
|
|
142
|
+
identificationCode: this.config.identificationCode,
|
|
143
|
+
...this.config.hostname && { hostname: this.config.hostname }
|
|
144
|
+
}), this.initialized = !0, this.log("Initialized successfully", this.config);
|
|
145
|
+
} catch (i) {
|
|
146
|
+
throw console.error(
|
|
147
|
+
"[Pirsch-Client] Failed to initialize. Make sure pirsch-sdk is installed:",
|
|
148
|
+
i
|
|
149
|
+
), i;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
identify(i, e) {
|
|
154
|
+
!this.isEnabled() || !this.initialized || !this.client || (this.client.event("user_identified", 0, {
|
|
155
|
+
userId: i,
|
|
156
|
+
...e
|
|
157
|
+
}).catch((s) => {
|
|
158
|
+
console.error("[Pirsch-Client] Failed to track identify event:", s);
|
|
159
|
+
}), this.log("Identified user via event", { userId: i, traits: e }));
|
|
160
|
+
}
|
|
161
|
+
async track(i, e) {
|
|
162
|
+
var t, a;
|
|
163
|
+
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
164
|
+
const s = {
|
|
165
|
+
...i.properties,
|
|
166
|
+
category: i.category,
|
|
167
|
+
...i.userId && { userId: i.userId },
|
|
168
|
+
...i.sessionId && { sessionId: i.sessionId },
|
|
169
|
+
...(e == null ? void 0 : e.page) && {
|
|
170
|
+
page_path: e.page.path,
|
|
171
|
+
page_title: e.page.title,
|
|
172
|
+
page_referrer: e.page.referrer
|
|
173
|
+
},
|
|
174
|
+
...(e == null ? void 0 : e.device) && { device: e.device },
|
|
175
|
+
...(e == null ? void 0 : e.utm) && { utm: e.utm },
|
|
176
|
+
...((t = e == null ? void 0 : e.user) == null ? void 0 : t.email) && { user_email: e.user.email },
|
|
177
|
+
...((a = e == null ? void 0 : e.user) == null ? void 0 : a.traits) && { user_traits: e.user.traits }
|
|
178
|
+
};
|
|
179
|
+
try {
|
|
180
|
+
await this.client.event(i.action, 0, s), this.log("Tracked event", { event: i, context: e });
|
|
181
|
+
} catch (d) {
|
|
182
|
+
console.error("[Pirsch-Client] Failed to track event:", d);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
pageView(i, e) {
|
|
186
|
+
if (!(!this.isEnabled() || !this.initialized || !this.client || !l())) {
|
|
187
|
+
if (this.client.hit().catch((s) => {
|
|
188
|
+
console.error("[Pirsch-Client] Failed to track page view:", s);
|
|
189
|
+
}), i && Object.keys(i).length > 0) {
|
|
190
|
+
const s = {
|
|
191
|
+
...i,
|
|
192
|
+
...(e == null ? void 0 : e.page) && {
|
|
193
|
+
path: e.page.path,
|
|
194
|
+
title: e.page.title,
|
|
195
|
+
referrer: e.page.referrer
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
this.client.event("page_view", 0, s).catch((t) => {
|
|
199
|
+
console.error(
|
|
200
|
+
"[Pirsch-Client] Failed to track page view event:",
|
|
201
|
+
t
|
|
202
|
+
);
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
this.log("Tracked page view", { properties: i, context: e });
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
pageLeave(i, e) {
|
|
209
|
+
if (!this.isEnabled() || !this.initialized || !this.client || !l())
|
|
210
|
+
return;
|
|
211
|
+
const s = {
|
|
212
|
+
...i,
|
|
213
|
+
...(e == null ? void 0 : e.page) && {
|
|
214
|
+
path: e.page.path,
|
|
215
|
+
title: e.page.title
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
this.client.event("page_leave", 0, s).catch((t) => {
|
|
219
|
+
console.error("[Pirsch-Client] Failed to track page leave:", t);
|
|
220
|
+
}), this.log("Tracked page leave", { properties: i, context: e });
|
|
221
|
+
}
|
|
222
|
+
reset() {
|
|
223
|
+
!this.isEnabled() || !this.initialized || !this.client || !l() || (this.client.event("session_reset", 0, {}).catch((i) => {
|
|
224
|
+
console.error("[Pirsch-Client] Failed to track session reset:", i);
|
|
225
|
+
}), this.log("Reset user session"));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
class m extends o {
|
|
229
|
+
constructor(i) {
|
|
230
|
+
var e, s, t, a, d;
|
|
231
|
+
super({ debug: i.debug, enabled: i.enabled });
|
|
232
|
+
r(this, "name", "Proxy");
|
|
233
|
+
r(this, "config");
|
|
234
|
+
r(this, "queue", []);
|
|
235
|
+
r(this, "flushTimer");
|
|
236
|
+
r(this, "batchSize");
|
|
237
|
+
r(this, "batchInterval");
|
|
238
|
+
r(this, "retryAttempts");
|
|
239
|
+
r(this, "retryBackoff");
|
|
240
|
+
r(this, "retryInitialDelay");
|
|
241
|
+
this.config = i, this.batchSize = ((e = i.batch) == null ? void 0 : e.size) ?? 10, this.batchInterval = ((s = i.batch) == null ? void 0 : s.interval) ?? 5e3, this.retryAttempts = ((t = i.retry) == null ? void 0 : t.attempts) ?? 3, this.retryBackoff = ((a = i.retry) == null ? void 0 : a.backoff) ?? "exponential", this.retryInitialDelay = ((d = i.retry) == null ? void 0 : d.initialDelay) ?? 1e3, typeof window < "u" && (window.addEventListener("beforeunload", () => {
|
|
242
|
+
this.flush(!0);
|
|
243
|
+
}), document.addEventListener("visibilitychange", () => {
|
|
244
|
+
document.visibilityState === "hidden" && this.flush(!0);
|
|
245
|
+
}));
|
|
246
|
+
}
|
|
247
|
+
async initialize() {
|
|
248
|
+
this.isEnabled() && this.log("Initialized successfully", { endpoint: this.config.endpoint });
|
|
249
|
+
}
|
|
250
|
+
identify(i, e) {
|
|
251
|
+
this.isEnabled() && (this.queueEvent({
|
|
252
|
+
type: "identify",
|
|
253
|
+
userId: i,
|
|
254
|
+
traits: e
|
|
255
|
+
}), this.log("Queued identify event", { userId: i, traits: e }));
|
|
256
|
+
}
|
|
257
|
+
async track(i, e) {
|
|
258
|
+
this.isEnabled() && (this.queueEvent({
|
|
259
|
+
type: "track",
|
|
260
|
+
event: i,
|
|
261
|
+
context: this.enrichContext(e)
|
|
262
|
+
}), this.log("Queued track event", { event: i, context: e }));
|
|
263
|
+
}
|
|
264
|
+
pageView(i, e) {
|
|
265
|
+
this.isEnabled() && (this.queueEvent({
|
|
266
|
+
type: "pageView",
|
|
267
|
+
properties: i,
|
|
268
|
+
context: this.enrichContext(e)
|
|
269
|
+
}), this.log("Queued page view event", { properties: i, context: e }));
|
|
270
|
+
}
|
|
271
|
+
async reset() {
|
|
272
|
+
this.isEnabled() && (this.queueEvent({
|
|
273
|
+
type: "reset"
|
|
274
|
+
}), this.log("Queued reset event"));
|
|
275
|
+
}
|
|
276
|
+
async shutdown() {
|
|
277
|
+
await this.flush(!0), this.log("Shutdown complete");
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Manually flush all queued events
|
|
281
|
+
*/
|
|
282
|
+
async flush(i = !1) {
|
|
283
|
+
if (this.queue.length === 0) return;
|
|
284
|
+
const e = [...this.queue];
|
|
285
|
+
this.queue = [], this.flushTimer && (clearTimeout(this.flushTimer), this.flushTimer = void 0), await this.sendEvents(e, i);
|
|
286
|
+
}
|
|
287
|
+
queueEvent(i) {
|
|
288
|
+
if (this.queue.push(i), this.queue.length >= this.batchSize) {
|
|
289
|
+
this.flush().catch((e) => {
|
|
290
|
+
console.error("[Proxy] Failed to flush events:", e);
|
|
291
|
+
});
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
this.flushTimer || (this.flushTimer = setTimeout(() => {
|
|
295
|
+
this.flush().catch((e) => {
|
|
296
|
+
console.error("[Proxy] Failed to flush events:", e);
|
|
297
|
+
});
|
|
298
|
+
}, this.batchInterval));
|
|
299
|
+
}
|
|
300
|
+
async sendEvents(i, e = !1) {
|
|
301
|
+
const s = { events: i };
|
|
302
|
+
if (e && typeof navigator < "u" && navigator.sendBeacon) {
|
|
303
|
+
const t = new Blob([JSON.stringify(s)], {
|
|
304
|
+
type: "application/json"
|
|
305
|
+
});
|
|
306
|
+
navigator.sendBeacon(this.config.endpoint, t) || console.warn("[Proxy] Failed to send events via beacon");
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
await this.sendWithRetry(s);
|
|
310
|
+
}
|
|
311
|
+
async sendWithRetry(i, e = 0) {
|
|
312
|
+
try {
|
|
313
|
+
const s = await fetch(this.config.endpoint, {
|
|
314
|
+
method: "POST",
|
|
315
|
+
headers: {
|
|
316
|
+
"Content-Type": "application/json",
|
|
317
|
+
...this.config.headers
|
|
318
|
+
},
|
|
319
|
+
body: JSON.stringify(i),
|
|
320
|
+
// Don't include credentials by default
|
|
321
|
+
credentials: "same-origin"
|
|
322
|
+
});
|
|
323
|
+
if (!s.ok)
|
|
324
|
+
throw new Error(`HTTP ${s.status}: ${s.statusText}`);
|
|
325
|
+
this.log(`Sent ${i.events.length} events successfully`);
|
|
326
|
+
} catch (s) {
|
|
327
|
+
if (e < this.retryAttempts) {
|
|
328
|
+
const t = this.calculateRetryDelay(e);
|
|
329
|
+
return this.log(`Retry attempt ${e + 1} after ${t}ms`, { error: s }), await new Promise((a) => setTimeout(a, t)), this.sendWithRetry(i, e + 1);
|
|
330
|
+
}
|
|
331
|
+
throw console.error("[Proxy] Failed to send events after retries:", s), s;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
calculateRetryDelay(i) {
|
|
335
|
+
return this.retryBackoff === "exponential" ? this.retryInitialDelay * 2 ** i : this.retryInitialDelay * (i + 1);
|
|
336
|
+
}
|
|
337
|
+
enrichContext(i) {
|
|
338
|
+
return typeof window > "u" ? i || {} : {
|
|
339
|
+
...i,
|
|
340
|
+
page: {
|
|
341
|
+
path: window.location.pathname,
|
|
342
|
+
title: document.title,
|
|
343
|
+
referrer: document.referrer,
|
|
344
|
+
...i == null ? void 0 : i.page,
|
|
345
|
+
url: window.location.href
|
|
346
|
+
},
|
|
347
|
+
user: {
|
|
348
|
+
...i == null ? void 0 : i.user
|
|
349
|
+
},
|
|
350
|
+
device: {
|
|
351
|
+
...i == null ? void 0 : i.device,
|
|
352
|
+
userAgent: navigator.userAgent,
|
|
353
|
+
language: navigator.language,
|
|
354
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
355
|
+
screen: {
|
|
356
|
+
width: window.screen.width,
|
|
357
|
+
height: window.screen.height
|
|
358
|
+
},
|
|
359
|
+
viewport: {
|
|
360
|
+
width: window.innerWidth,
|
|
361
|
+
height: window.innerHeight
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
}
|
|
3
367
|
export {
|
|
4
|
-
|
|
5
|
-
|
|
368
|
+
o as BaseAnalyticsProvider,
|
|
369
|
+
y as BentoClientProvider,
|
|
370
|
+
w as PirschClientProvider,
|
|
371
|
+
E as PostHogClientProvider,
|
|
372
|
+
m as ProxyProvider
|
|
6
373
|
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { BaseEvent, EventContext } from '../../core/events/types.js';
|
|
2
|
+
import { BaseAnalyticsProvider } from '../base.provider.js';
|
|
3
|
+
export interface PirschClientConfig {
|
|
4
|
+
/**
|
|
5
|
+
* Your Pirsch identification code from the dashboard
|
|
6
|
+
* Found in: Settings > Integrations > JavaScript Snippet
|
|
7
|
+
*/
|
|
8
|
+
identificationCode: string;
|
|
9
|
+
/**
|
|
10
|
+
* The hostname/domain being tracked (e.g., "example.com")
|
|
11
|
+
*/
|
|
12
|
+
hostname?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Enable debug logging
|
|
15
|
+
*/
|
|
16
|
+
debug?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Enable/disable the provider
|
|
19
|
+
*/
|
|
20
|
+
enabled?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare class PirschClientProvider extends BaseAnalyticsProvider {
|
|
23
|
+
name: string;
|
|
24
|
+
private client?;
|
|
25
|
+
private initialized;
|
|
26
|
+
private config;
|
|
27
|
+
constructor(config: PirschClientConfig);
|
|
28
|
+
initialize(): Promise<void>;
|
|
29
|
+
identify(userId: string, traits?: Record<string, unknown>): void;
|
|
30
|
+
track(event: BaseEvent, context?: EventContext): Promise<void>;
|
|
31
|
+
pageView(properties?: Record<string, unknown>, context?: EventContext): void;
|
|
32
|
+
pageLeave(properties?: Record<string, unknown>, context?: EventContext): void;
|
|
33
|
+
reset(): void;
|
|
34
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { BaseEvent, EventContext } from '../../core/events/types.js';
|
|
2
|
+
import { BaseAnalyticsProvider } from '../base.provider.js';
|
|
3
|
+
import { PirschProxyHeader, Protocol } from 'pirsch-sdk';
|
|
4
|
+
export interface PirschServerConfig {
|
|
5
|
+
/**
|
|
6
|
+
* The hostname/domain being tracked (required)
|
|
7
|
+
* Example: "example.com"
|
|
8
|
+
*/
|
|
9
|
+
hostname: string;
|
|
10
|
+
/**
|
|
11
|
+
* Protocol to use (default: "https")
|
|
12
|
+
*/
|
|
13
|
+
protocol?: Protocol;
|
|
14
|
+
/**
|
|
15
|
+
* Client ID for OAuth authentication
|
|
16
|
+
* Required if not using access key
|
|
17
|
+
*/
|
|
18
|
+
clientId?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Client secret or access key for authentication
|
|
21
|
+
* Access keys start with "pa_"
|
|
22
|
+
*/
|
|
23
|
+
clientSecret: string;
|
|
24
|
+
/**
|
|
25
|
+
* Trusted proxy headers for IP extraction
|
|
26
|
+
*/
|
|
27
|
+
trustedProxyHeaders?: PirschProxyHeader[];
|
|
28
|
+
/**
|
|
29
|
+
* Enable debug logging
|
|
30
|
+
*/
|
|
31
|
+
debug?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Enable/disable the provider
|
|
34
|
+
*/
|
|
35
|
+
enabled?: boolean;
|
|
36
|
+
}
|
|
37
|
+
export declare class PirschServerProvider extends BaseAnalyticsProvider {
|
|
38
|
+
name: string;
|
|
39
|
+
private client?;
|
|
40
|
+
private initialized;
|
|
41
|
+
private config;
|
|
42
|
+
constructor(config: PirschServerConfig);
|
|
43
|
+
initialize(): Promise<void>;
|
|
44
|
+
identify(userId: string, traits?: Record<string, unknown>): void;
|
|
45
|
+
track(event: BaseEvent, context?: EventContext): Promise<void>;
|
|
46
|
+
pageView(properties?: Record<string, unknown>, context?: EventContext): void;
|
|
47
|
+
reset(): Promise<void>;
|
|
48
|
+
shutdown(): Promise<void>;
|
|
49
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { BaseEvent, EventContext } from '../../core/events/types.js';
|
|
2
|
+
import { BaseAnalyticsProvider } from '../base.provider.js';
|
|
3
|
+
import { ProxyBatchConfig, ProxyRetryConfig } from './types.js';
|
|
4
|
+
export interface ProxyProviderConfig {
|
|
5
|
+
/**
|
|
6
|
+
* The endpoint to send events to (e.g., '/api/events')
|
|
7
|
+
*/
|
|
8
|
+
endpoint: string;
|
|
9
|
+
/**
|
|
10
|
+
* Batching configuration
|
|
11
|
+
*/
|
|
12
|
+
batch?: ProxyBatchConfig;
|
|
13
|
+
/**
|
|
14
|
+
* Retry configuration
|
|
15
|
+
*/
|
|
16
|
+
retry?: ProxyRetryConfig;
|
|
17
|
+
/**
|
|
18
|
+
* Custom headers to include in requests
|
|
19
|
+
*/
|
|
20
|
+
headers?: Record<string, string>;
|
|
21
|
+
/**
|
|
22
|
+
* Enable debug logging
|
|
23
|
+
*/
|
|
24
|
+
debug?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Enable/disable the provider
|
|
27
|
+
*/
|
|
28
|
+
enabled?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare class ProxyProvider extends BaseAnalyticsProvider {
|
|
31
|
+
name: string;
|
|
32
|
+
private config;
|
|
33
|
+
private queue;
|
|
34
|
+
private flushTimer?;
|
|
35
|
+
private readonly batchSize;
|
|
36
|
+
private readonly batchInterval;
|
|
37
|
+
private readonly retryAttempts;
|
|
38
|
+
private readonly retryBackoff;
|
|
39
|
+
private readonly retryInitialDelay;
|
|
40
|
+
constructor(config: ProxyProviderConfig);
|
|
41
|
+
initialize(): Promise<void>;
|
|
42
|
+
identify(userId: string, traits?: Record<string, unknown>): void;
|
|
43
|
+
track(event: BaseEvent, context?: EventContext): Promise<void>;
|
|
44
|
+
pageView(properties?: Record<string, unknown>, context?: EventContext): void;
|
|
45
|
+
reset(): Promise<void>;
|
|
46
|
+
shutdown(): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Manually flush all queued events
|
|
49
|
+
*/
|
|
50
|
+
flush(useBeacon?: boolean): Promise<void>;
|
|
51
|
+
private queueEvent;
|
|
52
|
+
private sendEvents;
|
|
53
|
+
private sendWithRetry;
|
|
54
|
+
private calculateRetryDelay;
|
|
55
|
+
private enrichContext;
|
|
56
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ServerAnalytics } from '../../server.js';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for ingesting proxy events
|
|
4
|
+
*/
|
|
5
|
+
export interface IngestProxyEventsConfig {
|
|
6
|
+
/**
|
|
7
|
+
* Enrich context with server-side data
|
|
8
|
+
*/
|
|
9
|
+
enrichContext?: (request: Request) => Record<string, unknown>;
|
|
10
|
+
/**
|
|
11
|
+
* Extract IP address from request
|
|
12
|
+
* Default: Uses standard headers (X-Forwarded-For, X-Real-IP)
|
|
13
|
+
*/
|
|
14
|
+
extractIp?: (request: Request) => string | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Error handler
|
|
17
|
+
*/
|
|
18
|
+
onError?: (error: unknown) => void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Ingests events from ProxyProvider and replays them through server analytics
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // Next.js App Router
|
|
26
|
+
* export async function POST(req: Request) {
|
|
27
|
+
* await ingestProxyEvents(req, serverAnalytics);
|
|
28
|
+
* return new Response('OK');
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* // With custom IP extraction
|
|
32
|
+
* export async function POST(req: Request) {
|
|
33
|
+
* await ingestProxyEvents(req, serverAnalytics, {
|
|
34
|
+
* extractIp: (req) => req.headers.get('cf-connecting-ip') // Cloudflare
|
|
35
|
+
* });
|
|
36
|
+
* return new Response('OK');
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function ingestProxyEvents<TEventMap extends Record<string, Record<string, unknown>> = Record<string, Record<string, unknown>>, TUserTraits extends Record<string, unknown> = Record<string, unknown>>(request: Request, analytics: ServerAnalytics<TEventMap, TUserTraits>, config?: IngestProxyEventsConfig): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Creates a Request handler for common frameworks
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* // Next.js App Router
|
|
47
|
+
* export const POST = createProxyHandler(serverAnalytics);
|
|
48
|
+
*
|
|
49
|
+
* // With custom config
|
|
50
|
+
* export const POST = createProxyHandler(serverAnalytics, {
|
|
51
|
+
* extractIp: (req) => req.headers.get('cf-connecting-ip')
|
|
52
|
+
* });
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare function createProxyHandler<TEventMap extends Record<string, Record<string, unknown>> = Record<string, Record<string, unknown>>, TUserTraits extends Record<string, unknown> = Record<string, unknown>>(analytics: ServerAnalytics<TEventMap, TUserTraits>, config?: IngestProxyEventsConfig): (request: Request) => Promise<Response>;
|