@stacksee/analytics 0.9.4 → 0.9.5

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