humanbehavior-js
Version:
SDK for HumanBehavior session and event recording
374 lines (369 loc) • 12.2 kB
TypeScript
interface RedactionOptions {
redactedText?: string;
excludeSelectors?: string[];
userFields?: string[];
}
declare class RedactionManager {
private redactedText;
private userSelectedFields;
private excludeSelectors;
constructor(options?: RedactionOptions);
/**
* Set specific fields to be redacted using CSS selectors
* These selectors are used to configure rrweb's built-in masking
* @param fields Array of CSS selectors for fields to redact
*/
setFieldsToRedact(fields: string[]): void;
/**
* Check if redaction is currently active (has fields selected)
*/
isActive(): boolean;
/**
* Get the currently selected fields for redaction
*/
getSelectedFields(): string[];
/**
* Process an event and redact sensitive data if needed
* NOTE: This method is no longer used - events are handled directly by rrweb
* Kept for backward compatibility but not called in the current implementation
*/
processEvent(event: any): any;
/**
* Redact sensitive data in input events
*/
private redactInputEvent;
/**
* Redact sensitive data in DOM mutation events
*/
private redactDOMEvent;
/**
* Check if a DOM change should be redacted based on its ID
*/
private shouldRedactDOMChange;
/**
* Redact sensitive data in mouse/touch interaction events
*/
private redactMouseEvent;
/**
* Redact sensitive data in full snapshot events
*/
private redactFullSnapshot;
/**
* Recursively redact sensitive data in DOM nodes
*/
private redactNode;
/**
* Check if a node should be redacted based on its attributes
*/
private shouldRedactNode;
/**
* Check if a CSS selector would match a node based on its attributes
*/
private selectorMatchesNode;
/**
* Basic selector matching for environments where matches() is not available
*/
private basicSelectorMatch;
/**
* Check if an event is from a field that should be redacted
*/
private isFieldSelected;
/**
* Get CSS selectors for rrweb masking configuration
* Used to configure rrweb's maskTextSelector option
*/
getMaskTextSelector(): string | null;
/**
* Check if an element should be redacted (for rrweb maskTextFn/maskInputFn)
*/
shouldRedactElement(element: HTMLElement): boolean;
/**
* Apply rrweb masking classes to DOM elements
* Adds 'rr-mask' class to elements that should be redacted
* This enables rrweb's built-in masking functionality
*/
applyRedactionClasses(): void;
/**
* Get the original value of a redacted element (for debugging)
*/
getOriginalValue(element: HTMLElement): string | undefined;
/**
* Check if an element is currently being redacted
*/
isElementRedacted(element: HTMLElement): boolean;
}
declare const redactionManager: RedactionManager;
declare global {
interface Window {
HumanBehaviorTracker: typeof HumanBehaviorTracker;
__humanBehaviorGlobalTracker?: HumanBehaviorTracker;
}
}
declare class HumanBehaviorTracker {
private eventIngestionQueue;
private sessionId;
private userProperties;
private isProcessing;
private flushInterval;
private readonly FLUSH_INTERVAL_MS;
private api;
private endUserId;
private apiKey;
private initialized;
initializationPromise: Promise<void> | null;
private redactionManager;
private originalConsole;
private consoleTrackingEnabled;
navigationTrackingEnabled: boolean;
private currentUrl;
private previousUrl;
private originalPushState;
private originalReplaceState;
private navigationListeners;
private _connectionBlocked;
private recordInstance;
private sessionStartTime;
private rrwebRecord;
private fullSnapshotTimeout;
private recordCanvas;
/**
* Initialize the HumanBehavior tracker
* This is the main entry point - call this once per page
*/
static init(apiKey: string, options?: {
ingestionUrl?: string;
logLevel?: 'none' | 'error' | 'warn' | 'info' | 'debug';
redactFields?: string[];
enableAutomaticTracking?: boolean;
suppressConsoleErrors?: boolean;
recordCanvas?: boolean;
automaticTrackingOptions?: {
trackButtons?: boolean;
trackLinks?: boolean;
trackForms?: boolean;
includeText?: boolean;
includeClasses?: boolean;
};
}): HumanBehaviorTracker;
constructor(apiKey: string | undefined, ingestionUrl?: string);
private init;
private ensureInitialized;
/**
* Setup navigation event tracking for SPA navigation
*/
private setupNavigationTracking;
/**
* Track navigation events and send custom events
*/
trackNavigationEvent(type: string, fromUrl: string, toUrl: string): Promise<void>;
trackPageView(url?: string): Promise<void>;
customEvent(eventName: string, properties?: Record<string, any>): Promise<void>;
/**
* Setup automatic tracking for buttons, links, and forms
*/
private setupAutomaticTracking;
/**
* Setup automatic button tracking
*/
private setupAutomaticButtonTracking;
/**
* Setup automatic link tracking
*/
private setupAutomaticLinkTracking;
/**
* Setup automatic form tracking
*/
private setupAutomaticFormTracking;
/**
* Cleanup navigation tracking
*/
private cleanupNavigationTracking;
static logToStorage(message: string): void;
/**
* Configure logging behavior for the SDK
* @param config Logger configuration options
*/
static configureLogging(config: {
level?: 'none' | 'error' | 'warn' | 'info' | 'debug';
enableConsole?: boolean;
enableStorage?: boolean;
}): void;
/**
* Enable console event tracking
*/
enableConsoleTracking(): void;
/**
* Disable console event tracking
*/
disableConsoleTracking(): void;
private trackConsoleEvent;
private setupPageUnloadHandler;
viewLogs(): void;
/**
* Add user identification information to the tracker
* If userId is not provided, will use userProperties.email as the userId (if present)
*/
identifyUser({ userProperties }: {
userProperties: Record<string, any>;
}): Promise<string>;
/**
* Get current user attributes
*/
getUserAttributes(): Record<string, any>;
start(): Promise<void>;
/**
* Manually trigger a FullSnapshot (for navigation events)
* Delays snapshot to avoid capturing mid-animation states
*/
private takeFullSnapshot;
stop(): Promise<void>;
/**
* Add an event to the ingestion queue
* Events are sent directly without processing to avoid corruption
*/
addEvent(event: any): Promise<void>;
/**
* Flush events to the ingestion server
* Events are sent in chunks to handle large payloads efficiently
*/
private flush;
private setCookie;
getCookie(name: string): string | null;
/**
* Delete a cookie by setting its expiration date to the past
* @param name The name of the cookie to delete
*/
private deleteCookie;
/**
* Clear user data and reset session when user signs out of the site
* This should be called when a user logs out of your application to prevent
* data contamination between different users
*/
logout(): void;
/**
* Start redaction functionality for sensitive input fields
* @param options Optional configuration for redaction behavior
*/
redact(options?: RedactionOptions): Promise<void>;
/**
* Set specific fields to be redacted during session recording
* Uses rrweb's built-in masking instead of custom redaction processing
* @param fields Array of CSS selectors for fields to redact (e.g., ['input[type="password"]', '#email-field'])
*/
setRedactedFields(fields: string[]): void;
private restartWithNewRedaction;
/**
* Check if redaction is currently active
*/
isRedactionActive(): boolean;
/**
* Get the currently selected fields for redaction
*/
getRedactedFields(): string[];
/**
* Get the current session ID
*/
getSessionId(): string;
/**
* Get the current URL being tracked
*/
getCurrentUrl(): string;
/**
* Get current snapshot frequency info
* Uses configured values (5 minutes, 1000 events)
*/
getSnapshotFrequencyInfo(): {
sessionDuration: number;
currentInterval: number;
currentThreshold: number;
phase: string;
};
/**
* Test if the tracker can reach the ingestion server
*/
testConnection(): Promise<{
success: boolean;
error?: string;
}>;
/**
* Get connection status and recommendations
*/
getConnectionStatus(): {
blocked: boolean;
recommendations: string[];
};
/**
* Check if the current user is a preexisting user
* Returns true if the user has an existing endUserId cookie from a previous session
*/
isPreexistingUser(): boolean;
/**
* Get user information including whether they are preexisting
*/
getUserInfo(): {
endUserId: string | null;
sessionId: string;
isPreexistingUser: boolean;
initialized: boolean;
};
}
declare const MAX_CHUNK_SIZE_BYTES: number;
declare function isChunkSizeExceeded(currentChunk: any[], newEvent: any, sessionId: string): boolean;
declare function validateSingleEventSize(event: any, sessionId: string): void;
declare function splitLargeEvent(event: any, sessionId: string): any[];
declare class HumanBehaviorAPI {
private apiKey;
private baseUrl;
constructor({ apiKey, ingestionUrl }: {
apiKey: string;
ingestionUrl: string;
});
init(sessionId: string, userId: string | null): Promise<{
sessionId: any;
endUserId: any;
}>;
sendEvents(events: any[], sessionId: string, userId: string): Promise<void>;
sendEventsChunked(events: any[], sessionId: string, userId?: string): Promise<any[]>;
sendUserData(userId: string, userData: Record<string, any>, sessionId: string): Promise<any>;
sendUserAuth(userId: string, userData: Record<string, any>, sessionId: string, authFields: string[]): Promise<any>;
sendBeaconEvents(events: any[], sessionId: string): boolean;
sendCustomEvent(sessionId: string, eventName: string, eventProperties?: Record<string, any>): Promise<any>;
sendCustomEventBatch(sessionId: string, events: Array<{
eventName: string;
eventProperties?: Record<string, any>;
}>): Promise<any>;
}
declare enum LogLevel {
NONE = 0,
ERROR = 1,
WARN = 2,
INFO = 3,
DEBUG = 4
}
interface LoggerConfig {
level: LogLevel;
enableConsole: boolean;
enableStorage: boolean;
}
declare class Logger {
private config;
private isBrowser;
constructor(config?: Partial<LoggerConfig>);
setConfig(config: Partial<LoggerConfig>): void;
private shouldLog;
private formatMessage;
error(message: string, ...args: any[]): void;
warn(message: string, ...args: any[]): void;
info(message: string, ...args: any[]): void;
debug(message: string, ...args: any[]): void;
private logToStorage;
getLogs(): any[];
clearLogs(): void;
}
declare const logger: Logger;
declare const logError: (message: string, ...args: any[]) => void;
declare const logWarn: (message: string, ...args: any[]) => void;
declare const logInfo: (message: string, ...args: any[]) => void;
declare const logDebug: (message: string, ...args: any[]) => void;
export { HumanBehaviorAPI, HumanBehaviorTracker, LogLevel, MAX_CHUNK_SIZE_BYTES, RedactionManager, isChunkSizeExceeded, logDebug, logError, logInfo, logWarn, logger, redactionManager, splitLargeEvent, validateSingleEventSize };
export type { LoggerConfig, RedactionOptions };