aurea-tracking-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,444 @@
1
+ // src/index.ts
2
+ var AureaSDK = class {
3
+ constructor(config) {
4
+ this.eventQueue = [];
5
+ this.initialized = false;
6
+ this.config = {
7
+ apiUrl: "http://localhost:3000/api",
8
+ debug: false,
9
+ autoTrack: {
10
+ pageViews: true,
11
+ forms: true,
12
+ clicks: false,
13
+ scrollDepth: false
14
+ },
15
+ respectDoNotTrack: true,
16
+ anonymizeIp: true,
17
+ batchSize: 10,
18
+ batchInterval: 2e3,
19
+ ...config
20
+ };
21
+ this.sessionId = this.getOrCreateSessionId();
22
+ this.anonymousId = this.getOrCreateAnonymousId();
23
+ if (typeof window !== "undefined") {
24
+ const savedUserId = localStorage.getItem("aurea_user_id");
25
+ if (savedUserId) {
26
+ this.userId = savedUserId;
27
+ }
28
+ }
29
+ }
30
+ /**
31
+ * Initialize the SDK
32
+ */
33
+ init() {
34
+ if (this.initialized) {
35
+ console.warn("[Aurea SDK] Already initialized");
36
+ return;
37
+ }
38
+ if (this.config.respectDoNotTrack && typeof navigator !== "undefined" && (navigator.doNotTrack === "1" || navigator.msDoNotTrack === "1")) {
39
+ if (this.config.debug) {
40
+ console.log("[Aurea SDK] Do Not Track enabled, skipping initialization");
41
+ }
42
+ return;
43
+ }
44
+ this.initialized = true;
45
+ if (this.config.autoTrack?.pageViews) {
46
+ this.trackPageLoad();
47
+ this.trackPageChanges();
48
+ }
49
+ if (this.config.autoTrack?.forms) {
50
+ this.trackForms();
51
+ }
52
+ if (this.config.autoTrack?.scrollDepth) {
53
+ this.trackScrollDepth();
54
+ }
55
+ this.startBatchTimer();
56
+ this.startPurchasePolling();
57
+ if (this.config.debug) {
58
+ console.log("[Aurea SDK] Initialized", {
59
+ sessionId: this.sessionId,
60
+ anonymousId: this.anonymousId,
61
+ userId: this.userId
62
+ });
63
+ }
64
+ }
65
+ /**
66
+ * Track a custom event
67
+ */
68
+ track(eventName, properties) {
69
+ const event = {
70
+ eventId: this.generateEventId(),
71
+ eventName,
72
+ properties: properties || {},
73
+ context: this.buildContext(),
74
+ timestamp: Date.now()
75
+ };
76
+ this.enqueueEvent(event);
77
+ if (this.config.debug) {
78
+ console.log("[Aurea SDK] Event tracked:", eventName, properties);
79
+ }
80
+ }
81
+ /**
82
+ * Identify a user
83
+ */
84
+ identify(userId, traits) {
85
+ this.userId = userId;
86
+ if (typeof window !== "undefined") {
87
+ localStorage.setItem("aurea_user_id", userId);
88
+ if (traits) {
89
+ localStorage.setItem("aurea_user_traits", JSON.stringify(traits));
90
+ }
91
+ }
92
+ this.track("user_identified", {
93
+ userId,
94
+ traits
95
+ });
96
+ if (this.config.debug) {
97
+ console.log("[Aurea SDK] User identified:", userId);
98
+ }
99
+ }
100
+ /**
101
+ * Track a page view
102
+ */
103
+ page(name, properties) {
104
+ this.track("page_view", {
105
+ pageName: name || (typeof document !== "undefined" ? document.title : ""),
106
+ pageUrl: typeof window !== "undefined" ? window.location.href : "",
107
+ pagePath: typeof window !== "undefined" ? window.location.pathname : "",
108
+ pageSearch: typeof window !== "undefined" ? window.location.search : "",
109
+ referrer: typeof document !== "undefined" ? document.referrer : "",
110
+ ...properties
111
+ });
112
+ }
113
+ /**
114
+ * Track a conversion event
115
+ */
116
+ conversion(data) {
117
+ this.track("conversion", {
118
+ conversionType: data.type,
119
+ revenue: data.revenue,
120
+ currency: data.currency || "USD",
121
+ orderId: data.orderId,
122
+ ...data.properties
123
+ });
124
+ if (typeof sessionStorage !== "undefined") {
125
+ sessionStorage.setItem("aurea_converted", "true");
126
+ }
127
+ if (this.config.debug) {
128
+ console.log("[Aurea SDK] Conversion tracked:", data);
129
+ }
130
+ }
131
+ /**
132
+ * Get or create session ID
133
+ */
134
+ getOrCreateSessionId() {
135
+ if (typeof sessionStorage === "undefined") {
136
+ return this.generateId();
137
+ }
138
+ let sessionId = sessionStorage.getItem("aurea_session_id");
139
+ if (!sessionId) {
140
+ sessionId = this.generateId();
141
+ sessionStorage.setItem("aurea_session_id", sessionId);
142
+ }
143
+ return sessionId;
144
+ }
145
+ /**
146
+ * Get or create anonymous ID
147
+ */
148
+ getOrCreateAnonymousId() {
149
+ if (typeof localStorage === "undefined") {
150
+ return this.generateId();
151
+ }
152
+ let anonymousId = localStorage.getItem("aurea_anonymous_id");
153
+ if (!anonymousId) {
154
+ anonymousId = this.generateId();
155
+ localStorage.setItem("aurea_anonymous_id", anonymousId);
156
+ }
157
+ return anonymousId;
158
+ }
159
+ /**
160
+ * Build event context
161
+ */
162
+ buildContext() {
163
+ const url = typeof window !== "undefined" ? new URL(window.location.href) : new URL("http://localhost");
164
+ return {
165
+ page: typeof window !== "undefined" ? {
166
+ url: window.location.href,
167
+ path: window.location.pathname,
168
+ title: document.title,
169
+ referrer: document.referrer
170
+ } : void 0,
171
+ utm: {
172
+ source: url.searchParams.get("utm_source") || void 0,
173
+ medium: url.searchParams.get("utm_medium") || void 0,
174
+ campaign: url.searchParams.get("utm_campaign") || void 0,
175
+ term: url.searchParams.get("utm_term") || void 0,
176
+ content: url.searchParams.get("utm_content") || void 0
177
+ },
178
+ user: {
179
+ userId: this.userId,
180
+ anonymousId: this.anonymousId
181
+ },
182
+ session: {
183
+ sessionId: this.sessionId
184
+ },
185
+ device: typeof navigator !== "undefined" ? {
186
+ userAgent: navigator.userAgent,
187
+ screenWidth: window.screen?.width,
188
+ screenHeight: window.screen?.height,
189
+ language: navigator.language,
190
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
191
+ } : void 0
192
+ };
193
+ }
194
+ /**
195
+ * Track initial page load
196
+ */
197
+ trackPageLoad() {
198
+ if (typeof window !== "undefined") {
199
+ const justPurchased = localStorage.getItem("aurea_just_purchased");
200
+ const isThankYouPage = window.location.pathname.includes("/thank-you");
201
+ if (justPurchased === "true" && !isThankYouPage) {
202
+ console.log("[Aurea SDK] Purchase detected, redirecting to thank-you page...");
203
+ localStorage.removeItem("aurea_just_purchased");
204
+ window.location.href = "/thank-you?from_checkout=true";
205
+ return;
206
+ }
207
+ const referrer = document.referrer;
208
+ const urlParams = new URLSearchParams(window.location.search);
209
+ const fromCheckout = urlParams.get("from_checkout") === "true";
210
+ const whopReferrer = referrer.includes("whop.com");
211
+ if ((fromCheckout || whopReferrer || justPurchased === "true") && isThankYouPage) {
212
+ localStorage.removeItem("aurea_just_purchased");
213
+ this.track("checkout_return", {
214
+ referrer,
215
+ returnUrl: window.location.href,
216
+ fromWhop: whopReferrer,
217
+ landingPage: "/thank-you"
218
+ });
219
+ }
220
+ this.page();
221
+ }
222
+ }
223
+ /**
224
+ * Track page changes (for SPAs)
225
+ */
226
+ trackPageChanges() {
227
+ if (typeof window === "undefined") return;
228
+ let lastPath = window.location.pathname;
229
+ const observer = new MutationObserver(() => {
230
+ if (window.location.pathname !== lastPath) {
231
+ lastPath = window.location.pathname;
232
+ this.page();
233
+ }
234
+ });
235
+ observer.observe(document.body, {
236
+ childList: true,
237
+ subtree: true
238
+ });
239
+ window.addEventListener("popstate", () => {
240
+ this.page();
241
+ });
242
+ }
243
+ /**
244
+ * Track form submissions
245
+ */
246
+ trackForms() {
247
+ if (typeof document === "undefined") return;
248
+ document.addEventListener("submit", (e) => {
249
+ const form = e.target;
250
+ const formId = form.id || form.name || "unknown";
251
+ this.track("form_submit", {
252
+ formId,
253
+ formAction: form.action,
254
+ formMethod: form.method
255
+ });
256
+ });
257
+ }
258
+ /**
259
+ * Track scroll depth
260
+ */
261
+ trackScrollDepth() {
262
+ if (typeof window === "undefined") return;
263
+ const depths = [25, 50, 75, 100];
264
+ const tracked = /* @__PURE__ */ new Set();
265
+ const checkScroll = () => {
266
+ const scrollPercent = window.scrollY / (document.body.scrollHeight - window.innerHeight) * 100;
267
+ for (const depth of depths) {
268
+ if (scrollPercent >= depth && !tracked.has(depth)) {
269
+ tracked.add(depth);
270
+ this.track("scroll_depth", { depth });
271
+ }
272
+ }
273
+ };
274
+ window.addEventListener("scroll", checkScroll, { passive: true });
275
+ }
276
+ /**
277
+ * Enqueue event for batching
278
+ */
279
+ enqueueEvent(event) {
280
+ this.eventQueue.push(event);
281
+ if (this.eventQueue.length >= (this.config.batchSize || 10)) {
282
+ this.flushEvents();
283
+ }
284
+ }
285
+ /**
286
+ * Send events to API
287
+ */
288
+ async sendEvents(events) {
289
+ if (events.length === 0) return;
290
+ try {
291
+ const response = await fetch(`${this.config.apiUrl}/track/events`, {
292
+ method: "POST",
293
+ headers: {
294
+ "Content-Type": "application/json",
295
+ "X-Aurea-API-Key": this.config.apiKey,
296
+ "X-Aurea-Funnel-ID": this.config.funnelId
297
+ },
298
+ body: JSON.stringify({
299
+ events,
300
+ batch: true
301
+ }),
302
+ keepalive: true
303
+ });
304
+ if (!response.ok) {
305
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
306
+ }
307
+ if (this.config.debug) {
308
+ console.log("[Aurea SDK] Events sent successfully:", events.length);
309
+ }
310
+ } catch (error) {
311
+ console.error("[Aurea SDK] Failed to send events:", error);
312
+ if (typeof localStorage !== "undefined") {
313
+ const failedEvents = JSON.parse(localStorage.getItem("aurea_failed_events") || "[]") || [];
314
+ failedEvents.push(...events);
315
+ localStorage.setItem("aurea_failed_events", JSON.stringify(failedEvents));
316
+ }
317
+ }
318
+ }
319
+ /**
320
+ * Flush queued events
321
+ */
322
+ flushEvents() {
323
+ if (this.eventQueue.length === 0) return;
324
+ const eventsToSend = [...this.eventQueue];
325
+ this.eventQueue = [];
326
+ this.sendEvents(eventsToSend);
327
+ }
328
+ /**
329
+ * Start batch timer
330
+ */
331
+ startBatchTimer() {
332
+ if (typeof window === "undefined") return;
333
+ this.batchTimer = setInterval(() => {
334
+ this.flushEvents();
335
+ }, this.config.batchInterval || 2e3);
336
+ window.addEventListener("beforeunload", () => {
337
+ this.flushEvents();
338
+ });
339
+ document.addEventListener("visibilitychange", () => {
340
+ if (document.hidden) {
341
+ this.flushEvents();
342
+ }
343
+ });
344
+ }
345
+ /**
346
+ * Poll for purchase completion
347
+ * Checks every 3 seconds if user has made a purchase
348
+ */
349
+ startPurchasePolling() {
350
+ if (typeof window === "undefined") return;
351
+ this.checkForPurchase();
352
+ setInterval(() => {
353
+ this.checkForPurchase();
354
+ }, 3e3);
355
+ }
356
+ /**
357
+ * Check if user has completed a purchase
358
+ */
359
+ async checkForPurchase() {
360
+ try {
361
+ const response = await fetch(
362
+ `${this.config.apiUrl?.replace("/api", "")}/api/check-purchase?anonymousId=${this.anonymousId}`
363
+ );
364
+ const data = await response.json();
365
+ if (data.hasPurchased) {
366
+ console.log("[Aurea SDK] Purchase detected! Redirecting to thank-you page...");
367
+ localStorage.setItem("aurea_just_purchased", "true");
368
+ window.location.href = "/thank-you?from_checkout=true";
369
+ }
370
+ } catch (error) {
371
+ if (this.config.debug) {
372
+ console.log("[Aurea SDK] Purchase check failed:", error);
373
+ }
374
+ }
375
+ }
376
+ /**
377
+ * Generate unique ID
378
+ */
379
+ generateId() {
380
+ return `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
381
+ }
382
+ /**
383
+ * Generate event ID
384
+ */
385
+ generateEventId() {
386
+ return `evt_${this.generateId()}`;
387
+ }
388
+ };
389
+ var sdkInstance = null;
390
+ function initAurea(config) {
391
+ if (sdkInstance) {
392
+ console.warn("[Aurea SDK] SDK already initialized");
393
+ return sdkInstance;
394
+ }
395
+ sdkInstance = new AureaSDK(config);
396
+ sdkInstance.init();
397
+ if (typeof window !== "undefined") {
398
+ window.aurea = sdkInstance;
399
+ }
400
+ return sdkInstance;
401
+ }
402
+ function getAurea() {
403
+ return sdkInstance;
404
+ }
405
+ function trackEvent(name, properties) {
406
+ const aurea = getAurea();
407
+ if (aurea) {
408
+ aurea.track(name, properties);
409
+ } else {
410
+ console.warn("[Aurea SDK] SDK not initialized. Call initAurea() first.");
411
+ }
412
+ }
413
+ function identifyUser(userId, traits) {
414
+ const aurea = getAurea();
415
+ if (aurea) {
416
+ aurea.identify(userId, traits);
417
+ } else {
418
+ console.warn("[Aurea SDK] SDK not initialized. Call initAurea() first.");
419
+ }
420
+ }
421
+ function trackConversion(data) {
422
+ const aurea = getAurea();
423
+ if (aurea) {
424
+ aurea.conversion(data);
425
+ } else {
426
+ console.warn("[Aurea SDK] SDK not initialized. Call initAurea() first.");
427
+ }
428
+ }
429
+ function trackPage(name, properties) {
430
+ const aurea = getAurea();
431
+ if (aurea) {
432
+ aurea.page(name, properties);
433
+ } else {
434
+ console.warn("[Aurea SDK] SDK not initialized. Call initAurea() first.");
435
+ }
436
+ }
437
+ export {
438
+ getAurea,
439
+ identifyUser,
440
+ initAurea,
441
+ trackConversion,
442
+ trackEvent,
443
+ trackPage
444
+ };
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "aurea-tracking-sdk",
3
+ "version": "1.0.0",
4
+ "description": "Standalone tracking SDK for Aurea CRM external funnels",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "README.md"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsup src/index.ts --format cjs,esm --dts",
14
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "keywords": [
18
+ "analytics",
19
+ "tracking",
20
+ "aurea",
21
+ "crm",
22
+ "funnel",
23
+ "conversion"
24
+ ],
25
+ "author": "Aurea CRM",
26
+ "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/yourusername/aurea-tracking-sdk.git"
30
+ },
31
+ "bugs": {
32
+ "url": "https://github.com/yourusername/aurea-tracking-sdk/issues"
33
+ },
34
+ "homepage": "https://github.com/yourusername/aurea-tracking-sdk#readme",
35
+ "devDependencies": {
36
+ "@types/node": "^25.0.3",
37
+ "tsup": "^8.0.1",
38
+ "typescript": "^5.3.3"
39
+ }
40
+ }