humanbehavior-js 0.1.8 → 0.1.9
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/cjs/index.js +74 -57
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react/index.js +0 -1
- package/dist/cjs/react/index.js.map +1 -1
- package/dist/esm/index.js +74 -58
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/react/index.js +0 -1
- package/dist/esm/react/index.js.map +1 -1
- package/dist/index.min.js +2 -2
- package/dist/index.min.js.map +1 -1
- package/dist/types/index.d.ts +3 -5
- package/package.json +2 -1
- package/readme.md +2 -0
- package/simple-spa.html +75 -11
- package/src/api.ts +64 -10
- package/src/react/index.tsx +0 -1
- package/src/tracker.ts +22 -43
package/dist/types/index.d.ts
CHANGED
|
@@ -89,8 +89,6 @@ declare global {
|
|
|
89
89
|
declare class HumanBehaviorTracker {
|
|
90
90
|
private eventIngestionQueue;
|
|
91
91
|
private queueSizeBytes;
|
|
92
|
-
private rejectedEvents;
|
|
93
|
-
private isProcessingRejectedEvents;
|
|
94
92
|
private sessionId;
|
|
95
93
|
private userProperties;
|
|
96
94
|
private isProcessing;
|
|
@@ -197,7 +195,6 @@ declare class HumanBehaviorTracker {
|
|
|
197
195
|
start(): Promise<void>;
|
|
198
196
|
stop(): Promise<void>;
|
|
199
197
|
addEvent(event: any): Promise<void>;
|
|
200
|
-
private processRejectedEvents;
|
|
201
198
|
private flush;
|
|
202
199
|
private setCookie;
|
|
203
200
|
getCookie(name: string): string | null;
|
|
@@ -260,6 +257,7 @@ declare class HumanBehaviorTracker {
|
|
|
260
257
|
declare const MAX_CHUNK_SIZE_BYTES: number;
|
|
261
258
|
declare function isChunkSizeExceeded(currentChunk: any[], newEvent: any, sessionId: string): boolean;
|
|
262
259
|
declare function validateSingleEventSize(event: any, sessionId: string): void;
|
|
260
|
+
declare function splitLargeEvent(event: any, sessionId: string): any[];
|
|
263
261
|
declare class HumanBehaviorAPI {
|
|
264
262
|
private apiKey;
|
|
265
263
|
private baseUrl;
|
|
@@ -272,7 +270,7 @@ declare class HumanBehaviorAPI {
|
|
|
272
270
|
endUserId: any;
|
|
273
271
|
}>;
|
|
274
272
|
sendEvents(events: any[], sessionId: string, userId: string): Promise<void>;
|
|
275
|
-
sendEventsChunked(events: any[], sessionId: string): Promise<any[]>;
|
|
273
|
+
sendEventsChunked(events: any[], sessionId: string, userId?: string): Promise<any[]>;
|
|
276
274
|
sendUserData(userId: string, userData: Record<string, any>, sessionId: string): Promise<any>;
|
|
277
275
|
sendUserAuth(userId: string, userData: Record<string, any>, sessionId: string, authFields: string[]): Promise<any>;
|
|
278
276
|
sendBeaconEvents(events: any[], sessionId: string): boolean;
|
|
@@ -316,5 +314,5 @@ declare const logWarn: (message: string, ...args: any[]) => void;
|
|
|
316
314
|
declare const logInfo: (message: string, ...args: any[]) => void;
|
|
317
315
|
declare const logDebug: (message: string, ...args: any[]) => void;
|
|
318
316
|
|
|
319
|
-
export { HumanBehaviorAPI, HumanBehaviorTracker, LogLevel, MAX_CHUNK_SIZE_BYTES, RedactionManager, HumanBehaviorTracker as default, isChunkSizeExceeded, logDebug, logError, logInfo, logWarn, logger, redactionManager, validateSingleEventSize };
|
|
317
|
+
export { HumanBehaviorAPI, HumanBehaviorTracker, LogLevel, MAX_CHUNK_SIZE_BYTES, RedactionManager, HumanBehaviorTracker as default, isChunkSizeExceeded, logDebug, logError, logInfo, logWarn, logger, redactionManager, splitLargeEvent, validateSingleEventSize };
|
|
320
318
|
export type { LoggerConfig, RedactionOptions };
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "humanbehavior-js",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "SDK for HumanBehavior session and event recording",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
7
7
|
"module": "./dist/esm/index.js",
|
|
8
8
|
"types": "./dist/types/index.d.ts",
|
|
9
9
|
"unpkg": "dist/index.min.js",
|
|
10
|
+
"homepage": "https://documentation.humanbehavior.co",
|
|
10
11
|
"exports": {
|
|
11
12
|
".": {
|
|
12
13
|
"import": "./dist/esm/index.js",
|
package/readme.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
A simplified session recording and analytics SDK that maintains session continuity across page navigations.
|
|
4
4
|
|
|
5
|
+
📖 **[Full Documentation](https://documentation.humanbehavior.co)** - Complete API reference, examples, and integration guides
|
|
6
|
+
|
|
5
7
|
## Quick Start
|
|
6
8
|
|
|
7
9
|
### Single Page Application (Recommended)
|
package/simple-spa.html
CHANGED
|
@@ -280,10 +280,21 @@
|
|
|
280
280
|
|
|
281
281
|
console.log('Tracker created, waiting for initialization...');
|
|
282
282
|
|
|
283
|
-
// Wait for tracker to initialize
|
|
283
|
+
// Wait for tracker to initialize with timeout
|
|
284
284
|
if (tracker.initializationPromise) {
|
|
285
|
-
|
|
286
|
-
|
|
285
|
+
try {
|
|
286
|
+
await Promise.race([
|
|
287
|
+
tracker.initializationPromise,
|
|
288
|
+
new Promise((_, reject) =>
|
|
289
|
+
setTimeout(() => reject(new Error('Initialization timeout')), 10000)
|
|
290
|
+
)
|
|
291
|
+
]);
|
|
292
|
+
console.log('Tracker initialized successfully');
|
|
293
|
+
} catch (initError) {
|
|
294
|
+
console.warn('Tracker initialization failed or timed out:', initError);
|
|
295
|
+
addLog('Tracker initialization warning: ' + initError.message);
|
|
296
|
+
// Continue anyway - tracker might still work
|
|
297
|
+
}
|
|
287
298
|
} else {
|
|
288
299
|
console.log('No initialization promise, continuing...');
|
|
289
300
|
}
|
|
@@ -415,30 +426,35 @@
|
|
|
415
426
|
const sessionIdElements = document.querySelectorAll('#sessionId, #sessionId-about, #sessionId-status');
|
|
416
427
|
const sessionId = tracker.getSessionId ? tracker.getSessionId() : 'Not available';
|
|
417
428
|
sessionIdElements.forEach(el => {
|
|
418
|
-
el.textContent = sessionId;
|
|
429
|
+
if (el) el.textContent = sessionId;
|
|
419
430
|
});
|
|
420
431
|
|
|
421
432
|
const endUserIdElements = document.querySelectorAll('#endUserId, #endUserId-status');
|
|
422
433
|
const endUserId = tracker.endUserId || 'Not set';
|
|
423
434
|
endUserIdElements.forEach(el => {
|
|
424
|
-
el.textContent = endUserId;
|
|
435
|
+
if (el) el.textContent = endUserId;
|
|
425
436
|
});
|
|
426
437
|
|
|
427
438
|
// Update user type (preexisting vs new)
|
|
428
439
|
const userTypeElements = document.querySelectorAll('#userType, #userType-about, #userType-status');
|
|
429
440
|
let userType = 'Unknown';
|
|
430
441
|
if (tracker.isPreexistingUser) {
|
|
431
|
-
|
|
432
|
-
|
|
442
|
+
try {
|
|
443
|
+
const isPreexisting = tracker.isPreexistingUser();
|
|
444
|
+
userType = isPreexisting ? '🔄 Preexisting User' : '🆕 New User';
|
|
445
|
+
} catch (error) {
|
|
446
|
+
console.warn('Error checking preexisting user:', error);
|
|
447
|
+
userType = 'Error';
|
|
448
|
+
}
|
|
433
449
|
}
|
|
434
450
|
userTypeElements.forEach(el => {
|
|
435
|
-
el.textContent = userType;
|
|
451
|
+
if (el) el.textContent = userType;
|
|
436
452
|
});
|
|
437
453
|
|
|
438
454
|
const currentUrlElements = document.querySelectorAll('#currentUrl, #currentUrl-status');
|
|
439
455
|
const currentUrl = window.location.href;
|
|
440
456
|
currentUrlElements.forEach(el => {
|
|
441
|
-
el.textContent = currentUrl;
|
|
457
|
+
if (el) el.textContent = currentUrl;
|
|
442
458
|
});
|
|
443
459
|
|
|
444
460
|
const trackerInitialized = document.getElementById('trackerInitialized');
|
|
@@ -448,8 +464,13 @@
|
|
|
448
464
|
|
|
449
465
|
const connectionStatus = document.getElementById('connectionStatus');
|
|
450
466
|
if (connectionStatus && tracker.getConnectionStatus) {
|
|
451
|
-
|
|
452
|
-
|
|
467
|
+
try {
|
|
468
|
+
const status = tracker.getConnectionStatus();
|
|
469
|
+
connectionStatus.textContent = status.blocked ? 'Blocked' : 'Connected';
|
|
470
|
+
} catch (error) {
|
|
471
|
+
console.warn('Error getting connection status:', error);
|
|
472
|
+
connectionStatus.textContent = 'Error';
|
|
473
|
+
}
|
|
453
474
|
}
|
|
454
475
|
|
|
455
476
|
const pageLoadTime = document.getElementById('pageLoadTime');
|
|
@@ -458,6 +479,7 @@
|
|
|
458
479
|
}
|
|
459
480
|
} catch (error) {
|
|
460
481
|
console.error('Error updating status:', error);
|
|
482
|
+
// Don't let status update errors crash the app
|
|
461
483
|
}
|
|
462
484
|
}
|
|
463
485
|
|
|
@@ -589,6 +611,48 @@
|
|
|
589
611
|
|
|
590
612
|
// Initialize the app when the page loads
|
|
591
613
|
document.addEventListener('DOMContentLoaded', initApp);
|
|
614
|
+
|
|
615
|
+
// Add global error handler to prevent page from going blank
|
|
616
|
+
window.addEventListener('error', function(event) {
|
|
617
|
+
console.error('Global error caught:', event.error);
|
|
618
|
+
addLog('Global error: ' + event.error.message);
|
|
619
|
+
|
|
620
|
+
// Prevent the page from going blank by showing error content
|
|
621
|
+
const contentDiv = document.getElementById('content');
|
|
622
|
+
if (contentDiv && contentDiv.innerHTML.trim() === '') {
|
|
623
|
+
contentDiv.innerHTML = `
|
|
624
|
+
<h2>Application Error</h2>
|
|
625
|
+
<p>An error occurred but the application is still running:</p>
|
|
626
|
+
<div class="status">
|
|
627
|
+
<strong>Error:</strong> ${event.error.message}<br>
|
|
628
|
+
<strong>File:</strong> ${event.filename}<br>
|
|
629
|
+
<strong>Line:</strong> ${event.lineno}
|
|
630
|
+
</div>
|
|
631
|
+
<button class="button" onclick="loadPage('home')">Go to Home</button>
|
|
632
|
+
<button class="button secondary" onclick="location.reload()">Reload Page</button>
|
|
633
|
+
`;
|
|
634
|
+
}
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
// Add unhandled promise rejection handler
|
|
638
|
+
window.addEventListener('unhandledrejection', function(event) {
|
|
639
|
+
console.error('Unhandled promise rejection:', event.reason);
|
|
640
|
+
addLog('Unhandled promise rejection: ' + event.reason);
|
|
641
|
+
event.preventDefault(); // Prevent the default browser behavior
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
// Add periodic health check
|
|
645
|
+
setInterval(() => {
|
|
646
|
+
try {
|
|
647
|
+
const contentDiv = document.getElementById('content');
|
|
648
|
+
if (contentDiv && contentDiv.innerHTML.trim() === '') {
|
|
649
|
+
console.warn('Content div is empty, attempting to restore...');
|
|
650
|
+
loadPage('home');
|
|
651
|
+
}
|
|
652
|
+
} catch (error) {
|
|
653
|
+
console.error('Health check error:', error);
|
|
654
|
+
}
|
|
655
|
+
}, 5000); // Check every 5 seconds
|
|
592
656
|
</script>
|
|
593
657
|
</body>
|
|
594
658
|
</html>
|
package/src/api.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { logError, logInfo } from './utils/logger';
|
|
2
2
|
|
|
3
|
-
export const MAX_CHUNK_SIZE_BYTES = 1024 * 1024
|
|
3
|
+
export const MAX_CHUNK_SIZE_BYTES = 1024 * 1024; // 1MB chunk size - more conservative
|
|
4
4
|
|
|
5
5
|
export function isChunkSizeExceeded(currentChunk: any[], newEvent: any, sessionId: string): boolean {
|
|
6
6
|
const nextChunkSize = new TextEncoder().encode(JSON.stringify({
|
|
@@ -18,10 +18,62 @@ export function validateSingleEventSize(event: any, sessionId: string): void {
|
|
|
18
18
|
})).length;
|
|
19
19
|
|
|
20
20
|
if (singleEventSize > MAX_CHUNK_SIZE_BYTES) {
|
|
21
|
-
|
|
21
|
+
// Instead of throwing, log a warning and suggest reducing event size
|
|
22
|
+
console.warn(`Single event size (${singleEventSize} bytes) exceeds maximum chunk size (${MAX_CHUNK_SIZE_BYTES} bytes). Consider reducing event data size.`);
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
export function splitLargeEvent(event: any, sessionId: string): any[] {
|
|
27
|
+
const eventSize = new TextEncoder().encode(JSON.stringify({
|
|
28
|
+
sessionId,
|
|
29
|
+
events: [event]
|
|
30
|
+
})).length;
|
|
31
|
+
|
|
32
|
+
if (eventSize <= MAX_CHUNK_SIZE_BYTES) {
|
|
33
|
+
return [event];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// If event is too large, try to split it by removing large properties
|
|
37
|
+
const simplifiedEvent = { ...event };
|
|
38
|
+
|
|
39
|
+
// Remove potentially large properties
|
|
40
|
+
const largeProperties = ['screenshot', 'html', 'dom', 'fullText', 'innerHTML', 'outerHTML'];
|
|
41
|
+
largeProperties.forEach(prop => {
|
|
42
|
+
if (simplifiedEvent[prop]) {
|
|
43
|
+
delete simplifiedEvent[prop];
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Check if simplified event is now small enough
|
|
48
|
+
const simplifiedSize = new TextEncoder().encode(JSON.stringify({
|
|
49
|
+
sessionId,
|
|
50
|
+
events: [simplifiedEvent]
|
|
51
|
+
})).length;
|
|
52
|
+
|
|
53
|
+
if (simplifiedSize <= MAX_CHUNK_SIZE_BYTES) {
|
|
54
|
+
return [simplifiedEvent];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// If still too large, create a minimal event
|
|
58
|
+
const minimalEvent = {
|
|
59
|
+
type: event.type,
|
|
60
|
+
timestamp: event.timestamp,
|
|
61
|
+
url: event.url,
|
|
62
|
+
pathname: event.pathname,
|
|
63
|
+
// Keep only essential properties
|
|
64
|
+
...Object.fromEntries(
|
|
65
|
+
Object.entries(event).filter(([key, value]) =>
|
|
66
|
+
!largeProperties.includes(key) &&
|
|
67
|
+
typeof value !== 'object' &&
|
|
68
|
+
typeof value !== 'string' ||
|
|
69
|
+
(typeof value === 'string' && value.length < 1000)
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
return [minimalEvent];
|
|
75
|
+
}
|
|
76
|
+
|
|
25
77
|
export class HumanBehaviorAPI {
|
|
26
78
|
private apiKey: string;
|
|
27
79
|
private baseUrl: string;
|
|
@@ -98,7 +150,7 @@ export class HumanBehaviorAPI {
|
|
|
98
150
|
}
|
|
99
151
|
}
|
|
100
152
|
|
|
101
|
-
async sendEventsChunked(events: any[], sessionId: string) {
|
|
153
|
+
async sendEventsChunked(events: any[], sessionId: string, userId?: string) {
|
|
102
154
|
try {
|
|
103
155
|
const results = [];
|
|
104
156
|
let currentChunk: any[] = [];
|
|
@@ -115,7 +167,8 @@ export class HumanBehaviorAPI {
|
|
|
115
167
|
},
|
|
116
168
|
body: JSON.stringify({
|
|
117
169
|
sessionId,
|
|
118
|
-
events: currentChunk
|
|
170
|
+
events: currentChunk,
|
|
171
|
+
endUserId: userId
|
|
119
172
|
})
|
|
120
173
|
});
|
|
121
174
|
|
|
@@ -127,11 +180,11 @@ export class HumanBehaviorAPI {
|
|
|
127
180
|
currentChunk = [];
|
|
128
181
|
}
|
|
129
182
|
|
|
130
|
-
//
|
|
131
|
-
|
|
183
|
+
// Handle large events by splitting them
|
|
184
|
+
const splitEvents = splitLargeEvent(event, sessionId);
|
|
132
185
|
|
|
133
|
-
// Start new chunk with
|
|
134
|
-
currentChunk =
|
|
186
|
+
// Start new chunk with the split events
|
|
187
|
+
currentChunk = splitEvents;
|
|
135
188
|
} else {
|
|
136
189
|
// Add event to current chunk
|
|
137
190
|
currentChunk.push(event);
|
|
@@ -148,7 +201,8 @@ export class HumanBehaviorAPI {
|
|
|
148
201
|
},
|
|
149
202
|
body: JSON.stringify({
|
|
150
203
|
sessionId,
|
|
151
|
-
events: currentChunk
|
|
204
|
+
events: currentChunk,
|
|
205
|
+
endUserId: userId
|
|
152
206
|
})
|
|
153
207
|
});
|
|
154
208
|
|
|
@@ -256,7 +310,7 @@ export class HumanBehaviorAPI {
|
|
|
256
310
|
});
|
|
257
311
|
|
|
258
312
|
if (!response.ok) {
|
|
259
|
-
throw new Error(`Failed to send custom event: ${response.statusText}`);
|
|
313
|
+
throw new Error(`Failed to send custom event: ${response.status} ${response.statusText}`);
|
|
260
314
|
}
|
|
261
315
|
|
|
262
316
|
return await response.json();
|
package/src/react/index.tsx
CHANGED
|
@@ -114,7 +114,6 @@ export const HumanBehaviorProvider = ({ apiKey, client, children, options }: Hum
|
|
|
114
114
|
|
|
115
115
|
// Wait for initialization to complete
|
|
116
116
|
tracker.initializationPromise?.then(async () => {
|
|
117
|
-
// Start the tracker to enable event flushing and recording
|
|
118
117
|
await tracker.start();
|
|
119
118
|
setIsInitialized(true);
|
|
120
119
|
|
package/src/tracker.ts
CHANGED
|
@@ -18,8 +18,6 @@ declare global {
|
|
|
18
18
|
export class HumanBehaviorTracker {
|
|
19
19
|
private eventIngestionQueue: any[] = [];
|
|
20
20
|
private queueSizeBytes: number = 0;
|
|
21
|
-
private rejectedEvents: any[] = [];
|
|
22
|
-
private isProcessingRejectedEvents: boolean = false;
|
|
23
21
|
|
|
24
22
|
private sessionId!: string;
|
|
25
23
|
private userProperties: Record<string, any> = {};
|
|
@@ -183,7 +181,6 @@ export class HumanBehaviorTracker {
|
|
|
183
181
|
if (isBrowser) {
|
|
184
182
|
this.setupPageUnloadHandler();
|
|
185
183
|
this.setupNavigationTracking();
|
|
186
|
-
this.processRejectedEvents();
|
|
187
184
|
} else {
|
|
188
185
|
logWarn('HumanBehaviorTracker initialized in a non-browser environment. Session tracking is disabled.');
|
|
189
186
|
}
|
|
@@ -349,10 +346,21 @@ export class HumanBehaviorTracker {
|
|
|
349
346
|
await this.api.sendCustomEvent(this.sessionId, eventName, properties);
|
|
350
347
|
|
|
351
348
|
logDebug(`Custom event tracked: ${eventName}`, properties);
|
|
352
|
-
} catch (error) {
|
|
349
|
+
} catch (error: any) {
|
|
353
350
|
logError('Failed to track custom event:', error);
|
|
354
351
|
|
|
355
|
-
//
|
|
352
|
+
// Handle specific error types - check for any custom event failure
|
|
353
|
+
if (error.message?.includes('500') ||
|
|
354
|
+
error.message?.includes('Internal Server Error') ||
|
|
355
|
+
error.message?.includes('Failed to send custom event')) {
|
|
356
|
+
logWarn('Custom event endpoint failed, using fallback');
|
|
357
|
+
} else if (error.message?.includes('ERR_BLOCKED_BY_CLIENT')) {
|
|
358
|
+
logWarn('Custom event request blocked by ad blocker, using fallback');
|
|
359
|
+
} else if (error.message?.includes('Failed to fetch')) {
|
|
360
|
+
logWarn('Custom event network error, using fallback');
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Always try fallback for any custom event error
|
|
356
364
|
try {
|
|
357
365
|
const customEventData = {
|
|
358
366
|
eventName: eventName,
|
|
@@ -792,33 +800,6 @@ export class HumanBehaviorTracker {
|
|
|
792
800
|
this.queueSizeBytes += eventSize;
|
|
793
801
|
}
|
|
794
802
|
|
|
795
|
-
private async processRejectedEvents() {
|
|
796
|
-
if (this.isProcessingRejectedEvents || this.rejectedEvents.length === 0) return;
|
|
797
|
-
|
|
798
|
-
this.isProcessingRejectedEvents = true;
|
|
799
|
-
try {
|
|
800
|
-
// Create a new session ID for rejected events
|
|
801
|
-
const newSessionId = uuidv1();
|
|
802
|
-
if (isBrowser) {
|
|
803
|
-
localStorage.setItem('human_behavior_session_id', newSessionId);
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
// Try to send rejected events with new session ID using beacon
|
|
807
|
-
// sendBeacon returns true if the request was queued successfully
|
|
808
|
-
this.api.sendBeaconEvents(this.rejectedEvents, newSessionId);
|
|
809
|
-
|
|
810
|
-
// Clear rejected events and update session ID
|
|
811
|
-
// Note: We can't verify if the beacon data was actually sent,
|
|
812
|
-
// but we clear the events to prevent duplicate sending attempts
|
|
813
|
-
this.rejectedEvents = [];
|
|
814
|
-
this.sessionId = newSessionId;
|
|
815
|
-
} catch (error) {
|
|
816
|
-
logError('Failed to process rejected events:', error);
|
|
817
|
-
} finally {
|
|
818
|
-
this.isProcessingRejectedEvents = false;
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
|
|
822
803
|
private async flush() {
|
|
823
804
|
// Prevent concurrent flushes
|
|
824
805
|
if (this.isProcessing || !this.initialized) {
|
|
@@ -835,20 +816,18 @@ export class HumanBehaviorTracker {
|
|
|
835
816
|
if (eventsToProcess.length > 0) {
|
|
836
817
|
logDebug('Flushing events:', eventsToProcess);
|
|
837
818
|
try {
|
|
838
|
-
|
|
819
|
+
// Use chunked sending to handle large payloads
|
|
820
|
+
await this.api.sendEventsChunked(eventsToProcess, this.sessionId, this.endUserId!);
|
|
839
821
|
} catch (error: any) {
|
|
840
|
-
//
|
|
822
|
+
// Handle specific error types with graceful degradation
|
|
841
823
|
if (error.message?.includes('ERROR: Session already completed')) {
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
824
|
+
logWarn('Session expired, events will be lost');
|
|
825
|
+
} else if (error.message?.includes('413') || error.message?.includes('Content Too Large')) {
|
|
826
|
+
logWarn('Payload too large, events will be lost');
|
|
845
827
|
} else if (error.message?.includes('ERR_BLOCKED_BY_CLIENT') ||
|
|
846
828
|
error.message?.includes('Failed to fetch') ||
|
|
847
829
|
error.message?.includes('NetworkError')) {
|
|
848
|
-
|
|
849
|
-
logWarn('Request blocked by ad blocker or network issue, storing events for retry');
|
|
850
|
-
this.rejectedEvents.push(...eventsToProcess);
|
|
851
|
-
// Don't process rejected events immediately to avoid spam
|
|
830
|
+
logWarn('Request blocked by ad blocker or network issue, events will be lost');
|
|
852
831
|
} else {
|
|
853
832
|
throw error;
|
|
854
833
|
}
|
|
@@ -1005,8 +984,8 @@ export class HumanBehaviorTracker {
|
|
|
1005
984
|
const recommendations: string[] = [];
|
|
1006
985
|
let blocked = false;
|
|
1007
986
|
|
|
1008
|
-
// Check if we have
|
|
1009
|
-
if (this.
|
|
987
|
+
// Check if we have queued events (might indicate blocking)
|
|
988
|
+
if (this.eventIngestionQueue.length > 0) {
|
|
1010
989
|
blocked = true;
|
|
1011
990
|
recommendations.push('Some requests may be blocked by ad blockers');
|
|
1012
991
|
}
|