/** * Autocapture * * Automatic DOM event capture for clicks, form submissions, and input changes. * Privacy-first approach with element chain tracking and sensitive data filtering. * * Lifecycle (see docs/patterns/tracker-feature-lifecycle.md): * - Construction: created by FeatureManager when not hard-disabled. * - startIfEnabled: attaches DOM listeners when isEnabled becomes true. * - stop: detaches DOM listeners. Subsequent startIfEnabled re-attaches. * - onConfigUpdate: re-evaluates isEnabled on every config change and starts or * stops accordingly. This is what flips autocapture on when the * /decide endpoint returns `analytics.autocapture: true`. * * Enabled state precedence (highest first): * 1. _userOverride === false → off (set by vt.stopAutocapture()) * 2. _isDisabledServerSide === true → off (set by remote autocapture_opt_out) * 3. _userOverride === true → on (set by vt.startAutocapture()) * 4. config.autocapture truthy → on * 5. otherwise → off */ import type { VTilt } from "./vtilt"; import type { VTiltConfig } from "./types"; import type { Feature } from "./feature"; /** * Reasons isEnabled may evaluate to false. Surfaced by getDiagnostics() so that * integrators can pinpoint why no `$autocapture` events are flowing. */ export type AutocaptureDisabledReason = "user_stop_called" | "server_opt_out" | "config_autocapture_false" | "config_autocapture_undefined"; export interface AutocaptureDiagnostics { /** Whether the feature is enabled given current config and overrides. */ isEnabled: boolean; /** Whether DOM listeners are currently attached. */ isStarted: boolean; /** Why the feature is disabled (if any). */ disabledReason: AutocaptureDisabledReason | null; /** Snapshot of inputs that drove the decision. */ inputs: { configAutocapture: unknown; isDisabledServerSide: boolean; userOverride: boolean | null; elementsChainAsString: boolean; captureCopiedText: boolean; scrollDepthMilestones: boolean; scrollDepthPageleave: boolean; scrollDepthListenerAttached: boolean; }; } /** * Autocapture class for automatic DOM event tracking. * Implements the Feature interface for consistent lifecycle management. */ export declare class Autocapture implements Feature { readonly name = "Autocapture"; private _instance; private _initialized; private _isDisabledServerSide; /** Explicit user override via vt.startAutocapture() / vt.stopAutocapture(). */ private _userOverride; private _elementSelectors; private _rageclicks; /** * Compact-payload mode for `$autocapture`. When true (the default), the SDK * only sends the `$elements_chain` string and omits the verbose `$elements` * array — the array is duplicate information for the ingestion side and is * what pushes payloads past the client size cap on apps with deep DOM * trees / Tailwind / Material class soup. Integrators that still need * `$elements` (legacy filters / external pipelines) can opt out with * `vt.init({ elementsChainAsString: false })` or via `/decide`. */ private _elementsChainAsString; private _cachedConfig; private _cachedConfigSource; /** * Bound DOM handlers. Stored so stop() can detach them — passing the same * function reference is required by removeEventListener(). */ private _domHandler; private _copyHandler; private _copyHandlerAttached; private _scrollDepthTracker; private _pageviewUnsubscribe; static extractConfig(config: VTiltConfig): { enabled: boolean; }; constructor(instance: VTilt, _config?: { enabled: boolean; }); private get _config(); get isEnabled(): boolean; get isStarted(): boolean; startIfEnabled(): void; stop(): void; /** * Max scroll depth % for the current page when pageleave mode is enabled. * Used to enrich `$pageleave` payloads. */ getMaxScrollDepthPctForPageleave(): number | null; onConfigUpdate(config: VTiltConfig): void; /** * Update autocapture configuration (for programmatic control). * Called from vt.startAutocapture() / vt.stopAutocapture(). */ updateConfig(config: Partial<{ enabled: boolean; }>): void; getDiagnostics(): AutocaptureDiagnostics; setElementSelectors(selectors: Set): void; getElementSelectors(element: Element | null): string[] | null; /** * Single-source-of-truth for whether autocapture should be active. * Returns the disabled reason so diagnostics and logging can be precise. */ private _evaluateEnabled; private _addDomEventHandlers; private _removeDomEventHandlers; /** * Scroll depth listener — opt-in via `autocapture.scroll_depth` milestones and/or pageleave. */ private _syncScrollDepthHandler; private _teardownScrollDepth; /** * The copy/cut listener is opt-in via `autocapture.capture_copied_text`. * Callable from both startIfEnabled and onConfigUpdate so toggling the flag * mid-session correctly attaches or detaches the listener. */ private _syncCopyHandler; private _captureEvent; private _isBrowserSupported; }