@prodact.ai/sdk 0.0.6 → 0.0.8
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/cdn/sdk.global.js +81 -62
- package/dist/cdn/sdk.global.js.map +1 -1
- package/dist/index.d.ts +332 -0
- package/dist/index.js +120 -18
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +120 -18
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.ts +155 -0
- package/dist/react.js +120 -18
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +120 -18
- package/dist/react.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/recording/utils.ts","../src/recording/recorder.ts","../src/proactive.ts","../src/user-flows/utils.ts","../src/user-flows/tracker.ts","../src/core.ts"],"sourcesContent":["/**\n * Session Recording Utilities\n * Helper functions for session recording\n */\n\nimport type { DeviceInfo, RecordingConfig, RecordingPrivacyConfig, RecordingPerformanceConfig, RecordingCaptureConfig } from './types';\n\n/**\n * Generate a unique session ID\n */\nexport function generateSessionId(): string {\n const timestamp = Date.now().toString(36);\n const randomPart = Math.random().toString(36).substring(2, 15);\n return `rec_${timestamp}_${randomPart}`;\n}\n\n/**\n * Get device/browser information\n */\nexport function getDeviceInfo(): DeviceInfo {\n if (typeof window === 'undefined') {\n return {\n userAgent: 'unknown',\n screenWidth: 0,\n screenHeight: 0,\n viewportWidth: 0,\n viewportHeight: 0,\n devicePixelRatio: 1,\n language: 'en',\n platform: 'unknown',\n };\n }\n\n return {\n userAgent: navigator.userAgent,\n screenWidth: screen.width,\n screenHeight: screen.height,\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n devicePixelRatio: window.devicePixelRatio || 1,\n language: navigator.language,\n platform: navigator.platform,\n };\n}\n\n/**\n * Default privacy configuration\n */\nexport const DEFAULT_PRIVACY_CONFIG: Required<RecordingPrivacyConfig> = {\n maskAllInputs: true,\n maskAllText: false,\n maskSelectors: ['.sensitive', '[data-sensitive]', '.pii', '[data-pii]'],\n blockSelectors: ['.no-record', '[data-no-record]'],\n maskInputTypes: ['password', 'email', 'tel', 'credit-card'],\n maskCharacter: '*',\n};\n\n/**\n * Default performance configuration\n */\nexport const DEFAULT_PERFORMANCE_CONFIG: Required<RecordingPerformanceConfig> = {\n batchEvents: true,\n batchSize: 50,\n batchTimeout: 5000,\n compress: true,\n mouseMoveThrottle: 50,\n maxDuration: 30 * 60 * 1000, // 30 minutes\n};\n\n/**\n * Default capture configuration\n */\nexport const DEFAULT_CAPTURE_CONFIG: Required<RecordingCaptureConfig> = {\n console: true,\n network: false,\n performance: false,\n errors: true,\n customEvents: true,\n};\n\n/**\n * Merge user config with defaults\n */\nexport function mergeConfig(userConfig?: RecordingConfig): Required<RecordingConfig> {\n return {\n enabled: userConfig?.enabled ?? false,\n samplingRate: userConfig?.samplingRate ?? 1.0,\n privacy: { ...DEFAULT_PRIVACY_CONFIG, ...userConfig?.privacy },\n performance: { ...DEFAULT_PERFORMANCE_CONFIG, ...userConfig?.performance },\n capture: { ...DEFAULT_CAPTURE_CONFIG, ...userConfig?.capture },\n endpoint: userConfig?.endpoint ?? '',\n onStart: userConfig?.onStart ?? (() => {}),\n onStop: userConfig?.onStop ?? (() => {}),\n onError: userConfig?.onError ?? (() => {}),\n };\n}\n\n/**\n * Check if session should be recorded based on sampling rate\n */\nexport function shouldRecordSession(samplingRate: number): boolean {\n if (samplingRate >= 1) return true;\n if (samplingRate <= 0) return false;\n return Math.random() < samplingRate;\n}\n\n/**\n * Simple LZ-string compression for events\n * Uses a basic run-length encoding approach for demo\n * In production, you'd use the full lz-string library\n */\nexport function compressEvents(events: any[]): string {\n try {\n const json = JSON.stringify(events);\n // Use base64 encoding - in production, use proper compression\n if (typeof btoa !== 'undefined') {\n return btoa(encodeURIComponent(json));\n }\n return json;\n } catch (error) {\n console.warn('[Recording] Failed to compress events:', error);\n return JSON.stringify(events);\n }\n}\n\n/**\n * Decompress events\n */\nexport function decompressEvents(compressed: string): any[] {\n try {\n if (typeof atob !== 'undefined' && !compressed.startsWith('[')) {\n const json = decodeURIComponent(atob(compressed));\n return JSON.parse(json);\n }\n return JSON.parse(compressed);\n } catch (error) {\n console.warn('[Recording] Failed to decompress events:', error);\n return [];\n }\n}\n\n/**\n * Throttle function for mouse movements\n */\nexport function throttle<T extends (...args: any[]) => any>(\n func: T,\n limit: number\n): (...args: Parameters<T>) => void {\n let inThrottle = false;\n return function (this: any, ...args: Parameters<T>) {\n if (!inThrottle) {\n func.apply(this, args);\n inThrottle = true;\n setTimeout(() => (inThrottle = false), limit);\n }\n };\n}\n\n/**\n * Debounce function for batching\n */\nexport function debounce<T extends (...args: any[]) => any>(\n func: T,\n wait: number\n): (...args: Parameters<T>) => void {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n return function (this: any, ...args: Parameters<T>) {\n if (timeout) clearTimeout(timeout);\n timeout = setTimeout(() => func.apply(this, args), wait);\n };\n}\n\n/**\n * Format duration in human readable format\n */\nexport function formatDuration(ms: number): string {\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n\n if (hours > 0) {\n return `${hours}h ${minutes % 60}m ${seconds % 60}s`;\n }\n if (minutes > 0) {\n return `${minutes}m ${seconds % 60}s`;\n }\n return `${seconds}s`;\n}\n\n/**\n * Safe JSON stringify that handles circular references\n */\nexport function safeStringify(obj: any, maxDepth = 5): string {\n const seen = new WeakSet();\n return JSON.stringify(obj, (key, value) => {\n if (maxDepth <= 0) return '[Max Depth]';\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) return '[Circular]';\n seen.add(value);\n }\n return value;\n });\n}\n\n/**\n * Check if we're in a browser environment\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Get current page URL\n */\nexport function getCurrentUrl(): string {\n if (!isBrowser()) return '';\n return window.location.href;\n}\n","/**\n * Session Recorder\n * Core recording functionality using rrweb\n * \n * This module is completely isolated from the main SDK logic.\n * It can be enabled/disabled without affecting other SDK functionality.\n */\n\nimport type { recordOptions } from 'rrweb';\nimport type {\n RecordingConfig,\n RecordingEvent,\n RecordingEventBatch,\n RecordingSession,\n RecordingState,\n RecordingStats,\n CustomRecordingEvent,\n ConsoleLogEvent,\n ErrorEvent,\n} from './types';\nimport {\n generateSessionId,\n getDeviceInfo,\n mergeConfig,\n shouldRecordSession,\n compressEvents,\n isBrowser,\n getCurrentUrl,\n} from './utils';\n\n/**\n * SessionRecorder class\n * Handles all recording logic, isolated from main SDK\n */\nexport class SessionRecorder {\n private config: Required<RecordingConfig>;\n private state: RecordingState = 'idle';\n private sessionId: string | null = null;\n private sdkSessionToken: string | null = null;\n private apiUrl: string = '';\n private sdkKey: string | null = null;\n\n // Recording internals\n private stopRecording: (() => void) | null = null;\n private events: RecordingEvent[] = [];\n private eventCount = 0;\n private batchIndex = 0;\n private batchesSent = 0;\n private errorCount = 0;\n private startTime: Date | null = null;\n private batchTimeout: ReturnType<typeof setTimeout> | null = null;\n private maxDurationTimeout: ReturnType<typeof setTimeout> | null = null;\n\n // Cleanup handlers\n private consoleCleanup: (() => void) | null = null;\n private errorCleanup: (() => void) | null = null;\n\n constructor(config?: RecordingConfig) {\n this.config = mergeConfig(config);\n }\n\n /**\n * Initialize the recorder with SDK context\n */\n initialize(sdkSessionToken: string, apiUrl: string, sdkKey?: string): void {\n this.sdkSessionToken = sdkSessionToken;\n this.apiUrl = apiUrl;\n this.sdkKey = sdkKey || null;\n }\n\n /**\n * Update configuration\n */\n updateConfig(config: Partial<RecordingConfig>): void {\n this.config = mergeConfig({ ...this.config, ...config });\n }\n\n /**\n * Start recording session\n */\n async start(): Promise<string | null> {\n if (!isBrowser()) {\n console.warn('[Recording] Cannot record outside browser environment');\n return null;\n }\n\n if (!this.config.enabled) {\n return null;\n }\n\n if (this.state === 'recording') {\n console.warn('[Recording] Already recording');\n return this.sessionId;\n }\n\n // Check sampling rate\n if (!shouldRecordSession(this.config.samplingRate)) {\n console.log('[Recording] Session not sampled for recording');\n return null;\n }\n\n try {\n // Dynamically import rrweb to keep it optional\n const rrweb = await import('rrweb');\n\n this.sessionId = generateSessionId();\n this.events = [];\n this.eventCount = 0;\n this.batchIndex = 0;\n this.batchesSent = 0;\n this.errorCount = 0;\n this.startTime = new Date();\n this.state = 'recording';\n\n // Build rrweb options\n const rrwebOptions: recordOptions<RecordingEvent> = {\n emit: (event) => this.handleEvent(event),\n maskAllInputs: this.config.privacy.maskAllInputs,\n maskTextSelector: this.config.privacy.maskSelectors?.join(',') || undefined,\n blockSelector: this.config.privacy.blockSelectors?.join(',') || undefined,\n maskInputOptions: {\n password: true,\n email: this.config.privacy.maskInputTypes?.includes('email'),\n tel: this.config.privacy.maskInputTypes?.includes('tel'),\n },\n sampling: {\n mousemove: true,\n mouseInteraction: true,\n scroll: 150,\n media: 800,\n input: 'last',\n },\n };\n\n // Start rrweb recording\n this.stopRecording = rrweb.record(rrwebOptions);\n\n // Setup additional captures\n if (this.config.capture.console) {\n this.setupConsoleCapture();\n }\n if (this.config.capture.errors) {\n this.setupErrorCapture();\n }\n\n // Setup max duration timeout\n if (this.config.performance.maxDuration) {\n this.maxDurationTimeout = setTimeout(() => {\n console.log('[Recording] Max duration reached, stopping');\n this.stop();\n }, this.config.performance.maxDuration);\n }\n\n // Send session start to backend\n await this.sendSessionStart();\n\n this.config.onStart(this.sessionId);\n console.log('[Recording] Started session:', this.sessionId);\n\n return this.sessionId;\n } catch (error) {\n console.error('[Recording] Failed to start:', error);\n this.state = 'idle';\n this.config.onError(error instanceof Error ? error : new Error(String(error)));\n return null;\n }\n }\n\n /**\n * Stop recording\n */\n async stop(): Promise<void> {\n if (this.state !== 'recording' && this.state !== 'paused') {\n return;\n }\n\n try {\n // Stop rrweb\n if (this.stopRecording) {\n this.stopRecording();\n this.stopRecording = null;\n }\n\n // Cleanup captures\n if (this.consoleCleanup) {\n this.consoleCleanup();\n this.consoleCleanup = null;\n }\n if (this.errorCleanup) {\n this.errorCleanup();\n this.errorCleanup = null;\n }\n\n // Clear timeouts\n if (this.batchTimeout) {\n clearTimeout(this.batchTimeout);\n this.batchTimeout = null;\n }\n if (this.maxDurationTimeout) {\n clearTimeout(this.maxDurationTimeout);\n this.maxDurationTimeout = null;\n }\n\n // Send remaining events\n if (this.events.length > 0) {\n await this.sendBatch(true);\n }\n\n // Send session end\n await this.sendSessionEnd();\n\n const sessionId = this.sessionId;\n const eventCount = this.eventCount;\n\n this.state = 'stopped';\n this.config.onStop(sessionId || '', eventCount);\n console.log('[Recording] Stopped session:', sessionId, 'Events:', eventCount);\n } catch (error) {\n console.error('[Recording] Error stopping:', error);\n this.config.onError(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n /**\n * Pause recording\n */\n pause(): void {\n if (this.state !== 'recording') return;\n this.state = 'paused';\n // rrweb doesn't have built-in pause, we just stop emitting\n console.log('[Recording] Paused');\n }\n\n /**\n * Resume recording\n */\n resume(): void {\n if (this.state !== 'paused') return;\n this.state = 'recording';\n console.log('[Recording] Resumed');\n }\n\n /**\n * Add a custom event to the recording\n */\n addCustomEvent(event: CustomRecordingEvent): void {\n if (this.state !== 'recording' || !this.config.capture.customEvents) return;\n\n const customEvent: RecordingEvent = {\n type: 5, // rrweb custom event type\n data: {\n tag: 'custom',\n payload: event,\n },\n timestamp: event.timestamp || Date.now(),\n };\n\n this.handleEvent(customEvent);\n }\n\n /**\n * Get current recording stats\n */\n getStats(): RecordingStats {\n const duration = this.startTime\n ? Date.now() - this.startTime.getTime()\n : 0;\n\n return {\n state: this.state,\n sessionId: this.sessionId,\n eventCount: this.eventCount,\n startTime: this.startTime,\n duration,\n batchesSent: this.batchesSent,\n errors: this.errorCount,\n };\n }\n\n /**\n * Check if recording is active\n */\n isRecording(): boolean {\n return this.state === 'recording';\n }\n\n /**\n * Get session ID\n */\n getSessionId(): string | null {\n return this.sessionId;\n }\n\n // ============ Private Methods ============\n\n /**\n * Handle incoming event from rrweb\n */\n private handleEvent(event: RecordingEvent): void {\n if (this.state !== 'recording') return;\n\n this.events.push(event);\n this.eventCount++;\n\n // Check if we should send batch\n if (this.config.performance.batchEvents) {\n if (this.events.length >= this.config.performance.batchSize) {\n this.sendBatch();\n } else if (!this.batchTimeout) {\n this.batchTimeout = setTimeout(() => {\n this.batchTimeout = null;\n if (this.events.length > 0) {\n this.sendBatch();\n }\n }, this.config.performance.batchTimeout);\n }\n } else {\n // Send immediately\n this.sendBatch();\n }\n }\n\n /**\n * Send event batch to backend\n */\n private async sendBatch(isFinal = false): Promise<void> {\n if (this.events.length === 0) return;\n\n const eventsToSend = [...this.events];\n this.events = [];\n\n const batch: RecordingEventBatch = {\n sessionId: this.sessionId!,\n sdkSessionToken: this.sdkSessionToken!,\n events: eventsToSend,\n timestamp: new Date().toISOString(),\n batchIndex: this.batchIndex++,\n isFinal,\n };\n\n try {\n const endpoint = this.config.endpoint || `${this.apiUrl}/session-recordings/events`;\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.sdkKey) {\n headers['X-SDK-Key'] = this.sdkKey;\n }\n\n const body = this.config.performance.compress\n ? JSON.stringify({ ...batch, events: undefined, compressedEvents: compressEvents(eventsToSend) })\n : JSON.stringify(batch);\n\n await fetch(endpoint, {\n method: 'POST',\n headers,\n body,\n });\n\n this.batchesSent++;\n } catch (error) {\n console.error('[Recording] Failed to send batch:', error);\n this.errorCount++;\n // Put events back for retry\n this.events = [...eventsToSend, ...this.events];\n }\n }\n\n /**\n * Send session start notification\n */\n private async sendSessionStart(): Promise<void> {\n const session: Omit<RecordingSession, 'endTime' | 'eventCount'> = {\n id: this.sessionId!,\n sdkSessionToken: this.sdkSessionToken!,\n startUrl: getCurrentUrl(),\n startTime: this.startTime!,\n deviceInfo: getDeviceInfo(),\n };\n\n try {\n const endpoint = `${this.apiUrl}/session-recordings/start`;\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.sdkKey) {\n headers['X-SDK-Key'] = this.sdkKey;\n }\n\n await fetch(endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify(session),\n });\n } catch (error) {\n console.error('[Recording] Failed to send session start:', error);\n }\n }\n\n /**\n * Send session end notification\n */\n private async sendSessionEnd(): Promise<void> {\n try {\n const endpoint = `${this.apiUrl}/session-recordings/end`;\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.sdkKey) {\n headers['X-SDK-Key'] = this.sdkKey;\n }\n\n await fetch(endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n sessionId: this.sessionId,\n endTime: new Date().toISOString(),\n eventCount: this.eventCount,\n }),\n });\n } catch (error) {\n console.error('[Recording] Failed to send session end:', error);\n }\n }\n\n /**\n * Setup console log capture\n */\n private setupConsoleCapture(): void {\n const originalConsole = {\n log: console.log,\n info: console.info,\n warn: console.warn,\n error: console.error,\n debug: console.debug,\n };\n\n const captureConsole = (level: ConsoleLogEvent['level']) => {\n return (...args: any[]) => {\n // Call original\n originalConsole[level](...args);\n\n // Skip our own logs\n if (args[0]?.toString().includes('[Recording]')) return;\n\n // Add to recording\n const logEvent: ConsoleLogEvent = {\n level,\n message: args.map(arg => \n typeof arg === 'object' ? JSON.stringify(arg) : String(arg)\n ).join(' '),\n timestamp: Date.now(),\n };\n\n this.addCustomEvent({\n type: 'console',\n data: logEvent,\n });\n };\n };\n\n console.log = captureConsole('log');\n console.info = captureConsole('info');\n console.warn = captureConsole('warn');\n console.error = captureConsole('error');\n console.debug = captureConsole('debug');\n\n this.consoleCleanup = () => {\n console.log = originalConsole.log;\n console.info = originalConsole.info;\n console.warn = originalConsole.warn;\n console.error = originalConsole.error;\n console.debug = originalConsole.debug;\n };\n }\n\n /**\n * Setup error capture\n */\n private setupErrorCapture(): void {\n const errorHandler = (event: ErrorEvent) => {\n const errorEvent: ErrorEvent = {\n type: 'error',\n message: event.message,\n filename: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n timestamp: Date.now(),\n };\n\n this.addCustomEvent({\n type: 'error',\n data: errorEvent,\n });\n };\n\n const rejectionHandler = (event: PromiseRejectionEvent) => {\n const errorEvent: ErrorEvent = {\n type: 'unhandledrejection',\n message: event.reason?.message || String(event.reason),\n stack: event.reason?.stack,\n timestamp: Date.now(),\n };\n\n this.addCustomEvent({\n type: 'error',\n data: errorEvent,\n });\n };\n\n window.addEventListener('error', errorHandler as any);\n window.addEventListener('unhandledrejection', rejectionHandler);\n\n this.errorCleanup = () => {\n window.removeEventListener('error', errorHandler as any);\n window.removeEventListener('unhandledrejection', rejectionHandler);\n };\n }\n\n /**\n * Destroy the recorder\n */\n destroy(): void {\n this.stop();\n this.sessionId = null;\n this.sdkSessionToken = null;\n this.events = [];\n }\n}\n\n/**\n * Create a new SessionRecorder instance\n */\nexport function createSessionRecorder(config?: RecordingConfig): SessionRecorder {\n return new SessionRecorder(config);\n}\n\nexport default SessionRecorder;\n","/**\n * Proactive Chat Features\n * \n * Tracks user behavior and triggers contextual chat messages based on:\n * - Scroll Depth: Triggers when user scrolls past threshold\n * - Time on Page: Triggers after specified time\n * - Click Count: Triggers after X clicks\n * - Idle Time: Triggers when user is inactive\n * - Exit Intent: Triggers when mouse leaves viewport (abandonment)\n * - Page Changes: Triggers on SPA route changes\n */\n\nexport interface ProactiveTrigger {\n type: 'scroll' | 'time' | 'clicks' | 'idle' | 'exit' | 'pageChange';\n enabled: boolean;\n threshold?: number; // scroll %, time in ms, click count, idle time in ms\n message?: string; // Custom message override\n cooldown?: number; // Cooldown between triggers in ms\n onlyOnce?: boolean; // Only trigger once per session\n}\n\nexport interface ProactiveConfig {\n enabled: boolean;\n triggers: ProactiveTrigger[];\n maxProactiveMessages?: number; // Max proactive messages per session\n globalCooldown?: number; // Global cooldown between any proactive message\n respectUserPreference?: boolean; // Check localStorage for user opt-out\n}\n\nexport interface ProactiveContext {\n triggerType: ProactiveTrigger['type'];\n scrollDepth?: number;\n timeOnPage?: number;\n clickCount?: number;\n idleTime?: number;\n currentUrl?: string;\n previousUrl?: string;\n pageTitle?: string;\n}\n\nexport interface ProactiveCallbacks {\n onTrigger: (context: ProactiveContext, suggestedMessage: string) => void;\n onMessage?: (message: string) => void;\n}\n\nexport class ProactiveBehaviorTracker {\n private config: ProactiveConfig;\n private callbacks: ProactiveCallbacks;\n private isTracking: boolean = false;\n \n // Tracking state\n private scrollDepth: number = 0;\n private pageLoadTime: number = 0;\n private clickCount: number = 0;\n private lastActivityTime: number = 0;\n private currentUrl: string = '';\n private previousUrl: string = '';\n \n // Trigger state\n private triggeredSet: Set<string> = new Set();\n private lastTriggerTime: number = 0;\n private proactiveMessageCount: number = 0;\n \n // Listeners\n private scrollHandler: (() => void) | null = null;\n private clickHandler: (() => void) | null = null;\n private mouseMoveHandler: (() => void) | null = null;\n private mouseLeaveHandler: ((e: MouseEvent) => void) | null = null;\n private visibilityHandler: (() => void) | null = null;\n \n // Timers\n private timeCheckInterval: ReturnType<typeof setInterval> | null = null;\n private idleCheckInterval: ReturnType<typeof setInterval> | null = null;\n\n constructor(config: ProactiveConfig, callbacks: ProactiveCallbacks) {\n this.config = config;\n this.callbacks = callbacks;\n }\n\n /**\n * Start tracking user behavior\n */\n start(): void {\n if (!this.config.enabled || this.isTracking) return;\n if (typeof window === 'undefined') return;\n\n // Check user preference\n if (this.config.respectUserPreference) {\n const optOut = localStorage.getItem('produck_proactive_optout');\n if (optOut === 'true') return;\n }\n\n this.isTracking = true;\n this.pageLoadTime = Date.now();\n this.lastActivityTime = Date.now();\n this.currentUrl = window.location.href;\n\n this.setupScrollTracking();\n this.setupClickTracking();\n this.setupIdleTracking();\n this.setupExitIntentTracking();\n this.setupTimeTracking();\n this.setupPageChangeTracking();\n\n console.log('[Produck] Proactive behavior tracking started');\n }\n\n /**\n * Stop tracking\n */\n stop(): void {\n if (!this.isTracking) return;\n this.isTracking = false;\n\n // Remove event listeners\n if (this.scrollHandler) {\n window.removeEventListener('scroll', this.scrollHandler);\n }\n if (this.clickHandler) {\n document.removeEventListener('click', this.clickHandler);\n }\n if (this.mouseMoveHandler) {\n document.removeEventListener('mousemove', this.mouseMoveHandler);\n }\n if (this.mouseLeaveHandler) {\n document.removeEventListener('mouseleave', this.mouseLeaveHandler);\n }\n if (this.visibilityHandler) {\n document.removeEventListener('visibilitychange', this.visibilityHandler);\n }\n\n // Clear intervals\n if (this.timeCheckInterval) {\n clearInterval(this.timeCheckInterval);\n }\n if (this.idleCheckInterval) {\n clearInterval(this.idleCheckInterval);\n }\n\n console.log('[Produck] Proactive behavior tracking stopped');\n }\n\n /**\n * Reset tracking state (e.g., on page change)\n */\n reset(): void {\n this.scrollDepth = 0;\n this.clickCount = 0;\n this.pageLoadTime = Date.now();\n this.lastActivityTime = Date.now();\n // Note: triggeredSet is NOT reset to respect onlyOnce across navigation\n }\n\n /**\n * Get current tracking stats\n */\n getStats(): {\n scrollDepth: number;\n timeOnPage: number;\n clickCount: number;\n idleTime: number;\n proactiveMessageCount: number;\n } {\n return {\n scrollDepth: this.scrollDepth,\n timeOnPage: Date.now() - this.pageLoadTime,\n clickCount: this.clickCount,\n idleTime: Date.now() - this.lastActivityTime,\n proactiveMessageCount: this.proactiveMessageCount,\n };\n }\n\n /**\n * Check if a trigger should fire\n */\n private shouldTrigger(trigger: ProactiveTrigger): boolean {\n // Check if max messages reached\n if (this.config.maxProactiveMessages && \n this.proactiveMessageCount >= this.config.maxProactiveMessages) {\n return false;\n }\n\n // Check global cooldown\n if (this.config.globalCooldown && \n Date.now() - this.lastTriggerTime < this.config.globalCooldown) {\n return false;\n }\n\n // Check if already triggered (for onlyOnce triggers)\n const triggerKey = `${trigger.type}-${trigger.threshold || 'default'}`;\n if (trigger.onlyOnce && this.triggeredSet.has(triggerKey)) {\n return false;\n }\n\n // Check trigger-specific cooldown\n const lastTriggerKey = `${triggerKey}-lastTime`;\n const lastTime = parseInt(sessionStorage.getItem(lastTriggerKey) || '0', 10);\n if (trigger.cooldown && Date.now() - lastTime < trigger.cooldown) {\n return false;\n }\n\n return true;\n }\n\n /**\n * Fire a trigger\n */\n private fireTrigger(trigger: ProactiveTrigger, context: ProactiveContext): void {\n if (!this.shouldTrigger(trigger)) return;\n\n const triggerKey = `${trigger.type}-${trigger.threshold || 'default'}`;\n const lastTriggerKey = `${triggerKey}-lastTime`;\n\n // Mark as triggered\n this.triggeredSet.add(triggerKey);\n this.lastTriggerTime = Date.now();\n this.proactiveMessageCount++;\n sessionStorage.setItem(lastTriggerKey, Date.now().toString());\n\n // Generate contextual message\n const message = trigger.message || this.getDefaultMessage(trigger.type, context);\n\n // Call callbacks\n this.callbacks.onTrigger(context, message);\n if (this.callbacks.onMessage) {\n this.callbacks.onMessage(message);\n }\n\n console.log('[Produck] Proactive trigger fired:', trigger.type, context);\n }\n\n /**\n * Get default message for trigger type\n */\n private getDefaultMessage(type: ProactiveTrigger['type'], context: ProactiveContext): string {\n switch (type) {\n case 'scroll':\n return `I see you're exploring the page! Is there something specific you're looking for?`;\n case 'time':\n return `You've been here a while. Would you like some help finding what you need?`;\n case 'clicks':\n return `Looks like you're navigating around. Can I help you find something?`;\n case 'idle':\n return `Still there? Let me know if you have any questions!`;\n case 'exit':\n return `Wait! Before you go, is there anything I can help you with?`;\n case 'pageChange':\n return `I see you're exploring different pages. Need any guidance?`;\n default:\n return `How can I help you today?`;\n }\n }\n\n /**\n * Setup scroll depth tracking\n */\n private setupScrollTracking(): void {\n const scrollTriggers = this.config.triggers.filter(t => t.type === 'scroll' && t.enabled);\n if (scrollTriggers.length === 0) return;\n\n this.scrollHandler = () => {\n const docHeight = document.documentElement.scrollHeight - window.innerHeight;\n const scrollPercent = docHeight > 0 ? (window.scrollY / docHeight) * 100 : 0;\n this.scrollDepth = Math.max(this.scrollDepth, scrollPercent);\n this.lastActivityTime = Date.now();\n\n scrollTriggers.forEach(trigger => {\n if (trigger.threshold && this.scrollDepth >= trigger.threshold) {\n this.fireTrigger(trigger, {\n triggerType: 'scroll',\n scrollDepth: this.scrollDepth,\n currentUrl: window.location.href,\n pageTitle: document.title,\n });\n }\n });\n };\n\n window.addEventListener('scroll', this.scrollHandler, { passive: true });\n }\n\n /**\n * Setup click tracking\n */\n private setupClickTracking(): void {\n const clickTriggers = this.config.triggers.filter(t => t.type === 'clicks' && t.enabled);\n if (clickTriggers.length === 0) return;\n\n this.clickHandler = () => {\n this.clickCount++;\n this.lastActivityTime = Date.now();\n\n clickTriggers.forEach(trigger => {\n if (trigger.threshold && this.clickCount >= trigger.threshold) {\n this.fireTrigger(trigger, {\n triggerType: 'clicks',\n clickCount: this.clickCount,\n currentUrl: window.location.href,\n pageTitle: document.title,\n });\n }\n });\n };\n\n document.addEventListener('click', this.clickHandler);\n }\n\n /**\n * Setup idle tracking\n */\n private setupIdleTracking(): void {\n const idleTriggers = this.config.triggers.filter(t => t.type === 'idle' && t.enabled);\n if (idleTriggers.length === 0) return;\n\n // Track activity\n this.mouseMoveHandler = () => {\n this.lastActivityTime = Date.now();\n };\n document.addEventListener('mousemove', this.mouseMoveHandler, { passive: true });\n\n // Check idle time periodically\n this.idleCheckInterval = setInterval(() => {\n const idleTime = Date.now() - this.lastActivityTime;\n\n idleTriggers.forEach(trigger => {\n if (trigger.threshold && idleTime >= trigger.threshold) {\n this.fireTrigger(trigger, {\n triggerType: 'idle',\n idleTime,\n currentUrl: window.location.href,\n pageTitle: document.title,\n });\n }\n });\n }, 1000);\n }\n\n /**\n * Setup exit intent tracking\n */\n private setupExitIntentTracking(): void {\n const exitTriggers = this.config.triggers.filter(t => t.type === 'exit' && t.enabled);\n if (exitTriggers.length === 0) return;\n\n this.mouseLeaveHandler = (e: MouseEvent) => {\n // Only trigger if mouse leaves from top of viewport\n if (e.clientY <= 0) {\n exitTriggers.forEach(trigger => {\n this.fireTrigger(trigger, {\n triggerType: 'exit',\n currentUrl: window.location.href,\n pageTitle: document.title,\n });\n });\n }\n };\n\n document.addEventListener('mouseleave', this.mouseLeaveHandler);\n }\n\n /**\n * Setup time on page tracking\n */\n private setupTimeTracking(): void {\n const timeTriggers = this.config.triggers.filter(t => t.type === 'time' && t.enabled);\n if (timeTriggers.length === 0) return;\n\n this.timeCheckInterval = setInterval(() => {\n const timeOnPage = Date.now() - this.pageLoadTime;\n\n timeTriggers.forEach(trigger => {\n if (trigger.threshold && timeOnPage >= trigger.threshold) {\n this.fireTrigger(trigger, {\n triggerType: 'time',\n timeOnPage,\n currentUrl: window.location.href,\n pageTitle: document.title,\n });\n }\n });\n }, 1000);\n }\n\n /**\n * Setup SPA page change tracking\n */\n private setupPageChangeTracking(): void {\n const pageTriggers = this.config.triggers.filter(t => t.type === 'pageChange' && t.enabled);\n if (pageTriggers.length === 0) return;\n\n // Use visibility change and popstate for SPA detection\n this.visibilityHandler = () => {\n if (document.visibilityState === 'visible') {\n const newUrl = window.location.href;\n if (newUrl !== this.currentUrl) {\n this.previousUrl = this.currentUrl;\n this.currentUrl = newUrl;\n\n // Reset page-specific counters\n this.scrollDepth = 0;\n this.clickCount = 0;\n this.pageLoadTime = Date.now();\n\n pageTriggers.forEach(trigger => {\n this.fireTrigger(trigger, {\n triggerType: 'pageChange',\n currentUrl: this.currentUrl,\n previousUrl: this.previousUrl,\n pageTitle: document.title,\n });\n });\n }\n }\n };\n\n document.addEventListener('visibilitychange', this.visibilityHandler);\n\n // Also handle popstate for back/forward navigation\n window.addEventListener('popstate', () => {\n const newUrl = window.location.href;\n if (newUrl !== this.currentUrl) {\n this.previousUrl = this.currentUrl;\n this.currentUrl = newUrl;\n\n pageTriggers.forEach(trigger => {\n this.fireTrigger(trigger, {\n triggerType: 'pageChange',\n currentUrl: this.currentUrl,\n previousUrl: this.previousUrl,\n pageTitle: document.title,\n });\n });\n }\n });\n }\n\n /**\n * Manually trigger a proactive message (for custom integrations)\n */\n triggerManual(message: string, context?: Partial<ProactiveContext>): void {\n this.proactiveMessageCount++;\n this.lastTriggerTime = Date.now();\n\n const fullContext: ProactiveContext = {\n triggerType: 'time', // default\n currentUrl: window.location.href,\n pageTitle: document.title,\n ...context,\n };\n\n this.callbacks.onTrigger(fullContext, message);\n if (this.callbacks.onMessage) {\n this.callbacks.onMessage(message);\n }\n }\n\n /**\n * Opt out of proactive messages\n */\n optOut(): void {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem('produck_proactive_optout', 'true');\n }\n this.stop();\n }\n\n /**\n * Opt in to proactive messages\n */\n optIn(): void {\n if (typeof localStorage !== 'undefined') {\n localStorage.removeItem('produck_proactive_optout');\n }\n this.start();\n }\n}\n\n// Default proactive configuration\nexport const defaultProactiveConfig: ProactiveConfig = {\n enabled: false,\n triggers: [\n {\n type: 'scroll',\n enabled: true,\n threshold: 75, // 75% scroll depth\n onlyOnce: true,\n cooldown: 60000, // 1 minute\n },\n {\n type: 'time',\n enabled: true,\n threshold: 30000, // 30 seconds\n onlyOnce: true,\n },\n {\n type: 'idle',\n enabled: true,\n threshold: 60000, // 1 minute idle\n cooldown: 120000, // 2 minutes between\n },\n {\n type: 'exit',\n enabled: true,\n onlyOnce: true,\n },\n ],\n maxProactiveMessages: 3,\n globalCooldown: 30000, // 30 seconds between any proactive message\n respectUserPreference: true,\n};\n","/**\n * User Flow Tracker Utilities\n * Helper functions for tracking user interactions\n */\n\nimport type { DeviceInfo, ElementInfo, UserFlowConfig, ResolvedUserFlowConfig } from './types';\n\n/**\n * Check if we're in a browser environment\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Generate a unique session ID\n */\nexport function generateSessionId(): string {\n return 'ufs_' + Date.now().toString(36) + '_' + Math.random().toString(36).substring(2, 11);\n}\n\n/**\n * Get current page URL\n */\nexport function getCurrentUrl(): string {\n if (!isBrowser()) return '';\n return window.location.href;\n}\n\n/**\n * Get current page path\n */\nexport function getCurrentPath(): string {\n if (!isBrowser()) return '';\n return window.location.pathname;\n}\n\n/**\n * Get current page title\n */\nexport function getCurrentTitle(): string {\n if (!isBrowser()) return '';\n return document.title || '';\n}\n\n/**\n * Check if session should be tracked based on sampling rate\n */\nexport function shouldTrackSession(samplingRate: number = 1): boolean {\n return Math.random() < samplingRate;\n}\n\n/**\n * Get device information\n */\nexport function getDeviceInfo(): DeviceInfo {\n if (!isBrowser()) {\n return {\n deviceType: 'desktop',\n browser: 'unknown',\n os: 'unknown',\n viewportWidth: 0,\n viewportHeight: 0,\n userAgent: '',\n };\n }\n\n const ua = navigator.userAgent;\n \n // Detect device type\n let deviceType: 'desktop' | 'tablet' | 'mobile' = 'desktop';\n if (/Mobi|Android/i.test(ua)) {\n deviceType = /Tablet|iPad/i.test(ua) ? 'tablet' : 'mobile';\n }\n\n // Detect browser\n let browser = 'unknown';\n if (ua.includes('Firefox')) browser = 'Firefox';\n else if (ua.includes('Edg')) browser = 'Edge';\n else if (ua.includes('Chrome')) browser = 'Chrome';\n else if (ua.includes('Safari')) browser = 'Safari';\n else if (ua.includes('Opera') || ua.includes('OPR')) browser = 'Opera';\n\n // Detect OS\n let os = 'unknown';\n if (ua.includes('Windows')) os = 'Windows';\n else if (ua.includes('Mac OS')) os = 'macOS';\n else if (ua.includes('Linux')) os = 'Linux';\n else if (ua.includes('Android')) os = 'Android';\n else if (ua.includes('iOS') || ua.includes('iPhone') || ua.includes('iPad')) os = 'iOS';\n\n return {\n deviceType,\n browser,\n os,\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n userAgent: ua,\n };\n}\n\n/**\n * Get CSS selector path for an element\n */\nexport function getElementSelector(element: Element, depth: number = 5): string {\n const parts: string[] = [];\n let current: Element | null = element;\n let currentDepth = 0;\n\n while (current && current !== document.body && currentDepth < depth) {\n let selector = current.tagName.toLowerCase();\n\n // Add ID if present\n if (current.id) {\n selector += `#${current.id}`;\n parts.unshift(selector);\n break; // ID is unique, stop here\n }\n\n // Add first class if present\n if (current.className && typeof current.className === 'string') {\n const classes = current.className.trim().split(/\\s+/);\n if (classes.length > 0 && classes[0]) {\n selector += `.${classes[0]}`;\n }\n }\n\n // Add nth-child for disambiguation\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n (child) => child.tagName === current!.tagName\n );\n if (siblings.length > 1) {\n const index = siblings.indexOf(current) + 1;\n selector += `:nth-child(${index})`;\n }\n }\n\n parts.unshift(selector);\n current = current.parentElement;\n currentDepth++;\n }\n\n return parts.join(' > ');\n}\n\n/**\n * Get XPath for an element\n */\nexport function getElementXPath(element: Element): string {\n if (!element) return '';\n \n if (element.id) {\n return `//*[@id=\"${element.id}\"]`;\n }\n\n const parts: string[] = [];\n let current: Element | null = element;\n\n while (current && current.nodeType === Node.ELEMENT_NODE) {\n let index = 0;\n let sibling: Element | null = current.previousElementSibling;\n \n while (sibling) {\n if (sibling.tagName === current.tagName) {\n index++;\n }\n sibling = sibling.previousElementSibling;\n }\n\n const tagName = current.tagName.toLowerCase();\n const part = index > 0 ? `${tagName}[${index + 1}]` : tagName;\n parts.unshift(part);\n current = current.parentElement;\n }\n\n return '/' + parts.join('/');\n}\n\n/**\n * Get element information\n */\nexport function getElementInfo(\n element: Element,\n config: UserFlowConfig['element'] = {},\n): ElementInfo {\n const maxTextLength = config?.maxTextLength || 100;\n const maxHtmlLength = config?.maxHtmlLength || 500;\n const selectorDepth = config?.selectorDepth || 5;\n\n // Get text content\n let text = '';\n if (element instanceof HTMLElement) {\n text = element.innerText || element.textContent || '';\n text = text.trim().substring(0, maxTextLength);\n if (text.length === maxTextLength) text += '...';\n }\n\n // Get outer HTML\n let html: string | undefined;\n if (config?.captureHtml !== false) {\n html = element.outerHTML.substring(0, maxHtmlLength);\n if (html.length === maxHtmlLength) html += '...';\n }\n\n // Get bounding rect\n const rect = element.getBoundingClientRect();\n\n const info: ElementInfo = {\n tag: element.tagName.toLowerCase(),\n selector: getElementSelector(element, selectorDepth),\n };\n\n // Optional fields\n if (element.id) info.id = element.id;\n if (element.className && typeof element.className === 'string') {\n info.className = element.className;\n }\n if (text) info.text = text;\n if (element instanceof HTMLAnchorElement && element.href) {\n info.href = element.href;\n }\n info.xpath = getElementXPath(element);\n info.rect = {\n x: Math.round(rect.x),\n y: Math.round(rect.y),\n width: Math.round(rect.width),\n height: Math.round(rect.height),\n };\n if (html) info.html = html;\n\n return info;\n}\n\n/**\n * Check if element matches any of the given selectors\n */\nexport function matchesSelectors(element: Element, selectors: string[]): boolean {\n if (!selectors || selectors.length === 0) return false;\n \n return selectors.some((selector) => {\n try {\n return element.matches(selector) || element.closest(selector) !== null;\n } catch {\n return false;\n }\n });\n}\n\n/**\n * Capture element visual info (lightweight alternative to html2canvas)\n * Instead of full screenshots, we capture CSS visual properties\n * This is ~100x faster and doesn't block the main thread\n */\nexport function captureElementVisualInfo(element: Element): Record<string, string> | undefined {\n try {\n if (typeof window === 'undefined') return undefined;\n \n const htmlElement = element as HTMLElement;\n const styles = window.getComputedStyle(htmlElement);\n \n return {\n backgroundColor: styles.backgroundColor,\n color: styles.color,\n fontSize: styles.fontSize,\n fontWeight: styles.fontWeight,\n borderRadius: styles.borderRadius,\n border: styles.border,\n boxShadow: styles.boxShadow,\n padding: styles.padding,\n };\n } catch {\n return undefined;\n }\n}\n\n/**\n * Capture element screenshot (using html2canvas)\n * WARNING: This is expensive! Only use for:\n * - Specific important elements (CTAs, conversion points)\n * - Debugging/development mode\n * - Post-session analysis (not real-time)\n * \n * Consider using captureElementVisualInfo() for production\n */\nexport async function captureElementScreenshot(\n element: Element,\n maxSize: number = 200,\n): Promise<string | undefined> {\n try {\n // Check if we have html2canvas available\n if (typeof window === 'undefined') return undefined;\n\n // Try to dynamically import html2canvas\n const html2canvas = (window as any).html2canvas;\n if (!html2canvas) {\n // Try to import it - html2canvas is an optional peer dependency\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const module = await import(/* webpackIgnore: true */ 'html2canvas' as string);\n const canvas = await module.default(element as HTMLElement, {\n scale: 0.5,\n width: maxSize,\n height: maxSize,\n useCORS: true,\n logging: false,\n });\n return canvas.toDataURL('image/jpeg', 0.7);\n } catch {\n console.debug('[UserFlow] html2canvas not available for screenshots');\n return undefined;\n }\n }\n\n const canvas = await html2canvas(element as HTMLElement, {\n scale: 0.5,\n width: maxSize,\n height: maxSize,\n useCORS: true,\n logging: false,\n });\n\n return canvas.toDataURL('image/jpeg', 0.7);\n } catch (error) {\n console.debug('[UserFlow] Failed to capture screenshot:', error);\n return undefined;\n }\n}\n\n/**\n * Merge user config with defaults\n */\nexport function mergeConfig(config?: UserFlowConfig): ResolvedUserFlowConfig {\n const defaults: ResolvedUserFlowConfig = {\n enabled: false,\n samplingRate: 1,\n events: {\n clicks: true,\n navigation: true,\n formSubmit: true,\n inputs: false,\n scroll: false,\n ignoreSelectors: [],\n trackOnlySelectors: [],\n },\n element: {\n captureVisualStyles: true, // Lightweight - enabled by default\n captureScreenshot: false, // Expensive - disabled by default\n screenshotMaxSize: 200,\n captureHtml: true,\n maxHtmlLength: 500,\n maxTextLength: 100,\n selectorDepth: 5,\n },\n performance: {\n batchEvents: true,\n batchSize: 10,\n batchTimeout: 5000,\n clickDebounce: 500,\n },\n session: {\n endOnHidden: true,\n inactivityTimeout: 5 * 60 * 1000, // 5 minutes\n endOnExternalNavigation: true,\n autoRestart: true,\n },\n endpoint: '',\n onStart: () => {},\n onStop: () => {},\n onError: () => {},\n };\n\n if (!config) return defaults;\n\n return {\n enabled: config.enabled ?? defaults.enabled,\n samplingRate: config.samplingRate ?? defaults.samplingRate,\n events: { ...defaults.events, ...config.events },\n element: { ...defaults.element, ...config.element },\n performance: { ...defaults.performance, ...config.performance },\n session: { ...defaults.session, ...config.session },\n endpoint: config.endpoint ?? defaults.endpoint,\n onStart: config.onStart ?? defaults.onStart,\n onStop: config.onStop ?? defaults.onStop,\n onError: config.onError ?? defaults.onError,\n };\n}\n\n/**\n * Format duration in human readable format\n */\nexport function formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${Math.round(ms / 1000)}s`;\n return `${Math.round(ms / 60000)}m`;\n}\n","/**\n * User Flow Tracker\n * Core tracking functionality for user interactions\n * \n * This module is completely isolated from the main SDK logic.\n * It can be enabled/disabled without affecting other SDK functionality.\n */\n\nimport type {\n UserFlowConfig,\n UserFlowEvent,\n UserIdentification,\n TrackingState,\n TrackerStats,\n ResolvedUserFlowConfig,\n} from './types';\nimport {\n isBrowser,\n generateSessionId,\n getCurrentUrl,\n getCurrentPath,\n getCurrentTitle,\n getDeviceInfo,\n getElementInfo,\n matchesSelectors,\n captureElementScreenshot,\n captureElementVisualInfo,\n mergeConfig,\n shouldTrackSession,\n} from './utils';\n\n/**\n * UserFlowTracker class\n * Handles all user interaction tracking, isolated from main SDK\n */\nexport class UserFlowTracker {\n private config: ResolvedUserFlowConfig;\n private state: TrackingState = 'idle';\n private sessionId: string | null = null;\n private sdkSessionToken: string | null = null;\n private apiUrl: string = '';\n private sdkKey: string | null = null;\n private user: UserIdentification | null = null;\n\n // Tracking internals\n private events: UserFlowEvent[] = [];\n private eventCount = 0;\n private batchIndex = 0;\n private batchesSent = 0;\n private pageCount = 0;\n private startTime: Date | null = null;\n private batchTimeout: ReturnType<typeof setTimeout> | null = null;\n private inactivityTimeout: ReturnType<typeof setTimeout> | null = null;\n private lastActivityTime: number = Date.now();\n private lastClickTime: number = 0;\n private lastClickElement: Element | null = null;\n private currentPath: string = '';\n private visitedPaths: Set<string> = new Set();\n\n // Event listeners\n private clickHandler: ((e: MouseEvent) => void) | null = null;\n private navigationHandler: (() => void) | null = null;\n private formSubmitHandler: ((e: SubmitEvent) => void) | null = null;\n private beforeUnloadHandler: (() => void) | null = null;\n private visibilityHandler: (() => void) | null = null;\n\n constructor(config?: UserFlowConfig) {\n this.config = mergeConfig(config);\n }\n\n /**\n * Initialize the tracker with SDK context\n */\n initialize(sdkSessionToken: string, apiUrl: string, sdkKey?: string): void {\n this.sdkSessionToken = sdkSessionToken;\n this.apiUrl = apiUrl;\n this.sdkKey = sdkKey || null;\n }\n\n /**\n * Update configuration\n */\n updateConfig(config: Partial<UserFlowConfig>): void {\n this.config = mergeConfig({ ...this.config, ...config });\n }\n\n /**\n * Identify the user\n */\n identify(user: UserIdentification): void {\n this.user = user;\n\n // If already tracking, send identification update to backend\n if (this.state === 'tracking' && this.sessionId) {\n this.sendIdentificationUpdate().catch((err) => {\n console.error('[UserFlow] Failed to send identification update:', err);\n });\n }\n }\n\n // Linked recording session ID (if rrweb is also recording)\n private linkedRecordingSessionId: string | null = null;\n\n /**\n * Start tracking\n * @param linkedRecordingSessionId - Optional linked rrweb session ID for playback\n */\n async start(linkedRecordingSessionId?: string | null): Promise<string | null> {\n if (!isBrowser()) {\n console.warn('[UserFlow] Cannot track outside browser environment');\n return null;\n }\n\n if (!this.config.enabled) {\n return null;\n }\n\n if (this.state === 'tracking') {\n console.warn('[UserFlow] Already tracking');\n return this.sessionId;\n }\n\n // Check sampling rate\n if (!shouldTrackSession(this.config.samplingRate)) {\n console.log('[UserFlow] Session not sampled for tracking');\n return null;\n }\n\n try {\n this.sessionId = generateSessionId();\n this.linkedRecordingSessionId = linkedRecordingSessionId || null;\n this.events = [];\n this.eventCount = 0;\n this.batchIndex = 0;\n this.batchesSent = 0;\n this.pageCount = 1;\n this.startTime = new Date();\n this.currentPath = getCurrentPath();\n this.visitedPaths = new Set([this.currentPath]);\n this.state = 'tracking';\n\n // Setup event listeners\n this.setupEventListeners();\n\n // Send session start to backend\n await this.sendSessionStart();\n\n // Add initial navigation event\n this.addEvent({\n eventType: 'navigation',\n eventOrder: 0,\n timestamp: new Date().toISOString(),\n pageUrl: getCurrentUrl(),\n pageTitle: getCurrentTitle(),\n pagePath: this.currentPath,\n });\n\n this.config.onStart(this.sessionId);\n console.log('[UserFlow] Started tracking session:', this.sessionId);\n\n return this.sessionId;\n } catch (error) {\n console.error('[UserFlow] Failed to start tracking:', error);\n this.state = 'idle';\n this.config.onError(error instanceof Error ? error : new Error(String(error)));\n return null;\n }\n }\n\n /**\n * Stop tracking\n */\n async stop(): Promise<void> {\n if (this.state !== 'tracking' && this.state !== 'paused') {\n return;\n }\n\n try {\n // Remove event listeners\n this.removeEventListeners();\n\n // Clear batch timeout\n if (this.batchTimeout) {\n clearTimeout(this.batchTimeout);\n this.batchTimeout = null;\n }\n\n // Clear inactivity timeout\n if (this.inactivityTimeout) {\n clearTimeout(this.inactivityTimeout);\n this.inactivityTimeout = null;\n }\n\n // Send remaining events\n if (this.events.length > 0) {\n await this.sendEventBatch(true);\n }\n\n // Send session end\n await this.sendSessionEnd();\n\n this.state = 'stopped';\n const eventCount = this.eventCount;\n const sessionId = this.sessionId;\n\n // Reset state\n this.sessionId = null;\n this.events = [];\n this.eventCount = 0;\n this.startTime = null;\n\n this.config.onStop(sessionId!, eventCount);\n console.log('[UserFlow] Stopped tracking session:', sessionId);\n } catch (error) {\n console.error('[UserFlow] Error stopping tracking:', error);\n this.state = 'stopped';\n this.config.onError(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n /**\n * Pause tracking\n */\n pause(): void {\n if (this.state === 'tracking') {\n this.state = 'paused';\n console.log('[UserFlow] Tracking paused');\n }\n }\n\n /**\n * Resume tracking\n */\n resume(): void {\n if (this.state === 'paused') {\n this.state = 'tracking';\n console.log('[UserFlow] Tracking resumed');\n }\n }\n\n /**\n * Get tracker statistics\n */\n getStats(): TrackerStats {\n return {\n sessionId: this.sessionId,\n state: this.state,\n eventCount: this.eventCount,\n pageCount: this.pageCount,\n batchesSent: this.batchesSent,\n duration: this.startTime ? Date.now() - this.startTime.getTime() : 0,\n startTime: this.startTime,\n };\n }\n\n /**\n * Get tracking state\n */\n getState(): TrackingState {\n return this.state;\n }\n\n /**\n * Check if currently tracking\n */\n isTracking(): boolean {\n return this.state === 'tracking';\n }\n\n /**\n * Add a custom event\n */\n addCustomEvent(data: Record<string, any>): void {\n if (this.state !== 'tracking') return;\n\n this.addEvent({\n eventType: 'custom',\n eventOrder: this.eventCount,\n timestamp: new Date().toISOString(),\n pageUrl: getCurrentUrl(),\n pageTitle: getCurrentTitle(),\n pagePath: getCurrentPath(),\n metadata: data,\n });\n }\n\n // === Private methods ===\n\n /**\n * Setup event listeners\n */\n private setupEventListeners(): void {\n if (!isBrowser()) return;\n\n // Click handler\n if (this.config.events.clicks) {\n this.clickHandler = (e: MouseEvent) => this.handleClick(e);\n document.addEventListener('click', this.clickHandler, { capture: true, passive: true });\n }\n\n // Navigation handler (for SPAs)\n if (this.config.events.navigation) {\n this.navigationHandler = () => this.handleNavigation();\n window.addEventListener('popstate', this.navigationHandler);\n \n // Intercept pushState and replaceState\n const originalPushState = history.pushState;\n const originalReplaceState = history.replaceState;\n \n history.pushState = (...args) => {\n originalPushState.apply(history, args);\n this.handleNavigation();\n };\n \n history.replaceState = (...args) => {\n originalReplaceState.apply(history, args);\n this.handleNavigation();\n };\n }\n\n // Form submit handler\n if (this.config.events.formSubmit) {\n this.formSubmitHandler = (e: SubmitEvent) => this.handleFormSubmit(e);\n document.addEventListener('submit', this.formSubmitHandler, { capture: true });\n }\n\n // Before unload - send final batch and end session\n this.beforeUnloadHandler = () => {\n // Send any pending events\n if (this.events.length > 0) {\n this.sendEventBatchSync(true);\n }\n // End the session\n this.sendSessionEndSync();\n };\n window.addEventListener('beforeunload', this.beforeUnloadHandler);\n\n // Visibility change - end session when hidden (configurable)\n this.visibilityHandler = () => {\n if (document.visibilityState === 'hidden') {\n // Send batch when page becomes hidden\n if (this.events.length > 0) {\n this.sendEventBatch(true).catch(console.error);\n }\n \n // End session if configured\n if (this.config.session.endOnHidden) {\n this.stop().catch(console.error);\n }\n } else if (document.visibilityState === 'visible') {\n // Auto-restart if configured and was tracking\n if (this.config.session.autoRestart && this.state === 'stopped') {\n this.start().catch(console.error);\n }\n }\n };\n document.addEventListener('visibilitychange', this.visibilityHandler);\n\n // Start inactivity timeout\n this.resetInactivityTimeout();\n }\n\n /**\n * Remove event listeners\n */\n private removeEventListeners(): void {\n if (!isBrowser()) return;\n\n if (this.clickHandler) {\n document.removeEventListener('click', this.clickHandler, { capture: true } as any);\n this.clickHandler = null;\n }\n\n if (this.navigationHandler) {\n window.removeEventListener('popstate', this.navigationHandler);\n this.navigationHandler = null;\n }\n\n if (this.formSubmitHandler) {\n document.removeEventListener('submit', this.formSubmitHandler, { capture: true } as any);\n this.formSubmitHandler = null;\n }\n\n if (this.beforeUnloadHandler) {\n window.removeEventListener('beforeunload', this.beforeUnloadHandler);\n this.beforeUnloadHandler = null;\n }\n\n if (this.visibilityHandler) {\n document.removeEventListener('visibilitychange', this.visibilityHandler);\n this.visibilityHandler = null;\n }\n }\n\n /**\n * Handle click event\n */\n private async handleClick(e: MouseEvent): Promise<void> {\n if (this.state !== 'tracking') return;\n\n const target = e.target as Element;\n if (!target || !(target instanceof Element)) return;\n\n // Check ignore selectors\n if (\n this.config.events.ignoreSelectors &&\n this.config.events.ignoreSelectors.length > 0 &&\n matchesSelectors(target, this.config.events.ignoreSelectors)\n ) {\n return;\n }\n\n // Check track-only selectors\n if (\n this.config.events.trackOnlySelectors &&\n this.config.events.trackOnlySelectors.length > 0 &&\n !matchesSelectors(target, this.config.events.trackOnlySelectors)\n ) {\n return;\n }\n\n // Debounce same-element clicks\n const now = Date.now();\n if (\n this.lastClickElement === target &&\n now - this.lastClickTime < this.config.performance.clickDebounce\n ) {\n return;\n }\n this.lastClickTime = now;\n this.lastClickElement = target;\n\n // Get element info\n const elementInfo = getElementInfo(target, this.config.element);\n\n // Capture lightweight visual styles (fast - ~1ms)\n if (this.config.element.captureVisualStyles) {\n elementInfo.visualStyles = captureElementVisualInfo(target);\n }\n\n // Optionally capture full screenshot (slow - ~100-500ms, use sparingly)\n if (this.config.element.captureScreenshot) {\n try {\n elementInfo.screenshot = await captureElementScreenshot(\n target,\n this.config.element.screenshotMaxSize,\n );\n } catch {\n // Ignore screenshot errors\n }\n }\n\n // Create event\n const event: UserFlowEvent = {\n eventType: 'click',\n eventOrder: this.eventCount,\n timestamp: new Date().toISOString(),\n pageUrl: getCurrentUrl(),\n pageTitle: getCurrentTitle(),\n pagePath: getCurrentPath(),\n element: elementInfo,\n clickX: Math.round(e.pageX),\n clickY: Math.round(e.pageY),\n viewportX: Math.round(e.clientX),\n viewportY: Math.round(e.clientY),\n };\n\n this.addEvent(event);\n }\n\n /**\n * Handle navigation event\n */\n private handleNavigation(): void {\n if (this.state !== 'tracking') return;\n\n const newPath = getCurrentPath();\n if (newPath === this.currentPath) return;\n\n this.currentPath = newPath;\n \n if (!this.visitedPaths.has(newPath)) {\n this.visitedPaths.add(newPath);\n this.pageCount++;\n }\n\n const event: UserFlowEvent = {\n eventType: 'navigation',\n eventOrder: this.eventCount,\n timestamp: new Date().toISOString(),\n pageUrl: getCurrentUrl(),\n pageTitle: getCurrentTitle(),\n pagePath: newPath,\n };\n\n this.addEvent(event);\n }\n\n /**\n * Handle form submit event\n */\n private handleFormSubmit(e: SubmitEvent): void {\n if (this.state !== 'tracking') return;\n\n const form = e.target as HTMLFormElement;\n if (!form || !(form instanceof HTMLFormElement)) return;\n\n // Check ignore selectors\n if (\n this.config.events.ignoreSelectors &&\n matchesSelectors(form, this.config.events.ignoreSelectors)\n ) {\n return;\n }\n\n const elementInfo = getElementInfo(form, this.config.element);\n\n const event: UserFlowEvent = {\n eventType: 'form_submit',\n eventOrder: this.eventCount,\n timestamp: new Date().toISOString(),\n pageUrl: getCurrentUrl(),\n pageTitle: getCurrentTitle(),\n pagePath: getCurrentPath(),\n element: elementInfo,\n metadata: {\n action: form.action,\n method: form.method,\n name: form.name,\n },\n };\n\n this.addEvent(event);\n }\n\n /**\n * Add event to queue\n */\n private addEvent(event: UserFlowEvent): void {\n this.events.push(event);\n this.eventCount++;\n\n // Reset inactivity timeout on each event\n this.resetInactivityTimeout();\n\n // Check if we should send batch\n if (\n this.config.performance.batchEvents &&\n this.events.length >= this.config.performance.batchSize\n ) {\n this.sendEventBatch(false).catch(console.error);\n } else if (!this.batchTimeout) {\n // Set timeout for batch send\n this.batchTimeout = setTimeout(() => {\n this.batchTimeout = null;\n if (this.events.length > 0) {\n this.sendEventBatch(false).catch(console.error);\n }\n }, this.config.performance.batchTimeout);\n }\n }\n\n /**\n * Send session start to backend\n */\n private async sendSessionStart(): Promise<void> {\n const endpoint = this.config.endpoint || `${this.apiUrl}/user-flows/session/start`;\n const device = getDeviceInfo();\n\n const body = {\n sessionId: this.sessionId,\n sdkSessionToken: this.sdkSessionToken,\n startUrl: getCurrentUrl(),\n startTime: this.startTime?.toISOString(),\n user: this.user,\n device,\n // Link to rrweb recording session if available\n linkedRecordingSessionId: this.linkedRecordingSessionId,\n };\n\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(this.sdkKey ? { 'X-SDK-Key': this.sdkKey } : {}),\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to start session: ${response.status}`);\n }\n }\n\n /**\n * Send event batch to backend\n */\n private async sendEventBatch(isFinal: boolean): Promise<void> {\n if (this.events.length === 0) return;\n\n const eventsToSend = [...this.events];\n this.events = [];\n\n const endpoint = this.config.endpoint\n ? `${this.config.endpoint}/events`\n : `${this.apiUrl}/user-flows/session/events`;\n\n const body = {\n sessionId: this.sessionId,\n events: eventsToSend,\n batchIndex: this.batchIndex++,\n timestamp: new Date().toISOString(),\n isFinal,\n };\n\n try {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(this.sdkKey ? { 'X-SDK-Key': this.sdkKey } : {}),\n },\n body: JSON.stringify(body),\n });\n\n if (response.ok) {\n this.batchesSent++;\n }\n } catch (error) {\n console.error('[UserFlow] Failed to send event batch:', error);\n // Re-add events to queue on failure\n this.events = [...eventsToSend, ...this.events];\n }\n }\n\n /**\n * Send event batch synchronously (for beforeunload)\n */\n private sendEventBatchSync(isFinal: boolean): void {\n if (this.events.length === 0) return;\n\n const endpoint = this.config.endpoint\n ? `${this.config.endpoint}/events`\n : `${this.apiUrl}/user-flows/session/events`;\n\n const body = {\n sessionId: this.sessionId,\n events: this.events,\n batchIndex: this.batchIndex++,\n timestamp: new Date().toISOString(),\n isFinal,\n };\n\n // Use sendBeacon for reliability on page unload\n if (navigator.sendBeacon) {\n const blob = new Blob([JSON.stringify(body)], { type: 'application/json' });\n navigator.sendBeacon(endpoint, blob);\n this.events = [];\n }\n }\n\n /**\n * Send session end to backend\n */\n private async sendSessionEnd(): Promise<void> {\n const endpoint = this.config.endpoint\n ? `${this.config.endpoint}/end`\n : `${this.apiUrl}/user-flows/session/end`;\n\n const body = {\n sessionId: this.sessionId,\n endTime: new Date().toISOString(),\n eventCount: this.eventCount,\n status: 'completed',\n };\n\n try {\n await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(this.sdkKey ? { 'X-SDK-Key': this.sdkKey } : {}),\n },\n body: JSON.stringify(body),\n });\n } catch (error) {\n console.error('[UserFlow] Failed to send session end:', error);\n }\n }\n\n /**\n * Send session end synchronously (for beforeunload)\n */\n private sendSessionEndSync(): void {\n const endpoint = this.config.endpoint\n ? `${this.config.endpoint}/end`\n : `${this.apiUrl}/user-flows/session/end`;\n\n const body = {\n sessionId: this.sessionId,\n endTime: new Date().toISOString(),\n eventCount: this.eventCount,\n status: 'completed',\n };\n\n // Use sendBeacon for reliability on page unload\n if (navigator.sendBeacon) {\n const blob = new Blob([JSON.stringify(body)], { type: 'application/json' });\n navigator.sendBeacon(endpoint, blob);\n }\n }\n\n /**\n * Reset inactivity timeout\n * Called on each user interaction\n */\n private resetInactivityTimeout(): void {\n // Clear existing timeout\n if (this.inactivityTimeout) {\n clearTimeout(this.inactivityTimeout);\n this.inactivityTimeout = null;\n }\n\n // Update last activity time\n this.lastActivityTime = Date.now();\n\n // Set new timeout if configured\n const timeout = this.config.session.inactivityTimeout;\n if (timeout && timeout > 0) {\n this.inactivityTimeout = setTimeout(() => {\n if (this.state === 'tracking') {\n console.log('[UserFlow] Session ended due to inactivity');\n this.stop().catch(console.error);\n }\n }, timeout);\n }\n }\n\n /**\n * Send identification update to backend\n */\n private async sendIdentificationUpdate(): Promise<void> {\n if (!this.sessionId || !this.user) return;\n\n const endpoint = this.config.endpoint\n ? `${this.config.endpoint}/identify`\n : `${this.apiUrl}/user-flows/session/identify`;\n\n const body = {\n sessionId: this.sessionId,\n user: this.user,\n };\n\n await fetch(endpoint, {\n method: 'PATCH',\n headers: {\n 'Content-Type': 'application/json',\n ...(this.sdkKey ? { 'X-SDK-Key': this.sdkKey } : {}),\n },\n body: JSON.stringify(body),\n });\n }\n}\n\n/**\n * Factory function to create a user flow tracker\n */\nexport function createUserFlowTracker(config?: UserFlowConfig): UserFlowTracker {\n return new UserFlowTracker(config);\n}\n","// Import recording types (optional feature)\nimport type { RecordingConfig, RecordingStats, CustomRecordingEvent } from './recording';\nimport { SessionRecorder } from './recording';\n\n// Import proactive behavior tracking (optional feature)\nimport type { ProactiveConfig, ProactiveContext } from './proactive';\nimport { ProactiveBehaviorTracker, defaultProactiveConfig } from './proactive';\n\n// Import user flow tracking (optional feature)\nimport type { UserFlowConfig, UserIdentification, TrackerStats as UserFlowStats } from './user-flows';\nimport { UserFlowTracker } from './user-flows';\n\n// Types\nexport interface ProduckConfig {\n guiderId?: string; // Legacy support\n sdkKey?: string; // New SDK key approach\n apiUrl?: string;\n onAction?: (actionKey: string, action: ActionPayload) => void;\n onMessage?: (message: ChatMessage) => void;\n onError?: (error: Error) => void;\n onFlowStart?: (flow: FlowPayload) => void;\n onFlowStepComplete?: (step: FlowStepResult, flow: FlowPayload) => void;\n onFlowComplete?: (result: FlowResult) => void;\n \n /** Session recording configuration (optional) */\n recording?: RecordingConfig;\n \n /** Proactive chat configuration (optional) */\n proactive?: ProactiveConfig;\n \n /** User flow tracking configuration (optional) */\n userFlows?: UserFlowConfig;\n \n /** Callback for proactive chat triggers */\n onProactiveMessage?: (message: string, context: ProactiveContext) => void;\n \n /** Auto-start conversation with initial message (for landing pages) */\n initialMessage?: string;\n \n /** Stream the initial message character by character */\n streamInitialMessage?: boolean;\n}\n\nexport interface ActionPayload {\n actionKey: string;\n name: string;\n actionType: string;\n actionConfig: Record<string, any>;\n responseMessage?: string;\n}\n\n// Flow types\nexport interface FlowStep {\n operationId: string;\n order: number;\n condition?: Record<string, any>;\n inputMapping?: Record<string, any>;\n}\n\nexport interface FlowPayload {\n flowId: string;\n name: string;\n description: string;\n steps: FlowStep[];\n}\n\nexport interface FlowStepResult {\n operationId: string;\n order: number;\n success: boolean;\n data?: any;\n error?: string;\n}\n\nexport interface FlowResult {\n flowId: string;\n name: string;\n steps: FlowStepResult[];\n completed: boolean;\n totalSteps: number;\n successfulSteps: number;\n}\n\nexport interface ChatMessage {\n role: 'user' | 'assistant';\n content: string;\n action?: ActionPayload;\n flow?: FlowPayload;\n flowResult?: FlowResult;\n visualFlows?: VisualFlowReference[];\n images?: ImageReference[];\n}\n\n// Visual Flow types for chat display\nexport interface VisualFlowReference {\n flowId: string;\n name: string;\n description: string;\n score: number;\n stepsCount?: number;\n tags?: string[];\n}\n\nexport interface ImageReference {\n url: string;\n name: string;\n description: string;\n score: number;\n}\n\nexport interface VisualFlowStep {\n id: string;\n stepOrder: number;\n title: string;\n description: string;\n screenshotUrl: string | null;\n elementSelector: string | null;\n pageUrl: string;\n}\n\nexport interface VisualFlowDetails {\n id: string;\n flowId: string;\n name: string;\n description: string;\n tags: string[];\n steps: VisualFlowStep[];\n}\n\nexport interface ActionHandler {\n (payload: ActionPayload): void | Promise<void>;\n}\n\nexport interface RegisteredAction {\n key: string;\n handler: ActionHandler;\n}\n\nexport type ProduckEventType = 'action' | 'message' | 'error' | 'ready' | 'flowStart' | 'flowStepComplete' | 'flowComplete' | 'proactive';\n\nexport interface ProduckEvent {\n type: ProduckEventType;\n data: any;\n}\n\n// Core SDK Class\nexport class ProduckSDK {\n private config: ProduckConfig;\n private actions: Map<string, ActionHandler> = new Map();\n private eventListeners: Map<ProduckEventType, Set<Function>> = new Map();\n private sessionToken: string | null = null;\n private isReady: boolean = false;\n \n /** Session recorder instance (optional, isolated module) */\n private recorder: SessionRecorder | null = null;\n \n /** Proactive behavior tracker instance (optional, isolated module) */\n private proactiveTracker: ProactiveBehaviorTracker | null = null;\n \n /** User flow tracker instance (optional, isolated module) */\n private userFlowTracker: UserFlowTracker | null = null;\n\n constructor(config: ProduckConfig) {\n // Determine API URL - use custom if provided, otherwise use smart defaults\n let apiUrl = config.apiUrl;\n \n if (!apiUrl) {\n // Check if we're in a browser environment and running on localhost\n if (typeof window !== 'undefined') {\n apiUrl = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1'\n ? 'http://localhost:4001/api/v1'\n : `${window.location.protocol}//${window.location.host}/api/v1`;\n } else {\n // Server-side default\n apiUrl = 'http://localhost:4001/api/v1';\n }\n }\n \n this.config = {\n apiUrl,\n ...config,\n };\n }\n\n /**\n * Initialize the SDK and create a chat session\n */\n async init(): Promise<void> {\n await this.log('info', 'SDK Initializing', {\n apiUrl: this.config.apiUrl,\n hasSDKKey: !!this.config.sdkKey,\n hasGuiderId: !!this.config.guiderId,\n });\n \n try {\n let endpoint: string;\n \n if (this.config.sdkKey) {\n // New SDK key approach\n endpoint = `${this.config.apiUrl}/sdk/session`;\n await this.log('info', 'Using SDK key authentication');\n } else if (this.config.guiderId) {\n // Legacy guider approach\n endpoint = `${this.config.apiUrl}/chat/${this.config.guiderId}/session`;\n await this.log('info', 'Using guider ID authentication');\n } else {\n throw new Error('Either sdkKey or guiderId must be provided');\n }\n\n await this.log('info', 'Creating session', { endpoint });\n\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.config.sdkKey) {\n headers['X-SDK-Key'] = this.config.sdkKey;\n }\n\n const response = await fetch(endpoint, {\n method: 'POST',\n headers,\n });\n\n if (!response.ok) {\n await this.log('error', 'Failed to create session', { status: response.status });\n throw new Error(`Failed to create session: ${response.status}`);\n }\n\n const session = await response.json();\n this.sessionToken = session.session_token;\n this.isReady = true;\n \n await this.log('info', 'SDK initialized successfully', { hasSessionToken: !!this.sessionToken });\n \n // Initialize session recording if enabled (isolated module)\n if (this.config.recording?.enabled) {\n await this.initRecording();\n }\n \n // Initialize proactive behavior tracking if enabled\n if (this.config.proactive?.enabled) {\n this.initProactive();\n }\n \n // Initialize user flow tracking if enabled\n if (this.config.userFlows?.enabled) {\n await this.initUserFlowTracking();\n }\n \n this.emit('ready', { sessionToken: this.sessionToken });\n \n // Send initial message if configured (for landing pages)\n if (this.config.initialMessage) {\n await this.sendInitialMessage();\n }\n } catch (error) {\n await this.log('error', 'SDK initialization failed', { error: error instanceof Error ? error.message : String(error) });\n this.emit('error', error);\n throw error;\n }\n }\n\n /**\n * Register an action handler\n */\n register(actionKey: string, handler: ActionHandler): void {\n this.actions.set(actionKey, handler);\n this.log('info', 'Action handler registered', { actionKey, totalActions: this.actions.size });\n }\n\n /**\n * Unregister an action handler\n */\n unregister(actionKey: string): void {\n this.actions.delete(actionKey);\n this.log('info', 'Action handler unregistered', { actionKey, remainingActions: this.actions.size });\n }\n\n /**\n * Send a message and handle potential action or flow triggers\n */\n async sendMessage(message: string): Promise<ChatMessage> {\n if (!this.isReady || !this.sessionToken) {\n throw new Error('SDK not initialized. Call init() first.');\n }\n\n const startTime = Date.now();\n await this.log('info', 'sendMessage called', { message });\n\n try {\n // First, check if message matches any SDK action or flow\n let intentEndpoint: string;\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n \n if (this.config.sdkKey) {\n intentEndpoint = `${this.config.apiUrl}/sdk/match-intent`;\n headers['X-SDK-Key'] = this.config.sdkKey;\n } else {\n intentEndpoint = `${this.config.apiUrl}/sdk/public/${this.config.guiderId}/match-intent`;\n }\n\n const intentResponse = await fetch(intentEndpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify({ userMessage: message }),\n });\n\n await this.log('info', 'Match-intent response received', { status: intentResponse.status });\n\n if (intentResponse.ok) {\n const intentResult = await intentResponse.json();\n \n // Handle FLOW match\n if (intentResult.matched && intentResult.type === 'flow' && intentResult.flow) {\n await this.log('info', 'Flow matched', {\n flowId: intentResult.flow.flowId,\n name: intentResult.flow.name,\n stepCount: intentResult.flow.steps?.length,\n });\n \n // Send log to backend\n await this.sendLogToBackend({\n userMessage: message,\n matched: true,\n actionKey: `flow:${intentResult.flow.flowId}`,\n responseMessage: intentResult.responseMessage,\n executionTimeMs: Date.now() - startTime,\n });\n \n // Execute the flow\n const flowResult = await this.executeFlow(intentResult.flow);\n \n const flowMessage: ChatMessage = {\n role: 'assistant',\n content: intentResult.responseMessage || `I've completed the \"${intentResult.flow.name}\" flow for you.`,\n flow: intentResult.flow,\n flowResult,\n };\n \n this.emit('message', flowMessage);\n return flowMessage;\n }\n \n // Handle OPERATION match (existing behavior)\n if (intentResult.matched && (intentResult.type === 'operation' || intentResult.action)) {\n const action = intentResult.action;\n await this.log('info', 'Action matched', {\n actionKey: action.actionKey,\n actionType: action.actionType,\n responseMessage: action.responseMessage,\n });\n \n // Send log to backend\n await this.sendLogToBackend({\n userMessage: message,\n matched: true,\n actionKey: action.actionKey,\n responseMessage: action.responseMessage,\n executionTimeMs: Date.now() - startTime,\n });\n \n // Execute the action\n await this.executeAction(action);\n \n const actionMessage: ChatMessage = {\n role: 'assistant',\n content: action.responseMessage || `I've triggered the \"${action.name}\" action for you.`,\n action: action,\n };\n \n this.emit('message', actionMessage);\n return actionMessage;\n } else {\n \n // Send log for no match\n await this.sendLogToBackend({\n userMessage: message,\n matched: false,\n executionTimeMs: Date.now() - startTime,\n });\n }\n }\n\n // No action matched, send to regular chat\n const sessionResponse = await fetch(\n `${this.config.apiUrl}/chat/sessions/${this.sessionToken}/message`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ message }),\n }\n );\n\n if (!sessionResponse.ok) {\n throw new Error(`Failed to send message: ${sessionResponse.status}`);\n }\n\n const result = await sessionResponse.json();\n const chatMessage: ChatMessage = {\n role: 'assistant',\n content: result.message?.content || result.response || '',\n visualFlows: result.flows || [],\n images: result.images || [],\n };\n\n await this.log('info', 'Chat response received', {\n hasFlows: (result.flows || []).length > 0,\n hasImages: (result.images || []).length > 0,\n });\n this.emit('message', chatMessage);\n return chatMessage;\n } catch (error) {\n await this.log('error', 'Error in sendMessage', { error: error instanceof Error ? error.message : String(error) });\n this.emit('error', error);\n throw error;\n }\n }\n\n /**\n * Execute a flow by running each step's operation sequentially\n */\n async executeFlow(flow: FlowPayload): Promise<FlowResult> {\n await this.log('info', 'executeFlow started', {\n flowId: flow.flowId,\n name: flow.name,\n stepCount: flow.steps.length,\n });\n\n // Emit flow start event\n this.emit('flowStart', flow);\n if (this.config.onFlowStart) {\n this.config.onFlowStart(flow);\n }\n\n const stepResults: FlowStepResult[] = [];\n let context: Record<string, any> = {};\n\n // Sort steps by order\n const sortedSteps = [...flow.steps].sort((a, b) => a.order - b.order);\n\n for (const step of sortedSteps) {\n await this.log('info', 'Executing flow step', {\n flowId: flow.flowId,\n operationId: step.operationId,\n order: step.order,\n });\n\n const stepResult: FlowStepResult = {\n operationId: step.operationId,\n order: step.order,\n success: false,\n };\n\n try {\n // Get the handler for this operation\n const handler = this.actions.get(step.operationId);\n \n if (handler) {\n // Create action payload for the step\n const actionPayload: ActionPayload = {\n actionKey: step.operationId,\n name: step.operationId,\n actionType: 'callback',\n actionConfig: {\n flowContext: context,\n inputMapping: step.inputMapping,\n },\n };\n\n // Execute the handler\n const result = await handler(actionPayload);\n \n stepResult.success = true;\n stepResult.data = result;\n \n // Update context with result for next step\n context = {\n ...context,\n [`step_${step.order}`]: result,\n previousResult: result,\n };\n\n await this.log('info', 'Flow step completed successfully', {\n flowId: flow.flowId,\n operationId: step.operationId,\n order: step.order,\n });\n } else {\n // No handler registered - log warning but continue\n await this.log('warn', 'No handler registered for flow step', {\n flowId: flow.flowId,\n operationId: step.operationId,\n });\n stepResult.success = true; // Consider it \"success\" if no handler needed\n stepResult.data = { skipped: true, reason: 'No handler registered' };\n }\n } catch (error) {\n stepResult.success = false;\n stepResult.error = error instanceof Error ? error.message : String(error);\n \n await this.log('error', 'Flow step failed', {\n flowId: flow.flowId,\n operationId: step.operationId,\n error: stepResult.error,\n });\n }\n\n stepResults.push(stepResult);\n\n // Emit step complete event\n this.emit('flowStepComplete', { step: stepResult, flow });\n if (this.config.onFlowStepComplete) {\n this.config.onFlowStepComplete(stepResult, flow);\n }\n }\n\n const flowResult: FlowResult = {\n flowId: flow.flowId,\n name: flow.name,\n steps: stepResults,\n completed: true,\n totalSteps: flow.steps.length,\n successfulSteps: stepResults.filter(s => s.success).length,\n };\n\n await this.log('info', 'Flow execution completed', {\n flowId: flow.flowId,\n totalSteps: flowResult.totalSteps,\n successfulSteps: flowResult.successfulSteps,\n });\n\n // Emit flow complete event\n this.emit('flowComplete', flowResult);\n if (this.config.onFlowComplete) {\n this.config.onFlowComplete(flowResult);\n }\n\n return flowResult;\n }\n\n /**\n * Send log data to backend for analytics\n */\n private async sendLogToBackend(logData: {\n userMessage: string;\n matched: boolean;\n actionKey?: string;\n responseMessage?: string;\n executionTimeMs?: number;\n error?: string;\n }): Promise<void> {\n try {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.config.sdkKey) {\n headers['X-SDK-Key'] = this.config.sdkKey;\n }\n\n const logEndpoint = `${this.config.apiUrl}/sdk-logs/client`;\n \n await fetch(logEndpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n ...logData,\n timestamp: new Date().toISOString(),\n sessionToken: this.sessionToken,\n }),\n });\n } catch (error) {\n // Silently fail - don't block operations due to logging failures\n }\n }\n\n /**\n * Send detailed log to backend\n */\n private async log(level: 'info' | 'warn' | 'error', message: string, data?: any): Promise<void> {\n try {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.config.sdkKey) {\n headers['X-SDK-Key'] = this.config.sdkKey;\n }\n\n const logEndpoint = `${this.config.apiUrl}/sdk-logs/client`;\n \n await fetch(logEndpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n level,\n message,\n data,\n timestamp: new Date().toISOString(),\n sessionToken: this.sessionToken,\n }),\n });\n } catch (error) {\n // Silently fail\n }\n }\n\n /**\n * Execute a registered action\n */\n private async executeAction(action: ActionPayload): Promise<void> {\n const registeredKeys = Array.from(this.actions.keys());\n \n // Very visible debug - will show popup in browser\n if (typeof window !== 'undefined') {\n console.log('%c🎯 SDK executeAction', 'background: #ff0; color: #000; font-size: 20px; padding: 10px;', {\n actionKey: action.actionKey,\n totalRegistered: this.actions.size,\n registeredKeys,\n });\n }\n \n await this.log('info', 'executeAction called', {\n actionKey: action.actionKey,\n actionType: typeof action.actionKey,\n totalRegistered: this.actions.size,\n registeredKeys,\n keyComparisons: registeredKeys.map(key => ({\n key,\n matches: key === action.actionKey,\n keyLength: key.length,\n actionKeyLength: action.actionKey.length,\n })),\n });\n \n const handler = this.actions.get(action.actionKey);\n \n if (typeof window !== 'undefined') {\n console.log('%c🔍 SDK Handler Lookup', 'background: #0ff; color: #000; font-size: 16px; padding: 5px;', {\n actionKey: action.actionKey,\n found: !!handler,\n hasConfigOnAction: !!this.config.onAction,\n registeredKeys: Array.from(this.actions.keys()),\n });\n }\n \n if (handler) {\n try {\n const startTime = Date.now();\n await handler(action);\n const executionTime = Date.now() - startTime;\n \n await this.log('info', 'Handler executed successfully', {\n actionKey: action.actionKey,\n executionTime,\n });\n \n await this.sendLogToBackend({\n userMessage: `Action executed: ${action.actionKey}`,\n matched: true,\n actionKey: action.actionKey,\n responseMessage: action.responseMessage || `Executed ${action.name}`,\n executionTimeMs: executionTime,\n });\n \n this.emit('action', action);\n this.config.onAction?.(action.actionKey, action);\n } catch (error) {\n await this.log('error', 'Handler execution failed', {\n actionKey: action.actionKey,\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n \n await this.sendLogToBackend({\n userMessage: `Action execution failed: ${action.actionKey}`,\n matched: true,\n actionKey: action.actionKey,\n error: error instanceof Error ? error.message : String(error),\n });\n \n this.emit('error', error);\n }\n } else {\n // No handler in SDK's internal registry, but try the config callback\n // (ProduckProvider registers handlers there via actionsRef)\n if (this.config.onAction) {\n await this.log('info', 'No internal handler, trying config.onAction callback', {\n actionKey: action.actionKey,\n });\n \n try {\n this.config.onAction(action.actionKey, action);\n this.emit('action', action);\n \n await this.log('info', 'Action dispatched via config.onAction', {\n actionKey: action.actionKey,\n });\n \n await this.sendLogToBackend({\n userMessage: `Action dispatched: ${action.actionKey}`,\n matched: true,\n actionKey: action.actionKey,\n responseMessage: action.responseMessage || `Dispatched ${action.name}`,\n });\n return;\n } catch (error) {\n await this.log('error', 'config.onAction callback failed', {\n actionKey: action.actionKey,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n \n await this.log('warn', 'No handler registered for action', {\n actionKey: action.actionKey,\n registeredActions: Array.from(this.actions.keys()),\n });\n \n await this.sendLogToBackend({\n userMessage: `No handler for action: ${action.actionKey}`,\n matched: false,\n actionKey: action.actionKey,\n error: `Handler not registered. Available: ${Array.from(this.actions.keys()).join(', ')}`,\n });\n }\n }\n\n /**\n * Add event listener\n */\n on(event: ProduckEventType, callback: Function): void {\n if (!this.eventListeners.has(event)) {\n this.eventListeners.set(event, new Set());\n }\n this.eventListeners.get(event)!.add(callback);\n }\n\n /**\n * Remove event listener\n */\n off(event: ProduckEventType, callback: Function): void {\n this.eventListeners.get(event)?.delete(callback);\n }\n\n /**\n * Emit event\n */\n private emit(event: ProduckEventType, data: any): void {\n this.eventListeners.get(event)?.forEach(callback => callback(data));\n }\n\n /**\n * Get session token\n */\n getSessionToken(): string | null {\n return this.sessionToken;\n }\n\n /**\n * Check if SDK is ready\n */\n getIsReady(): boolean {\n return this.isReady;\n }\n\n /**\n * Get registered action keys\n */\n getRegisteredActions(): string[] {\n return Array.from(this.actions.keys());\n }\n\n /**\n * Get guider ID for the current session\n */\n getGuiderId(): string | undefined {\n return this.config.guiderId;\n }\n\n /**\n * Fetch full visual flow details by flow ID\n */\n async getVisualFlow(flowId: string): Promise<VisualFlowDetails | null> {\n const guiderId = this.config.guiderId;\n if (!guiderId) {\n await this.log('warn', 'Cannot fetch visual flow without guiderId');\n return null;\n }\n\n try {\n const response = await fetch(\n `${this.config.apiUrl}/visual-flows/chat/${guiderId}/${flowId}`\n );\n\n if (!response.ok) {\n await this.log('warn', 'Visual flow not found', { flowId, status: response.status });\n return null;\n }\n\n const result = await response.json();\n if (!result.found || !result.flow) {\n return null;\n }\n\n return result.flow as VisualFlowDetails;\n } catch (error) {\n await this.log('error', 'Error fetching visual flow', { flowId, error });\n return null;\n }\n }\n\n // ============================================================\n // Session Recording Methods (Isolated Module)\n // These methods delegate to the SessionRecorder when enabled\n // ============================================================\n\n /**\n * Initialize session recording (internal)\n */\n private async initRecording(): Promise<void> {\n try {\n this.recorder = new SessionRecorder(this.config.recording);\n this.recorder.initialize(\n this.sessionToken!,\n this.config.apiUrl!,\n this.config.sdkKey\n );\n \n const sessionId = await this.recorder.start();\n if (sessionId) {\n await this.log('info', 'Session recording started', { recordingSessionId: sessionId });\n }\n } catch (error) {\n await this.log('warn', 'Failed to initialize session recording', { \n error: error instanceof Error ? error.message : String(error) \n });\n // Don't throw - recording is optional, shouldn't break main SDK\n }\n }\n\n /**\n * Start session recording manually (if not auto-started)\n */\n async startRecording(): Promise<string | null> {\n if (!this.isReady) {\n console.warn('[SDK] Cannot start recording before SDK is initialized');\n return null;\n }\n\n if (!this.recorder) {\n this.recorder = new SessionRecorder(this.config.recording);\n this.recorder.initialize(\n this.sessionToken!,\n this.config.apiUrl!,\n this.config.sdkKey\n );\n }\n\n return this.recorder.start();\n }\n\n /**\n * Stop session recording\n */\n async stopRecording(): Promise<void> {\n if (this.recorder) {\n await this.recorder.stop();\n }\n }\n\n /**\n * Pause session recording\n */\n pauseRecording(): void {\n this.recorder?.pause();\n }\n\n /**\n * Resume session recording\n */\n resumeRecording(): void {\n this.recorder?.resume();\n }\n\n /**\n * Add a custom event to the recording\n */\n addRecordingEvent(event: CustomRecordingEvent): void {\n this.recorder?.addCustomEvent(event);\n }\n\n /**\n * Get recording statistics\n */\n getRecordingStats(): RecordingStats | null {\n return this.recorder?.getStats() ?? null;\n }\n\n /**\n * Check if session recording is active\n */\n isRecordingActive(): boolean {\n return this.recorder?.isRecording() ?? false;\n }\n\n /**\n * Get recording session ID\n */\n getRecordingSessionId(): string | null {\n return this.recorder?.getSessionId() ?? null;\n }\n\n // ============================================================\n // Proactive Chat Methods (Isolated Module)\n // These methods manage proactive behavior tracking and messaging\n // ============================================================\n\n /**\n * Initialize proactive behavior tracking (internal)\n */\n private initProactive(): void {\n if (!this.config.proactive) return;\n\n this.proactiveTracker = new ProactiveBehaviorTracker(\n this.config.proactive,\n {\n onTrigger: async (context, suggestedMessage) => {\n // Emit proactive event\n this.emit('proactive', { context, message: suggestedMessage });\n \n // Call callback if provided\n if (this.config.onProactiveMessage) {\n this.config.onProactiveMessage(suggestedMessage, context);\n }\n \n // Send to backend for AI-generated contextual message\n try {\n await this.getProactiveAIMessage(context, suggestedMessage);\n } catch (error) {\n await this.log('warn', 'Failed to get AI proactive message', { error });\n }\n },\n }\n );\n\n this.proactiveTracker.start();\n this.log('info', 'Proactive behavior tracking initialized');\n }\n\n /**\n * Get AI-generated proactive message based on context\n */\n private async getProactiveAIMessage(context: ProactiveContext, fallbackMessage: string): Promise<string> {\n try {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.config.sdkKey) {\n headers['X-SDK-Key'] = this.config.sdkKey;\n }\n\n const response = await fetch(`${this.config.apiUrl}/sdk/proactive-message`, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n context,\n fallbackMessage,\n sessionToken: this.sessionToken,\n }),\n });\n\n if (!response.ok) {\n return fallbackMessage;\n }\n\n const result = await response.json();\n const message = result.message || fallbackMessage;\n \n // Emit the AI-generated message\n const chatMessage: ChatMessage = {\n role: 'assistant',\n content: message,\n };\n this.emit('message', chatMessage);\n \n return message;\n } catch (error) {\n return fallbackMessage;\n }\n }\n\n /**\n * Send initial message for landing page intros\n */\n private async sendInitialMessage(): Promise<void> {\n const message = this.config.initialMessage;\n if (!message) return;\n\n if (this.config.streamInitialMessage) {\n // Stream the message character by character\n await this.streamMessage(message);\n } else {\n // Send the full message immediately\n const chatMessage: ChatMessage = {\n role: 'assistant',\n content: message,\n };\n this.emit('message', chatMessage);\n if (this.config.onMessage) {\n this.config.onMessage(chatMessage);\n }\n }\n }\n\n /**\n * Stream a message character by character for typewriter effect\n */\n async streamMessage(message: string, delayMs: number = 30): Promise<void> {\n let currentContent = '';\n \n for (let i = 0; i < message.length; i++) {\n currentContent += message[i];\n \n const chatMessage: ChatMessage = {\n role: 'assistant',\n content: currentContent,\n };\n \n // Emit partial message\n this.emit('message', chatMessage);\n \n // Wait before next character\n await new Promise(resolve => setTimeout(resolve, delayMs));\n }\n }\n\n /**\n * Start proactive tracking manually\n */\n startProactiveTracking(): void {\n if (this.proactiveTracker) {\n this.proactiveTracker.start();\n }\n }\n\n /**\n * Stop proactive tracking\n */\n stopProactiveTracking(): void {\n if (this.proactiveTracker) {\n this.proactiveTracker.stop();\n }\n }\n\n /**\n * Get proactive tracking stats\n */\n getProactiveStats(): ReturnType<ProactiveBehaviorTracker['getStats']> | null {\n return this.proactiveTracker?.getStats() ?? null;\n }\n\n /**\n * Manually trigger a proactive message\n */\n triggerProactiveMessage(message: string, context?: Partial<ProactiveContext>): void {\n if (this.proactiveTracker) {\n this.proactiveTracker.triggerManual(message, context);\n } else {\n // Even without tracker, emit the message\n const chatMessage: ChatMessage = {\n role: 'assistant',\n content: message,\n };\n this.emit('message', chatMessage);\n if (this.config.onMessage) {\n this.config.onMessage(chatMessage);\n }\n }\n }\n\n /**\n * Opt out of proactive messages (respects user preference)\n */\n optOutProactive(): void {\n this.proactiveTracker?.optOut();\n }\n\n /**\n * Opt in to proactive messages\n */\n optInProactive(): void {\n this.proactiveTracker?.optIn();\n }\n\n // ============================================================\n // User Flow Tracking Methods (Isolated Module)\n // These methods manage user interaction tracking and flow analysis\n // ============================================================\n\n /**\n * Initialize user flow tracking (internal)\n */\n private async initUserFlowTracking(): Promise<void> {\n try {\n this.userFlowTracker = new UserFlowTracker(this.config.userFlows);\n this.userFlowTracker.initialize(\n this.sessionToken!,\n this.config.apiUrl!,\n this.config.sdkKey\n );\n \n // Link with recording session if both are enabled\n const recordingSessionId = this.recorder?.getSessionId?.() || null;\n \n const sessionId = await this.userFlowTracker.start(recordingSessionId);\n if (sessionId) {\n await this.log('info', 'User flow tracking started', { \n flowSessionId: sessionId,\n linkedRecordingSession: recordingSessionId \n });\n }\n } catch (error) {\n await this.log('warn', 'Failed to initialize user flow tracking', { \n error: error instanceof Error ? error.message : String(error) \n });\n // Don't throw - tracking is optional, shouldn't break main SDK\n }\n }\n\n /**\n * Identify the user for flow tracking and segmentation\n * Call this when you know who the user is (e.g., after login)\n */\n identify(user: UserIdentification): void {\n if (this.userFlowTracker) {\n this.userFlowTracker.identify(user);\n }\n \n this.log('info', 'User identified', { \n hasEmail: !!user.email,\n hasName: !!user.name,\n hasTags: !!user.tags && Object.keys(user.tags).length > 0,\n });\n }\n\n /**\n * Start user flow tracking manually (if not auto-started)\n */\n async startUserFlowTracking(): Promise<string | null> {\n if (!this.isReady) {\n console.warn('[SDK] Cannot start flow tracking before SDK is initialized');\n return null;\n }\n\n if (!this.userFlowTracker) {\n this.userFlowTracker = new UserFlowTracker(this.config.userFlows);\n this.userFlowTracker.initialize(\n this.sessionToken!,\n this.config.apiUrl!,\n this.config.sdkKey\n );\n }\n\n return this.userFlowTracker.start();\n }\n\n /**\n * Stop user flow tracking\n */\n async stopUserFlowTracking(): Promise<void> {\n if (this.userFlowTracker) {\n await this.userFlowTracker.stop();\n }\n }\n\n /**\n * Pause user flow tracking\n */\n pauseUserFlowTracking(): void {\n this.userFlowTracker?.pause();\n }\n\n /**\n * Resume user flow tracking\n */\n resumeUserFlowTracking(): void {\n this.userFlowTracker?.resume();\n }\n\n /**\n * Add a custom event to the user flow\n */\n trackEvent(eventData: Record<string, any>): void {\n this.userFlowTracker?.addCustomEvent(eventData);\n }\n\n /**\n * Get user flow tracking statistics\n */\n getUserFlowStats(): UserFlowStats | null {\n return this.userFlowTracker?.getStats() ?? null;\n }\n\n /**\n * Check if user flow tracking is active\n */\n isUserFlowTrackingActive(): boolean {\n return this.userFlowTracker?.isTracking() ?? false;\n }\n\n /**\n * Destroy the SDK instance\n */\n destroy(): void {\n // Stop recording if active\n if (this.recorder) {\n this.recorder.destroy();\n this.recorder = null;\n }\n \n // Stop proactive tracking if active\n if (this.proactiveTracker) {\n this.proactiveTracker.stop();\n this.proactiveTracker = null;\n }\n \n // Stop user flow tracking if active\n if (this.userFlowTracker) {\n this.userFlowTracker.stop();\n this.userFlowTracker = null;\n }\n \n this.actions.clear();\n this.eventListeners.clear();\n this.sessionToken = null;\n this.isReady = false;\n }\n}\n\n// Factory function\nexport function createProduck(config: ProduckConfig): ProduckSDK {\n return new ProduckSDK(config);\n}\n\n// Default export\nexport default ProduckSDK;\n"],"mappings":"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","names":["isBrowser","generateSessionId","getCurrentUrl","getDeviceInfo","canvas","mergeConfig","mergeConfig","isBrowser","generateSessionId","getCurrentUrl","getDeviceInfo"]}
|
|
1
|
+
{"version":3,"sources":["../src/recording/utils.ts","../src/recording/recorder.ts","../src/proactive.ts","../src/user-flows/utils.ts","../src/user-flows/tracker.ts","../src/core.ts"],"sourcesContent":["/**\n * Session Recording Utilities\n * Helper functions for session recording\n */\n\nimport type { DeviceInfo, RecordingConfig, RecordingPrivacyConfig, RecordingPerformanceConfig, RecordingCaptureConfig } from './types';\n\n/**\n * Generate a unique session ID\n */\nexport function generateSessionId(): string {\n const timestamp = Date.now().toString(36);\n const randomPart = Math.random().toString(36).substring(2, 15);\n return `rec_${timestamp}_${randomPart}`;\n}\n\n/**\n * Get device/browser information\n */\nexport function getDeviceInfo(): DeviceInfo {\n if (typeof window === 'undefined') {\n return {\n userAgent: 'unknown',\n screenWidth: 0,\n screenHeight: 0,\n viewportWidth: 0,\n viewportHeight: 0,\n devicePixelRatio: 1,\n language: 'en',\n platform: 'unknown',\n };\n }\n\n return {\n userAgent: navigator.userAgent,\n screenWidth: screen.width,\n screenHeight: screen.height,\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n devicePixelRatio: window.devicePixelRatio || 1,\n language: navigator.language,\n platform: navigator.platform,\n };\n}\n\n/**\n * Default privacy configuration\n */\nexport const DEFAULT_PRIVACY_CONFIG: Required<RecordingPrivacyConfig> = {\n maskAllInputs: true,\n maskAllText: false,\n maskSelectors: ['.sensitive', '[data-sensitive]', '.pii', '[data-pii]'],\n blockSelectors: ['.no-record', '[data-no-record]'],\n maskInputTypes: ['password', 'email', 'tel', 'credit-card'],\n maskCharacter: '*',\n};\n\n/**\n * Default performance configuration\n */\nexport const DEFAULT_PERFORMANCE_CONFIG: Required<RecordingPerformanceConfig> = {\n batchEvents: true,\n batchSize: 50,\n batchTimeout: 5000,\n compress: true,\n mouseMoveThrottle: 50,\n maxDuration: 30 * 60 * 1000, // 30 minutes\n};\n\n/**\n * Default capture configuration\n */\nexport const DEFAULT_CAPTURE_CONFIG: Required<RecordingCaptureConfig> = {\n console: true,\n network: false,\n performance: false,\n errors: true,\n customEvents: true,\n};\n\n/**\n * Merge user config with defaults\n * Note: Recording is ENABLED by default for production use\n */\nexport function mergeConfig(userConfig?: RecordingConfig): Required<RecordingConfig> {\n return {\n enabled: userConfig?.enabled ?? true, // Enabled by default!\n samplingRate: userConfig?.samplingRate ?? 1.0,\n privacy: { ...DEFAULT_PRIVACY_CONFIG, ...userConfig?.privacy },\n performance: { ...DEFAULT_PERFORMANCE_CONFIG, ...userConfig?.performance },\n capture: { ...DEFAULT_CAPTURE_CONFIG, ...userConfig?.capture },\n endpoint: userConfig?.endpoint ?? '',\n onStart: userConfig?.onStart ?? (() => {}),\n onStop: userConfig?.onStop ?? (() => {}),\n onError: userConfig?.onError ?? (() => {}),\n };\n}\n\n/**\n * Check if session should be recorded based on sampling rate\n */\nexport function shouldRecordSession(samplingRate: number): boolean {\n if (samplingRate >= 1) return true;\n if (samplingRate <= 0) return false;\n return Math.random() < samplingRate;\n}\n\n/**\n * Simple LZ-string compression for events\n * Uses a basic run-length encoding approach for demo\n * In production, you'd use the full lz-string library\n */\nexport function compressEvents(events: any[]): string {\n try {\n const json = JSON.stringify(events);\n // Use base64 encoding - in production, use proper compression\n if (typeof btoa !== 'undefined') {\n return btoa(encodeURIComponent(json));\n }\n return json;\n } catch (error) {\n console.warn('[Recording] Failed to compress events:', error);\n return JSON.stringify(events);\n }\n}\n\n/**\n * Decompress events\n */\nexport function decompressEvents(compressed: string): any[] {\n try {\n if (typeof atob !== 'undefined' && !compressed.startsWith('[')) {\n const json = decodeURIComponent(atob(compressed));\n return JSON.parse(json);\n }\n return JSON.parse(compressed);\n } catch (error) {\n console.warn('[Recording] Failed to decompress events:', error);\n return [];\n }\n}\n\n/**\n * Throttle function for mouse movements\n */\nexport function throttle<T extends (...args: any[]) => any>(\n func: T,\n limit: number\n): (...args: Parameters<T>) => void {\n let inThrottle = false;\n return function (this: any, ...args: Parameters<T>) {\n if (!inThrottle) {\n func.apply(this, args);\n inThrottle = true;\n setTimeout(() => (inThrottle = false), limit);\n }\n };\n}\n\n/**\n * Debounce function for batching\n */\nexport function debounce<T extends (...args: any[]) => any>(\n func: T,\n wait: number\n): (...args: Parameters<T>) => void {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n return function (this: any, ...args: Parameters<T>) {\n if (timeout) clearTimeout(timeout);\n timeout = setTimeout(() => func.apply(this, args), wait);\n };\n}\n\n/**\n * Format duration in human readable format\n */\nexport function formatDuration(ms: number): string {\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n\n if (hours > 0) {\n return `${hours}h ${minutes % 60}m ${seconds % 60}s`;\n }\n if (minutes > 0) {\n return `${minutes}m ${seconds % 60}s`;\n }\n return `${seconds}s`;\n}\n\n/**\n * Safe JSON stringify that handles circular references\n */\nexport function safeStringify(obj: any, maxDepth = 5): string {\n const seen = new WeakSet();\n return JSON.stringify(obj, (key, value) => {\n if (maxDepth <= 0) return '[Max Depth]';\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) return '[Circular]';\n seen.add(value);\n }\n return value;\n });\n}\n\n/**\n * Check if we're in a browser environment\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Get current page URL\n */\nexport function getCurrentUrl(): string {\n if (!isBrowser()) return '';\n return window.location.href;\n}\n","/**\n * Session Recorder\n * Core recording functionality using rrweb\n * \n * This module is completely isolated from the main SDK logic.\n * It can be enabled/disabled without affecting other SDK functionality.\n */\n\nimport type { recordOptions } from 'rrweb';\nimport type {\n RecordingConfig,\n RecordingEvent,\n RecordingEventBatch,\n RecordingSession,\n RecordingState,\n RecordingStats,\n CustomRecordingEvent,\n ConsoleLogEvent,\n ErrorEvent,\n} from './types';\nimport {\n generateSessionId,\n getDeviceInfo,\n mergeConfig,\n shouldRecordSession,\n compressEvents,\n isBrowser,\n getCurrentUrl,\n} from './utils';\n\n/**\n * SessionRecorder class\n * Handles all recording logic, isolated from main SDK\n */\nexport class SessionRecorder {\n private config: Required<RecordingConfig>;\n private state: RecordingState = 'idle';\n private sessionId: string | null = null;\n private sdkSessionToken: string | null = null;\n private apiUrl: string = '';\n private sdkKey: string | null = null;\n\n // Recording internals\n private stopRecording: (() => void) | null = null;\n private events: RecordingEvent[] = [];\n private eventCount = 0;\n private batchIndex = 0;\n private batchesSent = 0;\n private errorCount = 0;\n private startTime: Date | null = null;\n private batchTimeout: ReturnType<typeof setTimeout> | null = null;\n private maxDurationTimeout: ReturnType<typeof setTimeout> | null = null;\n\n // Cleanup handlers\n private consoleCleanup: (() => void) | null = null;\n private errorCleanup: (() => void) | null = null;\n\n constructor(config?: RecordingConfig) {\n this.config = mergeConfig(config);\n }\n\n /**\n * Initialize the recorder with SDK context\n */\n initialize(sdkSessionToken: string, apiUrl: string, sdkKey?: string): void {\n this.sdkSessionToken = sdkSessionToken;\n this.apiUrl = apiUrl;\n this.sdkKey = sdkKey || null;\n }\n\n /**\n * Update configuration\n */\n updateConfig(config: Partial<RecordingConfig>): void {\n this.config = mergeConfig({ ...this.config, ...config });\n }\n\n /**\n * Start recording session\n */\n async start(): Promise<string | null> {\n if (!isBrowser()) {\n console.warn('[Recording] Cannot record outside browser environment');\n return null;\n }\n\n if (!this.config.enabled) {\n return null;\n }\n\n if (this.state === 'recording') {\n console.warn('[Recording] Already recording');\n return this.sessionId;\n }\n\n // Check sampling rate\n if (!shouldRecordSession(this.config.samplingRate)) {\n console.log('[Recording] Session not sampled for recording');\n return null;\n }\n\n try {\n // Dynamically import rrweb to keep it optional\n const rrweb = await import('rrweb');\n\n this.sessionId = generateSessionId();\n this.events = [];\n this.eventCount = 0;\n this.batchIndex = 0;\n this.batchesSent = 0;\n this.errorCount = 0;\n this.startTime = new Date();\n this.state = 'recording';\n\n // Build rrweb options\n const rrwebOptions: recordOptions<RecordingEvent> = {\n emit: (event) => this.handleEvent(event),\n maskAllInputs: this.config.privacy.maskAllInputs,\n maskTextSelector: this.config.privacy.maskSelectors?.join(',') || undefined,\n blockSelector: this.config.privacy.blockSelectors?.join(',') || undefined,\n maskInputOptions: {\n password: true,\n email: this.config.privacy.maskInputTypes?.includes('email'),\n tel: this.config.privacy.maskInputTypes?.includes('tel'),\n },\n sampling: {\n mousemove: true,\n mouseInteraction: true,\n scroll: 150,\n media: 800,\n input: 'last',\n },\n };\n\n // Start rrweb recording\n this.stopRecording = rrweb.record(rrwebOptions);\n\n // Setup additional captures\n if (this.config.capture.console) {\n this.setupConsoleCapture();\n }\n if (this.config.capture.errors) {\n this.setupErrorCapture();\n }\n\n // Setup max duration timeout\n if (this.config.performance.maxDuration) {\n this.maxDurationTimeout = setTimeout(() => {\n console.log('[Recording] Max duration reached, stopping');\n this.stop();\n }, this.config.performance.maxDuration);\n }\n\n // Send session start to backend\n await this.sendSessionStart();\n\n this.config.onStart(this.sessionId);\n console.log('[Recording] Started session:', this.sessionId);\n\n return this.sessionId;\n } catch (error) {\n console.error('[Recording] Failed to start:', error);\n this.state = 'idle';\n this.config.onError(error instanceof Error ? error : new Error(String(error)));\n return null;\n }\n }\n\n /**\n * Stop recording\n */\n async stop(): Promise<void> {\n if (this.state !== 'recording' && this.state !== 'paused') {\n return;\n }\n\n try {\n // Stop rrweb\n if (this.stopRecording) {\n this.stopRecording();\n this.stopRecording = null;\n }\n\n // Cleanup captures\n if (this.consoleCleanup) {\n this.consoleCleanup();\n this.consoleCleanup = null;\n }\n if (this.errorCleanup) {\n this.errorCleanup();\n this.errorCleanup = null;\n }\n\n // Clear timeouts\n if (this.batchTimeout) {\n clearTimeout(this.batchTimeout);\n this.batchTimeout = null;\n }\n if (this.maxDurationTimeout) {\n clearTimeout(this.maxDurationTimeout);\n this.maxDurationTimeout = null;\n }\n\n // Send remaining events\n if (this.events.length > 0) {\n await this.sendBatch(true);\n }\n\n // Send session end\n await this.sendSessionEnd();\n\n const sessionId = this.sessionId;\n const eventCount = this.eventCount;\n\n this.state = 'stopped';\n this.config.onStop(sessionId || '', eventCount);\n console.log('[Recording] Stopped session:', sessionId, 'Events:', eventCount);\n } catch (error) {\n console.error('[Recording] Error stopping:', error);\n this.config.onError(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n /**\n * Pause recording\n */\n pause(): void {\n if (this.state !== 'recording') return;\n this.state = 'paused';\n // rrweb doesn't have built-in pause, we just stop emitting\n console.log('[Recording] Paused');\n }\n\n /**\n * Resume recording\n */\n resume(): void {\n if (this.state !== 'paused') return;\n this.state = 'recording';\n console.log('[Recording] Resumed');\n }\n\n /**\n * Add a custom event to the recording\n */\n addCustomEvent(event: CustomRecordingEvent): void {\n if (this.state !== 'recording' || !this.config.capture.customEvents) return;\n\n const customEvent: RecordingEvent = {\n type: 5, // rrweb custom event type\n data: {\n tag: 'custom',\n payload: event,\n },\n timestamp: event.timestamp || Date.now(),\n };\n\n this.handleEvent(customEvent);\n }\n\n /**\n * Get current recording stats\n */\n getStats(): RecordingStats {\n const duration = this.startTime\n ? Date.now() - this.startTime.getTime()\n : 0;\n\n return {\n state: this.state,\n sessionId: this.sessionId,\n eventCount: this.eventCount,\n startTime: this.startTime,\n duration,\n batchesSent: this.batchesSent,\n errors: this.errorCount,\n };\n }\n\n /**\n * Check if recording is active\n */\n isRecording(): boolean {\n return this.state === 'recording';\n }\n\n /**\n * Get session ID\n */\n getSessionId(): string | null {\n return this.sessionId;\n }\n\n // ============ Private Methods ============\n\n /**\n * Handle incoming event from rrweb\n */\n private handleEvent(event: RecordingEvent): void {\n if (this.state !== 'recording') return;\n\n this.events.push(event);\n this.eventCount++;\n\n // Check if we should send batch\n if (this.config.performance.batchEvents) {\n if (this.events.length >= this.config.performance.batchSize) {\n this.sendBatch();\n } else if (!this.batchTimeout) {\n this.batchTimeout = setTimeout(() => {\n this.batchTimeout = null;\n if (this.events.length > 0) {\n this.sendBatch();\n }\n }, this.config.performance.batchTimeout);\n }\n } else {\n // Send immediately\n this.sendBatch();\n }\n }\n\n /**\n * Send event batch to backend\n */\n private async sendBatch(isFinal = false): Promise<void> {\n if (this.events.length === 0) return;\n\n const eventsToSend = [...this.events];\n this.events = [];\n\n const batch: RecordingEventBatch = {\n sessionId: this.sessionId!,\n sdkSessionToken: this.sdkSessionToken!,\n events: eventsToSend,\n timestamp: new Date().toISOString(),\n batchIndex: this.batchIndex++,\n isFinal,\n };\n\n try {\n const endpoint = this.config.endpoint || `${this.apiUrl}/session-recordings/events`;\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.sdkKey) {\n headers['X-SDK-Key'] = this.sdkKey;\n }\n\n const body = this.config.performance.compress\n ? JSON.stringify({ ...batch, events: undefined, compressedEvents: compressEvents(eventsToSend) })\n : JSON.stringify(batch);\n\n await fetch(endpoint, {\n method: 'POST',\n headers,\n body,\n });\n\n this.batchesSent++;\n } catch (error) {\n console.error('[Recording] Failed to send batch:', error);\n this.errorCount++;\n // Put events back for retry\n this.events = [...eventsToSend, ...this.events];\n }\n }\n\n /**\n * Send session start notification\n */\n private async sendSessionStart(): Promise<void> {\n const session: Omit<RecordingSession, 'endTime' | 'eventCount'> = {\n id: this.sessionId!,\n sdkSessionToken: this.sdkSessionToken!,\n startUrl: getCurrentUrl(),\n startTime: this.startTime!,\n deviceInfo: getDeviceInfo(),\n };\n\n try {\n const endpoint = `${this.apiUrl}/session-recordings/start`;\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.sdkKey) {\n headers['X-SDK-Key'] = this.sdkKey;\n }\n\n await fetch(endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify(session),\n });\n } catch (error) {\n console.error('[Recording] Failed to send session start:', error);\n }\n }\n\n /**\n * Send session end notification\n */\n private async sendSessionEnd(): Promise<void> {\n try {\n const endpoint = `${this.apiUrl}/session-recordings/end`;\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.sdkKey) {\n headers['X-SDK-Key'] = this.sdkKey;\n }\n\n await fetch(endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n sessionId: this.sessionId,\n endTime: new Date().toISOString(),\n eventCount: this.eventCount,\n }),\n });\n } catch (error) {\n console.error('[Recording] Failed to send session end:', error);\n }\n }\n\n /**\n * Setup console log capture\n */\n private setupConsoleCapture(): void {\n const originalConsole = {\n log: console.log,\n info: console.info,\n warn: console.warn,\n error: console.error,\n debug: console.debug,\n };\n\n const captureConsole = (level: ConsoleLogEvent['level']) => {\n return (...args: any[]) => {\n // Call original\n originalConsole[level](...args);\n\n // Skip our own logs\n if (args[0]?.toString().includes('[Recording]')) return;\n\n // Add to recording\n const logEvent: ConsoleLogEvent = {\n level,\n message: args.map(arg => \n typeof arg === 'object' ? JSON.stringify(arg) : String(arg)\n ).join(' '),\n timestamp: Date.now(),\n };\n\n this.addCustomEvent({\n type: 'console',\n data: logEvent,\n });\n };\n };\n\n console.log = captureConsole('log');\n console.info = captureConsole('info');\n console.warn = captureConsole('warn');\n console.error = captureConsole('error');\n console.debug = captureConsole('debug');\n\n this.consoleCleanup = () => {\n console.log = originalConsole.log;\n console.info = originalConsole.info;\n console.warn = originalConsole.warn;\n console.error = originalConsole.error;\n console.debug = originalConsole.debug;\n };\n }\n\n /**\n * Setup error capture\n */\n private setupErrorCapture(): void {\n const errorHandler = (event: ErrorEvent) => {\n const errorEvent: ErrorEvent = {\n type: 'error',\n message: event.message,\n filename: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n timestamp: Date.now(),\n };\n\n this.addCustomEvent({\n type: 'error',\n data: errorEvent,\n });\n };\n\n const rejectionHandler = (event: PromiseRejectionEvent) => {\n const errorEvent: ErrorEvent = {\n type: 'unhandledrejection',\n message: event.reason?.message || String(event.reason),\n stack: event.reason?.stack,\n timestamp: Date.now(),\n };\n\n this.addCustomEvent({\n type: 'error',\n data: errorEvent,\n });\n };\n\n window.addEventListener('error', errorHandler as any);\n window.addEventListener('unhandledrejection', rejectionHandler);\n\n this.errorCleanup = () => {\n window.removeEventListener('error', errorHandler as any);\n window.removeEventListener('unhandledrejection', rejectionHandler);\n };\n }\n\n /**\n * Destroy the recorder\n */\n destroy(): void {\n this.stop();\n this.sessionId = null;\n this.sdkSessionToken = null;\n this.events = [];\n }\n}\n\n/**\n * Create a new SessionRecorder instance\n */\nexport function createSessionRecorder(config?: RecordingConfig): SessionRecorder {\n return new SessionRecorder(config);\n}\n\nexport default SessionRecorder;\n","/**\n * Proactive Chat Features\n * \n * Tracks user behavior and triggers contextual chat messages based on:\n * - Scroll Depth: Triggers when user scrolls past threshold\n * - Time on Page: Triggers after specified time\n * - Click Count: Triggers after X clicks\n * - Idle Time: Triggers when user is inactive\n * - Exit Intent: Triggers when mouse leaves viewport (abandonment)\n * - Page Changes: Triggers on SPA route changes\n */\n\nexport interface ProactiveTrigger {\n type: 'scroll' | 'time' | 'clicks' | 'idle' | 'exit' | 'pageChange';\n enabled: boolean;\n threshold?: number; // scroll %, time in ms, click count, idle time in ms\n message?: string; // Custom message override\n cooldown?: number; // Cooldown between triggers in ms\n onlyOnce?: boolean; // Only trigger once per session\n}\n\nexport interface ProactiveConfig {\n enabled: boolean;\n triggers: ProactiveTrigger[];\n maxProactiveMessages?: number; // Max proactive messages per session\n globalCooldown?: number; // Global cooldown between any proactive message\n respectUserPreference?: boolean; // Check localStorage for user opt-out\n}\n\nexport interface ProactiveContext {\n triggerType: ProactiveTrigger['type'];\n scrollDepth?: number;\n timeOnPage?: number;\n clickCount?: number;\n idleTime?: number;\n currentUrl?: string;\n previousUrl?: string;\n pageTitle?: string;\n}\n\nexport interface ProactiveCallbacks {\n onTrigger: (context: ProactiveContext, suggestedMessage: string) => void;\n onMessage?: (message: string) => void;\n}\n\nexport class ProactiveBehaviorTracker {\n private config: ProactiveConfig;\n private callbacks: ProactiveCallbacks;\n private isTracking: boolean = false;\n \n // Tracking state\n private scrollDepth: number = 0;\n private pageLoadTime: number = 0;\n private clickCount: number = 0;\n private lastActivityTime: number = 0;\n private currentUrl: string = '';\n private previousUrl: string = '';\n \n // Trigger state\n private triggeredSet: Set<string> = new Set();\n private lastTriggerTime: number = 0;\n private proactiveMessageCount: number = 0;\n \n // Listeners\n private scrollHandler: (() => void) | null = null;\n private clickHandler: (() => void) | null = null;\n private mouseMoveHandler: (() => void) | null = null;\n private mouseLeaveHandler: ((e: MouseEvent) => void) | null = null;\n private visibilityHandler: (() => void) | null = null;\n \n // Timers\n private timeCheckInterval: ReturnType<typeof setInterval> | null = null;\n private idleCheckInterval: ReturnType<typeof setInterval> | null = null;\n\n constructor(config: ProactiveConfig, callbacks: ProactiveCallbacks) {\n this.config = config;\n this.callbacks = callbacks;\n }\n\n /**\n * Start tracking user behavior\n */\n start(): void {\n if (!this.config.enabled || this.isTracking) return;\n if (typeof window === 'undefined') return;\n\n // Check user preference\n if (this.config.respectUserPreference) {\n const optOut = localStorage.getItem('produck_proactive_optout');\n if (optOut === 'true') return;\n }\n\n this.isTracking = true;\n this.pageLoadTime = Date.now();\n this.lastActivityTime = Date.now();\n this.currentUrl = window.location.href;\n\n this.setupScrollTracking();\n this.setupClickTracking();\n this.setupIdleTracking();\n this.setupExitIntentTracking();\n this.setupTimeTracking();\n this.setupPageChangeTracking();\n\n console.log('[Produck] Proactive behavior tracking started');\n }\n\n /**\n * Stop tracking\n */\n stop(): void {\n if (!this.isTracking) return;\n this.isTracking = false;\n\n // Remove event listeners\n if (this.scrollHandler) {\n window.removeEventListener('scroll', this.scrollHandler);\n }\n if (this.clickHandler) {\n document.removeEventListener('click', this.clickHandler);\n }\n if (this.mouseMoveHandler) {\n document.removeEventListener('mousemove', this.mouseMoveHandler);\n }\n if (this.mouseLeaveHandler) {\n document.removeEventListener('mouseleave', this.mouseLeaveHandler);\n }\n if (this.visibilityHandler) {\n document.removeEventListener('visibilitychange', this.visibilityHandler);\n }\n\n // Clear intervals\n if (this.timeCheckInterval) {\n clearInterval(this.timeCheckInterval);\n }\n if (this.idleCheckInterval) {\n clearInterval(this.idleCheckInterval);\n }\n\n console.log('[Produck] Proactive behavior tracking stopped');\n }\n\n /**\n * Reset tracking state (e.g., on page change)\n */\n reset(): void {\n this.scrollDepth = 0;\n this.clickCount = 0;\n this.pageLoadTime = Date.now();\n this.lastActivityTime = Date.now();\n // Note: triggeredSet is NOT reset to respect onlyOnce across navigation\n }\n\n /**\n * Get current tracking stats\n */\n getStats(): {\n scrollDepth: number;\n timeOnPage: number;\n clickCount: number;\n idleTime: number;\n proactiveMessageCount: number;\n } {\n return {\n scrollDepth: this.scrollDepth,\n timeOnPage: Date.now() - this.pageLoadTime,\n clickCount: this.clickCount,\n idleTime: Date.now() - this.lastActivityTime,\n proactiveMessageCount: this.proactiveMessageCount,\n };\n }\n\n /**\n * Check if a trigger should fire\n */\n private shouldTrigger(trigger: ProactiveTrigger): boolean {\n // Check if max messages reached\n if (this.config.maxProactiveMessages && \n this.proactiveMessageCount >= this.config.maxProactiveMessages) {\n return false;\n }\n\n // Check global cooldown\n if (this.config.globalCooldown && \n Date.now() - this.lastTriggerTime < this.config.globalCooldown) {\n return false;\n }\n\n // Check if already triggered (for onlyOnce triggers)\n const triggerKey = `${trigger.type}-${trigger.threshold || 'default'}`;\n if (trigger.onlyOnce && this.triggeredSet.has(triggerKey)) {\n return false;\n }\n\n // Check trigger-specific cooldown\n const lastTriggerKey = `${triggerKey}-lastTime`;\n const lastTime = parseInt(sessionStorage.getItem(lastTriggerKey) || '0', 10);\n if (trigger.cooldown && Date.now() - lastTime < trigger.cooldown) {\n return false;\n }\n\n return true;\n }\n\n /**\n * Fire a trigger\n */\n private fireTrigger(trigger: ProactiveTrigger, context: ProactiveContext): void {\n if (!this.shouldTrigger(trigger)) return;\n\n const triggerKey = `${trigger.type}-${trigger.threshold || 'default'}`;\n const lastTriggerKey = `${triggerKey}-lastTime`;\n\n // Mark as triggered\n this.triggeredSet.add(triggerKey);\n this.lastTriggerTime = Date.now();\n this.proactiveMessageCount++;\n sessionStorage.setItem(lastTriggerKey, Date.now().toString());\n\n // Generate contextual message\n const message = trigger.message || this.getDefaultMessage(trigger.type, context);\n\n // Call callbacks\n this.callbacks.onTrigger(context, message);\n if (this.callbacks.onMessage) {\n this.callbacks.onMessage(message);\n }\n\n console.log('[Produck] Proactive trigger fired:', trigger.type, context);\n }\n\n /**\n * Get default message for trigger type\n */\n private getDefaultMessage(type: ProactiveTrigger['type'], context: ProactiveContext): string {\n switch (type) {\n case 'scroll':\n return `I see you're exploring the page! Is there something specific you're looking for?`;\n case 'time':\n return `You've been here a while. Would you like some help finding what you need?`;\n case 'clicks':\n return `Looks like you're navigating around. Can I help you find something?`;\n case 'idle':\n return `Still there? Let me know if you have any questions!`;\n case 'exit':\n return `Wait! Before you go, is there anything I can help you with?`;\n case 'pageChange':\n return `I see you're exploring different pages. Need any guidance?`;\n default:\n return `How can I help you today?`;\n }\n }\n\n /**\n * Setup scroll depth tracking\n */\n private setupScrollTracking(): void {\n const scrollTriggers = this.config.triggers.filter(t => t.type === 'scroll' && t.enabled);\n if (scrollTriggers.length === 0) return;\n\n this.scrollHandler = () => {\n const docHeight = document.documentElement.scrollHeight - window.innerHeight;\n const scrollPercent = docHeight > 0 ? (window.scrollY / docHeight) * 100 : 0;\n this.scrollDepth = Math.max(this.scrollDepth, scrollPercent);\n this.lastActivityTime = Date.now();\n\n scrollTriggers.forEach(trigger => {\n if (trigger.threshold && this.scrollDepth >= trigger.threshold) {\n this.fireTrigger(trigger, {\n triggerType: 'scroll',\n scrollDepth: this.scrollDepth,\n currentUrl: window.location.href,\n pageTitle: document.title,\n });\n }\n });\n };\n\n window.addEventListener('scroll', this.scrollHandler, { passive: true });\n }\n\n /**\n * Setup click tracking\n */\n private setupClickTracking(): void {\n const clickTriggers = this.config.triggers.filter(t => t.type === 'clicks' && t.enabled);\n if (clickTriggers.length === 0) return;\n\n this.clickHandler = () => {\n this.clickCount++;\n this.lastActivityTime = Date.now();\n\n clickTriggers.forEach(trigger => {\n if (trigger.threshold && this.clickCount >= trigger.threshold) {\n this.fireTrigger(trigger, {\n triggerType: 'clicks',\n clickCount: this.clickCount,\n currentUrl: window.location.href,\n pageTitle: document.title,\n });\n }\n });\n };\n\n document.addEventListener('click', this.clickHandler);\n }\n\n /**\n * Setup idle tracking\n */\n private setupIdleTracking(): void {\n const idleTriggers = this.config.triggers.filter(t => t.type === 'idle' && t.enabled);\n if (idleTriggers.length === 0) return;\n\n // Track activity\n this.mouseMoveHandler = () => {\n this.lastActivityTime = Date.now();\n };\n document.addEventListener('mousemove', this.mouseMoveHandler, { passive: true });\n\n // Check idle time periodically\n this.idleCheckInterval = setInterval(() => {\n const idleTime = Date.now() - this.lastActivityTime;\n\n idleTriggers.forEach(trigger => {\n if (trigger.threshold && idleTime >= trigger.threshold) {\n this.fireTrigger(trigger, {\n triggerType: 'idle',\n idleTime,\n currentUrl: window.location.href,\n pageTitle: document.title,\n });\n }\n });\n }, 1000);\n }\n\n /**\n * Setup exit intent tracking\n */\n private setupExitIntentTracking(): void {\n const exitTriggers = this.config.triggers.filter(t => t.type === 'exit' && t.enabled);\n if (exitTriggers.length === 0) return;\n\n this.mouseLeaveHandler = (e: MouseEvent) => {\n // Only trigger if mouse leaves from top of viewport\n if (e.clientY <= 0) {\n exitTriggers.forEach(trigger => {\n this.fireTrigger(trigger, {\n triggerType: 'exit',\n currentUrl: window.location.href,\n pageTitle: document.title,\n });\n });\n }\n };\n\n document.addEventListener('mouseleave', this.mouseLeaveHandler);\n }\n\n /**\n * Setup time on page tracking\n */\n private setupTimeTracking(): void {\n const timeTriggers = this.config.triggers.filter(t => t.type === 'time' && t.enabled);\n if (timeTriggers.length === 0) return;\n\n this.timeCheckInterval = setInterval(() => {\n const timeOnPage = Date.now() - this.pageLoadTime;\n\n timeTriggers.forEach(trigger => {\n if (trigger.threshold && timeOnPage >= trigger.threshold) {\n this.fireTrigger(trigger, {\n triggerType: 'time',\n timeOnPage,\n currentUrl: window.location.href,\n pageTitle: document.title,\n });\n }\n });\n }, 1000);\n }\n\n /**\n * Setup SPA page change tracking\n */\n private setupPageChangeTracking(): void {\n const pageTriggers = this.config.triggers.filter(t => t.type === 'pageChange' && t.enabled);\n if (pageTriggers.length === 0) return;\n\n // Use visibility change and popstate for SPA detection\n this.visibilityHandler = () => {\n if (document.visibilityState === 'visible') {\n const newUrl = window.location.href;\n if (newUrl !== this.currentUrl) {\n this.previousUrl = this.currentUrl;\n this.currentUrl = newUrl;\n\n // Reset page-specific counters\n this.scrollDepth = 0;\n this.clickCount = 0;\n this.pageLoadTime = Date.now();\n\n pageTriggers.forEach(trigger => {\n this.fireTrigger(trigger, {\n triggerType: 'pageChange',\n currentUrl: this.currentUrl,\n previousUrl: this.previousUrl,\n pageTitle: document.title,\n });\n });\n }\n }\n };\n\n document.addEventListener('visibilitychange', this.visibilityHandler);\n\n // Also handle popstate for back/forward navigation\n window.addEventListener('popstate', () => {\n const newUrl = window.location.href;\n if (newUrl !== this.currentUrl) {\n this.previousUrl = this.currentUrl;\n this.currentUrl = newUrl;\n\n pageTriggers.forEach(trigger => {\n this.fireTrigger(trigger, {\n triggerType: 'pageChange',\n currentUrl: this.currentUrl,\n previousUrl: this.previousUrl,\n pageTitle: document.title,\n });\n });\n }\n });\n }\n\n /**\n * Manually trigger a proactive message (for custom integrations)\n */\n triggerManual(message: string, context?: Partial<ProactiveContext>): void {\n this.proactiveMessageCount++;\n this.lastTriggerTime = Date.now();\n\n const fullContext: ProactiveContext = {\n triggerType: 'time', // default\n currentUrl: window.location.href,\n pageTitle: document.title,\n ...context,\n };\n\n this.callbacks.onTrigger(fullContext, message);\n if (this.callbacks.onMessage) {\n this.callbacks.onMessage(message);\n }\n }\n\n /**\n * Opt out of proactive messages\n */\n optOut(): void {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem('produck_proactive_optout', 'true');\n }\n this.stop();\n }\n\n /**\n * Opt in to proactive messages\n */\n optIn(): void {\n if (typeof localStorage !== 'undefined') {\n localStorage.removeItem('produck_proactive_optout');\n }\n this.start();\n }\n}\n\n// Default proactive configuration\nexport const defaultProactiveConfig: ProactiveConfig = {\n enabled: false,\n triggers: [\n {\n type: 'scroll',\n enabled: true,\n threshold: 75, // 75% scroll depth\n onlyOnce: true,\n cooldown: 60000, // 1 minute\n },\n {\n type: 'time',\n enabled: true,\n threshold: 30000, // 30 seconds\n onlyOnce: true,\n },\n {\n type: 'idle',\n enabled: true,\n threshold: 60000, // 1 minute idle\n cooldown: 120000, // 2 minutes between\n },\n {\n type: 'exit',\n enabled: true,\n onlyOnce: true,\n },\n ],\n maxProactiveMessages: 3,\n globalCooldown: 30000, // 30 seconds between any proactive message\n respectUserPreference: true,\n};\n","/**\n * User Flow Tracker Utilities\n * Helper functions for tracking user interactions\n */\n\nimport type { DeviceInfo, ElementInfo, UserFlowConfig, ResolvedUserFlowConfig } from './types';\n\n/**\n * Check if we're in a browser environment\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Generate a unique session ID\n */\nexport function generateSessionId(): string {\n return 'ufs_' + Date.now().toString(36) + '_' + Math.random().toString(36).substring(2, 11);\n}\n\n/**\n * Get current page URL\n */\nexport function getCurrentUrl(): string {\n if (!isBrowser()) return '';\n return window.location.href;\n}\n\n/**\n * Get current page path\n */\nexport function getCurrentPath(): string {\n if (!isBrowser()) return '';\n return window.location.pathname;\n}\n\n/**\n * Get current page title\n */\nexport function getCurrentTitle(): string {\n if (!isBrowser()) return '';\n return document.title || '';\n}\n\n/**\n * Check if session should be tracked based on sampling rate\n */\nexport function shouldTrackSession(samplingRate: number = 1): boolean {\n return Math.random() < samplingRate;\n}\n\n/**\n * Get device information\n */\nexport function getDeviceInfo(): DeviceInfo {\n if (!isBrowser()) {\n return {\n deviceType: 'desktop',\n browser: 'unknown',\n os: 'unknown',\n viewportWidth: 0,\n viewportHeight: 0,\n userAgent: '',\n };\n }\n\n const ua = navigator.userAgent;\n \n // Detect device type\n let deviceType: 'desktop' | 'tablet' | 'mobile' = 'desktop';\n if (/Mobi|Android/i.test(ua)) {\n deviceType = /Tablet|iPad/i.test(ua) ? 'tablet' : 'mobile';\n }\n\n // Detect browser\n let browser = 'unknown';\n if (ua.includes('Firefox')) browser = 'Firefox';\n else if (ua.includes('Edg')) browser = 'Edge';\n else if (ua.includes('Chrome')) browser = 'Chrome';\n else if (ua.includes('Safari')) browser = 'Safari';\n else if (ua.includes('Opera') || ua.includes('OPR')) browser = 'Opera';\n\n // Detect OS\n let os = 'unknown';\n if (ua.includes('Windows')) os = 'Windows';\n else if (ua.includes('Mac OS')) os = 'macOS';\n else if (ua.includes('Linux')) os = 'Linux';\n else if (ua.includes('Android')) os = 'Android';\n else if (ua.includes('iOS') || ua.includes('iPhone') || ua.includes('iPad')) os = 'iOS';\n\n return {\n deviceType,\n browser,\n os,\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n userAgent: ua,\n };\n}\n\n/**\n * Get CSS selector path for an element\n */\nexport function getElementSelector(element: Element, depth: number = 5): string {\n const parts: string[] = [];\n let current: Element | null = element;\n let currentDepth = 0;\n\n while (current && current !== document.body && currentDepth < depth) {\n let selector = current.tagName.toLowerCase();\n\n // Add ID if present\n if (current.id) {\n selector += `#${current.id}`;\n parts.unshift(selector);\n break; // ID is unique, stop here\n }\n\n // Add first class if present\n if (current.className && typeof current.className === 'string') {\n const classes = current.className.trim().split(/\\s+/);\n if (classes.length > 0 && classes[0]) {\n selector += `.${classes[0]}`;\n }\n }\n\n // Add nth-child for disambiguation\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n (child) => child.tagName === current!.tagName\n );\n if (siblings.length > 1) {\n const index = siblings.indexOf(current) + 1;\n selector += `:nth-child(${index})`;\n }\n }\n\n parts.unshift(selector);\n current = current.parentElement;\n currentDepth++;\n }\n\n return parts.join(' > ');\n}\n\n/**\n * Get XPath for an element\n */\nexport function getElementXPath(element: Element): string {\n if (!element) return '';\n \n if (element.id) {\n return `//*[@id=\"${element.id}\"]`;\n }\n\n const parts: string[] = [];\n let current: Element | null = element;\n\n while (current && current.nodeType === Node.ELEMENT_NODE) {\n let index = 0;\n let sibling: Element | null = current.previousElementSibling;\n \n while (sibling) {\n if (sibling.tagName === current.tagName) {\n index++;\n }\n sibling = sibling.previousElementSibling;\n }\n\n const tagName = current.tagName.toLowerCase();\n const part = index > 0 ? `${tagName}[${index + 1}]` : tagName;\n parts.unshift(part);\n current = current.parentElement;\n }\n\n return '/' + parts.join('/');\n}\n\n/**\n * Get element information\n */\nexport function getElementInfo(\n element: Element,\n config: UserFlowConfig['element'] = {},\n): ElementInfo {\n const maxTextLength = config?.maxTextLength || 100;\n const maxHtmlLength = config?.maxHtmlLength || 500;\n const selectorDepth = config?.selectorDepth || 5;\n\n // Get text content\n let text = '';\n if (element instanceof HTMLElement) {\n text = element.innerText || element.textContent || '';\n text = text.trim().substring(0, maxTextLength);\n if (text.length === maxTextLength) text += '...';\n }\n\n // Get outer HTML\n let html: string | undefined;\n if (config?.captureHtml !== false) {\n html = element.outerHTML.substring(0, maxHtmlLength);\n if (html.length === maxHtmlLength) html += '...';\n }\n\n // Get bounding rect\n const rect = element.getBoundingClientRect();\n\n const info: ElementInfo = {\n tag: element.tagName.toLowerCase(),\n selector: getElementSelector(element, selectorDepth),\n };\n\n // Optional fields\n if (element.id) info.id = element.id;\n if (element.className && typeof element.className === 'string') {\n info.className = element.className;\n }\n if (text) info.text = text;\n if (element instanceof HTMLAnchorElement && element.href) {\n info.href = element.href;\n }\n info.xpath = getElementXPath(element);\n info.rect = {\n x: Math.round(rect.x),\n y: Math.round(rect.y),\n width: Math.round(rect.width),\n height: Math.round(rect.height),\n };\n if (html) info.html = html;\n\n return info;\n}\n\n/**\n * Check if element matches any of the given selectors\n */\nexport function matchesSelectors(element: Element, selectors: string[]): boolean {\n if (!selectors || selectors.length === 0) return false;\n \n return selectors.some((selector) => {\n try {\n return element.matches(selector) || element.closest(selector) !== null;\n } catch {\n return false;\n }\n });\n}\n\n/**\n * Capture element visual info (lightweight alternative to html2canvas)\n * Instead of full screenshots, we capture CSS visual properties\n * This is ~100x faster and doesn't block the main thread\n */\nexport function captureElementVisualInfo(element: Element): Record<string, string> | undefined {\n try {\n if (typeof window === 'undefined') return undefined;\n \n const htmlElement = element as HTMLElement;\n const styles = window.getComputedStyle(htmlElement);\n \n return {\n backgroundColor: styles.backgroundColor,\n color: styles.color,\n fontSize: styles.fontSize,\n fontWeight: styles.fontWeight,\n borderRadius: styles.borderRadius,\n border: styles.border,\n boxShadow: styles.boxShadow,\n padding: styles.padding,\n };\n } catch {\n return undefined;\n }\n}\n\n/**\n * Capture element screenshot (using html2canvas)\n * WARNING: This is expensive! Only use for:\n * - Specific important elements (CTAs, conversion points)\n * - Debugging/development mode\n * - Post-session analysis (not real-time)\n * \n * Consider using captureElementVisualInfo() for production\n */\nexport async function captureElementScreenshot(\n element: Element,\n maxSize: number = 200,\n): Promise<string | undefined> {\n try {\n // Check if we have html2canvas available\n if (typeof window === 'undefined') return undefined;\n\n // Try to dynamically import html2canvas\n const html2canvas = (window as any).html2canvas;\n if (!html2canvas) {\n // Try to import it - html2canvas is an optional peer dependency\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const module = await import(/* webpackIgnore: true */ 'html2canvas' as string);\n const canvas = await module.default(element as HTMLElement, {\n scale: 0.5,\n width: maxSize,\n height: maxSize,\n useCORS: true,\n logging: false,\n });\n return canvas.toDataURL('image/jpeg', 0.7);\n } catch {\n console.debug('[UserFlow] html2canvas not available for screenshots');\n return undefined;\n }\n }\n\n const canvas = await html2canvas(element as HTMLElement, {\n scale: 0.5,\n width: maxSize,\n height: maxSize,\n useCORS: true,\n logging: false,\n });\n\n return canvas.toDataURL('image/jpeg', 0.7);\n } catch (error) {\n console.debug('[UserFlow] Failed to capture screenshot:', error);\n return undefined;\n }\n}\n\n/**\n * Merge user config with defaults\n * Note: User flow tracking is ENABLED by default for production use\n */\nexport function mergeConfig(config?: UserFlowConfig): ResolvedUserFlowConfig {\n const defaults: ResolvedUserFlowConfig = {\n enabled: true, // Enabled by default!\n samplingRate: 1,\n events: {\n clicks: true,\n navigation: true,\n formSubmit: true,\n inputs: false,\n scroll: false,\n ignoreSelectors: [],\n trackOnlySelectors: [],\n },\n element: {\n captureVisualStyles: true, // Lightweight - enabled by default\n captureScreenshot: false, // Expensive - disabled by default\n screenshotMaxSize: 200,\n captureHtml: true,\n maxHtmlLength: 500,\n maxTextLength: 100,\n selectorDepth: 5,\n },\n performance: {\n batchEvents: true,\n batchSize: 10,\n batchTimeout: 5000,\n clickDebounce: 500,\n },\n session: {\n endOnHidden: true,\n inactivityTimeout: 5 * 60 * 1000, // 5 minutes\n endOnExternalNavigation: true,\n autoRestart: true,\n },\n endpoint: '',\n onStart: () => {},\n onStop: () => {},\n onError: () => {},\n };\n\n if (!config) return defaults;\n\n return {\n enabled: config.enabled ?? defaults.enabled,\n samplingRate: config.samplingRate ?? defaults.samplingRate,\n events: { ...defaults.events, ...config.events },\n element: { ...defaults.element, ...config.element },\n performance: { ...defaults.performance, ...config.performance },\n session: { ...defaults.session, ...config.session },\n endpoint: config.endpoint ?? defaults.endpoint,\n onStart: config.onStart ?? defaults.onStart,\n onStop: config.onStop ?? defaults.onStop,\n onError: config.onError ?? defaults.onError,\n };\n}\n\n/**\n * Format duration in human readable format\n */\nexport function formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${Math.round(ms / 1000)}s`;\n return `${Math.round(ms / 60000)}m`;\n}\n","/**\n * User Flow Tracker\n * Core tracking functionality for user interactions\n * \n * This module is completely isolated from the main SDK logic.\n * It can be enabled/disabled without affecting other SDK functionality.\n */\n\nimport type {\n UserFlowConfig,\n UserFlowEvent,\n UserIdentification,\n TrackingState,\n TrackerStats,\n ResolvedUserFlowConfig,\n} from './types';\nimport {\n isBrowser,\n generateSessionId,\n getCurrentUrl,\n getCurrentPath,\n getCurrentTitle,\n getDeviceInfo,\n getElementInfo,\n matchesSelectors,\n captureElementScreenshot,\n captureElementVisualInfo,\n mergeConfig,\n shouldTrackSession,\n} from './utils';\n\n/**\n * UserFlowTracker class\n * Handles all user interaction tracking, isolated from main SDK\n */\nexport class UserFlowTracker {\n private config: ResolvedUserFlowConfig;\n private state: TrackingState = 'idle';\n private sessionId: string | null = null;\n private sdkSessionToken: string | null = null;\n private apiUrl: string = '';\n private sdkKey: string | null = null;\n private user: UserIdentification | null = null;\n\n // Tracking internals\n private events: UserFlowEvent[] = [];\n private eventCount = 0;\n private batchIndex = 0;\n private batchesSent = 0;\n private pageCount = 0;\n private startTime: Date | null = null;\n private batchTimeout: ReturnType<typeof setTimeout> | null = null;\n private inactivityTimeout: ReturnType<typeof setTimeout> | null = null;\n private lastActivityTime: number = Date.now();\n private lastClickTime: number = 0;\n private lastClickElement: Element | null = null;\n private currentPath: string = '';\n private visitedPaths: Set<string> = new Set();\n\n // Event listeners\n private clickHandler: ((e: MouseEvent) => void) | null = null;\n private navigationHandler: (() => void) | null = null;\n private formSubmitHandler: ((e: SubmitEvent) => void) | null = null;\n private beforeUnloadHandler: (() => void) | null = null;\n private visibilityHandler: (() => void) | null = null;\n\n constructor(config?: UserFlowConfig) {\n this.config = mergeConfig(config);\n }\n\n /**\n * Initialize the tracker with SDK context\n */\n initialize(sdkSessionToken: string, apiUrl: string, sdkKey?: string): void {\n this.sdkSessionToken = sdkSessionToken;\n this.apiUrl = apiUrl;\n this.sdkKey = sdkKey || null;\n }\n\n /**\n * Update configuration\n */\n updateConfig(config: Partial<UserFlowConfig>): void {\n this.config = mergeConfig({ ...this.config, ...config });\n }\n\n /**\n * Identify the user\n */\n identify(user: UserIdentification): void {\n this.user = user;\n\n // If already tracking, send identification update to backend\n if (this.state === 'tracking' && this.sessionId) {\n this.sendIdentificationUpdate().catch((err) => {\n console.error('[UserFlow] Failed to send identification update:', err);\n });\n }\n }\n\n // Linked recording session ID (if rrweb is also recording)\n private linkedRecordingSessionId: string | null = null;\n\n /**\n * Start tracking\n * @param linkedRecordingSessionId - Optional linked rrweb session ID for playback\n */\n async start(linkedRecordingSessionId?: string | null): Promise<string | null> {\n if (!isBrowser()) {\n console.warn('[UserFlow] Cannot track outside browser environment');\n return null;\n }\n\n if (!this.config.enabled) {\n return null;\n }\n\n if (this.state === 'tracking') {\n console.warn('[UserFlow] Already tracking');\n return this.sessionId;\n }\n\n // Check sampling rate\n if (!shouldTrackSession(this.config.samplingRate)) {\n console.log('[UserFlow] Session not sampled for tracking');\n return null;\n }\n\n try {\n this.sessionId = generateSessionId();\n this.linkedRecordingSessionId = linkedRecordingSessionId || null;\n this.events = [];\n this.eventCount = 0;\n this.batchIndex = 0;\n this.batchesSent = 0;\n this.pageCount = 1;\n this.startTime = new Date();\n this.currentPath = getCurrentPath();\n this.visitedPaths = new Set([this.currentPath]);\n this.state = 'tracking';\n\n // Setup event listeners\n this.setupEventListeners();\n\n // Send session start to backend\n await this.sendSessionStart();\n\n // Add initial navigation event\n this.addEvent({\n eventType: 'navigation',\n eventOrder: 0,\n timestamp: new Date().toISOString(),\n pageUrl: getCurrentUrl(),\n pageTitle: getCurrentTitle(),\n pagePath: this.currentPath,\n });\n\n this.config.onStart(this.sessionId);\n console.log('[UserFlow] Started tracking session:', this.sessionId);\n\n return this.sessionId;\n } catch (error) {\n console.error('[UserFlow] Failed to start tracking:', error);\n this.state = 'idle';\n this.config.onError(error instanceof Error ? error : new Error(String(error)));\n return null;\n }\n }\n\n /**\n * Stop tracking\n */\n async stop(): Promise<void> {\n if (this.state !== 'tracking' && this.state !== 'paused') {\n return;\n }\n\n try {\n // Remove event listeners\n this.removeEventListeners();\n\n // Clear batch timeout\n if (this.batchTimeout) {\n clearTimeout(this.batchTimeout);\n this.batchTimeout = null;\n }\n\n // Clear inactivity timeout\n if (this.inactivityTimeout) {\n clearTimeout(this.inactivityTimeout);\n this.inactivityTimeout = null;\n }\n\n // Send remaining events\n if (this.events.length > 0) {\n await this.sendEventBatch(true);\n }\n\n // Send session end\n await this.sendSessionEnd();\n\n this.state = 'stopped';\n const eventCount = this.eventCount;\n const sessionId = this.sessionId;\n\n // Reset state\n this.sessionId = null;\n this.events = [];\n this.eventCount = 0;\n this.startTime = null;\n\n this.config.onStop(sessionId!, eventCount);\n console.log('[UserFlow] Stopped tracking session:', sessionId);\n } catch (error) {\n console.error('[UserFlow] Error stopping tracking:', error);\n this.state = 'stopped';\n this.config.onError(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n /**\n * Pause tracking\n */\n pause(): void {\n if (this.state === 'tracking') {\n this.state = 'paused';\n console.log('[UserFlow] Tracking paused');\n }\n }\n\n /**\n * Resume tracking\n */\n resume(): void {\n if (this.state === 'paused') {\n this.state = 'tracking';\n console.log('[UserFlow] Tracking resumed');\n }\n }\n\n /**\n * Get tracker statistics\n */\n getStats(): TrackerStats {\n return {\n sessionId: this.sessionId,\n state: this.state,\n eventCount: this.eventCount,\n pageCount: this.pageCount,\n batchesSent: this.batchesSent,\n duration: this.startTime ? Date.now() - this.startTime.getTime() : 0,\n startTime: this.startTime,\n };\n }\n\n /**\n * Get tracking state\n */\n getState(): TrackingState {\n return this.state;\n }\n\n /**\n * Check if currently tracking\n */\n isTracking(): boolean {\n return this.state === 'tracking';\n }\n\n /**\n * Add a custom event\n */\n addCustomEvent(data: Record<string, any>): void {\n if (this.state !== 'tracking') return;\n\n this.addEvent({\n eventType: 'custom',\n eventOrder: this.eventCount,\n timestamp: new Date().toISOString(),\n pageUrl: getCurrentUrl(),\n pageTitle: getCurrentTitle(),\n pagePath: getCurrentPath(),\n metadata: data,\n });\n }\n\n // === Private methods ===\n\n /**\n * Setup event listeners\n */\n private setupEventListeners(): void {\n if (!isBrowser()) return;\n\n // Click handler\n if (this.config.events.clicks) {\n this.clickHandler = (e: MouseEvent) => this.handleClick(e);\n document.addEventListener('click', this.clickHandler, { capture: true, passive: true });\n }\n\n // Navigation handler (for SPAs)\n if (this.config.events.navigation) {\n this.navigationHandler = () => this.handleNavigation();\n window.addEventListener('popstate', this.navigationHandler);\n \n // Intercept pushState and replaceState\n const originalPushState = history.pushState;\n const originalReplaceState = history.replaceState;\n \n history.pushState = (...args) => {\n originalPushState.apply(history, args);\n this.handleNavigation();\n };\n \n history.replaceState = (...args) => {\n originalReplaceState.apply(history, args);\n this.handleNavigation();\n };\n }\n\n // Form submit handler\n if (this.config.events.formSubmit) {\n this.formSubmitHandler = (e: SubmitEvent) => this.handleFormSubmit(e);\n document.addEventListener('submit', this.formSubmitHandler, { capture: true });\n }\n\n // Before unload - send final batch and end session\n this.beforeUnloadHandler = () => {\n // Send any pending events\n if (this.events.length > 0) {\n this.sendEventBatchSync(true);\n }\n // End the session\n this.sendSessionEndSync();\n };\n window.addEventListener('beforeunload', this.beforeUnloadHandler);\n\n // Visibility change - end session when hidden (configurable)\n this.visibilityHandler = () => {\n if (document.visibilityState === 'hidden') {\n // Send batch when page becomes hidden\n if (this.events.length > 0) {\n this.sendEventBatch(true).catch(console.error);\n }\n \n // End session if configured\n if (this.config.session.endOnHidden) {\n this.stop().catch(console.error);\n }\n } else if (document.visibilityState === 'visible') {\n // Auto-restart if configured and was tracking\n if (this.config.session.autoRestart && this.state === 'stopped') {\n this.start().catch(console.error);\n }\n }\n };\n document.addEventListener('visibilitychange', this.visibilityHandler);\n\n // Start inactivity timeout\n this.resetInactivityTimeout();\n }\n\n /**\n * Remove event listeners\n */\n private removeEventListeners(): void {\n if (!isBrowser()) return;\n\n if (this.clickHandler) {\n document.removeEventListener('click', this.clickHandler, { capture: true } as any);\n this.clickHandler = null;\n }\n\n if (this.navigationHandler) {\n window.removeEventListener('popstate', this.navigationHandler);\n this.navigationHandler = null;\n }\n\n if (this.formSubmitHandler) {\n document.removeEventListener('submit', this.formSubmitHandler, { capture: true } as any);\n this.formSubmitHandler = null;\n }\n\n if (this.beforeUnloadHandler) {\n window.removeEventListener('beforeunload', this.beforeUnloadHandler);\n this.beforeUnloadHandler = null;\n }\n\n if (this.visibilityHandler) {\n document.removeEventListener('visibilitychange', this.visibilityHandler);\n this.visibilityHandler = null;\n }\n }\n\n /**\n * Handle click event\n */\n private async handleClick(e: MouseEvent): Promise<void> {\n if (this.state !== 'tracking') return;\n\n const target = e.target as Element;\n if (!target || !(target instanceof Element)) return;\n\n // Check ignore selectors\n if (\n this.config.events.ignoreSelectors &&\n this.config.events.ignoreSelectors.length > 0 &&\n matchesSelectors(target, this.config.events.ignoreSelectors)\n ) {\n return;\n }\n\n // Check track-only selectors\n if (\n this.config.events.trackOnlySelectors &&\n this.config.events.trackOnlySelectors.length > 0 &&\n !matchesSelectors(target, this.config.events.trackOnlySelectors)\n ) {\n return;\n }\n\n // Debounce same-element clicks\n const now = Date.now();\n if (\n this.lastClickElement === target &&\n now - this.lastClickTime < this.config.performance.clickDebounce\n ) {\n return;\n }\n this.lastClickTime = now;\n this.lastClickElement = target;\n\n // Get element info\n const elementInfo = getElementInfo(target, this.config.element);\n\n // Capture lightweight visual styles (fast - ~1ms)\n if (this.config.element.captureVisualStyles) {\n elementInfo.visualStyles = captureElementVisualInfo(target);\n }\n\n // Optionally capture full screenshot (slow - ~100-500ms, use sparingly)\n if (this.config.element.captureScreenshot) {\n try {\n elementInfo.screenshot = await captureElementScreenshot(\n target,\n this.config.element.screenshotMaxSize,\n );\n } catch {\n // Ignore screenshot errors\n }\n }\n\n // Create event\n const event: UserFlowEvent = {\n eventType: 'click',\n eventOrder: this.eventCount,\n timestamp: new Date().toISOString(),\n pageUrl: getCurrentUrl(),\n pageTitle: getCurrentTitle(),\n pagePath: getCurrentPath(),\n element: elementInfo,\n clickX: Math.round(e.pageX),\n clickY: Math.round(e.pageY),\n viewportX: Math.round(e.clientX),\n viewportY: Math.round(e.clientY),\n };\n\n this.addEvent(event);\n }\n\n /**\n * Handle navigation event\n */\n private handleNavigation(): void {\n if (this.state !== 'tracking') return;\n\n const newPath = getCurrentPath();\n if (newPath === this.currentPath) return;\n\n this.currentPath = newPath;\n \n if (!this.visitedPaths.has(newPath)) {\n this.visitedPaths.add(newPath);\n this.pageCount++;\n }\n\n const event: UserFlowEvent = {\n eventType: 'navigation',\n eventOrder: this.eventCount,\n timestamp: new Date().toISOString(),\n pageUrl: getCurrentUrl(),\n pageTitle: getCurrentTitle(),\n pagePath: newPath,\n };\n\n this.addEvent(event);\n }\n\n /**\n * Handle form submit event\n */\n private handleFormSubmit(e: SubmitEvent): void {\n if (this.state !== 'tracking') return;\n\n const form = e.target as HTMLFormElement;\n if (!form || !(form instanceof HTMLFormElement)) return;\n\n // Check ignore selectors\n if (\n this.config.events.ignoreSelectors &&\n matchesSelectors(form, this.config.events.ignoreSelectors)\n ) {\n return;\n }\n\n const elementInfo = getElementInfo(form, this.config.element);\n\n const event: UserFlowEvent = {\n eventType: 'form_submit',\n eventOrder: this.eventCount,\n timestamp: new Date().toISOString(),\n pageUrl: getCurrentUrl(),\n pageTitle: getCurrentTitle(),\n pagePath: getCurrentPath(),\n element: elementInfo,\n metadata: {\n action: form.action,\n method: form.method,\n name: form.name,\n },\n };\n\n this.addEvent(event);\n }\n\n /**\n * Add event to queue\n */\n private addEvent(event: UserFlowEvent): void {\n this.events.push(event);\n this.eventCount++;\n\n // Reset inactivity timeout on each event\n this.resetInactivityTimeout();\n\n // Check if we should send batch\n if (\n this.config.performance.batchEvents &&\n this.events.length >= this.config.performance.batchSize\n ) {\n this.sendEventBatch(false).catch(console.error);\n } else if (!this.batchTimeout) {\n // Set timeout for batch send\n this.batchTimeout = setTimeout(() => {\n this.batchTimeout = null;\n if (this.events.length > 0) {\n this.sendEventBatch(false).catch(console.error);\n }\n }, this.config.performance.batchTimeout);\n }\n }\n\n /**\n * Send session start to backend\n */\n private async sendSessionStart(): Promise<void> {\n const endpoint = this.config.endpoint || `${this.apiUrl}/user-flows/session/start`;\n const device = getDeviceInfo();\n\n const body = {\n sessionId: this.sessionId,\n sdkSessionToken: this.sdkSessionToken,\n startUrl: getCurrentUrl(),\n startTime: this.startTime?.toISOString(),\n user: this.user,\n device,\n // Link to rrweb recording session if available\n linkedRecordingSessionId: this.linkedRecordingSessionId,\n };\n\n try {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(this.sdkKey ? { 'X-SDK-Key': this.sdkKey } : {}),\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n console.error('[UserFlow] Failed to start session:', response.status, response.statusText);\n console.error('[UserFlow] Endpoint:', endpoint);\n throw new Error(`Failed to start session: ${response.status}`);\n }\n \n console.log('[UserFlow] Session started successfully:', this.sessionId);\n } catch (error) {\n console.error('[UserFlow] Network error starting session:', error);\n console.error('[UserFlow] Attempted endpoint:', endpoint);\n throw error;\n }\n }\n\n /**\n * Send event batch to backend\n */\n private async sendEventBatch(isFinal: boolean): Promise<void> {\n if (this.events.length === 0) return;\n\n const eventsToSend = [...this.events];\n this.events = [];\n\n const endpoint = this.config.endpoint\n ? `${this.config.endpoint}/events`\n : `${this.apiUrl}/user-flows/session/events`;\n\n const body = {\n sessionId: this.sessionId,\n events: eventsToSend,\n batchIndex: this.batchIndex++,\n timestamp: new Date().toISOString(),\n isFinal,\n };\n\n try {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(this.sdkKey ? { 'X-SDK-Key': this.sdkKey } : {}),\n },\n body: JSON.stringify(body),\n });\n\n if (response.ok) {\n this.batchesSent++;\n console.log(`[UserFlow] Event batch ${this.batchIndex - 1} sent (${eventsToSend.length} events)`);\n } else {\n console.error('[UserFlow] Failed to send event batch:', response.status, response.statusText);\n console.error('[UserFlow] Endpoint:', endpoint);\n // Re-add events to queue on failure\n this.events = [...eventsToSend, ...this.events];\n }\n } catch (error) {\n console.error('[UserFlow] Network error sending event batch:', error);\n console.error('[UserFlow] Endpoint:', endpoint);\n // Re-add events to queue on failure\n this.events = [...eventsToSend, ...this.events];\n }\n }\n\n /**\n * Send event batch synchronously (for beforeunload)\n */\n private sendEventBatchSync(isFinal: boolean): void {\n if (this.events.length === 0) return;\n\n const endpoint = this.config.endpoint\n ? `${this.config.endpoint}/events`\n : `${this.apiUrl}/user-flows/session/events`;\n\n const body = {\n sessionId: this.sessionId,\n events: this.events,\n batchIndex: this.batchIndex++,\n timestamp: new Date().toISOString(),\n isFinal,\n };\n\n // Use sendBeacon for reliability on page unload\n if (navigator.sendBeacon) {\n const blob = new Blob([JSON.stringify(body)], { type: 'application/json' });\n navigator.sendBeacon(endpoint, blob);\n this.events = [];\n }\n }\n\n /**\n * Send session end to backend\n */\n private async sendSessionEnd(): Promise<void> {\n const endpoint = this.config.endpoint\n ? `${this.config.endpoint}/end`\n : `${this.apiUrl}/user-flows/session/end`;\n\n const body = {\n sessionId: this.sessionId,\n endTime: new Date().toISOString(),\n eventCount: this.eventCount,\n status: 'completed',\n };\n\n try {\n await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(this.sdkKey ? { 'X-SDK-Key': this.sdkKey } : {}),\n },\n body: JSON.stringify(body),\n });\n } catch (error) {\n console.error('[UserFlow] Failed to send session end:', error);\n }\n }\n\n /**\n * Send session end synchronously (for beforeunload)\n */\n private sendSessionEndSync(): void {\n const endpoint = this.config.endpoint\n ? `${this.config.endpoint}/end`\n : `${this.apiUrl}/user-flows/session/end`;\n\n const body = {\n sessionId: this.sessionId,\n endTime: new Date().toISOString(),\n eventCount: this.eventCount,\n status: 'completed',\n };\n\n // Use sendBeacon for reliability on page unload\n if (navigator.sendBeacon) {\n const blob = new Blob([JSON.stringify(body)], { type: 'application/json' });\n navigator.sendBeacon(endpoint, blob);\n }\n }\n\n /**\n * Reset inactivity timeout\n * Called on each user interaction\n */\n private resetInactivityTimeout(): void {\n // Clear existing timeout\n if (this.inactivityTimeout) {\n clearTimeout(this.inactivityTimeout);\n this.inactivityTimeout = null;\n }\n\n // Update last activity time\n this.lastActivityTime = Date.now();\n\n // Set new timeout if configured\n const timeout = this.config.session.inactivityTimeout;\n if (timeout && timeout > 0) {\n this.inactivityTimeout = setTimeout(() => {\n if (this.state === 'tracking') {\n console.log('[UserFlow] Session ended due to inactivity');\n this.stop().catch(console.error);\n }\n }, timeout);\n }\n }\n\n /**\n * Send identification update to backend\n */\n private async sendIdentificationUpdate(): Promise<void> {\n if (!this.sessionId || !this.user) return;\n\n const endpoint = this.config.endpoint\n ? `${this.config.endpoint}/identify`\n : `${this.apiUrl}/user-flows/session/identify`;\n\n const body = {\n sessionId: this.sessionId,\n user: this.user,\n };\n\n await fetch(endpoint, {\n method: 'PATCH',\n headers: {\n 'Content-Type': 'application/json',\n ...(this.sdkKey ? { 'X-SDK-Key': this.sdkKey } : {}),\n },\n body: JSON.stringify(body),\n });\n }\n}\n\n/**\n * Factory function to create a user flow tracker\n */\nexport function createUserFlowTracker(config?: UserFlowConfig): UserFlowTracker {\n return new UserFlowTracker(config);\n}\n","// Import recording types (optional feature)\nimport type { RecordingConfig, RecordingStats, CustomRecordingEvent } from './recording';\nimport { SessionRecorder } from './recording';\n\n// Import proactive behavior tracking (optional feature)\nimport type { ProactiveConfig, ProactiveContext } from './proactive';\nimport { ProactiveBehaviorTracker, defaultProactiveConfig } from './proactive';\n\n// Import user flow tracking (optional feature)\nimport type { UserFlowConfig, UserIdentification, TrackerStats as UserFlowStats } from './user-flows';\nimport { UserFlowTracker } from './user-flows';\n\n// Types\nexport interface ProduckConfig {\n guiderId?: string; // Legacy support\n sdkKey?: string; // New SDK key approach\n apiUrl?: string;\n onAction?: (actionKey: string, action: ActionPayload) => void;\n onMessage?: (message: ChatMessage) => void;\n onError?: (error: Error) => void;\n onFlowStart?: (flow: FlowPayload) => void;\n onFlowStepComplete?: (step: FlowStepResult, flow: FlowPayload) => void;\n onFlowComplete?: (result: FlowResult) => void;\n \n /** Session recording configuration (optional) */\n recording?: RecordingConfig;\n \n /** Proactive chat configuration (optional) */\n proactive?: ProactiveConfig;\n \n /** User flow tracking configuration (optional) */\n userFlows?: UserFlowConfig;\n \n /** Callback for proactive chat triggers */\n onProactiveMessage?: (message: string, context: ProactiveContext) => void;\n \n /** Auto-start conversation with initial message (for landing pages) */\n initialMessage?: string;\n \n /** Stream the initial message character by character */\n streamInitialMessage?: boolean;\n}\n\nexport interface ActionPayload {\n actionKey: string;\n name: string;\n actionType: string;\n actionConfig: Record<string, any>;\n responseMessage?: string;\n}\n\n// Flow types\nexport interface FlowStep {\n operationId: string;\n order: number;\n condition?: Record<string, any>;\n inputMapping?: Record<string, any>;\n}\n\nexport interface FlowPayload {\n flowId: string;\n name: string;\n description: string;\n steps: FlowStep[];\n}\n\nexport interface FlowStepResult {\n operationId: string;\n order: number;\n success: boolean;\n data?: any;\n error?: string;\n}\n\nexport interface FlowResult {\n flowId: string;\n name: string;\n steps: FlowStepResult[];\n completed: boolean;\n totalSteps: number;\n successfulSteps: number;\n}\n\nexport interface ChatMessage {\n role: 'user' | 'assistant';\n content: string;\n action?: ActionPayload;\n flow?: FlowPayload;\n flowResult?: FlowResult;\n visualFlows?: VisualFlowReference[];\n images?: ImageReference[];\n}\n\n// Visual Flow types for chat display\nexport interface VisualFlowReference {\n flowId: string;\n name: string;\n description: string;\n score: number;\n stepsCount?: number;\n tags?: string[];\n}\n\nexport interface ImageReference {\n url: string;\n name: string;\n description: string;\n score: number;\n}\n\nexport interface VisualFlowStep {\n id: string;\n stepOrder: number;\n title: string;\n description: string;\n screenshotUrl: string | null;\n elementSelector: string | null;\n pageUrl: string;\n}\n\nexport interface VisualFlowDetails {\n id: string;\n flowId: string;\n name: string;\n description: string;\n tags: string[];\n steps: VisualFlowStep[];\n}\n\nexport interface ActionHandler {\n (payload: ActionPayload): void | Promise<void>;\n}\n\nexport interface RegisteredAction {\n key: string;\n handler: ActionHandler;\n}\n\nexport type ProduckEventType = 'action' | 'message' | 'error' | 'ready' | 'flowStart' | 'flowStepComplete' | 'flowComplete' | 'proactive';\n\nexport interface ProduckEvent {\n type: ProduckEventType;\n data: any;\n}\n\n// Core SDK Class\nexport class ProduckSDK {\n private config: ProduckConfig;\n private actions: Map<string, ActionHandler> = new Map();\n private eventListeners: Map<ProduckEventType, Set<Function>> = new Map();\n private sessionToken: string | null = null;\n private isReady: boolean = false;\n \n /** Session recorder instance (optional, isolated module) */\n private recorder: SessionRecorder | null = null;\n \n /** Proactive behavior tracker instance (optional, isolated module) */\n private proactiveTracker: ProactiveBehaviorTracker | null = null;\n \n /** User flow tracker instance (optional, isolated module) */\n private userFlowTracker: UserFlowTracker | null = null;\n\n constructor(config: ProduckConfig) {\n // Determine API URL - use custom if provided, otherwise use smart defaults\n let apiUrl = config.apiUrl;\n let apiUrlAutoDetected = false;\n \n if (!apiUrl) {\n apiUrlAutoDetected = true;\n // Check if we're in a browser environment and running on localhost\n if (typeof window !== 'undefined') {\n const isLocalhost = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1';\n \n if (isLocalhost) {\n apiUrl = 'http://localhost:4001/api/v1';\n } else {\n // PRODUCTION WARNING: Auto-detection in production is usually wrong!\n // The SDK will try to use the current domain which is likely NOT your backend\n apiUrl = `${window.location.protocol}//${window.location.host}/api/v1`;\n \n // Log a visible warning in the console\n console.warn(\n '%c⚠️ Produck SDK Warning: apiUrl not configured!',\n 'background: #fbbf24; color: #000; padding: 4px 8px; font-weight: bold;'\n );\n console.warn(\n `The SDK is auto-detecting apiUrl as: ${apiUrl}\\n` +\n `This is likely WRONG for production. Your backend is probably at a different URL.\\n\\n` +\n `To fix this, provide apiUrl in your SDK config:\\n\\n` +\n ` createProduck({\\n` +\n ` sdkKey: 'your_sdk_key',\\n` +\n ` apiUrl: 'https://your-backend.com/api/v1', // <-- Add this!\\n` +\n ` })\\n`\n );\n }\n } else {\n // Server-side default\n apiUrl = 'http://localhost:4001/api/v1';\n }\n }\n \n this.config = {\n apiUrl,\n ...config,\n };\n \n // Log the final configuration for debugging\n if (typeof window !== 'undefined') {\n console.log(\n '%c🔧 Produck SDK Config',\n 'background: #3b82f6; color: #fff; padding: 2px 6px; border-radius: 3px;',\n {\n apiUrl: this.config.apiUrl,\n apiUrlAutoDetected,\n sdkKey: this.config.sdkKey ? `${this.config.sdkKey.substring(0, 10)}...` : 'not set',\n guiderId: this.config.guiderId || 'not set',\n }\n );\n }\n }\n\n /**\n * Initialize the SDK and create a chat session\n */\n async init(): Promise<void> {\n // Log initialization start with visible console message\n if (typeof window !== 'undefined') {\n console.log(\n '%c🚀 Produck SDK Initializing...',\n 'background: #10b981; color: #fff; padding: 2px 6px; border-radius: 3px;',\n { endpoint: this.config.apiUrl }\n );\n }\n \n await this.log('info', 'SDK Initializing', {\n apiUrl: this.config.apiUrl,\n hasSDKKey: !!this.config.sdkKey,\n hasGuiderId: !!this.config.guiderId,\n });\n \n try {\n let endpoint: string;\n \n if (this.config.sdkKey) {\n // New SDK key approach\n endpoint = `${this.config.apiUrl}/sdk/session`;\n await this.log('info', 'Using SDK key authentication');\n } else if (this.config.guiderId) {\n // Legacy guider approach\n endpoint = `${this.config.apiUrl}/chat/${this.config.guiderId}/session`;\n await this.log('info', 'Using guider ID authentication');\n } else {\n throw new Error('Either sdkKey or guiderId must be provided');\n }\n\n await this.log('info', 'Creating session', { endpoint });\n\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.config.sdkKey) {\n headers['X-SDK-Key'] = this.config.sdkKey;\n }\n\n const response = await fetch(endpoint, {\n method: 'POST',\n headers,\n });\n\n if (!response.ok) {\n // Get response text for better error messages\n let errorDetail = '';\n try {\n errorDetail = await response.text();\n } catch {\n errorDetail = 'Could not read response body';\n }\n \n console.error(\n '%c❌ Produck SDK: Failed to create session',\n 'background: #ef4444; color: #fff; padding: 2px 6px; border-radius: 3px;'\n );\n console.error(`Status: ${response.status} ${response.statusText}`);\n console.error(`Endpoint: ${endpoint}`);\n console.error(`Response: ${errorDetail}`);\n \n if (response.status === 404) {\n console.error(\n '\\n💡 Tip: A 404 error usually means the apiUrl is wrong.\\n' +\n `Current apiUrl: ${this.config.apiUrl}\\n` +\n 'Make sure your backend is running and the URL is correct.'\n );\n }\n \n await this.log('error', 'Failed to create session', { status: response.status, errorDetail });\n throw new Error(`Failed to create session: ${response.status}`);\n }\n\n const session = await response.json();\n this.sessionToken = session.session_token;\n this.isReady = true;\n \n await this.log('info', 'SDK initialized successfully', { hasSessionToken: !!this.sessionToken });\n \n // Initialize session recording (enabled by default unless explicitly disabled)\n // Users can disable with: recording: { enabled: false }\n const recordingEnabled = this.config.recording?.enabled !== false;\n if (recordingEnabled) {\n await this.initRecording();\n }\n \n // Initialize proactive behavior tracking if enabled\n if (this.config.proactive?.enabled) {\n this.initProactive();\n }\n \n // Initialize user flow tracking (enabled by default unless explicitly disabled)\n // Users can disable with: userFlows: { enabled: false }\n const userFlowsEnabled = this.config.userFlows?.enabled !== false;\n if (userFlowsEnabled) {\n await this.initUserFlowTracking();\n }\n \n this.emit('ready', { sessionToken: this.sessionToken });\n \n // Send initial message if configured (for landing pages)\n if (this.config.initialMessage) {\n await this.sendInitialMessage();\n }\n } catch (error) {\n // Enhanced error logging for debugging\n const errorMessage = error instanceof Error ? error.message : String(error);\n const isNetworkError = errorMessage.includes('fetch') || \n errorMessage.includes('network') || \n errorMessage.includes('Failed to fetch') ||\n errorMessage.includes('NetworkError');\n \n console.error(\n '%c❌ Produck SDK initialization failed',\n 'background: #ef4444; color: #fff; padding: 4px 8px; font-weight: bold;'\n );\n console.error(`Error: ${errorMessage}`);\n console.error(`API URL: ${this.config.apiUrl}`);\n \n if (isNetworkError) {\n console.error(\n '\\n💡 This looks like a network error. Common causes:\\n' +\n ' 1. The apiUrl is incorrect or the backend is not running\\n' +\n ' 2. CORS is blocking the request\\n' +\n ' 3. The backend server is unreachable\\n\\n' +\n `Current apiUrl: ${this.config.apiUrl}\\n` +\n 'Check the Network tab in DevTools for more details.'\n );\n }\n \n await this.log('error', 'SDK initialization failed', { error: errorMessage });\n this.emit('error', error);\n throw error;\n }\n }\n\n /**\n * Register an action handler\n */\n register(actionKey: string, handler: ActionHandler): void {\n this.actions.set(actionKey, handler);\n this.log('info', 'Action handler registered', { actionKey, totalActions: this.actions.size });\n }\n\n /**\n * Unregister an action handler\n */\n unregister(actionKey: string): void {\n this.actions.delete(actionKey);\n this.log('info', 'Action handler unregistered', { actionKey, remainingActions: this.actions.size });\n }\n\n /**\n * Send a message and handle potential action or flow triggers\n */\n async sendMessage(message: string): Promise<ChatMessage> {\n if (!this.isReady || !this.sessionToken) {\n throw new Error('SDK not initialized. Call init() first.');\n }\n\n const startTime = Date.now();\n await this.log('info', 'sendMessage called', { message });\n\n try {\n // First, check if message matches any SDK action or flow\n let intentEndpoint: string;\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n \n if (this.config.sdkKey) {\n intentEndpoint = `${this.config.apiUrl}/sdk/match-intent`;\n headers['X-SDK-Key'] = this.config.sdkKey;\n } else {\n intentEndpoint = `${this.config.apiUrl}/sdk/public/${this.config.guiderId}/match-intent`;\n }\n\n const intentResponse = await fetch(intentEndpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify({ userMessage: message }),\n });\n\n await this.log('info', 'Match-intent response received', { status: intentResponse.status });\n\n if (intentResponse.ok) {\n const intentResult = await intentResponse.json();\n \n // Handle FLOW match\n if (intentResult.matched && intentResult.type === 'flow' && intentResult.flow) {\n await this.log('info', 'Flow matched', {\n flowId: intentResult.flow.flowId,\n name: intentResult.flow.name,\n stepCount: intentResult.flow.steps?.length,\n });\n \n // Send log to backend\n await this.sendLogToBackend({\n userMessage: message,\n matched: true,\n actionKey: `flow:${intentResult.flow.flowId}`,\n responseMessage: intentResult.responseMessage,\n executionTimeMs: Date.now() - startTime,\n });\n \n // Execute the flow\n const flowResult = await this.executeFlow(intentResult.flow);\n \n const flowMessage: ChatMessage = {\n role: 'assistant',\n content: intentResult.responseMessage || `I've completed the \"${intentResult.flow.name}\" flow for you.`,\n flow: intentResult.flow,\n flowResult,\n };\n \n this.emit('message', flowMessage);\n return flowMessage;\n }\n \n // Handle OPERATION match (existing behavior)\n if (intentResult.matched && (intentResult.type === 'operation' || intentResult.action)) {\n const action = intentResult.action;\n await this.log('info', 'Action matched', {\n actionKey: action.actionKey,\n actionType: action.actionType,\n responseMessage: action.responseMessage,\n });\n \n // Send log to backend\n await this.sendLogToBackend({\n userMessage: message,\n matched: true,\n actionKey: action.actionKey,\n responseMessage: action.responseMessage,\n executionTimeMs: Date.now() - startTime,\n });\n \n // Execute the action\n await this.executeAction(action);\n \n const actionMessage: ChatMessage = {\n role: 'assistant',\n content: action.responseMessage || `I've triggered the \"${action.name}\" action for you.`,\n action: action,\n };\n \n this.emit('message', actionMessage);\n return actionMessage;\n } else {\n \n // Send log for no match\n await this.sendLogToBackend({\n userMessage: message,\n matched: false,\n executionTimeMs: Date.now() - startTime,\n });\n }\n }\n\n // No action matched, send to regular chat\n const sessionResponse = await fetch(\n `${this.config.apiUrl}/chat/sessions/${this.sessionToken}/message`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ message }),\n }\n );\n\n if (!sessionResponse.ok) {\n throw new Error(`Failed to send message: ${sessionResponse.status}`);\n }\n\n const result = await sessionResponse.json();\n const chatMessage: ChatMessage = {\n role: 'assistant',\n content: result.message?.content || result.response || '',\n visualFlows: result.flows || [],\n images: result.images || [],\n };\n\n await this.log('info', 'Chat response received', {\n hasFlows: (result.flows || []).length > 0,\n hasImages: (result.images || []).length > 0,\n });\n this.emit('message', chatMessage);\n return chatMessage;\n } catch (error) {\n await this.log('error', 'Error in sendMessage', { error: error instanceof Error ? error.message : String(error) });\n this.emit('error', error);\n throw error;\n }\n }\n\n /**\n * Execute a flow by running each step's operation sequentially\n */\n async executeFlow(flow: FlowPayload): Promise<FlowResult> {\n await this.log('info', 'executeFlow started', {\n flowId: flow.flowId,\n name: flow.name,\n stepCount: flow.steps.length,\n });\n\n // Emit flow start event\n this.emit('flowStart', flow);\n if (this.config.onFlowStart) {\n this.config.onFlowStart(flow);\n }\n\n const stepResults: FlowStepResult[] = [];\n let context: Record<string, any> = {};\n\n // Sort steps by order\n const sortedSteps = [...flow.steps].sort((a, b) => a.order - b.order);\n\n for (const step of sortedSteps) {\n await this.log('info', 'Executing flow step', {\n flowId: flow.flowId,\n operationId: step.operationId,\n order: step.order,\n });\n\n const stepResult: FlowStepResult = {\n operationId: step.operationId,\n order: step.order,\n success: false,\n };\n\n try {\n // Get the handler for this operation\n const handler = this.actions.get(step.operationId);\n \n if (handler) {\n // Create action payload for the step\n const actionPayload: ActionPayload = {\n actionKey: step.operationId,\n name: step.operationId,\n actionType: 'callback',\n actionConfig: {\n flowContext: context,\n inputMapping: step.inputMapping,\n },\n };\n\n // Execute the handler\n const result = await handler(actionPayload);\n \n stepResult.success = true;\n stepResult.data = result;\n \n // Update context with result for next step\n context = {\n ...context,\n [`step_${step.order}`]: result,\n previousResult: result,\n };\n\n await this.log('info', 'Flow step completed successfully', {\n flowId: flow.flowId,\n operationId: step.operationId,\n order: step.order,\n });\n } else {\n // No handler registered - log warning but continue\n await this.log('warn', 'No handler registered for flow step', {\n flowId: flow.flowId,\n operationId: step.operationId,\n });\n stepResult.success = true; // Consider it \"success\" if no handler needed\n stepResult.data = { skipped: true, reason: 'No handler registered' };\n }\n } catch (error) {\n stepResult.success = false;\n stepResult.error = error instanceof Error ? error.message : String(error);\n \n await this.log('error', 'Flow step failed', {\n flowId: flow.flowId,\n operationId: step.operationId,\n error: stepResult.error,\n });\n }\n\n stepResults.push(stepResult);\n\n // Emit step complete event\n this.emit('flowStepComplete', { step: stepResult, flow });\n if (this.config.onFlowStepComplete) {\n this.config.onFlowStepComplete(stepResult, flow);\n }\n }\n\n const flowResult: FlowResult = {\n flowId: flow.flowId,\n name: flow.name,\n steps: stepResults,\n completed: true,\n totalSteps: flow.steps.length,\n successfulSteps: stepResults.filter(s => s.success).length,\n };\n\n await this.log('info', 'Flow execution completed', {\n flowId: flow.flowId,\n totalSteps: flowResult.totalSteps,\n successfulSteps: flowResult.successfulSteps,\n });\n\n // Emit flow complete event\n this.emit('flowComplete', flowResult);\n if (this.config.onFlowComplete) {\n this.config.onFlowComplete(flowResult);\n }\n\n return flowResult;\n }\n\n /**\n * Send log data to backend for analytics\n */\n private async sendLogToBackend(logData: {\n userMessage: string;\n matched: boolean;\n actionKey?: string;\n responseMessage?: string;\n executionTimeMs?: number;\n error?: string;\n }): Promise<void> {\n try {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.config.sdkKey) {\n headers['X-SDK-Key'] = this.config.sdkKey;\n }\n\n const logEndpoint = `${this.config.apiUrl}/sdk-logs/client`;\n \n await fetch(logEndpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n ...logData,\n timestamp: new Date().toISOString(),\n sessionToken: this.sessionToken,\n }),\n });\n } catch (error) {\n // Silently fail - don't block operations due to logging failures\n }\n }\n\n /**\n * Send detailed log to backend\n */\n private async log(level: 'info' | 'warn' | 'error', message: string, data?: any): Promise<void> {\n try {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.config.sdkKey) {\n headers['X-SDK-Key'] = this.config.sdkKey;\n }\n\n const logEndpoint = `${this.config.apiUrl}/sdk-logs/client`;\n \n await fetch(logEndpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n level,\n message,\n data,\n timestamp: new Date().toISOString(),\n sessionToken: this.sessionToken,\n }),\n });\n } catch (error) {\n // Silently fail\n }\n }\n\n /**\n * Execute a registered action\n */\n private async executeAction(action: ActionPayload): Promise<void> {\n const registeredKeys = Array.from(this.actions.keys());\n \n // Very visible debug - will show popup in browser\n if (typeof window !== 'undefined') {\n console.log('%c🎯 SDK executeAction', 'background: #ff0; color: #000; font-size: 20px; padding: 10px;', {\n actionKey: action.actionKey,\n totalRegistered: this.actions.size,\n registeredKeys,\n });\n }\n \n await this.log('info', 'executeAction called', {\n actionKey: action.actionKey,\n actionType: typeof action.actionKey,\n totalRegistered: this.actions.size,\n registeredKeys,\n keyComparisons: registeredKeys.map(key => ({\n key,\n matches: key === action.actionKey,\n keyLength: key.length,\n actionKeyLength: action.actionKey.length,\n })),\n });\n \n const handler = this.actions.get(action.actionKey);\n \n if (typeof window !== 'undefined') {\n console.log('%c🔍 SDK Handler Lookup', 'background: #0ff; color: #000; font-size: 16px; padding: 5px;', {\n actionKey: action.actionKey,\n found: !!handler,\n hasConfigOnAction: !!this.config.onAction,\n registeredKeys: Array.from(this.actions.keys()),\n });\n }\n \n if (handler) {\n try {\n const startTime = Date.now();\n await handler(action);\n const executionTime = Date.now() - startTime;\n \n await this.log('info', 'Handler executed successfully', {\n actionKey: action.actionKey,\n executionTime,\n });\n \n await this.sendLogToBackend({\n userMessage: `Action executed: ${action.actionKey}`,\n matched: true,\n actionKey: action.actionKey,\n responseMessage: action.responseMessage || `Executed ${action.name}`,\n executionTimeMs: executionTime,\n });\n \n this.emit('action', action);\n this.config.onAction?.(action.actionKey, action);\n } catch (error) {\n await this.log('error', 'Handler execution failed', {\n actionKey: action.actionKey,\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n \n await this.sendLogToBackend({\n userMessage: `Action execution failed: ${action.actionKey}`,\n matched: true,\n actionKey: action.actionKey,\n error: error instanceof Error ? error.message : String(error),\n });\n \n this.emit('error', error);\n }\n } else {\n // No handler in SDK's internal registry, but try the config callback\n // (ProduckProvider registers handlers there via actionsRef)\n if (this.config.onAction) {\n await this.log('info', 'No internal handler, trying config.onAction callback', {\n actionKey: action.actionKey,\n });\n \n try {\n this.config.onAction(action.actionKey, action);\n this.emit('action', action);\n \n await this.log('info', 'Action dispatched via config.onAction', {\n actionKey: action.actionKey,\n });\n \n await this.sendLogToBackend({\n userMessage: `Action dispatched: ${action.actionKey}`,\n matched: true,\n actionKey: action.actionKey,\n responseMessage: action.responseMessage || `Dispatched ${action.name}`,\n });\n return;\n } catch (error) {\n await this.log('error', 'config.onAction callback failed', {\n actionKey: action.actionKey,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n \n await this.log('warn', 'No handler registered for action', {\n actionKey: action.actionKey,\n registeredActions: Array.from(this.actions.keys()),\n });\n \n await this.sendLogToBackend({\n userMessage: `No handler for action: ${action.actionKey}`,\n matched: false,\n actionKey: action.actionKey,\n error: `Handler not registered. Available: ${Array.from(this.actions.keys()).join(', ')}`,\n });\n }\n }\n\n /**\n * Add event listener\n */\n on(event: ProduckEventType, callback: Function): void {\n if (!this.eventListeners.has(event)) {\n this.eventListeners.set(event, new Set());\n }\n this.eventListeners.get(event)!.add(callback);\n }\n\n /**\n * Remove event listener\n */\n off(event: ProduckEventType, callback: Function): void {\n this.eventListeners.get(event)?.delete(callback);\n }\n\n /**\n * Emit event\n */\n private emit(event: ProduckEventType, data: any): void {\n this.eventListeners.get(event)?.forEach(callback => callback(data));\n }\n\n /**\n * Get session token\n */\n getSessionToken(): string | null {\n return this.sessionToken;\n }\n\n /**\n * Check if SDK is ready\n */\n getIsReady(): boolean {\n return this.isReady;\n }\n\n /**\n * Get registered action keys\n */\n getRegisteredActions(): string[] {\n return Array.from(this.actions.keys());\n }\n\n /**\n * Get guider ID for the current session\n */\n getGuiderId(): string | undefined {\n return this.config.guiderId;\n }\n\n /**\n * Fetch full visual flow details by flow ID\n */\n async getVisualFlow(flowId: string): Promise<VisualFlowDetails | null> {\n const guiderId = this.config.guiderId;\n if (!guiderId) {\n await this.log('warn', 'Cannot fetch visual flow without guiderId');\n return null;\n }\n\n try {\n const response = await fetch(\n `${this.config.apiUrl}/visual-flows/chat/${guiderId}/${flowId}`\n );\n\n if (!response.ok) {\n await this.log('warn', 'Visual flow not found', { flowId, status: response.status });\n return null;\n }\n\n const result = await response.json();\n if (!result.found || !result.flow) {\n return null;\n }\n\n return result.flow as VisualFlowDetails;\n } catch (error) {\n await this.log('error', 'Error fetching visual flow', { flowId, error });\n return null;\n }\n }\n\n // ============================================================\n // Session Recording Methods (Isolated Module)\n // These methods delegate to the SessionRecorder when enabled\n // ============================================================\n\n /**\n * Initialize session recording (internal)\n */\n private async initRecording(): Promise<void> {\n try {\n this.recorder = new SessionRecorder(this.config.recording);\n this.recorder.initialize(\n this.sessionToken!,\n this.config.apiUrl!,\n this.config.sdkKey\n );\n \n const sessionId = await this.recorder.start();\n if (sessionId) {\n await this.log('info', 'Session recording started', { recordingSessionId: sessionId });\n }\n } catch (error) {\n await this.log('warn', 'Failed to initialize session recording', { \n error: error instanceof Error ? error.message : String(error) \n });\n // Don't throw - recording is optional, shouldn't break main SDK\n }\n }\n\n /**\n * Start session recording manually (if not auto-started)\n */\n async startRecording(): Promise<string | null> {\n if (!this.isReady) {\n console.warn('[SDK] Cannot start recording before SDK is initialized');\n return null;\n }\n\n if (!this.recorder) {\n this.recorder = new SessionRecorder(this.config.recording);\n this.recorder.initialize(\n this.sessionToken!,\n this.config.apiUrl!,\n this.config.sdkKey\n );\n }\n\n return this.recorder.start();\n }\n\n /**\n * Stop session recording\n */\n async stopRecording(): Promise<void> {\n if (this.recorder) {\n await this.recorder.stop();\n }\n }\n\n /**\n * Pause session recording\n */\n pauseRecording(): void {\n this.recorder?.pause();\n }\n\n /**\n * Resume session recording\n */\n resumeRecording(): void {\n this.recorder?.resume();\n }\n\n /**\n * Add a custom event to the recording\n */\n addRecordingEvent(event: CustomRecordingEvent): void {\n this.recorder?.addCustomEvent(event);\n }\n\n /**\n * Get recording statistics\n */\n getRecordingStats(): RecordingStats | null {\n return this.recorder?.getStats() ?? null;\n }\n\n /**\n * Check if session recording is active\n */\n isRecordingActive(): boolean {\n return this.recorder?.isRecording() ?? false;\n }\n\n /**\n * Get recording session ID\n */\n getRecordingSessionId(): string | null {\n return this.recorder?.getSessionId() ?? null;\n }\n\n // ============================================================\n // Proactive Chat Methods (Isolated Module)\n // These methods manage proactive behavior tracking and messaging\n // ============================================================\n\n /**\n * Initialize proactive behavior tracking (internal)\n */\n private initProactive(): void {\n if (!this.config.proactive) return;\n\n this.proactiveTracker = new ProactiveBehaviorTracker(\n this.config.proactive,\n {\n onTrigger: async (context, suggestedMessage) => {\n // Emit proactive event\n this.emit('proactive', { context, message: suggestedMessage });\n \n // Call callback if provided\n if (this.config.onProactiveMessage) {\n this.config.onProactiveMessage(suggestedMessage, context);\n }\n \n // Send to backend for AI-generated contextual message\n try {\n await this.getProactiveAIMessage(context, suggestedMessage);\n } catch (error) {\n await this.log('warn', 'Failed to get AI proactive message', { error });\n }\n },\n }\n );\n\n this.proactiveTracker.start();\n this.log('info', 'Proactive behavior tracking initialized');\n }\n\n /**\n * Get AI-generated proactive message based on context\n */\n private async getProactiveAIMessage(context: ProactiveContext, fallbackMessage: string): Promise<string> {\n try {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.config.sdkKey) {\n headers['X-SDK-Key'] = this.config.sdkKey;\n }\n\n const response = await fetch(`${this.config.apiUrl}/sdk/proactive-message`, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n context,\n fallbackMessage,\n sessionToken: this.sessionToken,\n }),\n });\n\n if (!response.ok) {\n return fallbackMessage;\n }\n\n const result = await response.json();\n const message = result.message || fallbackMessage;\n \n // Emit the AI-generated message\n const chatMessage: ChatMessage = {\n role: 'assistant',\n content: message,\n };\n this.emit('message', chatMessage);\n \n return message;\n } catch (error) {\n return fallbackMessage;\n }\n }\n\n /**\n * Send initial message for landing page intros\n */\n private async sendInitialMessage(): Promise<void> {\n const message = this.config.initialMessage;\n if (!message) return;\n\n if (this.config.streamInitialMessage) {\n // Stream the message character by character\n await this.streamMessage(message);\n } else {\n // Send the full message immediately\n const chatMessage: ChatMessage = {\n role: 'assistant',\n content: message,\n };\n this.emit('message', chatMessage);\n if (this.config.onMessage) {\n this.config.onMessage(chatMessage);\n }\n }\n }\n\n /**\n * Stream a message character by character for typewriter effect\n */\n async streamMessage(message: string, delayMs: number = 30): Promise<void> {\n let currentContent = '';\n \n for (let i = 0; i < message.length; i++) {\n currentContent += message[i];\n \n const chatMessage: ChatMessage = {\n role: 'assistant',\n content: currentContent,\n };\n \n // Emit partial message\n this.emit('message', chatMessage);\n \n // Wait before next character\n await new Promise(resolve => setTimeout(resolve, delayMs));\n }\n }\n\n /**\n * Start proactive tracking manually\n */\n startProactiveTracking(): void {\n if (this.proactiveTracker) {\n this.proactiveTracker.start();\n }\n }\n\n /**\n * Stop proactive tracking\n */\n stopProactiveTracking(): void {\n if (this.proactiveTracker) {\n this.proactiveTracker.stop();\n }\n }\n\n /**\n * Get proactive tracking stats\n */\n getProactiveStats(): ReturnType<ProactiveBehaviorTracker['getStats']> | null {\n return this.proactiveTracker?.getStats() ?? null;\n }\n\n /**\n * Manually trigger a proactive message\n */\n triggerProactiveMessage(message: string, context?: Partial<ProactiveContext>): void {\n if (this.proactiveTracker) {\n this.proactiveTracker.triggerManual(message, context);\n } else {\n // Even without tracker, emit the message\n const chatMessage: ChatMessage = {\n role: 'assistant',\n content: message,\n };\n this.emit('message', chatMessage);\n if (this.config.onMessage) {\n this.config.onMessage(chatMessage);\n }\n }\n }\n\n /**\n * Opt out of proactive messages (respects user preference)\n */\n optOutProactive(): void {\n this.proactiveTracker?.optOut();\n }\n\n /**\n * Opt in to proactive messages\n */\n optInProactive(): void {\n this.proactiveTracker?.optIn();\n }\n\n // ============================================================\n // User Flow Tracking Methods (Isolated Module)\n // These methods manage user interaction tracking and flow analysis\n // ============================================================\n\n /**\n * Initialize user flow tracking (internal)\n */\n private async initUserFlowTracking(): Promise<void> {\n try {\n this.userFlowTracker = new UserFlowTracker(this.config.userFlows);\n this.userFlowTracker.initialize(\n this.sessionToken!,\n this.config.apiUrl!,\n this.config.sdkKey\n );\n \n // Link with recording session if both are enabled\n const recordingSessionId = this.recorder?.getSessionId?.() || null;\n \n const sessionId = await this.userFlowTracker.start(recordingSessionId);\n if (sessionId) {\n await this.log('info', 'User flow tracking started', { \n flowSessionId: sessionId,\n linkedRecordingSession: recordingSessionId \n });\n }\n } catch (error) {\n await this.log('warn', 'Failed to initialize user flow tracking', { \n error: error instanceof Error ? error.message : String(error) \n });\n // Don't throw - tracking is optional, shouldn't break main SDK\n }\n }\n\n /**\n * Identify the user for flow tracking and segmentation\n * Call this when you know who the user is (e.g., after login)\n */\n identify(user: UserIdentification): void {\n if (this.userFlowTracker) {\n this.userFlowTracker.identify(user);\n }\n \n this.log('info', 'User identified', { \n hasEmail: !!user.email,\n hasName: !!user.name,\n hasTags: !!user.tags && Object.keys(user.tags).length > 0,\n });\n }\n\n /**\n * Start user flow tracking manually (if not auto-started)\n */\n async startUserFlowTracking(): Promise<string | null> {\n if (!this.isReady) {\n console.warn('[SDK] Cannot start flow tracking before SDK is initialized');\n return null;\n }\n\n if (!this.userFlowTracker) {\n this.userFlowTracker = new UserFlowTracker(this.config.userFlows);\n this.userFlowTracker.initialize(\n this.sessionToken!,\n this.config.apiUrl!,\n this.config.sdkKey\n );\n }\n\n return this.userFlowTracker.start();\n }\n\n /**\n * Stop user flow tracking\n */\n async stopUserFlowTracking(): Promise<void> {\n if (this.userFlowTracker) {\n await this.userFlowTracker.stop();\n }\n }\n\n /**\n * Pause user flow tracking\n */\n pauseUserFlowTracking(): void {\n this.userFlowTracker?.pause();\n }\n\n /**\n * Resume user flow tracking\n */\n resumeUserFlowTracking(): void {\n this.userFlowTracker?.resume();\n }\n\n /**\n * Add a custom event to the user flow\n */\n trackEvent(eventData: Record<string, any>): void {\n this.userFlowTracker?.addCustomEvent(eventData);\n }\n\n /**\n * Get user flow tracking statistics\n */\n getUserFlowStats(): UserFlowStats | null {\n return this.userFlowTracker?.getStats() ?? null;\n }\n\n /**\n * Check if user flow tracking is active\n */\n isUserFlowTrackingActive(): boolean {\n return this.userFlowTracker?.isTracking() ?? false;\n }\n\n /**\n * Destroy the SDK instance\n */\n destroy(): void {\n // Stop recording if active\n if (this.recorder) {\n this.recorder.destroy();\n this.recorder = null;\n }\n \n // Stop proactive tracking if active\n if (this.proactiveTracker) {\n this.proactiveTracker.stop();\n this.proactiveTracker = null;\n }\n \n // Stop user flow tracking if active\n if (this.userFlowTracker) {\n this.userFlowTracker.stop();\n this.userFlowTracker = null;\n }\n \n this.actions.clear();\n this.eventListeners.clear();\n this.sessionToken = null;\n this.isReady = false;\n }\n}\n\n// Factory function\nexport function createProduck(config: ProduckConfig): ProduckSDK {\n return new ProduckSDK(config);\n}\n\n// Default export\nexport default ProduckSDK;\n"],"mappings":"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","names":["isBrowser","generateSessionId","getCurrentUrl","getDeviceInfo","canvas","mergeConfig","mergeConfig","isBrowser","generateSessionId","getCurrentUrl","getDeviceInfo"]}
|