humanbehavior-js 0.4.3 → 0.4.5

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.
@@ -1,5 +1,229 @@
1
1
  import { LoaderFunctionArgs } from '@remix-run/node';
2
- export { HumanBehaviorProvider, useHumanBehavior } from '../react';
2
+ import React, { ReactNode } from 'react';
3
+
4
+ interface RedactionOptions {
5
+ redactedText?: string;
6
+ excludeSelectors?: string[];
7
+ userFields?: string[];
8
+ }
9
+
10
+ declare global {
11
+ interface Window {
12
+ HumanBehaviorTracker: typeof HumanBehaviorTracker;
13
+ __humanBehaviorGlobalTracker?: HumanBehaviorTracker;
14
+ }
15
+ }
16
+ declare class HumanBehaviorTracker {
17
+ private eventIngestionQueue;
18
+ private sessionId;
19
+ private userProperties;
20
+ private isProcessing;
21
+ private flushInterval;
22
+ private readonly FLUSH_INTERVAL_MS;
23
+ private api;
24
+ private endUserId;
25
+ private apiKey;
26
+ private initialized;
27
+ initializationPromise: Promise<void> | null;
28
+ private redactionManager;
29
+ private originalConsole;
30
+ private consoleTrackingEnabled;
31
+ navigationTrackingEnabled: boolean;
32
+ private currentUrl;
33
+ private previousUrl;
34
+ private originalPushState;
35
+ private originalReplaceState;
36
+ private navigationListeners;
37
+ private _connectionBlocked;
38
+ private recordInstance;
39
+ private sessionStartTime;
40
+ /**
41
+ * Initialize the HumanBehavior tracker
42
+ * This is the main entry point - call this once per page
43
+ */
44
+ static init(apiKey: string, options?: {
45
+ ingestionUrl?: string;
46
+ logLevel?: 'none' | 'error' | 'warn' | 'info' | 'debug';
47
+ redactFields?: string[];
48
+ enableAutomaticTracking?: boolean;
49
+ automaticTrackingOptions?: {
50
+ trackButtons?: boolean;
51
+ trackLinks?: boolean;
52
+ trackForms?: boolean;
53
+ includeText?: boolean;
54
+ includeClasses?: boolean;
55
+ };
56
+ }): HumanBehaviorTracker;
57
+ constructor(apiKey: string | undefined, ingestionUrl?: string);
58
+ private init;
59
+ private ensureInitialized;
60
+ /**
61
+ * Setup navigation event tracking for SPA navigation
62
+ */
63
+ private setupNavigationTracking;
64
+ /**
65
+ * Track navigation events and send custom events
66
+ */
67
+ trackNavigationEvent(type: string, fromUrl: string, toUrl: string): Promise<void>;
68
+ trackPageView(url?: string): Promise<void>;
69
+ customEvent(eventName: string, properties?: Record<string, any>): Promise<void>;
70
+ /**
71
+ * Setup automatic tracking for buttons, links, and forms
72
+ */
73
+ private setupAutomaticTracking;
74
+ /**
75
+ * Setup automatic button tracking
76
+ */
77
+ private setupAutomaticButtonTracking;
78
+ /**
79
+ * Setup automatic link tracking
80
+ */
81
+ private setupAutomaticLinkTracking;
82
+ /**
83
+ * Setup automatic form tracking
84
+ */
85
+ private setupAutomaticFormTracking;
86
+ /**
87
+ * Cleanup navigation tracking
88
+ */
89
+ private cleanupNavigationTracking;
90
+ static logToStorage(message: string): void;
91
+ /**
92
+ * Configure logging behavior for the SDK
93
+ * @param config Logger configuration options
94
+ */
95
+ static configureLogging(config: {
96
+ level?: 'none' | 'error' | 'warn' | 'info' | 'debug';
97
+ enableConsole?: boolean;
98
+ enableStorage?: boolean;
99
+ }): void;
100
+ /**
101
+ * Enable console event tracking
102
+ */
103
+ enableConsoleTracking(): void;
104
+ /**
105
+ * Disable console event tracking
106
+ */
107
+ disableConsoleTracking(): void;
108
+ private trackConsoleEvent;
109
+ private setupPageUnloadHandler;
110
+ viewLogs(): void;
111
+ /**
112
+ * Add user identification information to the tracker
113
+ * If userId is not provided, will use userProperties.email as the userId (if present)
114
+ */
115
+ identifyUser({ userProperties }: {
116
+ userProperties: Record<string, any>;
117
+ }): Promise<string>;
118
+ /**
119
+ * Get current user attributes
120
+ */
121
+ getUserAttributes(): Record<string, any>;
122
+ start(): Promise<void>;
123
+ stop(): Promise<void>;
124
+ /**
125
+ * Add an event to the ingestion queue
126
+ * Events are sent directly without processing to avoid corruption
127
+ */
128
+ addEvent(event: any): Promise<void>;
129
+ /**
130
+ * Flush events to the ingestion server
131
+ * Events are sent in chunks to handle large payloads efficiently
132
+ */
133
+ private flush;
134
+ private setCookie;
135
+ getCookie(name: string): string | null;
136
+ /**
137
+ * Delete a cookie by setting its expiration date to the past
138
+ * @param name The name of the cookie to delete
139
+ */
140
+ private deleteCookie;
141
+ /**
142
+ * Clear user data and reset session when user signs out of the site
143
+ * This should be called when a user logs out of your application to prevent
144
+ * data contamination between different users
145
+ */
146
+ logout(): void;
147
+ /**
148
+ * Start redaction functionality for sensitive input fields
149
+ * @param options Optional configuration for redaction behavior
150
+ */
151
+ redact(options?: RedactionOptions): Promise<void>;
152
+ /**
153
+ * Set specific fields to be redacted during session recording
154
+ * Uses rrweb's built-in masking instead of custom redaction processing
155
+ * @param fields Array of CSS selectors for fields to redact (e.g., ['input[type="password"]', '#email-field'])
156
+ */
157
+ setRedactedFields(fields: string[]): void;
158
+ private restartWithNewRedaction;
159
+ /**
160
+ * Check if redaction is currently active
161
+ */
162
+ isRedactionActive(): boolean;
163
+ /**
164
+ * Get the currently selected fields for redaction
165
+ */
166
+ getRedactedFields(): string[];
167
+ /**
168
+ * Get the current session ID
169
+ */
170
+ getSessionId(): string;
171
+ /**
172
+ * Get the current URL being tracked
173
+ */
174
+ getCurrentUrl(): string;
175
+ /**
176
+ * Get current snapshot frequency info
177
+ * Uses configured values (5 minutes, 1000 events)
178
+ */
179
+ getSnapshotFrequencyInfo(): {
180
+ sessionDuration: number;
181
+ currentInterval: number;
182
+ currentThreshold: number;
183
+ phase: string;
184
+ };
185
+ /**
186
+ * Test if the tracker can reach the ingestion server
187
+ */
188
+ testConnection(): Promise<{
189
+ success: boolean;
190
+ error?: string;
191
+ }>;
192
+ /**
193
+ * Get connection status and recommendations
194
+ */
195
+ getConnectionStatus(): {
196
+ blocked: boolean;
197
+ recommendations: string[];
198
+ };
199
+ /**
200
+ * Check if the current user is a preexisting user
201
+ * Returns true if the user has an existing endUserId cookie from a previous session
202
+ */
203
+ isPreexistingUser(): boolean;
204
+ /**
205
+ * Get user information including whether they are preexisting
206
+ */
207
+ getUserInfo(): {
208
+ endUserId: string | null;
209
+ sessionId: string;
210
+ isPreexistingUser: boolean;
211
+ initialized: boolean;
212
+ };
213
+ }
214
+
215
+ interface HumanBehaviorProviderProps {
216
+ apiKey?: string;
217
+ client?: HumanBehaviorTracker;
218
+ children: ReactNode;
219
+ options?: {
220
+ ingestionUrl?: string;
221
+ logLevel?: 'none' | 'error' | 'warn' | 'info' | 'debug';
222
+ redactFields?: string[];
223
+ };
224
+ }
225
+ declare const HumanBehaviorProvider: ({ apiKey, client, children, options }: HumanBehaviorProviderProps) => React.JSX.Element;
226
+ declare const useHumanBehavior: () => HumanBehaviorTracker;
3
227
 
4
228
  declare function createHumanBehaviorLoader(): ({ request }: LoaderFunctionArgs) => Promise<{
5
229
  ENV: {
@@ -7,4 +231,4 @@ declare function createHumanBehaviorLoader(): ({ request }: LoaderFunctionArgs)
7
231
  };
8
232
  }>;
9
233
 
10
- export { createHumanBehaviorLoader };
234
+ export { HumanBehaviorProvider, createHumanBehaviorLoader, useHumanBehavior };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "humanbehavior-js",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "description": "SDK for HumanBehavior session and event recording",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",
@@ -1,4 +1,4 @@
1
- import { HumanBehaviorTracker } from '../index';
1
+ import { HumanBehaviorTracker } from '../index.js';
2
2
 
3
3
  // Angular NgModule for legacy Angular applications
4
4
  export class HumanBehaviorModule {
@@ -1,4 +1,4 @@
1
- import { HumanBehaviorTracker } from '../index';
1
+ import { HumanBehaviorTracker } from '../index.js';
2
2
  import type { LoaderFunctionArgs } from '@remix-run/node';
3
3
 
4
4
  // Remix-specific loader helper
@@ -13,4 +13,4 @@ export function createHumanBehaviorLoader() {
13
13
  }
14
14
 
15
15
  // Re-export React components for convenience
16
- export { HumanBehaviorProvider, useHumanBehavior } from '../react';
16
+ export { HumanBehaviorProvider, useHumanBehavior } from '../react/index.js';
package/src/tracker.ts CHANGED
@@ -126,8 +126,8 @@ export class HumanBehaviorTracker {
126
126
 
127
127
  // Handle session restoration with improved continuity
128
128
  if (isBrowser) {
129
- const existingSessionId = localStorage.getItem('human_behavior_session_id');
130
- const lastActivity = localStorage.getItem('human_behavior_last_activity');
129
+ const existingSessionId = localStorage.getItem(`human_behavior_session_id_${this.apiKey}`);
130
+ const lastActivity = localStorage.getItem(`human_behavior_last_activity_${this.apiKey}`);
131
131
  const fifteenMinutesAgo = Date.now() - (15 * 60 * 1000);
132
132
 
133
133
  // Check if we have an existing session that's still within the activity window
@@ -135,18 +135,18 @@ export class HumanBehaviorTracker {
135
135
  this.sessionId = existingSessionId;
136
136
  logDebug(`Reusing existing session: ${this.sessionId}`);
137
137
  // Update activity timestamp to extend the session window
138
- localStorage.setItem('human_behavior_last_activity', Date.now().toString());
138
+ localStorage.setItem(`human_behavior_last_activity_${this.apiKey}`, Date.now().toString());
139
139
  } else {
140
140
  // Clear old session data if it's expired
141
141
  if (existingSessionId) {
142
142
  logDebug(`Session expired, clearing old session: ${existingSessionId}`);
143
- localStorage.removeItem('human_behavior_session_id');
144
- localStorage.removeItem('human_behavior_last_activity');
143
+ localStorage.removeItem(`human_behavior_session_id_${this.apiKey}`);
144
+ localStorage.removeItem(`human_behavior_last_activity_${this.apiKey}`);
145
145
  }
146
146
  this.sessionId = uuidv1();
147
147
  logDebug(`Creating new session: ${this.sessionId}`);
148
- localStorage.setItem('human_behavior_session_id', this.sessionId);
149
- localStorage.setItem('human_behavior_last_activity', Date.now().toString());
148
+ localStorage.setItem(`human_behavior_session_id_${this.apiKey}`, this.sessionId);
149
+ localStorage.setItem(`human_behavior_last_activity_${this.apiKey}`, Date.now().toString());
150
150
  }
151
151
 
152
152
  this.currentUrl = window.location.href;
@@ -172,7 +172,7 @@ export class HumanBehaviorTracker {
172
172
  this.sessionId = sessionId;
173
173
  // Update localStorage with server's session ID for continuity
174
174
  if (isBrowser) {
175
- localStorage.setItem('human_behavior_session_id', this.sessionId);
175
+ localStorage.setItem(`human_behavior_session_id_${this.apiKey}`, this.sessionId);
176
176
  }
177
177
  }
178
178
 
@@ -693,7 +693,7 @@ export class HumanBehaviorTracker {
693
693
 
694
694
  // Update activity timestamp on user interaction (not on page load)
695
695
  const updateActivity = () => {
696
- localStorage.setItem('human_behavior_last_activity', Date.now().toString());
696
+ localStorage.setItem(`human_behavior_last_activity_${this.apiKey}`, Date.now().toString());
697
697
  };
698
698
 
699
699
  // Listen for user interactions to update activity timestamp
@@ -1013,8 +1013,8 @@ export class HumanBehaviorTracker {
1013
1013
  this.deleteCookie(userIdCookieName);
1014
1014
 
1015
1015
  // Clear session data from localStorage
1016
- localStorage.removeItem('human_behavior_session_id');
1017
- localStorage.removeItem('human_behavior_last_activity');
1016
+ localStorage.removeItem(`human_behavior_session_id_${this.apiKey}`);
1017
+ localStorage.removeItem(`human_behavior_last_activity_${this.apiKey}`);
1018
1018
 
1019
1019
  // Reset user-related properties
1020
1020
  this.endUserId = null;
@@ -1023,8 +1023,8 @@ export class HumanBehaviorTracker {
1023
1023
  // Generate a new session ID for the next user
1024
1024
  this.sessionId = uuidv1();
1025
1025
  if (isBrowser) {
1026
- localStorage.setItem('human_behavior_session_id', this.sessionId);
1027
- localStorage.setItem('human_behavior_last_activity', Date.now().toString());
1026
+ localStorage.setItem(`human_behavior_session_id_${this.apiKey}`, this.sessionId);
1027
+ localStorage.setItem(`human_behavior_last_activity_${this.apiKey}`, Date.now().toString());
1028
1028
  }
1029
1029
 
1030
1030
  logInfo('User logged out - cleared all user data and started fresh session');
package/src/vue/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { HumanBehaviorTracker } from '../index';
1
+ import { HumanBehaviorTracker } from '../index.js';
2
2
  import type { App } from 'vue';
3
3
 
4
4
  interface HumanBehaviorPluginOptions {