@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.
@@ -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';
@@ -1,6 +1,373 @@
1
- import { B as e } from "../base.provider-AfFL5W_P.js";
2
- import { P as t } from "../client-DTHZYkxx.js";
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
- e as BaseAnalyticsProvider,
5
- t as PostHogClientProvider
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>;