@stacksee/analytics 0.12.0 → 0.13.1
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-DaMA6jEr.js +8 -0
- package/dist/{bento-node-sdk.esm-CWEAoj97.js → bento-node-sdk.esm-CT4oS3Kp.js} +1 -1
- package/dist/providers/client.js +8 -7
- package/dist/providers/emitkit/server.d.ts +33 -1
- package/dist/providers/pirsch/client.d.ts +5 -0
- package/dist/providers/pirsch/server.d.ts +38 -4
- package/dist/providers/server.js +366 -271
- package/dist/web-D-ZwlgeQ.js +2034 -0
- package/package.json +1 -1
- package/dist/_commonjsHelpers-B4e78b8K.js +0 -28
- package/dist/axios-0_CwElpL.js +0 -1820
- package/dist/index-zS7gy63J.js +0 -829
- package/dist/web-imCcOhDC.js +0 -220
package/dist/providers/server.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { B } from "../base.provider-AfFL5W_P.js";
|
|
5
|
-
import { P as
|
|
6
|
-
class
|
|
1
|
+
var U = Object.defineProperty;
|
|
2
|
+
var F = (d, u, i) => u in d ? U(d, u, { enumerable: !0, configurable: !0, writable: !0, value: i }) : d[u] = i;
|
|
3
|
+
var c = (d, u, i) => F(d, typeof u != "symbol" ? u + "" : u, i);
|
|
4
|
+
import { B as y } from "../base.provider-AfFL5W_P.js";
|
|
5
|
+
import { P as H } from "../server-DjEk1fUD.js";
|
|
6
|
+
class O extends y {
|
|
7
7
|
constructor(i) {
|
|
8
8
|
super({ debug: i.debug, enabled: i.enabled });
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
c(this, "name", "Bento-Server");
|
|
10
|
+
c(this, "client");
|
|
11
|
+
c(this, "initialized", !1);
|
|
12
|
+
c(this, "config");
|
|
13
|
+
c(this, "currentUserEmail");
|
|
14
14
|
this.config = i;
|
|
15
15
|
}
|
|
16
16
|
async initialize() {
|
|
@@ -23,8 +23,8 @@ class H extends B {
|
|
|
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-
|
|
27
|
-
this.client = new r(
|
|
26
|
+
const { Analytics: r } = await import("../bento-node-sdk.esm-CT4oS3Kp.js"), { debug: s, enabled: a, ...t } = this.config;
|
|
27
|
+
this.client = new r(t), this.initialized = !0, this.log("Initialized successfully", {
|
|
28
28
|
siteUuid: this.config.siteUuid
|
|
29
29
|
});
|
|
30
30
|
} catch (r) {
|
|
@@ -46,25 +46,25 @@ class H extends B {
|
|
|
46
46
|
return;
|
|
47
47
|
}
|
|
48
48
|
this.currentUserEmail = r;
|
|
49
|
-
const
|
|
50
|
-
|
|
49
|
+
const s = e ? { ...e } : {};
|
|
50
|
+
s.email = void 0, this.client.V1.addSubscriber({
|
|
51
51
|
email: r,
|
|
52
|
-
fields:
|
|
53
|
-
}).catch((
|
|
54
|
-
console.error("[Bento-Server] Failed to identify user:",
|
|
52
|
+
fields: s
|
|
53
|
+
}).catch((a) => {
|
|
54
|
+
console.error("[Bento-Server] Failed to identify user:", a);
|
|
55
55
|
}), this.log("Identified user", { userId: i, email: r, traits: e });
|
|
56
56
|
}
|
|
57
57
|
async track(i, e) {
|
|
58
|
-
var
|
|
58
|
+
var t, h, l, n;
|
|
59
59
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
60
|
-
const r = ((
|
|
60
|
+
const r = ((t = e == null ? void 0 : e.user) == null ? void 0 : t.email) || this.currentUserEmail || ((h = e == null ? void 0 : e.user) == null ? void 0 : h.userId) || i.userId;
|
|
61
61
|
if (!r || !r.includes("@")) {
|
|
62
62
|
console.warn(
|
|
63
63
|
"[Bento-Server] Skipping event - Bento requires an email address. Anonymous events are not currently supported by the Bento Node SDK. For now, use the Bento client provider for anonymous tracking. If you're using a proxy, use the hybrid pattern as described in the docs. For identified users, call identify() with a valid email before tracking events."
|
|
64
64
|
);
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
67
|
-
const
|
|
67
|
+
const s = {
|
|
68
68
|
...i.properties,
|
|
69
69
|
category: i.category,
|
|
70
70
|
timestamp: i.timestamp || Date.now(),
|
|
@@ -83,30 +83,30 @@ class H extends B {
|
|
|
83
83
|
...(e == null ? void 0 : e.device) && { device: e.device },
|
|
84
84
|
...(e == null ? void 0 : e.utm) && { utm: e.utm },
|
|
85
85
|
site: this.config.siteUuid,
|
|
86
|
-
...((
|
|
87
|
-
},
|
|
86
|
+
...((l = e == null ? void 0 : e.user) == null ? void 0 : l.userId) && { visitor: e.user.userId }
|
|
87
|
+
}, a = ((n = e == null ? void 0 : e.user) == null ? void 0 : n.traits) || {};
|
|
88
88
|
try {
|
|
89
89
|
await this.client.V1.track({
|
|
90
90
|
email: r,
|
|
91
91
|
type: `$${i.action}`,
|
|
92
|
-
details:
|
|
93
|
-
fields:
|
|
92
|
+
details: s,
|
|
93
|
+
fields: a
|
|
94
94
|
}), this.log("Tracked event", { event: i, context: e });
|
|
95
|
-
} catch (
|
|
96
|
-
console.error("[Bento-Server] Failed to track event:",
|
|
95
|
+
} catch (o) {
|
|
96
|
+
console.error("[Bento-Server] Failed to track event:", o);
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
pageView(i, e) {
|
|
100
|
-
var
|
|
100
|
+
var t, h, l;
|
|
101
101
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
102
|
-
const r = ((
|
|
102
|
+
const r = ((t = e == null ? void 0 : e.user) == null ? void 0 : t.email) || this.currentUserEmail;
|
|
103
103
|
if (!r || !r.includes("@")) {
|
|
104
104
|
console.warn(
|
|
105
105
|
"[Bento-Server] Skipping pageView - Bento requires an email address. Anonymous events are not currently supported by the Bento Node SDK. For now, use the Bento client provider for anonymous tracking. If you're using a proxy, use the hybrid pattern as described in the docs. For identified users, call identify() with a valid email before tracking events."
|
|
106
106
|
);
|
|
107
107
|
return;
|
|
108
108
|
}
|
|
109
|
-
const
|
|
109
|
+
const s = {
|
|
110
110
|
...i,
|
|
111
111
|
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
112
112
|
...(e == null ? void 0 : e.page) && {
|
|
@@ -121,15 +121,15 @@ class H extends B {
|
|
|
121
121
|
}
|
|
122
122
|
},
|
|
123
123
|
site: this.config.siteUuid,
|
|
124
|
-
...((
|
|
125
|
-
},
|
|
124
|
+
...((h = e == null ? void 0 : e.user) == null ? void 0 : h.userId) && { visitor: e.user.userId }
|
|
125
|
+
}, a = ((l = e == null ? void 0 : e.user) == null ? void 0 : l.traits) || {};
|
|
126
126
|
this.client.V1.track({
|
|
127
127
|
email: r,
|
|
128
128
|
type: "$view",
|
|
129
|
-
details:
|
|
130
|
-
fields:
|
|
131
|
-
}).catch((
|
|
132
|
-
console.error("[Bento-Server] Failed to track page view:",
|
|
129
|
+
details: s,
|
|
130
|
+
fields: a
|
|
131
|
+
}).catch((n) => {
|
|
132
|
+
console.error("[Bento-Server] Failed to track page view:", n);
|
|
133
133
|
}), this.log("Tracked page view", { properties: i, context: e });
|
|
134
134
|
}
|
|
135
135
|
async reset() {
|
|
@@ -139,186 +139,257 @@ class H extends B {
|
|
|
139
139
|
this.client = void 0, this.initialized = !1, this.log("Shutdown complete");
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
|
-
|
|
142
|
+
const T = "https://api.pirsch.io", K = 1e4;
|
|
143
|
+
class j extends y {
|
|
143
144
|
constructor(i) {
|
|
144
145
|
super({ debug: i.debug, enabled: i.enabled });
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
146
|
+
c(this, "name", "Pirsch-Server");
|
|
147
|
+
c(this, "initialized", !1);
|
|
148
|
+
c(this, "config");
|
|
149
|
+
c(this, "accessToken", "");
|
|
150
|
+
c(this, "tokenExpiresAt", null);
|
|
151
|
+
c(this, "isAccessKey", !1);
|
|
149
152
|
this.config = i;
|
|
150
153
|
}
|
|
151
154
|
async initialize() {
|
|
152
|
-
if (
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
)
|
|
162
|
-
try {
|
|
163
|
-
const { Pirsch: e } = await import("../index-zS7gy63J.js").then((d) => d.i), { debug: r, enabled: a, ...s } = this.config;
|
|
164
|
-
this.client = new e(s), this.initialized = !0, this.log("Initialized successfully", {
|
|
155
|
+
if (this.isEnabled() && !this.initialized) {
|
|
156
|
+
if (!this.config.hostname || typeof this.config.hostname != "string")
|
|
157
|
+
throw new Error("Pirsch requires a hostname");
|
|
158
|
+
if (!this.config.clientSecret || typeof this.config.clientSecret != "string")
|
|
159
|
+
throw new Error("Pirsch requires a clientSecret (or access key)");
|
|
160
|
+
if (this.isAccessKey = this.config.clientSecret.startsWith("pa_"), !this.isAccessKey && !this.config.clientId)
|
|
161
|
+
throw new Error(
|
|
162
|
+
"Pirsch requires a clientId when using OAuth authentication (clientSecret doesn't start with 'pa_'). Either provide a clientId or use an access key (starts with 'pa_') as clientSecret."
|
|
163
|
+
);
|
|
164
|
+
this.isAccessKey && (this.accessToken = this.config.clientSecret), this.initialized = !0, this.log("Initialized successfully", {
|
|
165
165
|
hostname: this.config.hostname,
|
|
166
|
-
authMode:
|
|
166
|
+
authMode: this.isAccessKey ? "access-key" : "oauth"
|
|
167
167
|
});
|
|
168
|
-
} catch (e) {
|
|
169
|
-
throw console.error(
|
|
170
|
-
"[Pirsch-Server] Failed to initialize. Make sure pirsch-sdk is installed:",
|
|
171
|
-
e
|
|
172
|
-
), e;
|
|
173
168
|
}
|
|
174
169
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
};
|
|
189
|
-
this.client.event("user_identified", r, 0, a).catch((s) => {
|
|
190
|
-
console.error("[Pirsch-Server] Failed to track identify event:", s);
|
|
191
|
-
}), this.log("Identified user via event", { userId: i, traits: e });
|
|
170
|
+
/**
|
|
171
|
+
* Fetch with timeout using AbortController
|
|
172
|
+
*/
|
|
173
|
+
async fetchWithTimeout(i, e, r) {
|
|
174
|
+
const s = new AbortController(), a = r ?? this.config.timeout ?? K, t = setTimeout(() => s.abort(), a);
|
|
175
|
+
try {
|
|
176
|
+
return await fetch(i, {
|
|
177
|
+
...e,
|
|
178
|
+
signal: s.signal
|
|
179
|
+
});
|
|
180
|
+
} finally {
|
|
181
|
+
clearTimeout(t);
|
|
182
|
+
}
|
|
192
183
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
if (
|
|
198
|
-
this.
|
|
199
|
-
|
|
184
|
+
/**
|
|
185
|
+
* Ensure we have a valid access token (for OAuth mode)
|
|
186
|
+
*/
|
|
187
|
+
async ensureToken() {
|
|
188
|
+
if (this.isAccessKey)
|
|
189
|
+
return this.accessToken;
|
|
190
|
+
if (this.accessToken && this.tokenExpiresAt && /* @__PURE__ */ new Date() < new Date(this.tokenExpiresAt.getTime() - 6e4))
|
|
191
|
+
return this.accessToken;
|
|
192
|
+
try {
|
|
193
|
+
const i = await this.fetchWithTimeout(
|
|
194
|
+
`${T}/api/v1/token`,
|
|
200
195
|
{
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
196
|
+
method: "POST",
|
|
197
|
+
headers: { "Content-Type": "application/json" },
|
|
198
|
+
body: JSON.stringify({
|
|
199
|
+
client_id: this.config.clientId,
|
|
200
|
+
client_secret: this.config.clientSecret
|
|
201
|
+
})
|
|
204
202
|
}
|
|
205
203
|
);
|
|
206
|
-
|
|
204
|
+
if (!i.ok) {
|
|
205
|
+
const r = await i.text();
|
|
206
|
+
throw new Error(`Failed to get Pirsch token: ${i.status} ${r}`);
|
|
207
|
+
}
|
|
208
|
+
const e = await i.json();
|
|
209
|
+
return this.accessToken = e.access_token, this.tokenExpiresAt = new Date(e.expires_at), this.log("OAuth token refreshed", { expiresAt: e.expires_at }), this.accessToken;
|
|
210
|
+
} catch (i) {
|
|
211
|
+
throw console.error("[Pirsch-Server] Failed to refresh token:", i), i;
|
|
207
212
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Make an authenticated request to Pirsch API
|
|
216
|
+
*/
|
|
217
|
+
async request(i, e, r = !0) {
|
|
218
|
+
const s = await this.ensureToken();
|
|
219
|
+
try {
|
|
220
|
+
const a = await this.fetchWithTimeout(
|
|
221
|
+
`${T}${i}`,
|
|
222
|
+
{
|
|
223
|
+
method: "POST",
|
|
224
|
+
headers: {
|
|
225
|
+
"Content-Type": "application/json",
|
|
226
|
+
Authorization: `Bearer ${s}`
|
|
227
|
+
},
|
|
228
|
+
body: JSON.stringify(e)
|
|
229
|
+
}
|
|
230
|
+
);
|
|
231
|
+
if (a.status === 401 && r && !this.isAccessKey)
|
|
232
|
+
return this.accessToken = "", this.tokenExpiresAt = null, this.request(i, e, !1);
|
|
233
|
+
if (!a.ok) {
|
|
234
|
+
const t = await a.text();
|
|
235
|
+
throw new Error(`Pirsch API error: ${a.status} ${t}`);
|
|
236
|
+
}
|
|
237
|
+
} catch (a) {
|
|
238
|
+
throw a instanceof Error && a.name === "AbortError" ? new Error(
|
|
239
|
+
`Pirsch request timeout after ${this.config.timeout ?? K}ms`
|
|
240
|
+
) : a;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Filter object to only include scalar values (string, number, boolean)
|
|
245
|
+
*/
|
|
246
|
+
filterScalars(i) {
|
|
247
|
+
return Object.fromEntries(
|
|
248
|
+
Object.entries(i).filter(
|
|
249
|
+
([, e]) => typeof e == "string" || typeof e == "number" || typeof e == "boolean"
|
|
250
|
+
)
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Convert object values to strings for Pirsch event_meta
|
|
255
|
+
* Pirsch API requires event_meta to be a single dimension object of string values
|
|
256
|
+
*/
|
|
257
|
+
toStringRecord(i) {
|
|
258
|
+
return Object.fromEntries(
|
|
259
|
+
Object.entries(i).filter(
|
|
260
|
+
([, e]) => e != null && typeof e != "object"
|
|
261
|
+
).map(([e, r]) => [e, String(r)])
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Build a Pirsch hit from context
|
|
266
|
+
*/
|
|
267
|
+
buildHit(i) {
|
|
268
|
+
var t, h, l, n, o, p, g, f, m, v, w, b, k, E, _, S, I, A, z, P;
|
|
269
|
+
const e = i, r = ((t = e == null ? void 0 : e.device) == null ? void 0 : t.ip) || ((h = e == null ? void 0 : e.server) == null ? void 0 : h.ip), s = ((l = e == null ? void 0 : e.server) == null ? void 0 : l.userAgent) || ((n = e == null ? void 0 : e.device) == null ? void 0 : n.userAgent);
|
|
270
|
+
return !r || !s ? null : {
|
|
271
|
+
url: ((o = i == null ? void 0 : i.page) == null ? void 0 : o.url) || ((p = i == null ? void 0 : i.page) != null && p.protocol && ((g = i == null ? void 0 : i.page) != null && g.host) && ((f = i == null ? void 0 : i.page) != null && f.path) ? `${i.page.protocol}://${i.page.host}${i.page.path}` : (m = i == null ? void 0 : i.page) != null && m.path ? `https://${this.config.hostname}${i.page.path}` : `https://${this.config.hostname}`),
|
|
272
|
+
ip: r,
|
|
211
273
|
user_agent: s,
|
|
212
|
-
...((
|
|
213
|
-
...((
|
|
214
|
-
...((
|
|
215
|
-
screen_width:
|
|
274
|
+
...((v = i == null ? void 0 : i.page) == null ? void 0 : v.title) && { title: i.page.title },
|
|
275
|
+
...((w = i == null ? void 0 : i.page) == null ? void 0 : w.referrer) && { referrer: i.page.referrer },
|
|
276
|
+
...((k = (b = i == null ? void 0 : i.device) == null ? void 0 : b.screen) == null ? void 0 : k.width) && {
|
|
277
|
+
screen_width: i.device.screen.width
|
|
216
278
|
},
|
|
217
|
-
...((
|
|
218
|
-
screen_height:
|
|
279
|
+
...((_ = (E = i == null ? void 0 : i.device) == null ? void 0 : E.screen) == null ? void 0 : _.height) && {
|
|
280
|
+
screen_height: i.device.screen.height
|
|
219
281
|
},
|
|
220
|
-
...((
|
|
221
|
-
sec_ch_viewport_width: String(
|
|
282
|
+
...((I = (S = i == null ? void 0 : i.device) == null ? void 0 : S.viewport) == null ? void 0 : I.width) && {
|
|
283
|
+
sec_ch_viewport_width: String(i.device.viewport.width)
|
|
222
284
|
},
|
|
223
|
-
...((A =
|
|
224
|
-
accept_language:
|
|
285
|
+
...((A = i == null ? void 0 : i.device) == null ? void 0 : A.language) && {
|
|
286
|
+
accept_language: i.device.language
|
|
225
287
|
},
|
|
226
|
-
...((
|
|
227
|
-
sec_ch_ua_mobile:
|
|
288
|
+
...((z = i == null ? void 0 : i.device) == null ? void 0 : z.type) && {
|
|
289
|
+
sec_ch_ua_mobile: i.device.type === "mobile" || i.device.type === "tablet" ? "?1" : "?0"
|
|
228
290
|
},
|
|
229
|
-
...((
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
291
|
+
...((P = i == null ? void 0 : i.device) == null ? void 0 : P.os) && { sec_ch_ua_platform: i.device.os },
|
|
292
|
+
...this.config.disableBotFilter && { disable_bot_filter: !0 }
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
identify(i, e) {
|
|
296
|
+
if (!this.isEnabled() || !this.initialized) return;
|
|
297
|
+
const r = {
|
|
298
|
+
url: `https://${this.config.hostname}/identify`,
|
|
299
|
+
ip: "0.0.0.0",
|
|
300
|
+
user_agent: "stacksee-analytics",
|
|
301
|
+
...this.config.disableBotFilter && { disable_bot_filter: !0 }
|
|
302
|
+
}, s = this.toStringRecord({
|
|
303
|
+
userId: i,
|
|
304
|
+
...e
|
|
305
|
+
}), a = {
|
|
306
|
+
...r,
|
|
307
|
+
event_name: "user_identified",
|
|
308
|
+
event_duration: 0,
|
|
309
|
+
event_meta: s,
|
|
310
|
+
non_interactive: !0
|
|
311
|
+
// Synthetic event shouldn't affect bounce rate
|
|
312
|
+
};
|
|
313
|
+
this.request("/api/v1/event", a).catch((t) => {
|
|
314
|
+
console.error("[Pirsch-Server] Failed to track identify event:", t);
|
|
315
|
+
}), this.log("Identified user via event", { userId: i, traits: e });
|
|
316
|
+
}
|
|
317
|
+
async track(i, e) {
|
|
318
|
+
var h, l, n, o;
|
|
319
|
+
if (!this.isEnabled() || !this.initialized) return;
|
|
320
|
+
const r = this.buildHit(e);
|
|
321
|
+
if (!r) {
|
|
322
|
+
this.log("Skipping event - missing required IP or user-agent", {
|
|
323
|
+
event: i.action
|
|
324
|
+
});
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
const s = this.toStringRecord({
|
|
328
|
+
...i.properties,
|
|
236
329
|
category: i.category,
|
|
237
|
-
timestamp:
|
|
330
|
+
timestamp: i.timestamp || Date.now(),
|
|
238
331
|
...i.userId && { userId: i.userId },
|
|
239
332
|
...i.sessionId && { sessionId: i.sessionId },
|
|
240
|
-
...((
|
|
241
|
-
...((
|
|
242
|
-
...((
|
|
333
|
+
...((h = e == null ? void 0 : e.user) == null ? void 0 : h.email) && { user_email: e.user.email },
|
|
334
|
+
...((l = e == null ? void 0 : e.device) == null ? void 0 : l.timezone) && { timezone: e.device.timezone },
|
|
335
|
+
...((n = e == null ? void 0 : e.device) == null ? void 0 : n.browser) && { browser: e.device.browser }
|
|
336
|
+
}), a = ((o = i.properties) == null ? void 0 : o.non_interactive) === !0, t = {
|
|
337
|
+
...r,
|
|
338
|
+
event_name: i.action,
|
|
339
|
+
event_duration: 0,
|
|
340
|
+
event_meta: s,
|
|
341
|
+
...a && { non_interactive: !0 }
|
|
243
342
|
};
|
|
244
343
|
try {
|
|
245
|
-
await this.
|
|
246
|
-
} catch (
|
|
247
|
-
console.error("[Pirsch-Server] Failed to track event:",
|
|
344
|
+
await this.request("/api/v1/event", t), this.log("Tracked event", { event: i.action });
|
|
345
|
+
} catch (p) {
|
|
346
|
+
console.error("[Pirsch-Server] Failed to track event:", p);
|
|
248
347
|
}
|
|
249
348
|
}
|
|
250
349
|
pageView(i, e) {
|
|
251
|
-
var
|
|
252
|
-
if (!this.isEnabled() || !this.initialized
|
|
253
|
-
const r =
|
|
254
|
-
if (!
|
|
255
|
-
this.log(
|
|
256
|
-
"Skipping pageView - missing required IP or user-agent from context",
|
|
257
|
-
{
|
|
258
|
-
hasIp: !!a,
|
|
259
|
-
hasUserAgent: !!s
|
|
260
|
-
}
|
|
261
|
-
);
|
|
350
|
+
var s;
|
|
351
|
+
if (!this.isEnabled() || !this.initialized) return;
|
|
352
|
+
const r = this.buildHit(e);
|
|
353
|
+
if (!r) {
|
|
354
|
+
this.log("Skipping pageView - missing required IP or user-agent");
|
|
262
355
|
return;
|
|
263
356
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
user_agent: s,
|
|
268
|
-
...((b = e == null ? void 0 : e.page) == null ? void 0 : b.title) && { title: e.page.title },
|
|
269
|
-
...((E = e == null ? void 0 : e.page) == null ? void 0 : E.referrer) && { referrer: e.page.referrer },
|
|
270
|
-
...((k = (I = e == null ? void 0 : e.device) == null ? void 0 : I.screen) == null ? void 0 : k.width) && {
|
|
271
|
-
screen_width: e.device.screen.width
|
|
272
|
-
},
|
|
273
|
-
...((_ = (S = e == null ? void 0 : e.device) == null ? void 0 : S.screen) == null ? void 0 : _.height) && {
|
|
274
|
-
screen_height: e.device.screen.height
|
|
275
|
-
},
|
|
276
|
-
...((P = (z = e == null ? void 0 : e.device) == null ? void 0 : z.viewport) == null ? void 0 : P.width) && {
|
|
277
|
-
sec_ch_viewport_width: String(e.device.viewport.width)
|
|
278
|
-
},
|
|
279
|
-
...((U = e == null ? void 0 : e.device) == null ? void 0 : U.language) && {
|
|
280
|
-
accept_language: e.device.language
|
|
281
|
-
},
|
|
282
|
-
...((K = e == null ? void 0 : e.device) == null ? void 0 : K.type) && {
|
|
283
|
-
sec_ch_ua_mobile: e.device.type === "mobile" || e.device.type === "tablet" ? "?1" : "?0"
|
|
284
|
-
},
|
|
285
|
-
...((A = e == null ? void 0 : e.device) == null ? void 0 : A.os) && { sec_ch_ua_platform: e.device.os },
|
|
286
|
-
...i && {
|
|
287
|
-
tags: Object.fromEntries(
|
|
288
|
-
Object.entries(i).filter(
|
|
289
|
-
([, f]) => typeof f == "string" || typeof f == "number" || typeof f == "boolean"
|
|
290
|
-
)
|
|
291
|
-
)
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
this.client.hit(p).catch((f) => {
|
|
295
|
-
console.error("[Pirsch-Server] Failed to track page view:", f);
|
|
296
|
-
}), this.log("Tracked page view", { properties: i, context: e });
|
|
357
|
+
i && Object.keys(i).length > 0 && (r.tags = this.filterScalars(i)), this.request("/api/v1/hit", r).catch((a) => {
|
|
358
|
+
console.error("[Pirsch-Server] Failed to track page view:", a);
|
|
359
|
+
}), this.log("Tracked page view", { path: (s = e == null ? void 0 : e.page) == null ? void 0 : s.path });
|
|
297
360
|
}
|
|
298
361
|
async reset() {
|
|
299
|
-
if (!this.isEnabled() || !this.initialized
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
362
|
+
if (!this.isEnabled() || !this.initialized) return;
|
|
363
|
+
const e = {
|
|
364
|
+
...{
|
|
365
|
+
url: `https://${this.config.hostname}/session-reset`,
|
|
366
|
+
ip: "0.0.0.0",
|
|
367
|
+
user_agent: "stacksee-analytics",
|
|
368
|
+
...this.config.disableBotFilter && { disable_bot_filter: !0 }
|
|
369
|
+
},
|
|
370
|
+
event_name: "session_reset",
|
|
371
|
+
event_duration: 0,
|
|
372
|
+
event_meta: {},
|
|
373
|
+
non_interactive: !0
|
|
374
|
+
// Synthetic event shouldn't affect bounce rate
|
|
304
375
|
};
|
|
305
|
-
await this.
|
|
306
|
-
console.error("[Pirsch-Server] Failed to track session reset:",
|
|
376
|
+
await this.request("/api/v1/event", e).catch((r) => {
|
|
377
|
+
console.error("[Pirsch-Server] Failed to track session reset:", r);
|
|
307
378
|
}), this.log("Reset user session");
|
|
308
379
|
}
|
|
309
380
|
async shutdown() {
|
|
310
|
-
this.
|
|
381
|
+
this.accessToken = "", this.tokenExpiresAt = null, this.initialized = !1, this.log("Shutdown complete");
|
|
311
382
|
}
|
|
312
383
|
}
|
|
313
|
-
class
|
|
384
|
+
class N extends y {
|
|
314
385
|
constructor(i) {
|
|
315
386
|
super({ debug: i.debug, enabled: i.enabled });
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
387
|
+
c(this, "name", "EmitKit-Server");
|
|
388
|
+
c(this, "client");
|
|
389
|
+
c(this, "initialized", !1);
|
|
390
|
+
c(this, "config");
|
|
391
|
+
c(this, "currentUserId");
|
|
392
|
+
c(this, "currentUserEmail");
|
|
322
393
|
this.config = i;
|
|
323
394
|
}
|
|
324
395
|
async initialize() {
|
|
@@ -330,7 +401,9 @@ class G extends B {
|
|
|
330
401
|
);
|
|
331
402
|
try {
|
|
332
403
|
const { EmitKit: i } = await import("../index-CBs091W0.js");
|
|
333
|
-
this.client = new i(this.config.apiKey
|
|
404
|
+
this.client = new i(this.config.apiKey, {
|
|
405
|
+
...this.config.timeout && { timeout: this.config.timeout }
|
|
406
|
+
}), this.initialized = !0, this.log("Initialized successfully");
|
|
334
407
|
} catch (i) {
|
|
335
408
|
throw console.error(
|
|
336
409
|
"[EmitKit-Server] Failed to initialize. Make sure @emitkit/js is installed:",
|
|
@@ -343,33 +416,33 @@ class G extends B {
|
|
|
343
416
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
344
417
|
this.currentUserId = i;
|
|
345
418
|
const r = (e == null ? void 0 : e.email) || i;
|
|
346
|
-
r && r.includes("@") && (this.currentUserEmail = r);
|
|
347
|
-
const
|
|
348
|
-
i &&
|
|
419
|
+
r != null && r.includes("@") && (this.currentUserEmail = r);
|
|
420
|
+
const s = [];
|
|
421
|
+
i && s.push(i), r && r !== i && s.push(r), e != null && e.username && typeof e.username == "string" && s.push(e.username), this.client.identify({
|
|
349
422
|
user_id: i,
|
|
350
423
|
properties: e || {},
|
|
351
|
-
aliases:
|
|
352
|
-
}).then((
|
|
353
|
-
var
|
|
424
|
+
aliases: s.length > 0 ? s : void 0
|
|
425
|
+
}).then((a) => {
|
|
426
|
+
var t, h, l, n, o;
|
|
354
427
|
this.log("Identified user", {
|
|
355
428
|
userId: i,
|
|
356
429
|
email: r,
|
|
357
|
-
identityId:
|
|
358
|
-
aliasesCreated: ((
|
|
359
|
-
aliasesFailed: ((
|
|
360
|
-
}), (
|
|
430
|
+
identityId: a.data.id,
|
|
431
|
+
aliasesCreated: ((h = (t = a.data.aliases) == null ? void 0 : t.created) == null ? void 0 : h.length) || 0,
|
|
432
|
+
aliasesFailed: ((n = (l = a.data.aliases) == null ? void 0 : l.failed) == null ? void 0 : n.length) || 0
|
|
433
|
+
}), (o = a.data.aliases) != null && o.failed && a.data.aliases.failed.length > 0 && console.warn(
|
|
361
434
|
"[EmitKit-Server] Some aliases failed to create:",
|
|
362
|
-
|
|
435
|
+
a.data.aliases.failed
|
|
363
436
|
);
|
|
364
|
-
}).catch((
|
|
365
|
-
console.error("[EmitKit-Server] Failed to identify user:",
|
|
437
|
+
}).catch((a) => {
|
|
438
|
+
console.error("[EmitKit-Server] Failed to identify user:", a);
|
|
366
439
|
});
|
|
367
440
|
}
|
|
368
441
|
async track(i, e) {
|
|
369
|
-
var
|
|
442
|
+
var o, p;
|
|
370
443
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
371
|
-
const r = ((
|
|
372
|
-
...
|
|
444
|
+
const r = ((o = e == null ? void 0 : e.user) == null ? void 0 : o.email) || ((p = e == null ? void 0 : e.user) == null ? void 0 : p.userId) || i.userId || this.currentUserEmail || this.currentUserId, s = this.formatEventTitle(i.action), { __emitkit_channel: a, ...t } = i.properties || {}, h = {
|
|
445
|
+
...t,
|
|
373
446
|
category: i.category,
|
|
374
447
|
timestamp: i.timestamp || Date.now(),
|
|
375
448
|
...i.sessionId && { sessionId: i.sessionId },
|
|
@@ -387,37 +460,37 @@ class G extends B {
|
|
|
387
460
|
...(e == null ? void 0 : e.device) && { device: e.device },
|
|
388
461
|
...(e == null ? void 0 : e.utm) && { utm: e.utm },
|
|
389
462
|
...(e == null ? void 0 : e.server) && { server: e.server }
|
|
390
|
-
},
|
|
391
|
-
i.category &&
|
|
392
|
-
const
|
|
463
|
+
}, l = [];
|
|
464
|
+
i.category && l.push(i.category), t != null && t.tags && Array.isArray(t.tags) && t.tags.every((g) => typeof g == "string") && l.push(...t.tags);
|
|
465
|
+
const n = this.resolveChannelName(i);
|
|
393
466
|
try {
|
|
394
|
-
const
|
|
395
|
-
channelName:
|
|
396
|
-
title:
|
|
467
|
+
const g = await this.client.events.create({
|
|
468
|
+
channelName: n,
|
|
469
|
+
title: s,
|
|
397
470
|
description: this.getEventDescription(i, e),
|
|
398
471
|
icon: this.getEventIcon(i.category),
|
|
399
|
-
tags:
|
|
400
|
-
metadata:
|
|
472
|
+
tags: l.length > 0 ? l : void 0,
|
|
473
|
+
metadata: h,
|
|
401
474
|
userId: r || null,
|
|
402
475
|
notify: this.config.notify ?? !0,
|
|
403
476
|
displayAs: this.config.displayAs || "notification",
|
|
404
477
|
source: "stacksee-analytics"
|
|
405
478
|
});
|
|
406
479
|
this.log("Tracked event", {
|
|
407
|
-
eventId:
|
|
480
|
+
eventId: g.data.id,
|
|
408
481
|
action: i.action,
|
|
409
482
|
userId: r,
|
|
410
|
-
channelName:
|
|
483
|
+
channelName: n
|
|
411
484
|
});
|
|
412
|
-
} catch (
|
|
413
|
-
throw console.error("[EmitKit-Server] Failed to track event:",
|
|
485
|
+
} catch (g) {
|
|
486
|
+
throw console.error("[EmitKit-Server] Failed to track event:", g), g;
|
|
414
487
|
}
|
|
415
488
|
}
|
|
416
489
|
pageView(i, e) {
|
|
417
|
-
var
|
|
490
|
+
var n, o, p;
|
|
418
491
|
if (!this.isEnabled() || !this.initialized || !this.client) return;
|
|
419
|
-
const r = ((
|
|
420
|
-
...
|
|
492
|
+
const r = ((n = e == null ? void 0 : e.user) == null ? void 0 : n.email) || ((o = e == null ? void 0 : e.user) == null ? void 0 : o.userId) || this.currentUserEmail || this.currentUserId, { __emitkit_channel: s, ...a } = i || {}, t = {
|
|
493
|
+
...a,
|
|
421
494
|
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
422
495
|
...(e == null ? void 0 : e.page) && {
|
|
423
496
|
page: {
|
|
@@ -433,28 +506,33 @@ class G extends B {
|
|
|
433
506
|
...(e == null ? void 0 : e.device) && { device: e.device },
|
|
434
507
|
...(e == null ? void 0 : e.utm) && { utm: e.utm },
|
|
435
508
|
...(e == null ? void 0 : e.server) && { server: e.server }
|
|
436
|
-
},
|
|
509
|
+
}, h = {
|
|
510
|
+
action: "page_view",
|
|
511
|
+
category: "navigation",
|
|
512
|
+
properties: i || {}
|
|
513
|
+
}, l = this.resolveChannelName(h);
|
|
437
514
|
this.client.events.create({
|
|
438
|
-
channelName:
|
|
515
|
+
channelName: l,
|
|
439
516
|
title: "Page View",
|
|
440
|
-
description: ((
|
|
517
|
+
description: ((p = e == null ? void 0 : e.page) == null ? void 0 : p.path) || "User viewed a page",
|
|
441
518
|
icon: "👁️",
|
|
442
519
|
tags: ["page_view", "navigation"],
|
|
443
|
-
metadata:
|
|
520
|
+
metadata: t,
|
|
444
521
|
userId: r || null,
|
|
445
522
|
notify: !1,
|
|
446
523
|
// Don't notify for page views by default
|
|
447
524
|
displayAs: "message",
|
|
448
525
|
source: "stacksee-analytics"
|
|
449
|
-
}).then((
|
|
450
|
-
var
|
|
526
|
+
}).then((g) => {
|
|
527
|
+
var f;
|
|
451
528
|
this.log("Tracked page view", {
|
|
452
|
-
eventId:
|
|
453
|
-
path: (
|
|
454
|
-
userId: r
|
|
529
|
+
eventId: g.data.id,
|
|
530
|
+
path: (f = e == null ? void 0 : e.page) == null ? void 0 : f.path,
|
|
531
|
+
userId: r,
|
|
532
|
+
channelName: l
|
|
455
533
|
});
|
|
456
|
-
}).catch((
|
|
457
|
-
console.error("[EmitKit-Server] Failed to track page view:",
|
|
534
|
+
}).catch((g) => {
|
|
535
|
+
console.error("[EmitKit-Server] Failed to track page view:", g);
|
|
458
536
|
});
|
|
459
537
|
}
|
|
460
538
|
async reset() {
|
|
@@ -477,8 +555,8 @@ class G extends B {
|
|
|
477
555
|
* Generate a description for the event
|
|
478
556
|
*/
|
|
479
557
|
getEventDescription(i, e) {
|
|
480
|
-
var
|
|
481
|
-
return (
|
|
558
|
+
var s;
|
|
559
|
+
return (s = i.properties) != null && s.description && typeof i.properties.description == "string" ? i.properties.description : {
|
|
482
560
|
engagement: "User interaction event",
|
|
483
561
|
user: "User lifecycle event",
|
|
484
562
|
navigation: "Navigation event",
|
|
@@ -500,81 +578,98 @@ class G extends B {
|
|
|
500
578
|
conversion: "💰"
|
|
501
579
|
}[i];
|
|
502
580
|
}
|
|
581
|
+
/**
|
|
582
|
+
* Resolve the channel name for an event based on priority:
|
|
583
|
+
* 1. Event property __emitkit_channel (highest priority)
|
|
584
|
+
* 2. Category mapping via categoryChannelMap
|
|
585
|
+
* 3. Default channelName (fallback, default: 'general')
|
|
586
|
+
*/
|
|
587
|
+
resolveChannelName(i, e) {
|
|
588
|
+
var r;
|
|
589
|
+
if ((r = i.properties) != null && r.__emitkit_channel && typeof i.properties.__emitkit_channel == "string")
|
|
590
|
+
return i.properties.__emitkit_channel;
|
|
591
|
+
if (this.config.categoryChannelMap && i.category) {
|
|
592
|
+
const s = this.config.categoryChannelMap[i.category];
|
|
593
|
+
if (s)
|
|
594
|
+
return s;
|
|
595
|
+
}
|
|
596
|
+
return e || this.config.channelName || "general";
|
|
597
|
+
}
|
|
503
598
|
}
|
|
504
|
-
async function
|
|
505
|
-
var e, r,
|
|
599
|
+
async function B(d, u, i) {
|
|
600
|
+
var e, r, s, a;
|
|
506
601
|
try {
|
|
507
|
-
const
|
|
508
|
-
if (!
|
|
602
|
+
const t = await d.json();
|
|
603
|
+
if (!t.events || !Array.isArray(t.events))
|
|
509
604
|
throw new Error("Invalid payload: missing events array");
|
|
510
|
-
const
|
|
511
|
-
for (const
|
|
605
|
+
const h = i != null && i.extractIp ? i.extractIp(d) : $(d), l = d.headers.get("user-agent"), n = i != null && i.enrichContext ? i.enrichContext(d) : {};
|
|
606
|
+
for (const o of t.events)
|
|
512
607
|
try {
|
|
513
|
-
switch (
|
|
608
|
+
switch (o.type) {
|
|
514
609
|
case "track": {
|
|
515
|
-
const
|
|
516
|
-
...
|
|
517
|
-
...
|
|
610
|
+
const p = {
|
|
611
|
+
...o.context,
|
|
612
|
+
...n,
|
|
518
613
|
server: {
|
|
519
|
-
...(e =
|
|
520
|
-
...typeof (
|
|
521
|
-
...
|
|
614
|
+
...(e = o.context) == null ? void 0 : e.server,
|
|
615
|
+
...typeof (n == null ? void 0 : n.server) == "object" && n.server !== null ? n.server : {},
|
|
616
|
+
...l ? { userAgent: l } : {}
|
|
522
617
|
},
|
|
523
618
|
device: {
|
|
524
|
-
...(r =
|
|
525
|
-
...
|
|
619
|
+
...(r = o.context) == null ? void 0 : r.device,
|
|
620
|
+
...h ? { ip: h } : {}
|
|
526
621
|
}
|
|
527
622
|
};
|
|
528
|
-
await
|
|
529
|
-
|
|
623
|
+
await u.track(
|
|
624
|
+
o.event.action,
|
|
530
625
|
// biome-ignore lint/suspicious/noExplicitAny: Properties from JSON cannot be type-checked against TEventMap at compile time
|
|
531
|
-
|
|
626
|
+
o.event.properties,
|
|
532
627
|
{
|
|
533
|
-
userId:
|
|
534
|
-
sessionId:
|
|
535
|
-
context:
|
|
628
|
+
userId: o.event.userId,
|
|
629
|
+
sessionId: o.event.sessionId,
|
|
630
|
+
context: p
|
|
536
631
|
}
|
|
537
632
|
);
|
|
538
633
|
break;
|
|
539
634
|
}
|
|
540
635
|
case "identify": {
|
|
541
|
-
|
|
636
|
+
u.identify(o.userId, o.traits);
|
|
542
637
|
break;
|
|
543
638
|
}
|
|
544
639
|
case "pageView": {
|
|
545
|
-
const
|
|
546
|
-
...
|
|
547
|
-
...
|
|
640
|
+
const p = {
|
|
641
|
+
...o.context,
|
|
642
|
+
...n,
|
|
548
643
|
server: {
|
|
549
|
-
...(
|
|
550
|
-
...typeof (
|
|
551
|
-
...
|
|
644
|
+
...(s = o.context) == null ? void 0 : s.server,
|
|
645
|
+
...typeof (n == null ? void 0 : n.server) == "object" && n.server !== null ? n.server : {},
|
|
646
|
+
...l ? { userAgent: l } : {}
|
|
552
647
|
},
|
|
553
648
|
device: {
|
|
554
|
-
...(
|
|
555
|
-
...
|
|
649
|
+
...(a = o.context) == null ? void 0 : a.device,
|
|
650
|
+
...h ? { ip: h } : {}
|
|
556
651
|
}
|
|
557
652
|
};
|
|
558
|
-
|
|
559
|
-
context:
|
|
653
|
+
u.pageView(o.properties, {
|
|
654
|
+
context: p
|
|
560
655
|
});
|
|
561
656
|
break;
|
|
562
657
|
}
|
|
563
658
|
case "reset":
|
|
564
659
|
break;
|
|
565
660
|
default:
|
|
566
|
-
console.warn("[Proxy] Unknown event type:",
|
|
661
|
+
console.warn("[Proxy] Unknown event type:", o);
|
|
567
662
|
}
|
|
568
|
-
} catch (
|
|
569
|
-
i != null && i.onError ? i.onError(
|
|
663
|
+
} catch (p) {
|
|
664
|
+
i != null && i.onError ? i.onError(p) : console.error("[Proxy] Failed to process event:", p);
|
|
570
665
|
}
|
|
571
|
-
} catch (
|
|
572
|
-
throw i != null && i.onError ? i.onError(
|
|
666
|
+
} catch (t) {
|
|
667
|
+
throw i != null && i.onError ? i.onError(t) : console.error("[Proxy] Failed to ingest events:", t), t;
|
|
573
668
|
}
|
|
574
669
|
}
|
|
575
|
-
function
|
|
670
|
+
function $(d) {
|
|
576
671
|
var i;
|
|
577
|
-
const
|
|
672
|
+
const u = [
|
|
578
673
|
"x-forwarded-for",
|
|
579
674
|
"x-real-ip",
|
|
580
675
|
"cf-connecting-ip",
|
|
@@ -582,27 +677,27 @@ function N(g) {
|
|
|
582
677
|
"x-client-ip",
|
|
583
678
|
"x-cluster-client-ip"
|
|
584
679
|
];
|
|
585
|
-
for (const e of
|
|
586
|
-
const r =
|
|
680
|
+
for (const e of u) {
|
|
681
|
+
const r = d.headers.get(e);
|
|
587
682
|
if (r)
|
|
588
683
|
return (i = r.split(",")[0]) == null ? void 0 : i.trim();
|
|
589
684
|
}
|
|
590
685
|
}
|
|
591
|
-
function
|
|
686
|
+
function V(d, u) {
|
|
592
687
|
return async (i) => {
|
|
593
688
|
try {
|
|
594
|
-
return await
|
|
689
|
+
return await B(i, d, u), new Response("OK", { status: 200 });
|
|
595
690
|
} catch (e) {
|
|
596
691
|
return console.error("[Proxy] Handler error:", e), new Response("Internal Server Error", { status: 500 });
|
|
597
692
|
}
|
|
598
693
|
};
|
|
599
694
|
}
|
|
600
695
|
export {
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
696
|
+
y as BaseAnalyticsProvider,
|
|
697
|
+
O as BentoServerProvider,
|
|
698
|
+
N as EmitKitServerProvider,
|
|
699
|
+
j as PirschServerProvider,
|
|
700
|
+
H as PostHogServerProvider,
|
|
701
|
+
V as createProxyHandler,
|
|
702
|
+
B as ingestProxyEvents
|
|
608
703
|
};
|