import { RedactionOptions } from './redact'; import { ErrorMechanism } from './errors/error-payload'; import { type InactiveSpan } from './tracing'; export declare class HumanBehaviorTracker { private eventQueue; private pendingCustomEvents; private pendingLogs; private pendingNetworkErrors; /** * Outbound custom-event batch queue. Debounced flush at * CUSTOM_EVENT_FLUSH_MS or hard-flush at CUSTOM_EVENT_BATCH_MAX. Mirrors * PostHog's 100ms / 50-event default. Preserves insertion order. */ private customEventBatch; private customEventBatchTimer; private readonly CUSTOM_EVENT_FLUSH_MS; private readonly CUSTOM_EVENT_BATCH_MAX; private sessionId; private windowId; private _sessionActivityTimestamp; private _sessionStartTimestamp; private userProperties; private isProcessing; private flushInterval; private readonly IDLE_FLUSH_INTERVAL_MS; private readonly LIVE_FLUSH_INTERVAL_MS; private readonly LIVE_FLUSH_GRACE_MS; private flushTier; private liveFlushDeadline; private readonly MAX_QUEUE_SIZE; private heartbeatInterval; private readonly HEARTBEAT_INTERVAL_MS; private readonly SESSION_IDLE_TIMEOUT_MS; private readonly SESSION_MAX_LENGTH_MS; /** Only emit `$focus` blurred after blur lasts this long (quick alt-tab → no chop). */ private focusBlurGraceTimeout; private readonly FOCUS_BLUR_GRACE_MS; /** Last `$focus` marker we pushed (`null` = never blurred in this session tree). */ private lastEmittedFocusState; private api; private endUserId; private apiKey; private ingestionUrl; private initialized; initializationPromise: Promise | null; private monthlyLimitReached; private redactionManager; private propertyManager; private isDomReady; private requestQueue; private domReadyHandlers; private originalConsole; private consoleTrackingEnabled; private originalFetch; private networkTrackingEnabled; private captureRequestBodiesFlag; private lastRequestContext?; private lastRequestContextAt; private readonly ERROR_REQUEST_WINDOW_MS; private enableConsoleTrackingFlag; private enableNetworkTrackingFlag; private enableErrorTrackingFlag; private enableWebVitalsFlag; private enableTracingFlag; private tracing; private errorCapture; private errorFilterOptions; private captureThirdPartyResourceErrorsFlag; private readonly breadcrumbs; private release; private environment; private commitSha; private dist; navigationTrackingEnabled: boolean; private currentUrl; private previousUrl; private originalPushState; private originalReplaceState; private navigationListeners; /** * Timestamp of the last `pushState` call. Used by the `hashchange` * listener to suppress the dup pageview when a `pushState('/foo#bar')` * also fires `hashchange` synchronously. */ private lastPushStateAt; /** Window for hashchange-after-pushState dedupe. */ private readonly NAVIGATION_DEDUPE_MS; private _connectionBlocked; private recordInstance; private sessionStartTime; private rrwebRecord; private fullSnapshotTimeout; private cssSnapshotCapture; private localAssetSnapshotCapture; private contrastCapture; private brokenAssetHandler; private brokenAssetSeen; private recordCanvas; private isStarted; private minimumDurationMilliseconds; private readonly _window_id_storage_key; private readonly _primary_window_exists_storage_key; private _isIdle; private _lastActivityTimestamp; private readonly IDLE_THRESHOLD_MS; private frictionClicks; private frictionMutationObserver; /** * Check if the tracker has been started */ get isTrackerStarted(): boolean; /** * DOM ready detection - more aggressive */ private setupDomReadyHandler; /** * Called when DOM is ready - processes queued requests */ private onDomReady; /** * Queue a request until DOM is ready */ private queueRequest; /** * Process a request (called after DOM is ready) */ private processRequest; /** * Register a handler to be called when DOM is ready */ private registerDomReadyHandler; /** * 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[]; redactionStrategy?: { mode: 'privacy-first' | 'visibility-first'; unredactFields?: string[]; redactFields?: string[]; }; enableAutomaticTracking?: boolean; suppressConsoleErrors?: boolean; recordCanvas?: boolean; enableAutomaticProperties?: boolean; propertyDenylist?: string[]; automaticTrackingOptions?: { trackButtons?: boolean; trackLinks?: boolean; trackForms?: boolean; includeText?: boolean; includeClasses?: boolean; }; maxQueueSize?: number; enableConsoleTracking?: boolean; enableNetworkTracking?: boolean; enableErrorTracking?: boolean; ignoreErrors?: (string | RegExp)[]; denyUrls?: (string | RegExp)[]; allowUrls?: (string | RegExp)[]; captureThirdPartyResourceErrors?: boolean; release?: string; environment?: string; commitSha?: string; dist?: string; captureRequestBodies?: boolean; enableWebVitals?: boolean; enableTracing?: boolean; minimumDurationMilliseconds?: number; }): HumanBehaviorTracker; constructor(apiKey: string | undefined, ingestionUrl?: string, options?: { enableAutomaticProperties?: boolean; propertyDenylist?: string[]; redactionStrategy?: { mode: 'privacy-first' | 'visibility-first'; unredactFields?: string[]; redactFields?: string[]; }; redactFields?: string[]; maxQueueSize?: number; enableConsoleTracking?: boolean; enableNetworkTracking?: boolean; enableErrorTracking?: boolean; ignoreErrors?: (string | RegExp)[]; denyUrls?: (string | RegExp)[]; allowUrls?: (string | RegExp)[]; captureThirdPartyResourceErrors?: boolean; release?: string; environment?: string; commitSha?: string; dist?: string; captureRequestBodies?: boolean; enableWebVitals?: boolean; enableTracing?: boolean; minimumDurationMilliseconds?: number; }); private init; /** * ✅ FIXED: Wait for Kafka-based initialization to complete */ 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; trackPageView(url?: string): Promise; customEvent(eventName: string, properties?: Record): Promise; /** Append to the outbound batch and arm/refresh the flush timer. */ private queueCustomEvent; /** * Teardown-path flush of the outbound custom-event batch: synchronous * sendBeacon (survives navigation), falling back to a keepalive fetch * when the beacon is unavailable or refuses the payload. Never awaited — * callers are unload/hidden handlers that cannot block. */ private flushCustomEventBatchBeacon; /** * Drain the sub-minimum-duration buffer into the outbound batch. The * minimum-duration gate is a delivery *delay*, not a filter — every event * in `pendingCustomEvents` is sent verbatim once the session crosses the * threshold. FullSnapshots bypass that gate entirely, so the replay * already exists server-side; a teardown that drops this buffer is what * produces replays with zero analytics events. Called from the hidden/ * pagehide handlers right before the batch is beaconed out. */ private drainPendingCustomEventsForTeardown; /** * Flush the outbound custom-event batch. Falls back to per-event * `sendCustomEvent` (and finally to the rrweb event-stream Type-5 * payload) when the batch endpoint errors — this is the same fallback * behaviour pre-0.7 had for individual sends. */ private flushCustomEventBatch; /** * Setup automatic tracking for buttons, links, and forms */ private setupAutomaticTracking; /** * PostHog/Mixpanel-style autocapture. One `$click` event per user click. * Walks up to the nearest interactive ancestor so a click on a * inside a