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