humanbehavior-js 0.1.0 → 0.1.2
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 +101 -21
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +101 -21
- package/dist/esm/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 +15 -1
- package/package.json +1 -1
- package/simple-demo.html +26 -0
- package/simple-spa.html +50 -0
- package/src/api.ts +1 -11
- package/src/tracker.ts +109 -20
package/dist/esm/index.js
CHANGED
|
@@ -4347,6 +4347,7 @@ class HumanBehaviorAPI {
|
|
|
4347
4347
|
if (!response.ok) {
|
|
4348
4348
|
throw new Error(`Failed to authenticate user: ${response.statusText} with API key: ${this.apiKey}`);
|
|
4349
4349
|
}
|
|
4350
|
+
// Returns: { success: true, message: '...', userId: '...' }
|
|
4350
4351
|
return yield response.json();
|
|
4351
4352
|
}
|
|
4352
4353
|
catch (error) {
|
|
@@ -4362,8 +4363,6 @@ class HumanBehaviorAPI {
|
|
|
4362
4363
|
data.append('timestamp', encodeURIComponent(Date.now().toString()));
|
|
4363
4364
|
data.append('apiKey', encodeURIComponent(this.apiKey));
|
|
4364
4365
|
navigator.sendBeacon(`${this.baseUrl}/api/ingestion/events`, data);
|
|
4365
|
-
// KoalawareTracker.logToStorage(`Sending events beacon: ${this.baseUrl}/api/ingestion/events`);
|
|
4366
|
-
// KoalawareTracker.logToStorage(`Events beacon success: ${success}`);
|
|
4367
4366
|
}
|
|
4368
4367
|
}
|
|
4369
4368
|
|
|
@@ -4805,7 +4804,7 @@ class HumanBehaviorTracker {
|
|
|
4805
4804
|
}
|
|
4806
4805
|
// Test connection (non-blocking)
|
|
4807
4806
|
if (isBrowser) {
|
|
4808
|
-
const testUrl = tracker.api['baseUrl'] + '/api/
|
|
4807
|
+
const testUrl = tracker.api['baseUrl'] + '/api/health';
|
|
4809
4808
|
fetch(testUrl, { method: 'HEAD' })
|
|
4810
4809
|
.then(() => logDebug('Connection test successful'))
|
|
4811
4810
|
.catch((error) => {
|
|
@@ -4851,19 +4850,29 @@ class HumanBehaviorTracker {
|
|
|
4851
4850
|
});
|
|
4852
4851
|
this.apiKey = apiKey;
|
|
4853
4852
|
this.redactionManager = new RedactionManager();
|
|
4854
|
-
// Handle session restoration
|
|
4853
|
+
// Handle session restoration with improved continuity
|
|
4855
4854
|
if (isBrowser) {
|
|
4856
4855
|
const existingSessionId = localStorage.getItem('human_behavior_session_id');
|
|
4857
4856
|
const lastActivity = localStorage.getItem('human_behavior_last_activity');
|
|
4858
4857
|
const thirtyMinutesAgo = Date.now() - (30 * 60 * 1000);
|
|
4858
|
+
// Check if we have an existing session that's still within the activity window
|
|
4859
4859
|
if (existingSessionId && lastActivity && parseInt(lastActivity) > thirtyMinutesAgo) {
|
|
4860
4860
|
this.sessionId = existingSessionId;
|
|
4861
4861
|
logDebug(`Reusing existing session: ${this.sessionId}`);
|
|
4862
|
+
// Update activity timestamp to extend the session window
|
|
4863
|
+
localStorage.setItem('human_behavior_last_activity', Date.now().toString());
|
|
4862
4864
|
}
|
|
4863
4865
|
else {
|
|
4866
|
+
// Clear old session data if it's expired
|
|
4867
|
+
if (existingSessionId) {
|
|
4868
|
+
logDebug(`Session expired, clearing old session: ${existingSessionId}`);
|
|
4869
|
+
localStorage.removeItem('human_behavior_session_id');
|
|
4870
|
+
localStorage.removeItem('human_behavior_last_activity');
|
|
4871
|
+
}
|
|
4864
4872
|
this.sessionId = v1();
|
|
4865
4873
|
logDebug(`Creating new session: ${this.sessionId}`);
|
|
4866
4874
|
localStorage.setItem('human_behavior_session_id', this.sessionId);
|
|
4875
|
+
localStorage.setItem('human_behavior_last_activity', Date.now().toString());
|
|
4867
4876
|
}
|
|
4868
4877
|
this.currentUrl = window.location.href;
|
|
4869
4878
|
window.__humanBehaviorGlobalTracker = this;
|
|
@@ -4880,11 +4889,11 @@ class HumanBehaviorTracker {
|
|
|
4880
4889
|
const userId = this.getCookie(`human_behavior_end_user_id_${this.apiKey}`);
|
|
4881
4890
|
logDebug(`Initializing with sessionId: ${this.sessionId}, userId: ${userId}`);
|
|
4882
4891
|
const { sessionId, endUserId } = yield this.api.init(this.sessionId, userId);
|
|
4883
|
-
// Check if server returned a different session ID
|
|
4892
|
+
// Check if server returned a different session ID (for session continuity)
|
|
4884
4893
|
if (sessionId !== this.sessionId) {
|
|
4885
4894
|
logDebug(`Server returned different sessionId: ${sessionId} (client had: ${this.sessionId})`);
|
|
4886
4895
|
this.sessionId = sessionId;
|
|
4887
|
-
// Update localStorage with server's session ID
|
|
4896
|
+
// Update localStorage with server's session ID for continuity
|
|
4888
4897
|
if (isBrowser) {
|
|
4889
4898
|
localStorage.setItem('human_behavior_session_id', this.sessionId);
|
|
4890
4899
|
}
|
|
@@ -5231,7 +5240,12 @@ class HumanBehaviorTracker {
|
|
|
5231
5240
|
if (!this.userProperties || Object.keys(this.userProperties).length === 0) {
|
|
5232
5241
|
throw new Error('No user info available. Call addUserInfo() first.');
|
|
5233
5242
|
}
|
|
5234
|
-
yield this.api.sendUserAuth(this.endUserId, this.userProperties, this.sessionId, authFields);
|
|
5243
|
+
const response = yield this.api.sendUserAuth(this.endUserId, this.userProperties, this.sessionId, authFields);
|
|
5244
|
+
if (response && response.userId && response.userId !== this.endUserId) {
|
|
5245
|
+
// Update endUserId and cookie if backend returns a new userId
|
|
5246
|
+
this.endUserId = response.userId;
|
|
5247
|
+
this.setCookie(`human_behavior_end_user_id_${this.apiKey}`, response.userId, 365);
|
|
5248
|
+
}
|
|
5235
5249
|
});
|
|
5236
5250
|
}
|
|
5237
5251
|
start() {
|
|
@@ -5253,6 +5267,7 @@ class HumanBehaviorTracker {
|
|
|
5253
5267
|
inlineStylesheet: true,
|
|
5254
5268
|
recordCanvas: true,
|
|
5255
5269
|
collectFonts: true,
|
|
5270
|
+
inlineImages: true,
|
|
5256
5271
|
blockClass: 'rr-block',
|
|
5257
5272
|
ignoreClass: 'rr-ignore',
|
|
5258
5273
|
maskTextClass: 'rr-ignore'
|
|
@@ -5356,28 +5371,70 @@ class HumanBehaviorTracker {
|
|
|
5356
5371
|
}
|
|
5357
5372
|
});
|
|
5358
5373
|
}
|
|
5359
|
-
// Add helper methods for cookie management
|
|
5374
|
+
// Add helper methods for cookie management with localStorage fallback
|
|
5360
5375
|
setCookie(name, value, daysToExpire) {
|
|
5361
5376
|
if (!isBrowser)
|
|
5362
5377
|
return;
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5378
|
+
try {
|
|
5379
|
+
// Try to set cookie first
|
|
5380
|
+
const date = new Date();
|
|
5381
|
+
date.setTime(date.getTime() + (daysToExpire * 24 * 60 * 60 * 1000));
|
|
5382
|
+
const expires = `expires=${date.toUTCString()}`;
|
|
5383
|
+
document.cookie = `${name}=${value};${expires};path=/;SameSite=Lax`;
|
|
5384
|
+
// Also store in localStorage as backup
|
|
5385
|
+
localStorage.setItem(name, value);
|
|
5386
|
+
logDebug(`Set cookie and localStorage: ${name}`);
|
|
5387
|
+
}
|
|
5388
|
+
catch (error) {
|
|
5389
|
+
// If cookie fails, use localStorage only
|
|
5390
|
+
try {
|
|
5391
|
+
localStorage.setItem(name, value);
|
|
5392
|
+
logDebug(`Cookie blocked, using localStorage: ${name}`);
|
|
5393
|
+
}
|
|
5394
|
+
catch (localStorageError) {
|
|
5395
|
+
logError('Failed to store user ID in both cookie and localStorage:', localStorageError);
|
|
5396
|
+
}
|
|
5397
|
+
}
|
|
5367
5398
|
}
|
|
5368
5399
|
getCookie(name) {
|
|
5369
5400
|
if (!isBrowser)
|
|
5370
5401
|
return null;
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
c =
|
|
5377
|
-
|
|
5378
|
-
|
|
5402
|
+
try {
|
|
5403
|
+
// Try to get from cookie first
|
|
5404
|
+
const nameEQ = name + "=";
|
|
5405
|
+
const ca = document.cookie.split(';');
|
|
5406
|
+
for (let i = 0; i < ca.length; i++) {
|
|
5407
|
+
let c = ca[i];
|
|
5408
|
+
while (c.charAt(0) === ' ')
|
|
5409
|
+
c = c.substring(1, c.length);
|
|
5410
|
+
if (c.indexOf(nameEQ) === 0) {
|
|
5411
|
+
const cookieValue = c.substring(nameEQ.length, c.length);
|
|
5412
|
+
logDebug(`Found cookie: ${name}`);
|
|
5413
|
+
return cookieValue;
|
|
5414
|
+
}
|
|
5415
|
+
}
|
|
5416
|
+
// If cookie not found, try localStorage
|
|
5417
|
+
const localStorageValue = localStorage.getItem(name);
|
|
5418
|
+
if (localStorageValue) {
|
|
5419
|
+
logDebug(`Cookie not found, using localStorage: ${name}`);
|
|
5420
|
+
return localStorageValue;
|
|
5421
|
+
}
|
|
5422
|
+
return null;
|
|
5423
|
+
}
|
|
5424
|
+
catch (error) {
|
|
5425
|
+
// If cookie access fails, try localStorage
|
|
5426
|
+
try {
|
|
5427
|
+
const localStorageValue = localStorage.getItem(name);
|
|
5428
|
+
if (localStorageValue) {
|
|
5429
|
+
logDebug(`Cookie access failed, using localStorage: ${name}`);
|
|
5430
|
+
return localStorageValue;
|
|
5431
|
+
}
|
|
5432
|
+
}
|
|
5433
|
+
catch (localStorageError) {
|
|
5434
|
+
logError('Failed to access both cookie and localStorage:', localStorageError);
|
|
5435
|
+
}
|
|
5436
|
+
return null;
|
|
5379
5437
|
}
|
|
5380
|
-
return null;
|
|
5381
5438
|
}
|
|
5382
5439
|
/**
|
|
5383
5440
|
* Start redaction functionality for sensitive input fields
|
|
@@ -5472,6 +5529,29 @@ class HumanBehaviorTracker {
|
|
|
5472
5529
|
}
|
|
5473
5530
|
return { blocked, recommendations };
|
|
5474
5531
|
}
|
|
5532
|
+
/**
|
|
5533
|
+
* Check if the current user is a preexisting user
|
|
5534
|
+
* Returns true if the user has an existing endUserId cookie from a previous session
|
|
5535
|
+
*/
|
|
5536
|
+
isPreexistingUser() {
|
|
5537
|
+
if (!isBrowser) {
|
|
5538
|
+
return false;
|
|
5539
|
+
}
|
|
5540
|
+
// Check if there's an existing endUserId cookie for this API key
|
|
5541
|
+
const existingEndUserId = this.getCookie(`human_behavior_end_user_id_${this.apiKey}`);
|
|
5542
|
+
return existingEndUserId !== null && existingEndUserId !== this.endUserId;
|
|
5543
|
+
}
|
|
5544
|
+
/**
|
|
5545
|
+
* Get user information including whether they are preexisting
|
|
5546
|
+
*/
|
|
5547
|
+
getUserInfo() {
|
|
5548
|
+
return {
|
|
5549
|
+
endUserId: this.endUserId,
|
|
5550
|
+
sessionId: this.sessionId,
|
|
5551
|
+
isPreexistingUser: this.isPreexistingUser(),
|
|
5552
|
+
initialized: this.initialized
|
|
5553
|
+
};
|
|
5554
|
+
}
|
|
5475
5555
|
}
|
|
5476
5556
|
// Only expose to window object in browser environments
|
|
5477
5557
|
if (isBrowser) {
|