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.
- package/dist/cjs/angular/index.cjs +14207 -5
- package/dist/cjs/angular/index.cjs.map +1 -1
- package/dist/cjs/index.cjs +13 -13
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/react/index.cjs +13 -13
- package/dist/cjs/react/index.cjs.map +1 -1
- package/dist/cjs/remix/index.cjs +14313 -9
- package/dist/cjs/remix/index.cjs.map +1 -1
- package/dist/cjs/svelte/index.cjs +13 -13
- package/dist/cjs/svelte/index.cjs.map +1 -1
- package/dist/cjs/vue/index.cjs +14204 -2
- package/dist/cjs/vue/index.cjs.map +1 -1
- package/dist/esm/angular/index.js +14203 -1
- package/dist/esm/angular/index.js.map +1 -1
- package/dist/esm/index.js +13 -13
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/react/index.js +13 -13
- package/dist/esm/react/index.js.map +1 -1
- package/dist/esm/remix/index.js +14312 -2
- package/dist/esm/remix/index.js.map +1 -1
- package/dist/esm/svelte/index.js +13 -13
- package/dist/esm/svelte/index.js.map +1 -1
- package/dist/esm/vue/index.js +14203 -1
- package/dist/esm/vue/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/types/remix/index.d.ts +226 -2
- package/package.json +1 -1
- package/src/angular/index.ts +1 -1
- package/src/remix/index.ts +2 -2
- package/src/tracker.ts +13 -13
- package/src/vue/index.ts +1 -1
|
@@ -1,5 +1,229 @@
|
|
|
1
1
|
import { LoaderFunctionArgs } from '@remix-run/node';
|
|
2
|
-
|
|
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
package/src/angular/index.ts
CHANGED
package/src/remix/index.ts
CHANGED
|
@@ -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(
|
|
130
|
-
const lastActivity = localStorage.getItem(
|
|
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(
|
|
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(
|
|
144
|
-
localStorage.removeItem(
|
|
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(
|
|
149
|
-
localStorage.setItem(
|
|
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(
|
|
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(
|
|
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(
|
|
1017
|
-
localStorage.removeItem(
|
|
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(
|
|
1027
|
-
localStorage.setItem(
|
|
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