ainamika-sdk 1.2.2 → 1.2.4
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/ainamika-sdk.js +1 -1
- package/dist/ainamika-sdk.js.map +1 -1
- package/dist/sdk.d.ts +15 -0
- package/package.json +1 -1
package/dist/ainamika-sdk.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ainamika-sdk.js","mappings":"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","sources":["webpack://AInamikaSDKPro/webpack/universalModuleDefinition","webpack://AInamikaSDKPro/webpack/bootstrap","webpack://AInamikaSDKPro/webpack/runtime/define property getters","webpack://AInamikaSDKPro/webpack/runtime/hasOwnProperty shorthand","webpack://AInamikaSDKPro/./src/error-tracker.ts","webpack://AInamikaSDKPro/./src/error-storage.ts","webpack://AInamikaSDKPro/./src/config.ts","webpack://AInamikaSDKPro/./src/user-manager.ts","webpack://AInamikaSDKPro/./src/journey-tracker.ts","webpack://AInamikaSDKPro/./src/auth-manager.ts","webpack://AInamikaSDKPro/./src/advanced-tracker.ts","webpack://AInamikaSDKPro/./src/sdk.ts"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"AInamikaSDKPro\"] = factory();\n\telse\n\t\troot[\"AInamikaSDKPro\"] = factory();\n})((typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : typeof global !== \"undefined\" ? global : this), function() {\nreturn ","// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// error-tracker.ts - Advanced Error Tracking System for AInamika SDK\n\nimport { AuthManager } from './auth-manager';\n\nexport interface ErrorConfig {\n endpoint: string;\n clientId: string;\n apiKey?: string; // Made optional for backward compatibility\n authManager?: AuthManager; // New: pass authManager for JWT auth\n projectKey?: string; // Project key for project-based error tracking\n captureScreenshots?: boolean;\n captureDomSnapshots?: boolean;\n maxStackTraceDepth?: number;\n maxErrorsPerSession?: number;\n debounceMs?: number;\n enableNetworkTracking?: boolean;\n enableConsoleCapture?: boolean;\n}\n\nexport interface ErrorData {\n id?: string;\n client_id: string;\n project_key?: string; // Project key for project-based error tracking\n error_type: 'javascript' | 'network' | 'unhandled' | 'console' | 'custom';\n message: string;\n stack_trace?: string;\n url: string;\n user_agent: string;\n timestamp: number;\n error_metadata: {\n line?: number;\n column?: number;\n filename?: string;\n component?: string;\n props?: Record<string, any>;\n userId?: string;\n sessionId?: string;\n breadcrumbs?: ErrorBreadcrumb[];\n networkInfo?: NetworkInfo;\n performance?: PerformanceInfo;\n deviceInfo?: DeviceInfo;\n };\n dom_snapshot?: string;\n screen_snapshot?: string;\n severity: 'low' | 'medium' | 'high' | 'critical';\n session_id: string;\n user_id?: string;\n}\n\nexport interface ErrorBreadcrumb {\n timestamp: number;\n type: 'navigation' | 'click' | 'console' | 'network' | 'error';\n message: string;\n data?: Record<string, any>;\n}\n\nexport interface NetworkInfo {\n effectiveType?: string;\n downlink?: number;\n rtt?: number;\n saveData?: boolean;\n}\n\nexport interface PerformanceInfo {\n memory?: {\n usedJSHeapSize: number;\n totalJSHeapSize: number;\n jsHeapSizeLimit: number;\n };\n timing?: {\n domContentLoaded: number;\n load: number;\n firstPaint?: number;\n firstContentfulPaint?: number;\n };\n}\n\nexport interface DeviceInfo {\n deviceType: 'desktop' | 'mobile' | 'tablet';\n os: string;\n osVersion: string;\n browser: string;\n browserVersion: string;\n screenWidth: number;\n screenHeight: number;\n language: string;\n timezone: string;\n}\n\nexport class ErrorTracker {\n private config: ErrorConfig;\n private breadcrumbs: ErrorBreadcrumb[] = [];\n private errorCount = 0;\n private errorDebounceMap = new Map<string, number>();\n private originalConsole: Console;\n private sessionId: string;\n private userId?: string;\n private authManager?: AuthManager;\n\n constructor(config: ErrorConfig) {\n this.config = {\n captureScreenshots: false, // Disabled by default - loads html2canvas when enabled\n captureDomSnapshots: false, // Disabled - DOM snapshots are not used\n maxStackTraceDepth: 50,\n maxErrorsPerSession: 100,\n debounceMs: 1000,\n enableNetworkTracking: true,\n enableConsoleCapture: true,\n ...config\n };\n\n this.authManager = config.authManager;\n this.sessionId = this.generateSessionId();\n this.originalConsole = { ...console };\n this.initialize();\n }\n\n private html2canvasLoaded = false;\n private html2canvasLoading: Promise<boolean> | null = null;\n private isCapturingScreenshot = false; // Flag to prevent infinite loops during screenshot capture\n\n private async loadHtml2Canvas(): Promise<boolean> {\n // Return if already loaded\n if (this.html2canvasLoaded || typeof (window as any).html2canvas === 'function') {\n this.html2canvasLoaded = true;\n return true;\n }\n\n // Return existing loading promise if already loading\n if (this.html2canvasLoading) {\n return this.html2canvasLoading;\n }\n\n // Load html2canvas dynamically\n this.html2canvasLoading = new Promise<boolean>((resolve) => {\n const script = document.createElement('script');\n script.src = 'https://html2canvas.hertzen.com/dist/html2canvas.min.js';\n script.async = true;\n\n script.onload = () => {\n console.log('[AInamika Error Tracker] html2canvas loaded successfully');\n this.html2canvasLoaded = true;\n resolve(true);\n };\n\n script.onerror = () => {\n console.error('[AInamika Error Tracker] Failed to load html2canvas');\n resolve(false);\n };\n\n document.head.appendChild(script);\n });\n\n return this.html2canvasLoading;\n }\n\n private initialize() {\n // Global error handler\n window.addEventListener('error', (event) => {\n this.handleError({\n type: 'javascript',\n message: event.message,\n filename: event.filename,\n line: event.lineno,\n column: event.colno,\n error: event.error\n });\n });\n\n // Unhandled promise rejection handler\n window.addEventListener('unhandledrejection', (event) => {\n this.handleError({\n type: 'unhandled',\n message: event.reason?.message || 'Unhandled Promise Rejection',\n error: event.reason,\n promise: true\n });\n });\n\n // Network error tracking\n if (this.config.enableNetworkTracking) {\n this.setupNetworkTracking();\n }\n\n // Console capture\n if (this.config.enableConsoleCapture) {\n this.setupConsoleCapture();\n }\n\n // Navigation breadcrumbs\n this.setupNavigationTracking();\n\n // Click breadcrumbs\n this.setupClickTracking();\n\n // Preload html2canvas if screenshot capture is enabled\n if (this.config.captureScreenshots) {\n this.loadHtml2Canvas();\n }\n\n console.log('[AInamika Error Tracker] Initialized successfully');\n }\n\n private generateSessionId(): string {\n return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n }\n\n private addBreadcrumb(breadcrumb: Omit<ErrorBreadcrumb, 'timestamp'>) {\n this.breadcrumbs.push({\n ...breadcrumb,\n timestamp: Date.now()\n });\n\n // Keep only last 50 breadcrumbs\n if (this.breadcrumbs.length > 50) {\n this.breadcrumbs = this.breadcrumbs.slice(-50);\n }\n }\n\n private handleError(errorInfo: any) {\n if (this.errorCount >= this.config.maxErrorsPerSession!) {\n console.warn('[AInamika Error Tracker] Max errors per session reached');\n return;\n }\n\n const errorKey = `${errorInfo.message}_${errorInfo.filename}_${errorInfo.line}`;\n const now = Date.now();\n \n // Debounce duplicate errors\n if (this.errorDebounceMap.has(errorKey)) {\n const lastTime = this.errorDebounceMap.get(errorKey)!;\n if (now - lastTime < this.config.debounceMs!) {\n return;\n }\n }\n this.errorDebounceMap.set(errorKey, now);\n\n this.errorCount++;\n this.captureError(errorInfo);\n }\n\n private async captureError(errorInfo: any) {\n try {\n const errorData: ErrorData = {\n client_id: this.config.clientId,\n project_key: this.config.projectKey, // Include project_key for project-based tracking\n error_type: errorInfo.type || 'javascript',\n message: errorInfo.message || 'Unknown error',\n stack_trace: this.extractStackTrace(errorInfo.error),\n url: window.location.href,\n user_agent: navigator.userAgent,\n timestamp: Date.now(),\n error_metadata: {\n line: errorInfo.line,\n column: errorInfo.column,\n filename: errorInfo.filename,\n userId: this.userId,\n sessionId: this.sessionId,\n breadcrumbs: [...this.breadcrumbs],\n networkInfo: this.getNetworkInfo(),\n performance: this.getPerformanceInfo(),\n deviceInfo: this.getDeviceInfo()\n },\n severity: this.assessSeverity(errorInfo),\n session_id: this.sessionId,\n user_id: this.userId\n };\n\n // DOM snapshot capture disabled - not used in dashboard\n\n // Capture screenshot\n if (this.config.captureScreenshots) {\n errorData.screen_snapshot = await this.captureScreenshot();\n }\n\n // Send error to backend\n await this.sendError(errorData);\n\n // Add error breadcrumb\n this.addBreadcrumb({\n type: 'error',\n message: `${errorData.error_type}: ${errorData.message}`,\n data: { severity: errorData.severity }\n });\n\n } catch (captureError) {\n console.error('[AInamika Error Tracker] Failed to capture error:', captureError);\n }\n }\n\n private extractStackTrace(error: Error): string {\n if (!error || !error.stack) return '';\n \n const stack = error.stack.split('\\n');\n const maxDepth = this.config.maxStackTraceDepth!;\n \n return stack.slice(0, maxDepth).join('\\n');\n }\n\n private assessSeverity(errorInfo: any): 'low' | 'medium' | 'high' | 'critical' {\n const message = errorInfo.message?.toLowerCase() || '';\n \n // Critical errors\n if (message.includes('out of memory') || \n message.includes('security') ||\n message.includes('permission denied') ||\n errorInfo.type === 'unhandled') {\n return 'critical';\n }\n \n // High severity\n if (message.includes('network') || \n message.includes('timeout') ||\n message.includes('failed to fetch') ||\n message.includes('cors')) {\n return 'high';\n }\n \n // Medium severity\n if (message.includes('undefined') || \n message.includes('null') ||\n message.includes('cannot read property')) {\n return 'medium';\n }\n \n return 'low';\n }\n\n private captureDomSnapshot(): string {\n try {\n // Create a simplified DOM snapshot\n const snapshot = {\n url: window.location.href,\n title: document.title,\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight\n },\n elements: this.extractDomElements()\n };\n \n return JSON.stringify(snapshot);\n } catch (error) {\n console.error('[AInamika Error Tracker] Failed to capture DOM snapshot:', error);\n return '';\n }\n }\n\n private extractDomElements(): any[] {\n const elements: any[] = [];\n const maxElements = 100;\n \n // Get key elements\n const selectors = [\n 'body > *',\n '[id]',\n '[class*=\"error\"]',\n '[class*=\"modal\"]',\n 'form',\n 'button',\n 'input[type=\"submit\"]'\n ];\n \n selectors.forEach(selector => {\n try {\n const els = document.querySelectorAll(selector);\n Array.from(els).slice(0, maxElements - elements.length).forEach(el => {\n elements.push({\n tagName: el.tagName,\n id: el.id,\n className: el.className,\n textContent: el.textContent?.substring(0, 100),\n attributes: this.getElementAttributes(el)\n });\n });\n } catch (e) {\n // Ignore selector errors\n }\n });\n \n return elements;\n }\n\n private getElementAttributes(element: Element): Record<string, string> {\n const attrs: Record<string, string> = {};\n const importantAttrs = ['id', 'class', 'type', 'name', 'value', 'href', 'src'];\n \n importantAttrs.forEach(attr => {\n const value = element.getAttribute(attr);\n if (value) attrs[attr] = value;\n });\n \n return attrs;\n }\n\n private async captureScreenshot(): Promise<string> {\n // Prevent recursive screenshot capture (html2canvas makes network calls that could trigger errors)\n if (this.isCapturingScreenshot) {\n return '';\n }\n\n this.isCapturingScreenshot = true;\n\n try {\n // Dynamically load html2canvas if not already loaded\n const loaded = await this.loadHtml2Canvas();\n if (!loaded) {\n console.warn('[AInamika Error Tracker] html2canvas not available, skipping screenshot');\n return '';\n }\n\n // Use html2canvas to capture screenshot\n if (typeof (window as any).html2canvas === 'function') {\n const canvas = await (window as any).html2canvas(document.body, {\n height: Math.min(window.innerHeight, 1000),\n width: Math.min(window.innerWidth, 1000),\n useCORS: true,\n logging: false // Disable html2canvas logging\n });\n return canvas.toDataURL('image/jpeg', 0.7);\n }\n return '';\n } catch (error) {\n console.error('[AInamika Error Tracker] Failed to capture screenshot:', error);\n return '';\n } finally {\n this.isCapturingScreenshot = false;\n }\n }\n\n private getNetworkInfo(): NetworkInfo {\n const connection = (navigator as any).connection || \n (navigator as any).mozConnection || \n (navigator as any).webkitConnection;\n \n if (!connection) return {};\n \n return {\n effectiveType: connection.effectiveType,\n downlink: connection.downlink,\n rtt: connection.rtt,\n saveData: connection.saveData\n };\n }\n\n private getPerformanceInfo(): PerformanceInfo {\n const info: PerformanceInfo = {};\n \n // Memory info\n if ((performance as any).memory) {\n info.memory = {\n usedJSHeapSize: (performance as any).memory.usedJSHeapSize,\n totalJSHeapSize: (performance as any).memory.totalJSHeapSize,\n jsHeapSizeLimit: (performance as any).memory.jsHeapSizeLimit\n };\n }\n \n // Timing info\n if (performance.timing) {\n const timing = performance.timing;\n info.timing = {\n domContentLoaded: timing.domContentLoadedEventEnd - timing.navigationStart,\n load: timing.loadEventEnd - timing.navigationStart\n };\n \n // Paint timings\n if (performance.getEntriesByType) {\n const paintEntries = performance.getEntriesByType('paint');\n paintEntries.forEach((entry: any) => {\n if (entry.name === 'first-paint') {\n info.timing!.firstPaint = entry.startTime;\n } else if (entry.name === 'first-contentful-paint') {\n info.timing!.firstContentfulPaint = entry.startTime;\n }\n });\n }\n }\n \n return info;\n }\n\n private getDeviceInfo(): DeviceInfo {\n const ua = navigator.userAgent;\n\n // Detect device type\n let deviceType: 'desktop' | 'mobile' | 'tablet' = 'desktop';\n if (/tablet|ipad|playbook|silk/i.test(ua)) {\n deviceType = 'tablet';\n } else if (/mobile|iphone|ipod|android|blackberry|opera mini|iemobile/i.test(ua)) {\n deviceType = 'mobile';\n }\n\n // Detect OS\n let os = 'Unknown';\n let osVersion = '';\n if (/windows/i.test(ua)) {\n os = 'Windows';\n const match = ua.match(/Windows NT (\\d+\\.\\d+)/);\n if (match) osVersion = match[1];\n } else if (/macintosh|mac os x/i.test(ua)) {\n os = 'macOS';\n const match = ua.match(/Mac OS X (\\d+[._]\\d+)/);\n if (match) osVersion = match[1].replace('_', '.');\n } else if (/android/i.test(ua)) {\n os = 'Android';\n const match = ua.match(/Android (\\d+(\\.\\d+)?)/);\n if (match) osVersion = match[1];\n } else if (/iphone|ipad|ipod/i.test(ua)) {\n os = 'iOS';\n const match = ua.match(/OS (\\d+[._]\\d+)/);\n if (match) osVersion = match[1].replace('_', '.');\n } else if (/linux/i.test(ua)) {\n os = 'Linux';\n }\n\n // Detect browser\n let browser = 'Unknown';\n let browserVersion = '';\n if (/edg/i.test(ua)) {\n browser = 'Edge';\n const match = ua.match(/Edg\\/(\\d+(\\.\\d+)?)/);\n if (match) browserVersion = match[1];\n } else if (/chrome/i.test(ua) && !/edg/i.test(ua)) {\n browser = 'Chrome';\n const match = ua.match(/Chrome\\/(\\d+(\\.\\d+)?)/);\n if (match) browserVersion = match[1];\n } else if (/safari/i.test(ua) && !/chrome/i.test(ua)) {\n browser = 'Safari';\n const match = ua.match(/Version\\/(\\d+(\\.\\d+)?)/);\n if (match) browserVersion = match[1];\n } else if (/firefox/i.test(ua)) {\n browser = 'Firefox';\n const match = ua.match(/Firefox\\/(\\d+(\\.\\d+)?)/);\n if (match) browserVersion = match[1];\n }\n\n return {\n deviceType,\n os,\n osVersion,\n browser,\n browserVersion,\n screenWidth: window.screen.width,\n screenHeight: window.screen.height,\n language: navigator.language || '',\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || ''\n };\n }\n\n private setupNetworkTracking() {\n // Override fetch\n const originalFetch = window.fetch;\n window.fetch = async (...args) => {\n const startTime = Date.now();\n const url = args[0] instanceof Request ? args[0].url : String(args[0]);\n \n try {\n const response = await originalFetch(...args);\n \n this.addBreadcrumb({\n type: 'network',\n message: `Fetch ${response.status} ${url}`,\n data: {\n url,\n status: response.status,\n duration: Date.now() - startTime\n }\n });\n \n if (!response.ok) {\n this.handleError({\n type: 'network',\n message: `Network request failed: ${response.status} ${response.statusText}`,\n url,\n status: response.status\n });\n }\n \n return response;\n } catch (error: any) {\n this.addBreadcrumb({\n type: 'network',\n message: `Fetch failed ${url}`,\n data: { url, error: error?.message || 'Unknown error' }\n });\n \n this.handleError({\n type: 'network',\n message: `Network request failed: ${error?.message || 'Unknown error'}`,\n url,\n error\n });\n \n throw error;\n }\n };\n\n // Override XMLHttpRequest\n const originalXHROpen = XMLHttpRequest.prototype.open;\n const originalXHRSend = XMLHttpRequest.prototype.send;\n \n XMLHttpRequest.prototype.open = function(method: string, url: string | URL, async?: boolean, username?: string | null, password?: string | null) {\n (this as any)._errorTracker = { method, url, startTime: Date.now() };\n return originalXHROpen.call(this, method, url, async || true, username, password);\n };\n \n XMLHttpRequest.prototype.send = function(...args) {\n const tracker = (this as any)._errorTracker;\n \n this.addEventListener('loadend', () => {\n if (tracker) {\n const duration = Date.now() - tracker.startTime;\n \n if (this.status >= 400) {\n this.dispatchEvent(new CustomEvent('networkerror', {\n detail: {\n type: 'network',\n message: `XHR request failed: ${this.status} ${this.statusText}`,\n url: tracker.url,\n status: this.status\n }\n }));\n }\n \n this.dispatchEvent(new CustomEvent('networkbreadcrumb', {\n detail: {\n type: 'network',\n message: `XHR ${this.status} ${tracker.url}`,\n data: {\n method: tracker.method,\n url: tracker.url,\n status: this.status,\n duration\n }\n }\n }));\n }\n });\n \n return originalXHRSend.call(this, ...args);\n };\n \n // Listen for custom events\n document.addEventListener('networkerror', (event: any) => {\n this.handleError(event.detail);\n });\n \n document.addEventListener('networkbreadcrumb', (event: any) => {\n this.addBreadcrumb(event.detail);\n });\n }\n\n private setupConsoleCapture() {\n // Override console methods\n ['error', 'warn'].forEach(method => {\n const original = this.originalConsole[method as keyof Console] as Function;\n (console as any)[method] = (...args: any[]) => {\n if (typeof original === 'function') {\n original.call(console, ...args);\n }\n \n if (method === 'error') {\n this.handleError({\n type: 'console',\n message: args.map(arg => String(arg)).join(' '),\n consoleMethod: method\n });\n }\n \n this.addBreadcrumb({\n type: 'console',\n message: `Console ${method}: ${args.map(arg => String(arg)).join(' ')}`,\n data: { level: method }\n });\n };\n });\n }\n\n private setupNavigationTracking() {\n // Track page changes\n let currentUrl = window.location.href;\n \n const trackNavigation = () => {\n const newUrl = window.location.href;\n if (newUrl !== currentUrl) {\n this.addBreadcrumb({\n type: 'navigation',\n message: `Navigation from ${currentUrl} to ${newUrl}`,\n data: { from: currentUrl, to: newUrl }\n });\n currentUrl = newUrl;\n }\n };\n \n // Listen for various navigation events\n window.addEventListener('popstate', trackNavigation);\n window.addEventListener('hashchange', trackNavigation);\n \n // Override pushState and replaceState\n const originalPushState = history.pushState;\n const originalReplaceState = history.replaceState;\n \n history.pushState = function(...args) {\n originalPushState.apply(this, args);\n setTimeout(trackNavigation, 0);\n };\n \n history.replaceState = function(...args) {\n originalReplaceState.apply(this, args);\n setTimeout(trackNavigation, 0);\n };\n }\n\n private setupClickTracking() {\n document.addEventListener('click', (event) => {\n const target = event.target as Element;\n if (!target) return;\n \n const selector = this.getElementSelector(target);\n const text = target.textContent?.trim().substring(0, 50) || '';\n \n this.addBreadcrumb({\n type: 'click',\n message: `Clicked ${selector}${text ? `: ${text}` : ''}`,\n data: {\n selector,\n text,\n tagName: target.tagName,\n id: target.id,\n className: target.className\n }\n });\n });\n }\n\n private getElementSelector(element: Element): string {\n if (element.id) return `#${element.id}`;\n if (element.className) {\n const classes = element.className.split(' ').filter(c => c).slice(0, 2);\n if (classes.length) return `.${classes.join('.')}`;\n }\n return element.tagName.toLowerCase();\n }\n\n private async sendError(errorData: ErrorData) {\n try {\n let headers: Record<string, string> = { 'Content-Type': 'application/json' };\n\n // Use authManager if available, otherwise fall back to apiKey\n if (this.authManager) {\n const authHeaders = await this.authManager.getAuthHeaders();\n headers = { ...headers, ...authHeaders };\n } else if (this.config.apiKey) {\n headers['Authorization'] = `Bearer ${this.config.apiKey}`;\n }\n\n const response = await fetch(`${this.config.endpoint}/api/v1/errors`, {\n method: 'POST',\n headers,\n body: JSON.stringify(errorData)\n });\n\n if (!response.ok) {\n throw new Error(`Failed to send error: ${response.status} ${response.statusText}`);\n }\n\n console.log('[AInamika Error Tracker] Error sent successfully');\n } catch (error) {\n console.error('[AInamika Error Tracker] Failed to send error:', error);\n // Store error locally for retry\n this.storeErrorLocally(errorData);\n }\n }\n\n private storeErrorLocally(errorData: ErrorData) {\n try {\n const stored = localStorage.getItem('ainamika_errors') || '[]';\n const errors = JSON.parse(stored);\n errors.push(errorData);\n \n // Keep only last 50 errors\n if (errors.length > 50) {\n errors.splice(0, errors.length - 50);\n }\n \n localStorage.setItem('ainamika_errors', JSON.stringify(errors));\n } catch (error) {\n console.error('[AInamika Error Tracker] Failed to store error locally:', error);\n }\n }\n\n // Public methods\n public captureException(error: Error, context?: Record<string, any>) {\n this.handleError({\n type: 'custom',\n message: error.message,\n error,\n context\n });\n }\n\n public setUser(userId: string) {\n this.userId = userId;\n }\n\n public addTag(key: string, value: string) {\n // Add custom tags to error metadata\n if (!this.config.clientId) {\n this.config.clientId += `_${key}:${value}`;\n }\n }\n\n public async flushStoredErrors() {\n try {\n const stored = localStorage.getItem('ainamika_errors');\n if (!stored) return;\n \n const errors = JSON.parse(stored);\n if (errors.length === 0) return;\n \n console.log(`[AInamika Error Tracker] Flushing ${errors.length} stored errors`);\n \n for (const error of errors) {\n await this.sendError(error);\n }\n \n localStorage.removeItem('ainamika_errors');\n } catch (error) {\n console.error('[AInamika Error Tracker] Failed to flush stored errors:', error);\n }\n }\n}\n","// error-storage.ts - Offline Storage and Queue Management for Error Tracking\n\nexport interface StoredError {\n id: string;\n errorData: any;\n timestamp: number;\n retryCount: number;\n lastRetry?: number;\n}\n\nexport interface StorageConfig {\n maxStorageSize: number;\n maxRetries: number;\n retryInterval: number;\n compressionEnabled: boolean;\n encryptionEnabled: boolean;\n endpoint?: string; // Base API endpoint URL\n}\n\nexport class ErrorStorage {\n private config: StorageConfig;\n private readonly STORAGE_KEY = 'ainamika_error_queue';\n private readonly METADATA_KEY = 'ainamika_error_metadata';\n private retryTimer?: number;\n private isProcessing = false;\n\n constructor(config: Partial<StorageConfig> = {}) {\n this.config = {\n maxStorageSize: 5 * 1024 * 1024, // 5MB\n maxRetries: 5,\n retryInterval: 30000, // 30 seconds\n compressionEnabled: true,\n encryptionEnabled: false,\n ...config\n };\n\n this.initialize();\n }\n\n private initialize() {\n this.cleanupOldErrors();\n this.startRetryTimer();\n this.setupStorageListener();\n \n // Process any existing errors on initialization\n setTimeout(() => this.processQueue(), 1000);\n }\n\n /**\n * Store error data with automatic compression and queue management\n */\n public async storeError(errorData: any): Promise<string> {\n try {\n const errorId = this.generateErrorId();\n const storedError: StoredError = {\n id: errorId,\n errorData: this.config.compressionEnabled ? this.compressData(errorData) : errorData,\n timestamp: Date.now(),\n retryCount: 0\n };\n\n await this.addToQueue(storedError);\n this.updateMetadata();\n \n // Trigger immediate processing\n setTimeout(() => this.processQueue(), 100);\n \n return errorId;\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to store error:', error);\n throw error;\n }\n }\n\n /**\n * Get all stored errors\n */\n public getStoredErrors(): StoredError[] {\n try {\n const stored = localStorage.getItem(this.STORAGE_KEY);\n if (!stored) return [];\n \n const errors = JSON.parse(stored) as StoredError[];\n return errors.map(error => ({\n ...error,\n errorData: this.config.compressionEnabled ? this.decompressData(error.errorData) : error.errorData\n }));\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to get stored errors:', error);\n return [];\n }\n }\n\n /**\n * Remove error from storage\n */\n public removeError(errorId: string): boolean {\n try {\n const errors = this.getQueueRaw();\n const filteredErrors = errors.filter(error => error.id !== errorId);\n \n if (filteredErrors.length !== errors.length) {\n localStorage.setItem(this.STORAGE_KEY, JSON.stringify(filteredErrors));\n this.updateMetadata();\n return true;\n }\n return false;\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to remove error:', error);\n return false;\n }\n }\n\n /**\n * Clear all stored errors\n */\n public clearAll(): void {\n try {\n localStorage.removeItem(this.STORAGE_KEY);\n localStorage.removeItem(this.METADATA_KEY);\n console.log('[AInamika Error Storage] All errors cleared');\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to clear errors:', error);\n }\n }\n\n /**\n * Get storage statistics\n */\n public getStorageStats(): {\n errorCount: number;\n totalSize: number;\n oldestError?: number;\n newestError?: number;\n } {\n try {\n const errors = this.getQueueRaw();\n const totalSize = new Blob([localStorage.getItem(this.STORAGE_KEY) || '']).size;\n \n const timestamps = errors.map(e => e.timestamp).sort();\n \n return {\n errorCount: errors.length,\n totalSize,\n oldestError: timestamps[0],\n newestError: timestamps[timestamps.length - 1]\n };\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to get storage stats:', error);\n return { errorCount: 0, totalSize: 0 };\n }\n }\n\n /**\n * Process the error queue - attempt to send stored errors\n */\n public async processQueue(): Promise<void> {\n if (this.isProcessing) return;\n \n this.isProcessing = true;\n \n try {\n const errors = this.getQueueRaw();\n if (errors.length === 0) return;\n \n console.log(`[AInamika Error Storage] Processing ${errors.length} queued errors`);\n \n for (const storedError of errors) {\n if (storedError.retryCount >= this.config.maxRetries) {\n console.warn(`[AInamika Error Storage] Max retries reached for error ${storedError.id}`);\n this.removeError(storedError.id);\n continue;\n }\n\n // Check retry interval\n if (storedError.lastRetry && \n Date.now() - storedError.lastRetry < this.config.retryInterval) {\n continue;\n }\n\n try {\n const success = await this.sendError(storedError);\n if (success) {\n this.removeError(storedError.id);\n console.log(`[AInamika Error Storage] Successfully sent error ${storedError.id}`);\n } else {\n this.incrementRetryCount(storedError.id);\n }\n } catch (error) {\n console.error(`[AInamika Error Storage] Failed to send error ${storedError.id}:`, error);\n this.incrementRetryCount(storedError.id);\n }\n }\n } finally {\n this.isProcessing = false;\n }\n }\n\n /**\n * Force retry of a specific error\n */\n public async retryError(errorId: string): Promise<boolean> {\n const errors = this.getQueueRaw();\n const error = errors.find(e => e.id === errorId);\n \n if (!error) return false;\n \n try {\n const success = await this.sendError(error);\n if (success) {\n this.removeError(errorId);\n return true;\n } else {\n this.incrementRetryCount(errorId);\n return false;\n }\n } catch (err) {\n console.error(`[AInamika Error Storage] Failed to retry error ${errorId}:`, err);\n this.incrementRetryCount(errorId);\n return false;\n }\n }\n\n private async addToQueue(storedError: StoredError): Promise<void> {\n const errors = this.getQueueRaw();\n errors.push(storedError);\n \n // Check storage size limit\n const serialized = JSON.stringify(errors);\n if (new Blob([serialized]).size > this.config.maxStorageSize) {\n // Remove oldest errors until under limit\n while (errors.length > 0 && new Blob([JSON.stringify(errors)]).size > this.config.maxStorageSize) {\n errors.shift();\n console.warn('[AInamika Error Storage] Removed old error due to size limit');\n }\n }\n \n localStorage.setItem(this.STORAGE_KEY, JSON.stringify(errors));\n }\n\n private getQueueRaw(): StoredError[] {\n try {\n const stored = localStorage.getItem(this.STORAGE_KEY);\n return stored ? JSON.parse(stored) : [];\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to parse stored errors:', error);\n return [];\n }\n }\n\n private incrementRetryCount(errorId: string): void {\n try {\n const errors = this.getQueueRaw();\n const errorIndex = errors.findIndex(e => e.id === errorId);\n \n if (errorIndex !== -1) {\n errors[errorIndex].retryCount++;\n errors[errorIndex].lastRetry = Date.now();\n localStorage.setItem(this.STORAGE_KEY, JSON.stringify(errors));\n }\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to increment retry count:', error);\n }\n }\n\n private async sendError(storedError: StoredError): Promise<boolean> {\n try {\n const errorData = this.config.compressionEnabled ?\n this.decompressData(storedError.errorData) :\n storedError.errorData;\n\n // Use endpoint from config (passed during initialization) or from stored error data\n const endpoint = this.config.endpoint || errorData.endpoint;\n if (!endpoint) {\n console.error('[AInamika Error Storage] No endpoint configured for sending errors');\n return false;\n }\n\n const apiKey = errorData.apiKey || '';\n\n const response = await fetch(`${endpoint}/api/v1/errors`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': apiKey ? `Bearer ${apiKey}` : ''\n },\n body: JSON.stringify(errorData)\n });\n\n return response.ok;\n } catch (error) {\n console.error('[AInamika Error Storage] Network error sending stored error:', error);\n return false;\n }\n }\n\n private compressData(data: any): string {\n try {\n // Simple compression using JSON + base64\n const jsonString = JSON.stringify(data);\n return btoa(jsonString);\n } catch (error) {\n console.warn('[AInamika Error Storage] Compression failed, storing uncompressed:', error);\n return data;\n }\n }\n\n private decompressData(compressedData: any): any {\n try {\n if (typeof compressedData === 'string' && compressedData.length > 0) {\n const jsonString = atob(compressedData);\n return JSON.parse(jsonString);\n }\n return compressedData;\n } catch (error) {\n console.warn('[AInamika Error Storage] Decompression failed, returning raw data:', error);\n return compressedData;\n }\n }\n\n private generateErrorId(): string {\n return `error_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n }\n\n private cleanupOldErrors(): void {\n try {\n const errors = this.getQueueRaw();\n const cutoffTime = Date.now() - (7 * 24 * 60 * 60 * 1000); // 7 days\n \n const cleanErrors = errors.filter(error => error.timestamp > cutoffTime);\n \n if (cleanErrors.length !== errors.length) {\n localStorage.setItem(this.STORAGE_KEY, JSON.stringify(cleanErrors));\n console.log(`[AInamika Error Storage] Cleaned up ${errors.length - cleanErrors.length} old errors`);\n }\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to cleanup old errors:', error);\n }\n }\n\n private startRetryTimer(): void {\n this.retryTimer = window.setInterval(() => {\n this.processQueue();\n }, this.config.retryInterval);\n }\n\n private setupStorageListener(): void {\n // Listen for storage changes from other tabs\n window.addEventListener('storage', (event) => {\n if (event.key === this.STORAGE_KEY) {\n console.log('[AInamika Error Storage] Storage updated from another tab');\n setTimeout(() => this.processQueue(), 1000);\n }\n });\n\n // Listen for online/offline events\n window.addEventListener('online', () => {\n console.log('[AInamika Error Storage] Network back online, processing queue');\n setTimeout(() => this.processQueue(), 1000);\n });\n\n window.addEventListener('offline', () => {\n console.log('[AInamika Error Storage] Network offline, errors will be queued');\n });\n }\n\n private updateMetadata(): void {\n try {\n const stats = this.getStorageStats();\n const metadata = {\n lastUpdate: Date.now(),\n ...stats\n };\n localStorage.setItem(this.METADATA_KEY, JSON.stringify(metadata));\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to update metadata:', error);\n }\n }\n\n /**\n * Export stored errors for debugging\n */\n public exportErrors(): string {\n try {\n const errors = this.getStoredErrors();\n const exportData = {\n timestamp: Date.now(),\n version: '1.0',\n stats: this.getStorageStats(),\n errors: errors\n };\n return JSON.stringify(exportData, null, 2);\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to export errors:', error);\n return '{}';\n }\n }\n\n /**\n * Import errors from export\n */\n public importErrors(exportData: string): boolean {\n try {\n const data = JSON.parse(exportData);\n if (!data.errors || !Array.isArray(data.errors)) {\n throw new Error('Invalid export format');\n }\n\n this.clearAll();\n \n for (const errorData of data.errors) {\n this.storeError(errorData.errorData);\n }\n \n console.log(`[AInamika Error Storage] Imported ${data.errors.length} errors`);\n return true;\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to import errors:', error);\n return false;\n }\n }\n\n /**\n * Cleanup and destroy the storage instance\n */\n public destroy(): void {\n if (this.retryTimer) {\n clearInterval(this.retryTimer);\n this.retryTimer = undefined;\n }\n \n // Final attempt to process queue\n this.processQueue();\n \n console.log('[AInamika Error Storage] Storage instance destroyed');\n }\n}\n\n/**\n * Utility functions for error storage management\n */\nexport class ErrorStorageUtils {\n /**\n * Get total localStorage usage for AInamika\n */\n static getAinamikaStorageUsage(): { \n totalSize: number; \n errorSize: number; \n otherSize: number; \n } {\n let totalSize = 0;\n let errorSize = 0;\n let otherSize = 0;\n\n for (let key in localStorage) {\n if (localStorage.hasOwnProperty(key)) {\n const size = new Blob([localStorage.getItem(key) || '']).size;\n totalSize += size;\n \n if (key.startsWith('ainamika_error')) {\n errorSize += size;\n } else if (key.startsWith('ainamika_')) {\n otherSize += size;\n }\n }\n }\n\n return { totalSize, errorSize, otherSize };\n }\n\n /**\n * Check if localStorage has enough space\n */\n static checkStorageSpace(requiredBytes: number): boolean {\n try {\n const testKey = 'ainamika_storage_test';\n const testData = 'x'.repeat(Math.min(requiredBytes, 1024 * 1024));\n \n localStorage.setItem(testKey, testData);\n localStorage.removeItem(testKey);\n \n return true;\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Clean up all AInamika storage\n */\n static cleanupAllAinamikaStorage(): void {\n const keysToRemove: string[] = [];\n \n for (let key in localStorage) {\n if (key.startsWith('ainamika_')) {\n keysToRemove.push(key);\n }\n }\n \n keysToRemove.forEach(key => localStorage.removeItem(key));\n console.log(`[AInamika Storage Utils] Cleaned up ${keysToRemove.length} storage keys`);\n }\n\n /**\n * Generate storage report\n */\n static generateStorageReport(): {\n usage: ReturnType<typeof ErrorStorageUtils.getAinamikaStorageUsage>;\n errors: any[];\n metadata: any;\n } {\n const storage = new ErrorStorage();\n \n return {\n usage: ErrorStorageUtils.getAinamikaStorageUsage(),\n errors: storage.getStoredErrors(),\n metadata: storage.getStorageStats()\n };\n }\n}\n","// config.ts - Environment-based configuration for Ainamika SDK\n\nexport interface EnvironmentConfig {\n API_BASE_URL: string;\n APP_ENV: 'development' | 'production';\n DEBUG: boolean;\n}\n\n// Environment configuration with fallbacks\ndeclare global {\n interface Window {\n __AINAMIKA_CONFIG__?: EnvironmentConfig;\n }\n}\n\n// Production API URL - using proxy that routes to Kubernetes backend\nconst PRODUCTION_API_URL = 'https://ainamika-webhook-proxy-366651516847.asia-south1.run.app';\n\n// Get environment configuration\nfunction getEnvironmentConfig(): EnvironmentConfig {\n // Check for explicitly set configuration (allows override via apiDetails)\n if (typeof window !== 'undefined' && window.__AINAMIKA_CONFIG__) {\n return window.__AINAMIKA_CONFIG__;\n }\n\n // Always use production URLs for npm package\n // Users can override via apiDetails config option if needed\n return {\n API_BASE_URL: PRODUCTION_API_URL,\n APP_ENV: 'production',\n DEBUG: false\n };\n}\n\nexport const ENV_CONFIG = getEnvironmentConfig();\n\n// API endpoint configuration\nexport const API_ENDPOINTS = {\n EVENTS: `${ENV_CONFIG.API_BASE_URL}/api/v1/events`,\n ERRORS: `${ENV_CONFIG.API_BASE_URL}/api/errors/report`,\n CONFIG: `${ENV_CONFIG.API_BASE_URL}/api/v1/sdk/config`,\n DEBUG_EVENTS: `${ENV_CONFIG.API_BASE_URL}/api/v1/debug/events`,\n // Project-based endpoints\n PROJECTS_LOOKUP: `${ENV_CONFIG.API_BASE_URL}/api/v1/projects/lookup`,\n SAMPLING_CHECK: `${ENV_CONFIG.API_BASE_URL}/api/v1/projects/sampling/check`\n};\n\n// Configuration helper function\nexport function configureSDK(config: Partial<EnvironmentConfig>) {\n if (typeof window !== 'undefined') {\n window.__AINAMIKA_CONFIG__ = { ...ENV_CONFIG, ...config };\n }\n}\n\n","/**\n * User Manager Module\n * Handles user identification for hybrid tracking (anonymous + authenticated)\n */\n\nexport class UserManager {\n private userId: string | null = null;\n private userProperties: Record<string, any> = {};\n\n constructor() {\n this.initializeUser();\n }\n\n /**\n * Initialize user on module load\n */\n private initializeUser(): void {\n this.userId = this.getOrCreateUserId();\n }\n\n /**\n * Generate or retrieve persistent anonymous user ID\n */\n private getOrCreateUserId(): string {\n try {\n let userId = localStorage.getItem('ainamika_user_id');\n\n if (!userId) {\n userId = this.generateAnonymousId();\n localStorage.setItem('ainamika_user_id', userId);\n }\n\n return userId;\n } catch (error) {\n // Fallback for environments without localStorage\n console.warn('[UserManager] localStorage not available, using session ID');\n return this.generateAnonymousId();\n }\n }\n\n /**\n * Generate a new anonymous user ID\n */\n private generateAnonymousId(): string {\n return 'anon_' + Math.random().toString(36).substr(2, 9) + '_' + Date.now();\n }\n\n /**\n * Get current user ID\n */\n public getUserId(): string {\n if (!this.userId) {\n this.userId = this.getOrCreateUserId();\n }\n return this.userId;\n }\n\n /**\n * Get user properties\n */\n public getUserProperties(): Record<string, any> {\n return { ...this.userProperties };\n }\n\n /**\n * Identify user with authenticated ID\n * Merges anonymous session with authenticated user\n */\n public identifyUser(authenticatedUserId: string, properties?: Record<string, any>): void {\n const previousId = this.getUserId();\n\n try {\n // Update stored user ID\n localStorage.setItem('ainamika_user_id', authenticatedUserId);\n this.userId = authenticatedUserId;\n\n // Merge properties\n if (properties) {\n this.userProperties = {\n ...this.userProperties,\n ...properties\n };\n }\n\n console.log(`[UserManager] User identified: ${previousId} → ${authenticatedUserId}`);\n } catch (error) {\n console.error('[UserManager] Error identifying user:', error);\n }\n }\n\n /**\n * Update user properties\n */\n public updateUserProperties(properties: Record<string, any>): void {\n this.userProperties = {\n ...this.userProperties,\n ...properties\n };\n }\n\n /**\n * Clear user data (logout)\n */\n public clearUser(): void {\n try {\n localStorage.removeItem('ainamika_user_id');\n this.userId = null;\n this.userProperties = {};\n\n // Generate new anonymous ID for next session\n this.initializeUser();\n } catch (error) {\n console.error('[UserManager] Error clearing user:', error);\n }\n }\n\n /**\n * Get user identification event data\n * Used when upgrading from anonymous to authenticated\n */\n public getUserIdentificationEvent(authenticatedUserId: string): Record<string, any> {\n return {\n event: 'user_identified',\n previous_id: this.getUserId(),\n user_id: authenticatedUserId,\n timestamp: Date.now(),\n properties: this.userProperties\n };\n }\n\n /**\n * Check if current user is anonymous\n */\n public isAnonymousUser(): boolean {\n const userId = this.getUserId();\n return userId.startsWith('anon_');\n }\n\n /**\n * Get user type (anonymous or authenticated)\n */\n public getUserType(): 'anonymous' | 'authenticated' {\n return this.isAnonymousUser() ? 'anonymous' : 'authenticated';\n }\n}","/**\n * Journey Tracker Module\n * Tracks user journeys for funnel analysis\n */\n\ninterface JourneyEvent {\n eventName: string;\n timestamp: number;\n properties: Record<string, any>;\n sequenceIndex: number;\n}\n\ninterface JourneyContext {\n journeySequence: string[];\n eventCount: number;\n lastEventTime: number;\n journeyStartTime: number;\n timeSinceLastEvent: number;\n}\n\nexport class JourneyTracker {\n private userJourney: JourneyEvent[] = [];\n private journeyStartTime: number;\n private lastEventTime: number = 0;\n private sequenceIndex: number = 0;\n private maxJourneyLength: number = 50; // Limit journey size for performance\n private journeyAnalysisThreshold: number = 5; // Send for analysis after 5 events\n\n constructor() {\n this.journeyStartTime = Date.now();\n }\n\n /**\n * Add event to user journey\n */\n public trackEvent(eventName: string, properties: Record<string, any>): void {\n const currentTime = Date.now();\n const timeSinceLastEvent = this.lastEventTime ? currentTime - this.lastEventTime : 0;\n\n const journeyEvent: JourneyEvent = {\n eventName,\n timestamp: currentTime,\n properties: {\n ...properties,\n timeSinceLastEvent,\n journeyPosition: this.sequenceIndex\n },\n sequenceIndex: this.sequenceIndex++\n };\n\n this.userJourney.push(journeyEvent);\n this.lastEventTime = currentTime;\n\n // Maintain journey size limit\n if (this.userJourney.length > this.maxJourneyLength) {\n this.userJourney = this.userJourney.slice(-this.maxJourneyLength);\n }\n\n // Log journey progress\n console.log(`[JourneyTracker] Event tracked: ${eventName} (position: ${journeyEvent.sequenceIndex})`);\n }\n\n /**\n * Get current journey context\n */\n public getContext(): JourneyContext {\n const currentTime = Date.now();\n\n return {\n journeySequence: this.getJourneySequence(),\n eventCount: this.userJourney.length,\n lastEventTime: this.lastEventTime,\n journeyStartTime: this.journeyStartTime,\n timeSinceLastEvent: this.lastEventTime ? currentTime - this.lastEventTime : 0\n };\n }\n\n /**\n * Get journey as sequence of event names\n */\n public getJourneySequence(): string[] {\n return this.userJourney.map(event => event.eventName);\n }\n\n /**\n * Get full journey data\n */\n public getJourneyData(): JourneyEvent[] {\n return [...this.userJourney];\n }\n\n /**\n * Check if journey should be sent for analysis\n */\n public shouldAnalyzeJourney(): boolean {\n return this.userJourney.length >= this.journeyAnalysisThreshold &&\n this.userJourney.length % this.journeyAnalysisThreshold === 0;\n }\n\n /**\n * Get journey data for analysis\n */\n public getJourneyForAnalysis(): Record<string, any> {\n const journeyDuration = Date.now() - this.journeyStartTime;\n const avgTimeBetweenEvents = this.calculateAverageTimeBetweenEvents();\n\n return {\n journey: this.userJourney.map(event => ({\n name: event.eventName,\n timestamp: event.timestamp,\n properties: event.properties\n })),\n metadata: {\n journeyLength: this.userJourney.length,\n journeyDuration,\n avgTimeBetweenEvents,\n startTime: this.journeyStartTime,\n endTime: this.lastEventTime\n }\n };\n }\n\n /**\n * Calculate average time between events\n */\n private calculateAverageTimeBetweenEvents(): number {\n if (this.userJourney.length < 2) return 0;\n\n let totalTime = 0;\n for (let i = 1; i < this.userJourney.length; i++) {\n totalTime += this.userJourney[i].timestamp - this.userJourney[i - 1].timestamp;\n }\n\n return Math.round(totalTime / (this.userJourney.length - 1));\n }\n\n /**\n * Find patterns in journey (e.g., repeated sequences)\n */\n public findPatterns(): Record<string, number> {\n const patterns: Record<string, number> = {};\n const sequenceLength = 3; // Look for patterns of 3 events\n\n if (this.userJourney.length < sequenceLength) return patterns;\n\n for (let i = 0; i <= this.userJourney.length - sequenceLength; i++) {\n const sequence = this.userJourney\n .slice(i, i + sequenceLength)\n .map(e => e.eventName)\n .join(' → ');\n\n patterns[sequence] = (patterns[sequence] || 0) + 1;\n }\n\n // Filter out single occurrences\n return Object.fromEntries(\n Object.entries(patterns).filter(([_, count]) => count > 1)\n );\n }\n\n /**\n * Clear journey (for new session)\n */\n public clearJourney(): void {\n this.userJourney = [];\n this.sequenceIndex = 0;\n this.lastEventTime = 0;\n this.journeyStartTime = Date.now();\n }\n\n /**\n * Get journey segment (last N events)\n */\n public getJourneySegment(count: number): JourneyEvent[] {\n return this.userJourney.slice(-count);\n }\n\n /**\n * Check if user is in a potential funnel\n * Based on common funnel patterns\n */\n public detectPotentialFunnel(): string | null {\n const recentEvents = this.getJourneySequence().slice(-5);\n\n // Common funnel patterns\n const funnelPatterns: Record<string, string[]> = {\n 'signup_flow': ['view_pricing', 'click_signup', 'enter_email'],\n 'purchase_flow': ['view_product', 'add_to_cart', 'view_cart'],\n 'onboarding_flow': ['user_signup', 'profile_setup', 'tutorial_start']\n };\n\n for (const [funnelName, pattern] of Object.entries(funnelPatterns)) {\n const matchCount = pattern.filter(event =>\n recentEvents.includes(event)\n ).length;\n\n if (matchCount >= 2) {\n return funnelName;\n }\n }\n\n return null;\n }\n}","/**\n * Authentication Manager for Ainamika SDK\n *\n * Handles token generation, storage, and refresh for API authentication\n */\n\nexport interface AuthTokens {\n access_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n}\n\nexport class AuthManager {\n private accessToken: string | null = null;\n private refreshToken: string | null = null;\n private tokenExpiry: number | null = null;\n private clientId: string;\n private apiEndpoint: string;\n private refreshTimer?: NodeJS.Timeout;\n private debug: boolean;\n\n // Fixed storage key for auth tokens (no longer includes clientId)\n private static readonly STORAGE_KEY = 'ainamika_auth_token';\n\n constructor(clientId: string, apiEndpoint: string, debug: boolean = false) {\n this.clientId = clientId;\n this.apiEndpoint = apiEndpoint;\n this.debug = debug;\n\n // Load tokens from storage (validates clientId match)\n this.loadTokens();\n }\n\n /**\n * Initialize authentication by requesting tokens\n */\n async initialize(): Promise<boolean> {\n try {\n // Check if we have valid tokens\n if (this.isTokenValid()) {\n this.debugLog('Using existing valid token');\n return true;\n }\n\n // Try to refresh if we have a refresh token\n if (this.refreshToken) {\n const refreshed = await this.refreshAccessToken();\n if (refreshed) {\n return true;\n }\n }\n\n // Request new tokens\n const tokens = await this.requestTokens();\n if (tokens) {\n this.setTokens(tokens);\n return true;\n }\n\n return false;\n } catch (error) {\n this.debugLog('Authentication initialization failed:', error);\n return false;\n }\n }\n\n /**\n * Request new tokens from the server\n */\n private async requestTokens(): Promise<AuthTokens | null> {\n try {\n const response = await fetch(`${this.apiEndpoint}/api/v1/auth/token`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ client_id: this.clientId }),\n });\n\n if (!response.ok) {\n throw new Error(`Token request failed: ${response.status}`);\n }\n\n const tokens: AuthTokens = await response.json();\n return tokens;\n } catch (error) {\n this.debugLog('Token request error:', error);\n return null;\n }\n }\n\n /**\n * Refresh the access token using refresh token\n */\n async refreshAccessToken(): Promise<boolean> {\n if (!this.refreshToken) {\n return false;\n }\n\n try {\n const response = await fetch(`${this.apiEndpoint}/api/v1/auth/refresh`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ refresh_token: this.refreshToken }),\n });\n\n if (!response.ok) {\n // Refresh token is invalid, clear tokens\n this.clearTokens();\n return false;\n }\n\n const tokens: AuthTokens = await response.json();\n this.setTokens(tokens);\n return true;\n } catch (error) {\n this.debugLog('Token refresh error:', error);\n return false;\n }\n }\n\n /**\n * Get the current access token, refreshing if needed\n */\n async getAccessToken(): Promise<string | null> {\n // If token is expiring soon (within 5 minutes), refresh it\n if (this.shouldRefreshToken()) {\n await this.refreshAccessToken();\n }\n\n // If still no valid token, try to initialize\n if (!this.isTokenValid()) {\n const initialized = await this.initialize();\n if (!initialized) {\n return null;\n }\n }\n\n return this.accessToken;\n }\n\n /**\n * Get authorization headers for API requests\n */\n async getAuthHeaders(): Promise<Record<string, string>> {\n const token = await this.getAccessToken();\n\n if (token) {\n return {\n 'Authorization': `Bearer ${token}`,\n };\n }\n\n // Fallback to X-Client-ID for backward compatibility\n return {\n 'X-Client-ID': this.clientId,\n };\n }\n\n /**\n * Check if the current token is valid\n */\n private isTokenValid(): boolean {\n if (!this.accessToken || !this.tokenExpiry) {\n return false;\n }\n\n // Check if token has expired\n return Date.now() < this.tokenExpiry;\n }\n\n /**\n * Check if token should be refreshed (5 minutes before expiry)\n */\n private shouldRefreshToken(): boolean {\n if (!this.tokenExpiry || !this.refreshToken) {\n return false;\n }\n\n const fiveMinutes = 5 * 60 * 1000;\n return Date.now() > (this.tokenExpiry - fiveMinutes);\n }\n\n /**\n * Set tokens and schedule refresh\n */\n private setTokens(tokens: AuthTokens): void {\n this.accessToken = tokens.access_token;\n this.refreshToken = tokens.refresh_token || this.refreshToken;\n this.tokenExpiry = Date.now() + (tokens.expires_in * 1000);\n\n // Save to storage\n this.saveTokens();\n\n // Schedule token refresh\n this.scheduleTokenRefresh();\n\n this.debugLog('Tokens set successfully');\n }\n\n /**\n * Schedule automatic token refresh\n */\n private scheduleTokenRefresh(): void {\n // Clear existing timer\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer);\n }\n\n // Schedule refresh 5 minutes before expiry\n const refreshIn = Math.max(0, this.tokenExpiry! - Date.now() - (5 * 60 * 1000));\n\n this.refreshTimer = setTimeout(() => {\n this.refreshAccessToken();\n }, refreshIn);\n }\n\n /**\n * Save tokens to localStorage with fixed key\n */\n private saveTokens(): void {\n if (typeof window !== 'undefined' && window.localStorage) {\n const tokenData = {\n clientId: this.clientId, // Store clientId to validate on load\n accessToken: this.accessToken,\n refreshToken: this.refreshToken,\n tokenExpiry: this.tokenExpiry,\n };\n\n localStorage.setItem(AuthManager.STORAGE_KEY, JSON.stringify(tokenData));\n\n // Clean up any old dynamic keys from previous SDK versions\n this.cleanupLegacyTokens();\n }\n }\n\n /**\n * Remove old tokens stored with dynamic key format (ainamika_auth_<clientId>)\n */\n private cleanupLegacyTokens(): void {\n if (typeof window !== 'undefined' && window.localStorage) {\n const keysToRemove: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith('ainamika_auth_') && key !== AuthManager.STORAGE_KEY) {\n keysToRemove.push(key);\n }\n }\n keysToRemove.forEach(key => {\n localStorage.removeItem(key);\n this.debugLog('Removed legacy token key:', key);\n });\n }\n }\n\n /**\n * Load tokens from localStorage with clientId validation\n */\n private loadTokens(): void {\n if (typeof window !== 'undefined' && window.localStorage) {\n // Clean up legacy tokens first\n this.cleanupLegacyTokens();\n\n const stored = localStorage.getItem(AuthManager.STORAGE_KEY);\n\n if (stored) {\n try {\n const tokenData = JSON.parse(stored);\n\n // Validate clientId - if different, clear stored token\n if (tokenData.clientId && tokenData.clientId !== this.clientId) {\n this.debugLog('Stored token is for different clientId, clearing');\n localStorage.removeItem(AuthManager.STORAGE_KEY);\n return;\n }\n\n this.accessToken = tokenData.accessToken;\n this.refreshToken = tokenData.refreshToken;\n this.tokenExpiry = tokenData.tokenExpiry;\n\n // Schedule refresh if token is valid\n if (this.isTokenValid()) {\n this.scheduleTokenRefresh();\n }\n } catch (error) {\n this.debugLog('Failed to load stored tokens:', error);\n }\n }\n }\n }\n\n /**\n * Clear tokens\n */\n clearTokens(): void {\n this.accessToken = null;\n this.refreshToken = null;\n this.tokenExpiry = null;\n\n // Clear from storage (fixed key)\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.removeItem(AuthManager.STORAGE_KEY);\n // Also clean up any legacy keys\n this.cleanupLegacyTokens();\n }\n\n // Clear refresh timer\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer);\n this.refreshTimer = undefined;\n }\n }\n\n /**\n * Logout and clear authentication\n */\n async logout(): Promise<void> {\n try {\n if (this.accessToken) {\n await fetch(`${this.apiEndpoint}/api/v1/auth/logout`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.accessToken}`,\n },\n });\n }\n } catch (error) {\n this.debugLog('Logout error:', error);\n } finally {\n this.clearTokens();\n }\n }\n\n /**\n * Debug logging\n */\n private debugLog(...args: any[]): void {\n if (this.debug) {\n console.log('[Ainamika Auth]', ...args);\n }\n }\n}","// advanced-tracker.ts - Advanced Analytics Tracking for AInamika SDK\n// Provides: Performance tracking, Engagement metrics, API tracking, Smart event enrichment\n\nexport interface AdvancedTrackingConfig {\n trackPerformance?: boolean;\n trackEngagement?: boolean;\n trackScrollDepth?: boolean;\n trackRageClicks?: boolean;\n trackTimeOnPage?: boolean;\n trackAPIResponses?: boolean;\n scrollDepthThresholds?: number[];\n rageClickThreshold?: number;\n rageClickWindow?: number;\n apiTrackingPatterns?: string[];\n}\n\nexport interface PerformanceMetrics {\n // Core Web Vitals\n lcp?: number; // Largest Contentful Paint\n fid?: number; // First Input Delay\n cls?: number; // Cumulative Layout Shift\n fcp?: number; // First Contentful Paint\n ttfb?: number; // Time to First Byte\n // Page Load Timing\n domContentLoaded?: number;\n pageLoad?: number;\n // Resource Metrics\n resourceCount?: number;\n transferSize?: number;\n}\n\nexport interface EngagementMetrics {\n timeOnPage: number;\n scrollDepth: number;\n scrollDepthMilestones: number[];\n rageClicks: number;\n totalClicks: number;\n activeTime: number;\n idleTime: number;\n pageVisibilityChanges: number;\n}\n\nexport interface APITrackingEvent {\n url: string;\n method: string;\n status: number;\n duration: number;\n requestSize?: number;\n responseSize?: number;\n success: boolean;\n error?: string;\n timestamp: number;\n}\n\ntype EventCallback = (eventName: string, properties: Record<string, any>) => void;\n\nexport class AdvancedTracker {\n private config: AdvancedTrackingConfig;\n private onEvent: EventCallback;\n private performanceMetrics: PerformanceMetrics = {};\n private engagementMetrics: EngagementMetrics;\n private pageStartTime: number;\n private lastActivityTime: number;\n private scrollDepthReached: Set<number> = new Set();\n private clickHistory: number[] = [];\n private isPageVisible: boolean = true;\n private visibilityChangeCount: number = 0;\n private originalFetch: typeof fetch;\n private originalXHR: typeof XMLHttpRequest.prototype.open;\n\n constructor(config: AdvancedTrackingConfig, onEvent: EventCallback) {\n this.config = {\n trackPerformance: true,\n trackEngagement: true,\n trackScrollDepth: true,\n trackRageClicks: true,\n trackTimeOnPage: true,\n trackAPIResponses: false, // Opt-in for API tracking\n scrollDepthThresholds: [25, 50, 75, 90, 100],\n rageClickThreshold: 3,\n rageClickWindow: 1000, // 3 clicks within 1 second\n apiTrackingPatterns: [],\n ...config\n };\n\n this.onEvent = onEvent;\n this.pageStartTime = Date.now();\n this.lastActivityTime = Date.now();\n this.originalFetch = window.fetch.bind(window);\n this.originalXHR = XMLHttpRequest.prototype.open;\n\n this.engagementMetrics = {\n timeOnPage: 0,\n scrollDepth: 0,\n scrollDepthMilestones: [],\n rageClicks: 0,\n totalClicks: 0,\n activeTime: 0,\n idleTime: 0,\n pageVisibilityChanges: 0\n };\n\n this.initialize();\n }\n\n private initialize() {\n if (this.config.trackPerformance) {\n this.initPerformanceTracking();\n }\n\n if (this.config.trackEngagement) {\n this.initEngagementTracking();\n }\n\n if (this.config.trackScrollDepth) {\n this.initScrollTracking();\n }\n\n if (this.config.trackRageClicks) {\n this.initRageClickTracking();\n }\n\n if (this.config.trackTimeOnPage) {\n this.initTimeTracking();\n }\n\n if (this.config.trackAPIResponses) {\n this.initAPITracking();\n }\n\n // Track page unload\n window.addEventListener('beforeunload', () => {\n this.trackPageExit();\n });\n\n console.log('[AInamika Advanced Tracker] Initialized');\n }\n\n // ============= Performance Tracking =============\n\n private initPerformanceTracking() {\n // Track Core Web Vitals using PerformanceObserver\n if ('PerformanceObserver' in window) {\n // LCP - Largest Contentful Paint\n try {\n const lcpObserver = new PerformanceObserver((entryList) => {\n const entries = entryList.getEntries();\n const lastEntry = entries[entries.length - 1] as any;\n this.performanceMetrics.lcp = lastEntry.startTime;\n this.onEvent('performance_lcp', {\n value: lastEntry.startTime,\n element: lastEntry.element?.tagName\n });\n });\n lcpObserver.observe({ type: 'largest-contentful-paint', buffered: true });\n } catch (e) {\n console.debug('[Advanced Tracker] LCP not supported');\n }\n\n // FID - First Input Delay\n try {\n const fidObserver = new PerformanceObserver((entryList) => {\n const entries = entryList.getEntries();\n const firstEntry = entries[0] as any;\n this.performanceMetrics.fid = firstEntry.processingStart - firstEntry.startTime;\n this.onEvent('performance_fid', {\n value: this.performanceMetrics.fid,\n eventType: firstEntry.name\n });\n });\n fidObserver.observe({ type: 'first-input', buffered: true });\n } catch (e) {\n console.debug('[Advanced Tracker] FID not supported');\n }\n\n // CLS - Cumulative Layout Shift\n try {\n let clsValue = 0;\n const clsObserver = new PerformanceObserver((entryList) => {\n for (const entry of entryList.getEntries() as any[]) {\n if (!entry.hadRecentInput) {\n clsValue += entry.value;\n }\n }\n this.performanceMetrics.cls = clsValue;\n });\n clsObserver.observe({ type: 'layout-shift', buffered: true });\n\n // Report CLS on page hide\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') {\n this.onEvent('performance_cls', { value: clsValue });\n }\n });\n } catch (e) {\n console.debug('[Advanced Tracker] CLS not supported');\n }\n\n // FCP - First Contentful Paint\n try {\n const fcpObserver = new PerformanceObserver((entryList) => {\n const entries = entryList.getEntries();\n const fcpEntry = entries.find(e => e.name === 'first-contentful-paint');\n if (fcpEntry) {\n this.performanceMetrics.fcp = fcpEntry.startTime;\n this.onEvent('performance_fcp', { value: fcpEntry.startTime });\n }\n });\n fcpObserver.observe({ type: 'paint', buffered: true });\n } catch (e) {\n console.debug('[Advanced Tracker] FCP not supported');\n }\n }\n\n // Track page load timing\n window.addEventListener('load', () => {\n setTimeout(() => {\n const timing = performance.timing;\n this.performanceMetrics.ttfb = timing.responseStart - timing.navigationStart;\n this.performanceMetrics.domContentLoaded = timing.domContentLoadedEventEnd - timing.navigationStart;\n this.performanceMetrics.pageLoad = timing.loadEventEnd - timing.navigationStart;\n\n // Count resources\n const resources = performance.getEntriesByType('resource');\n this.performanceMetrics.resourceCount = resources.length;\n this.performanceMetrics.transferSize = resources.reduce((acc, r: any) => acc + (r.transferSize || 0), 0);\n\n this.onEvent('performance_page_load', {\n ttfb: this.performanceMetrics.ttfb,\n domContentLoaded: this.performanceMetrics.domContentLoaded,\n pageLoad: this.performanceMetrics.pageLoad,\n resourceCount: this.performanceMetrics.resourceCount,\n transferSizeKB: Math.round((this.performanceMetrics.transferSize || 0) / 1024)\n });\n }, 0);\n });\n }\n\n // ============= Engagement Tracking =============\n\n private initEngagementTracking() {\n // Track page visibility changes\n document.addEventListener('visibilitychange', () => {\n this.isPageVisible = document.visibilityState === 'visible';\n this.visibilityChangeCount++;\n this.engagementMetrics.pageVisibilityChanges = this.visibilityChangeCount;\n\n if (this.isPageVisible) {\n this.lastActivityTime = Date.now();\n } else {\n this.updateActiveTime();\n }\n });\n\n // Track user activity\n ['mousemove', 'keydown', 'touchstart', 'scroll'].forEach(eventType => {\n document.addEventListener(eventType, () => {\n this.lastActivityTime = Date.now();\n }, { passive: true });\n });\n\n // Track all clicks for engagement\n document.addEventListener('click', () => {\n this.engagementMetrics.totalClicks++;\n });\n }\n\n // ============= Scroll Depth Tracking =============\n\n private initScrollTracking() {\n let ticking = false;\n\n const updateScrollDepth = () => {\n const scrollTop = window.scrollY || document.documentElement.scrollTop;\n const docHeight = Math.max(\n document.body.scrollHeight,\n document.documentElement.scrollHeight\n ) - window.innerHeight;\n\n const scrollPercent = docHeight > 0 ? Math.round((scrollTop / docHeight) * 100) : 0;\n this.engagementMetrics.scrollDepth = Math.max(this.engagementMetrics.scrollDepth, scrollPercent);\n\n // Check milestones\n for (const threshold of this.config.scrollDepthThresholds!) {\n if (scrollPercent >= threshold && !this.scrollDepthReached.has(threshold)) {\n this.scrollDepthReached.add(threshold);\n this.engagementMetrics.scrollDepthMilestones.push(threshold);\n\n this.onEvent('engagement_scroll_depth', {\n depth: threshold,\n maxDepth: this.engagementMetrics.scrollDepth,\n timeToReach: Date.now() - this.pageStartTime\n });\n }\n }\n\n ticking = false;\n };\n\n window.addEventListener('scroll', () => {\n if (!ticking) {\n requestAnimationFrame(updateScrollDepth);\n ticking = true;\n }\n }, { passive: true });\n }\n\n // ============= Rage Click Tracking =============\n\n private initRageClickTracking() {\n document.addEventListener('click', (event) => {\n const now = Date.now();\n this.clickHistory.push(now);\n\n // Remove old clicks outside the window\n this.clickHistory = this.clickHistory.filter(\n time => now - time < this.config.rageClickWindow!\n );\n\n // Check for rage clicks\n if (this.clickHistory.length >= this.config.rageClickThreshold!) {\n this.engagementMetrics.rageClicks++;\n\n const target = event.target as HTMLElement;\n this.onEvent('engagement_rage_click', {\n clickCount: this.clickHistory.length,\n element: {\n tagName: target.tagName,\n id: target.id,\n className: target.className,\n textContent: target.textContent?.substring(0, 50)\n },\n position: { x: event.clientX, y: event.clientY },\n totalRageClicks: this.engagementMetrics.rageClicks\n });\n\n // Reset history after detecting rage click\n this.clickHistory = [];\n }\n });\n }\n\n // ============= Time on Page Tracking =============\n\n private initTimeTracking() {\n // Update time metrics every 30 seconds\n setInterval(() => {\n this.updateActiveTime();\n }, 30000);\n }\n\n private updateActiveTime() {\n const now = Date.now();\n const timeSinceLastActivity = now - this.lastActivityTime;\n\n this.engagementMetrics.timeOnPage = now - this.pageStartTime;\n\n // If last activity was within 30 seconds, count as active time\n if (timeSinceLastActivity < 30000) {\n this.engagementMetrics.activeTime += Math.min(timeSinceLastActivity, 30000);\n } else {\n this.engagementMetrics.idleTime += timeSinceLastActivity;\n }\n }\n\n // ============= API Response Tracking =============\n\n private initAPITracking() {\n // Intercept fetch\n window.fetch = async (...args) => {\n const startTime = Date.now();\n const url = args[0] instanceof Request ? args[0].url : String(args[0]);\n const method = args[1]?.method || 'GET';\n\n // Check if URL matches tracking patterns\n if (!this.shouldTrackAPI(url)) {\n return this.originalFetch(...args);\n }\n\n try {\n const response = await this.originalFetch(...args);\n const duration = Date.now() - startTime;\n\n this.trackAPICall({\n url,\n method,\n status: response.status,\n duration,\n success: response.ok,\n timestamp: Date.now()\n });\n\n return response;\n } catch (error: any) {\n const duration = Date.now() - startTime;\n\n this.trackAPICall({\n url,\n method,\n status: 0,\n duration,\n success: false,\n error: error?.message || 'Network error',\n timestamp: Date.now()\n });\n\n throw error;\n }\n };\n\n console.log('[Advanced Tracker] API tracking initialized');\n }\n\n private shouldTrackAPI(url: string): boolean {\n if (!this.config.apiTrackingPatterns || this.config.apiTrackingPatterns.length === 0) {\n // Track all APIs if no patterns specified\n return true;\n }\n\n return this.config.apiTrackingPatterns.some(pattern => {\n try {\n const regex = new RegExp(pattern);\n return regex.test(url);\n } catch {\n return url.includes(pattern);\n }\n });\n }\n\n private trackAPICall(event: APITrackingEvent) {\n this.onEvent('api_call', {\n url: event.url,\n method: event.method,\n status: event.status,\n duration: event.duration,\n success: event.success,\n error: event.error\n });\n }\n\n // ============= Public Methods =============\n\n /**\n * Manually track an API response with custom data\n * Use this when you need to track specific API data that's important for analytics\n */\n public trackAPI(\n endpoint: string,\n method: string,\n response: any,\n metadata?: Record<string, any>\n ) {\n this.onEvent('api_response_tracked', {\n endpoint,\n method,\n responseType: typeof response,\n responseKeys: response && typeof response === 'object' ? Object.keys(response) : [],\n hasData: !!response,\n dataCount: Array.isArray(response) ? response.length : undefined,\n ...metadata\n });\n }\n\n /**\n * Track custom engagement event\n */\n public trackEngagement(action: string, properties?: Record<string, any>) {\n this.onEvent(`engagement_${action}`, {\n ...properties,\n timeOnPage: Date.now() - this.pageStartTime,\n scrollDepth: this.engagementMetrics.scrollDepth\n });\n }\n\n /**\n * Track conversion/goal completion\n */\n public trackConversion(goalName: string, value?: number, properties?: Record<string, any>) {\n this.onEvent('conversion', {\n goal: goalName,\n value,\n ...properties,\n timeToConvert: Date.now() - this.pageStartTime,\n scrollDepthAtConversion: this.engagementMetrics.scrollDepth,\n clicksBeforeConversion: this.engagementMetrics.totalClicks\n });\n }\n\n /**\n * Get current performance metrics\n */\n public getPerformanceMetrics(): PerformanceMetrics {\n return { ...this.performanceMetrics };\n }\n\n /**\n * Get current engagement metrics\n */\n public getEngagementMetrics(): EngagementMetrics {\n this.updateActiveTime();\n return {\n ...this.engagementMetrics,\n timeOnPage: Date.now() - this.pageStartTime\n };\n }\n\n /**\n * Track page exit - called automatically on beforeunload\n */\n private trackPageExit() {\n this.updateActiveTime();\n\n this.onEvent('page_exit', {\n timeOnPage: Date.now() - this.pageStartTime,\n activeTime: this.engagementMetrics.activeTime,\n idleTime: this.engagementMetrics.idleTime,\n scrollDepth: this.engagementMetrics.scrollDepth,\n scrollMilestones: this.engagementMetrics.scrollDepthMilestones,\n totalClicks: this.engagementMetrics.totalClicks,\n rageClicks: this.engagementMetrics.rageClicks,\n visibilityChanges: this.engagementMetrics.pageVisibilityChanges,\n performance: this.performanceMetrics\n });\n }\n}\n\n/**\n * Smart Event Enrichment - Parse customdata and enrich event properties\n */\nexport function enrichEventWithCustomdata(element: HTMLElement): Record<string, any> {\n const enrichedData: Record<string, any> = {};\n\n // Get customdata attribute\n const customdata = element.getAttribute('customdata') || element.dataset.customdata;\n\n if (customdata) {\n try {\n // Try to parse as JSON\n const parsed = JSON.parse(customdata);\n enrichedData.customdata = parsed;\n\n // Extract common fields\n if (parsed.name) enrichedData.itemName = parsed.name;\n if (parsed.displayedTitle) enrichedData.section = parsed.displayedTitle;\n if (parsed.title) enrichedData.title = parsed.title;\n if (parsed.category) enrichedData.category = parsed.category;\n if (parsed.id) enrichedData.itemId = parsed.id;\n } catch {\n // Try regex extraction for truncated JSON\n const nameMatch = customdata.match(/\"name\"\\s*:\\s*\"([^\"]+)\"/);\n if (nameMatch) enrichedData.itemName = nameMatch[1];\n\n const titleMatch = customdata.match(/\"(?:displayedTitle|title)\"\\s*:\\s*\"([^\"]+)\"/);\n if (titleMatch) enrichedData.section = titleMatch[1];\n }\n }\n\n // Extract from element ID\n const elementId = element.id;\n if (elementId) {\n enrichedData.elementId = elementId;\n\n // Extract game/item name from ID pattern like \"uuid_GameName\"\n const idParts = elementId.split('_');\n if (idParts.length >= 2) {\n const namePart = idParts.slice(1).join('_');\n if (!enrichedData.itemName && namePart) {\n enrichedData.itemName = namePart;\n }\n }\n }\n\n // Extract text content\n const textContent = element.textContent?.trim();\n if (textContent && textContent.length < 100) {\n enrichedData.displayText = textContent;\n }\n\n // Get data attributes\n const dataset = element.dataset;\n for (const [key, value] of Object.entries(dataset)) {\n if (!enrichedData[key] && value) {\n enrichedData[`data_${key}`] = value;\n }\n }\n\n return enrichedData;\n}\n","// src/sdk.ts - Main SDK entry point\nimport { ErrorTracker, ErrorConfig } from './error-tracker';\nimport { ErrorStorage } from './error-storage';\nimport { ENV_CONFIG } from './config';\nimport { UserManager } from './user-manager';\nimport { JourneyTracker } from './journey-tracker';\nimport { AuthManager } from './auth-manager';\nimport { AdvancedTracker, AdvancedTrackingConfig, enrichEventWithCustomdata, PerformanceMetrics, EngagementMetrics } from './advanced-tracker';\n\ninterface AnalyticsConfig {\n // NEW: Project-based authentication (preferred)\n projectKey?: string; // Public project key (e.g., 'proj_a1b2c3d4e5f6')\n\n // LEGACY: Client-based authentication (for backward compatibility)\n apiKey?: string;\n clientId?: string;\n\n endpoint?: string;\n autoConfig?: boolean;\n batchInterval?: number;\n useWebWorker?: boolean;\n workerPath?: string;\n debug?: boolean;\n apiDetails?: {\n apiEndPoint: string;\n headers?: Record<string, string>;\n };\n workerConfig?: {\n batchSize?: number;\n batchInterval?: number;\n };\n errorTracking?: {\n enabled?: boolean;\n captureScreenshots?: boolean;\n captureDomSnapshots?: boolean;\n maxStackTraceDepth?: number;\n maxErrorsPerSession?: number;\n debounceMs?: number;\n enableNetworkTracking?: boolean;\n enableConsoleCapture?: boolean;\n };\n // NEW: Advanced tracking configuration\n advancedTracking?: {\n enabled?: boolean;\n trackPerformance?: boolean;\n trackEngagement?: boolean;\n trackScrollDepth?: boolean;\n trackRageClicks?: boolean;\n trackTimeOnPage?: boolean;\n trackAPIResponses?: boolean;\n scrollDepthThresholds?: number[];\n apiTrackingPatterns?: string[];\n };\n // Optional extra config - passed as-is with all events\n // Use this to pass custom data like userId, deviceId, appVersion, etc.\n extraConfig?: Record<string, any>;\n}\n\n// Sampling decision from server\ninterface SamplingDecision {\n should_sample: {\n events: boolean;\n errors: boolean;\n session_replay: boolean;\n };\n rates: {\n events: number;\n errors: number;\n session_replay: number;\n };\n decision: 'new' | 'existing';\n}\n\n// Project settings from server\ninterface ProjectSettings {\n project_id: number;\n name: string;\n settings: Record<string, any>;\n features: Record<string, boolean>;\n sampling: {\n events: number;\n errors: number;\n session_replay: number;\n };\n}\n\ninterface EventData {\n event: string;\n properties?: Record<string, any>;\n timestamp?: number;\n userId?: string;\n sessionId?: string;\n}\n\nclass AInamikaSDKPro {\n private config: AnalyticsConfig;\n private worker: Worker;\n private sessionId: string;\n private batchTimer?: number;\n private eventQueue: Map<string, any>[] = [];\n private isInitialized = false;\n private batchRetryCount: number = 0;\n private maxBatchRetries: number = 5;\n\n // --- Project-based Configuration ---\n private projectSettings?: ProjectSettings;\n private samplingDecision?: SamplingDecision;\n private userIdentifier: string; // Persistent user identifier for sampling\n\n // --- Error Tracking Components ---\n private errorTracker?: ErrorTracker;\n private errorStorage?: ErrorStorage;\n\n // --- User & Journey Tracking Components ---\n private userManager: UserManager;\n private journeyTracker: JourneyTracker;\n\n // --- Authentication Manager ---\n private authManager: AuthManager;\n\n // --- Advanced Tracking ---\n private advancedTracker?: AdvancedTracker;\n\n // --- Dynamic DOM Fingerprinting and Smart Debouncing ---\n private lastDomHash: string = '';\n private lastConfigHash: string = '';\n private mutationDebounceTimer: number | null = null;\n private mutationDebounceMs: number = 2000; // 2s debounce for dynamic DOM\n\n // Track attached event types per element to prevent duplicate listeners\n private attachedListeners: WeakMap<Element, Set<string>> = new WeakMap();\n\n // Track known element selectors to avoid sending duplicates to server\n private knownElementSelectors: Set<string> = new Set();\n\n // Track handled clicks to prevent generic events when specific ones are sent\n // Key: timestamp, Value: Set of event names sent for that click\n private handledClicks: Map<number, Set<string>> = new Map();\n private readonly CLICK_DEDUP_WINDOW_MS = 50; // 50ms window for same click\n\n // Store merged config for all tracked events\n private mergedConfig: { events_to_track: any[], tracking_config?: any } = { events_to_track: [] };\n\n constructor(config: AnalyticsConfig) {\n // Validate that either projectKey or clientId is provided\n if (!config.projectKey && !config.clientId && !config.apiKey) {\n throw new Error('[AInamika SDK] Either projectKey or clientId is required for initialization');\n }\n\n this.config = {\n endpoint: ENV_CONFIG.API_BASE_URL,\n batchInterval: 5000,\n useWebWorker: true,\n debug: ENV_CONFIG.DEBUG,\n errorTracking: {\n enabled: true,\n captureScreenshots: true,\n captureDomSnapshots: true,\n maxStackTraceDepth: 50,\n maxErrorsPerSession: 100,\n debounceMs: 1000,\n enableNetworkTracking: true,\n enableConsoleCapture: true\n },\n advancedTracking: {\n enabled: true,\n trackPerformance: true,\n trackEngagement: true,\n trackScrollDepth: true,\n trackRageClicks: true,\n trackTimeOnPage: true,\n trackAPIResponses: false, // Opt-in\n scrollDepthThresholds: [25, 50, 75, 90, 100]\n },\n ...config\n };\n\n this.sessionId = this.generateSessionId();\n\n // Initialize or retrieve persistent user identifier for sampling\n this.userIdentifier = this.getOrCreateUserIdentifier();\n\n // Initialize user and journey tracking\n this.userManager = new UserManager();\n this.journeyTracker = new JourneyTracker();\n\n // Initialize authentication manager (use clientId for legacy, or we'll get it from project lookup)\n this.authManager = new AuthManager(\n this.config.clientId || this.config.apiKey || '',\n this.config.endpoint!,\n this.config.debug\n );\n // Inline the worker code as a Blob to avoid cross-origin issues\n const workerCode = `\n self.eventQueue = [];\n self.config = {\n apiUrl: '',\n batchSize: 10,\n batchInterval: 5000,\n headers: { 'Content-Type': 'application/json' }\n };\n let batchTimer = null;\n function flushQueue() {\n self.postMessage({ status: 'debug', message: '[AInamika Worker] flushQueue called', eventQueue: self.eventQueue, config: self.config });\n if (self.eventQueue.length === 0) return;\n const batch = self.eventQueue.splice(0, self.config.batchSize);\n fetch(self.config.apiUrl, {\n method: 'POST',\n headers: self.config.headers,\n body: JSON.stringify({ events: batch })\n }).then(r => {\n if (r.ok) {\n self.postMessage({ status: 'success' });\n } else {\n self.postMessage({ status: 'error', error: r.statusText, failedEvents: batch });\n }\n }).catch(e => {\n self.postMessage({ status: 'error', error: e.message, failedEvents: batch });\n });\n }\n self.onmessage = function(e) {\n self.postMessage({ status: 'debug', message: '[AInamika Worker] onmessage', data: e.data });\n if (e.data.type === 'config') {\n self.config = { ...self.config, ...e.data.payload };\n if (batchTimer) clearInterval(batchTimer);\n batchTimer = setInterval(flushQueue, self.config.batchInterval);\n self.postMessage({ status: 'debug', message: '[AInamika Worker] config set', config: self.config });\n } else if (e.data.type === 'track') {\n self.eventQueue.push(e.data.payload);\n // Only send when timer triggers, not when batch size is reached\n // This ensures true batching behavior\n } else if (e.data.type === 'batch') {\n // Handle batch flush from main thread\n self.postMessage({ status: 'debug', message: '[AInamika Worker] Received batch from main thread', events: e.data.events });\n self.eventQueue.push(...e.data.events);\n flushQueue();\n } else if (e.data.type === 'initConfig') {\n // No-op for now, can be used for advanced config\n }\n };\n `;\n const blob = new Blob([workerCode], { type: 'application/javascript' });\n const workerUrl = URL.createObjectURL(blob);\n this.worker = new Worker(workerUrl);\n this.initialize();\n }\n\n private async initialize() {\n if (this.isInitialized) return;\n this.isInitialized = true;\n\n // If using projectKey, fetch project settings and sampling decision first\n if (this.config.projectKey) {\n try {\n await this.initializeProjectSettings();\n await this.initializeSamplingDecision();\n this.log('Project-based initialization complete', {\n projectKey: this.config.projectKey,\n projectSettings: this.projectSettings,\n samplingDecision: this.samplingDecision\n });\n } catch (error) {\n this.log('Project initialization failed:', error);\n console.warn('[AInamika SDK] Failed to initialize project settings. Some features may be limited.');\n }\n }\n\n // Initialize authentication (only for legacy clientId-based auth)\n if (this.config.clientId || this.config.apiKey) {\n try {\n await this.authManager.initialize();\n this.log('Authentication initialized');\n } catch (error) {\n this.log('Authentication initialization failed:', error);\n // Continue without authentication in development mode\n if (!this.config.debug) {\n console.warn('[Ainamika] Running without authentication. Some features may be limited.');\n }\n }\n }\n\n // Initialize Error Tracking (respecting sampling decision)\n if (this.config.errorTracking?.enabled && this.shouldSampleErrors()) {\n this.initializeErrorTracking();\n } else if (this.config.errorTracking?.enabled && !this.shouldSampleErrors()) {\n this.log('Error tracking disabled due to sampling decision');\n }\n\n // Initialize Advanced Tracking\n if (this.config.advancedTracking?.enabled) {\n this.initializeAdvancedTracking();\n }\n\n if (this.config.autoConfig) {\n await this.setupAutoConfiguration();\n\n // Enable dynamic DOM tracking only when autoConfig is enabled\n // This watches for DOM changes and fetches config for new elements\n this.setupDynamicDomTracking();\n }\n\n if (this.config.useWebWorker && typeof Worker !== 'undefined') {\n await this.setupWebWorker();\n } else {\n // Fallback for environments without web workers\n this.startBatchTimer();\n }\n this.log('AnalyticsPro SDK initialized', {\n config: this.config,\n projectKey: this.config.projectKey,\n sampling: this.samplingDecision\n });\n }\n\n // --- Project Initialization Methods ---\n\n private getOrCreateUserIdentifier(): string {\n const storageKey = 'ainamika_user_identifier';\n let identifier = localStorage.getItem(storageKey);\n\n if (!identifier) {\n // Generate anonymous user identifier\n identifier = 'anon_' + Math.random().toString(36).substr(2, 16) + Date.now().toString(36);\n localStorage.setItem(storageKey, identifier);\n this.log('Created new user identifier:', identifier);\n }\n\n return identifier;\n }\n\n private async initializeProjectSettings(): Promise<void> {\n if (!this.config.projectKey) return;\n\n try {\n const response = await fetch(`${this.config.endpoint}/api/v1/projects/lookup`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ project_key: this.config.projectKey })\n });\n\n if (!response.ok) {\n throw new Error(`Project lookup failed: ${response.status}`);\n }\n\n this.projectSettings = await response.json();\n this.log('Project settings loaded:', this.projectSettings);\n } catch (error) {\n this.log('Failed to load project settings:', error);\n throw error;\n }\n }\n\n private async initializeSamplingDecision(): Promise<void> {\n if (!this.config.projectKey) return;\n\n try {\n const response = await fetch(`${this.config.endpoint}/api/v1/projects/sampling/check`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n project_key: this.config.projectKey,\n user_identifier: this.userIdentifier\n })\n });\n\n if (!response.ok) {\n throw new Error(`Sampling check failed: ${response.status}`);\n }\n\n this.samplingDecision = await response.json();\n this.log('Sampling decision received:', this.samplingDecision);\n\n // Store sampling decision locally for offline access\n this.cacheSamplingDecision();\n } catch (error) {\n this.log('Failed to get sampling decision, using cached or defaults:', error);\n this.loadCachedSamplingDecision();\n }\n }\n\n // Fixed storage key for sampling decision (no longer includes projectKey)\n private static readonly SAMPLING_STORAGE_KEY = 'ainamika_sampling';\n\n private cacheSamplingDecision(): void {\n if (this.samplingDecision) {\n const cacheData = {\n projectKey: this.config.projectKey, // Store projectKey for validation\n ...this.samplingDecision\n };\n localStorage.setItem(AInamikaSDKPro.SAMPLING_STORAGE_KEY, JSON.stringify(cacheData));\n // Clean up legacy dynamic keys\n this.cleanupLegacySamplingKeys();\n }\n }\n\n private loadCachedSamplingDecision(): void {\n // Clean up legacy keys first\n this.cleanupLegacySamplingKeys();\n\n const cached = localStorage.getItem(AInamikaSDKPro.SAMPLING_STORAGE_KEY);\n\n if (cached) {\n try {\n const cacheData = JSON.parse(cached);\n\n // Validate projectKey - if different, clear and use defaults\n if (cacheData.projectKey && cacheData.projectKey !== this.config.projectKey) {\n this.log('Cached sampling is for different projectKey, clearing');\n localStorage.removeItem(AInamikaSDKPro.SAMPLING_STORAGE_KEY);\n this.samplingDecision = this.getDefaultSamplingDecision();\n return;\n }\n\n // Extract sampling decision (exclude projectKey from the decision object)\n const { projectKey, ...samplingData } = cacheData;\n this.samplingDecision = samplingData as SamplingDecision;\n this.log('Loaded cached sampling decision:', this.samplingDecision);\n } catch {\n // Use default (sample everything)\n this.samplingDecision = this.getDefaultSamplingDecision();\n }\n } else {\n // Default to sampling everything when no cached decision\n this.samplingDecision = this.getDefaultSamplingDecision();\n }\n }\n\n private getDefaultSamplingDecision(): SamplingDecision {\n return {\n should_sample: { events: true, errors: true, session_replay: false },\n rates: { events: 100, errors: 100, session_replay: 0 },\n decision: 'existing'\n };\n }\n\n private cleanupLegacySamplingKeys(): void {\n if (typeof window !== 'undefined' && window.localStorage) {\n const keysToRemove: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith('ainamika_sampling_') && key !== AInamikaSDKPro.SAMPLING_STORAGE_KEY) {\n keysToRemove.push(key);\n }\n }\n keysToRemove.forEach(key => {\n localStorage.removeItem(key);\n this.log('Removed legacy sampling key:', key);\n });\n }\n }\n\n // --- Sampling Check Methods ---\n\n private shouldSampleEvents(): boolean {\n // If no sampling decision (legacy mode), sample everything\n if (!this.samplingDecision) return true;\n return this.samplingDecision.should_sample.events;\n }\n\n private shouldSampleErrors(): boolean {\n // If no sampling decision (legacy mode), sample everything\n if (!this.samplingDecision) return true;\n return this.samplingDecision.should_sample.errors;\n }\n\n private shouldSampleSessionReplay(): boolean {\n // If no sampling decision (legacy mode), don't sample replay\n if (!this.samplingDecision) return false;\n return this.samplingDecision.should_sample.session_replay;\n }\n\n // Public method to check sampling status\n public getSamplingStatus(): SamplingDecision | null {\n return this.samplingDecision || null;\n }\n\n // Public method to get project info\n public getProjectInfo(): ProjectSettings | null {\n return this.projectSettings || null;\n }\n\n // Public method to get current tracking config status\n public getTrackingStatus(): {\n totalEvents: number;\n knownSelectors: number;\n mergedConfig: { events_to_track: any[], tracking_config?: any };\n } {\n return {\n totalEvents: this.mergedConfig.events_to_track.length,\n knownSelectors: this.knownElementSelectors.size,\n mergedConfig: this.mergedConfig\n };\n }\n\n // Public method to reset DOM tracking (useful for SPA route changes)\n public resetDomTracking(): void {\n this.knownElementSelectors.clear();\n this.mergedConfig = { events_to_track: [] };\n this.lastDomHash = '';\n this.attachedListeners = new WeakMap();\n this.log('DOM tracking reset - will re-analyze on next mutation');\n }\n\n /**\n * Clears all SDK caches from LocalStorage.\n * Call this method to force fresh config generation from the server.\n *\n * This clears:\n * - DOM config cache (ainamika_dom_config_cache)\n * - Sampling decision cache\n * - User identifier (optional)\n *\n * @param clearUserIdentifier - If true, also clears user identifier (default: false)\n */\n public clearAllCaches(clearUserIdentifier: boolean = false): void {\n try {\n // Clear DOM config cache\n localStorage.removeItem('ainamika_dom_config_cache');\n this.log('Cleared DOM config cache');\n\n // Clear last-known config (for instant loading)\n localStorage.removeItem('ainamika_last_known_config');\n this.log('Cleared last-known config cache');\n\n // Clear sampling decision cache (fixed key)\n localStorage.removeItem(AInamikaSDKPro.SAMPLING_STORAGE_KEY);\n // Also clean up any legacy dynamic keys\n this.cleanupLegacySamplingKeys();\n this.log('Cleared sampling decision cache');\n\n // Optionally clear user identifier\n if (clearUserIdentifier) {\n localStorage.removeItem('ainamika_user_identifier');\n this.log('Cleared user identifier');\n }\n\n // Reset in-memory state\n this.resetDomTracking();\n this.samplingDecision = undefined;\n\n this.log('All caches cleared successfully');\n } catch (error) {\n console.error('[AInamika SDK] Error clearing caches:', error);\n }\n }\n\n /**\n * Gets cache statistics for debugging\n */\n public getCacheStats(): {\n domConfigCacheSize: number;\n cachedDomHashes: string[];\n hasSamplingCache: boolean;\n hasUserIdentifier: boolean;\n hasLastKnownConfig: boolean;\n } {\n try {\n const cache = JSON.parse(localStorage.getItem('ainamika_dom_config_cache') || '{}');\n const domHashes = Object.keys(cache);\n\n return {\n domConfigCacheSize: domHashes.length,\n cachedDomHashes: domHashes,\n hasSamplingCache: !!localStorage.getItem(AInamikaSDKPro.SAMPLING_STORAGE_KEY),\n hasUserIdentifier: !!localStorage.getItem('ainamika_user_identifier'),\n hasLastKnownConfig: !!localStorage.getItem('ainamika_last_known_config')\n };\n } catch {\n return {\n domConfigCacheSize: 0,\n cachedDomHashes: [],\n hasSamplingCache: false,\n hasUserIdentifier: false,\n hasLastKnownConfig: false\n };\n }\n }\n\n // --- Error Tracking Initialization ---\n private initializeErrorTracking() {\n try {\n // Initialize error storage with endpoint from config\n this.errorStorage = new ErrorStorage({\n maxStorageSize: 5 * 1024 * 1024, // 5MB\n maxRetries: 5,\n retryInterval: 30000, // 30 seconds\n compressionEnabled: true,\n encryptionEnabled: false,\n endpoint: this.config.endpoint // Pass endpoint for retrying stored errors\n });\n\n // Initialize error tracker with endpoint from config\n const errorConfig: ErrorConfig = {\n endpoint: this.config.endpoint!,\n clientId: this.config.clientId || \"\",\n apiKey: this.config.apiKey, // Keep for backward compatibility\n authManager: this.authManager, // Pass authManager for JWT auth\n projectKey: this.config.projectKey, // Pass projectKey for project-based error tracking\n captureScreenshots: this.config.errorTracking?.captureScreenshots ?? true,\n captureDomSnapshots: this.config.errorTracking?.captureDomSnapshots ?? true,\n maxStackTraceDepth: this.config.errorTracking?.maxStackTraceDepth ?? 50,\n maxErrorsPerSession: this.config.errorTracking?.maxErrorsPerSession ?? 100,\n debounceMs: this.config.errorTracking?.debounceMs ?? 1000,\n enableNetworkTracking: this.config.errorTracking?.enableNetworkTracking ?? true,\n enableConsoleCapture: this.config.errorTracking?.enableConsoleCapture ?? true\n };\n\n this.errorTracker = new ErrorTracker(errorConfig);\n \n // Set user for error tracking if available\n const userId = this.getUserId();\n if (userId && this.errorTracker) {\n this.errorTracker.setUser(userId);\n }\n\n this.log('Error tracking initialized successfully');\n } catch (error) {\n console.error('[AInamika SDK] Failed to initialize error tracking:', error);\n }\n }\n\n // Public method to capture custom exceptions\n public captureException(error: Error, context?: Record<string, any>) {\n if (this.errorTracker) {\n this.errorTracker.captureException(error, context);\n }\n }\n\n // Public method to set user for error tracking (deprecated - use identifyUser instead)\n public setUser(userId: string) {\n console.warn('[AInamika SDK] setUser is deprecated. Please use identifyUser() instead.');\n this.identifyUser(userId);\n }\n\n // Public method to flush stored errors\n public async flushStoredErrors() {\n if (this.errorStorage) {\n await this.errorStorage.processQueue();\n }\n if (this.errorTracker) {\n await this.errorTracker.flushStoredErrors();\n }\n }\n\n // --- Advanced Tracking Initialization ---\n private initializeAdvancedTracking() {\n try {\n const advConfig: AdvancedTrackingConfig = {\n trackPerformance: this.config.advancedTracking?.trackPerformance ?? true,\n trackEngagement: this.config.advancedTracking?.trackEngagement ?? true,\n trackScrollDepth: this.config.advancedTracking?.trackScrollDepth ?? true,\n trackRageClicks: this.config.advancedTracking?.trackRageClicks ?? true,\n trackTimeOnPage: this.config.advancedTracking?.trackTimeOnPage ?? true,\n trackAPIResponses: this.config.advancedTracking?.trackAPIResponses ?? false,\n scrollDepthThresholds: this.config.advancedTracking?.scrollDepthThresholds || [25, 50, 75, 90, 100],\n apiTrackingPatterns: this.config.advancedTracking?.apiTrackingPatterns || []\n };\n\n this.advancedTracker = new AdvancedTracker(advConfig, (eventName, properties) => {\n this.sendToWorker(eventName, properties);\n });\n\n this.log('Advanced tracking initialized successfully');\n } catch (error) {\n console.error('[AInamika SDK] Failed to initialize advanced tracking:', error);\n }\n }\n\n // --- Public API Tracking Methods ---\n\n /**\n * Track an API response with custom data\n * Use this to track important API calls and their responses\n *\n * @example\n * // Track a game data API response\n * sdk.trackAPI('/api/games', 'GET', gamesData, { category: 'games' });\n *\n * // Track a user action API\n * sdk.trackAPI('/api/purchase', 'POST', purchaseResult, {\n * gameId: 'swing-monkey',\n * amount: 9.99\n * });\n */\n public trackAPI(endpoint: string, method: string, response: any, metadata?: Record<string, any>) {\n if (this.advancedTracker) {\n this.advancedTracker.trackAPI(endpoint, method, response, metadata);\n } else {\n // Fallback if advanced tracker not initialized\n this.track('api_response_tracked', {\n endpoint,\n method,\n responseType: typeof response,\n hasData: !!response,\n ...metadata\n });\n }\n }\n\n /**\n * Track a custom engagement event\n *\n * @example\n * sdk.trackEngagement('video_watched', { videoId: '123', duration: 120 });\n * sdk.trackEngagement('level_completed', { level: 5, score: 1000 });\n */\n public trackEngagement(action: string, properties?: Record<string, any>) {\n if (this.advancedTracker) {\n this.advancedTracker.trackEngagement(action, properties);\n } else {\n this.track(`engagement_${action}`, properties || {});\n }\n }\n\n /**\n * Track a conversion or goal completion\n *\n * @example\n * sdk.trackConversion('purchase', 9.99, { productId: 'game-123' });\n * sdk.trackConversion('signup', undefined, { source: 'organic' });\n */\n public trackConversion(goalName: string, value?: number, properties?: Record<string, any>) {\n if (this.advancedTracker) {\n this.advancedTracker.trackConversion(goalName, value, properties);\n } else {\n this.track('conversion', { goal: goalName, value, ...properties });\n }\n }\n\n /**\n * Get current performance metrics (Web Vitals, page load timing)\n */\n public getPerformanceMetrics(): PerformanceMetrics | null {\n return this.advancedTracker?.getPerformanceMetrics() || null;\n }\n\n /**\n * Get current engagement metrics (scroll depth, time on page, clicks)\n */\n public getEngagementMetrics(): EngagementMetrics | null {\n return this.advancedTracker?.getEngagementMetrics() || null;\n }\n\n private async setupAutoConfiguration() {\n try {\n this.log('Starting auto-configuration...');\n\n // IMMEDIATE TRACKING: Apply last-known config BEFORE DOM analysis (zero delay)\n // This ensures returning users get instant tracking\n let appliedFromCache = false;\n const lastKnownConfig = this.getLastKnownConfig();\n\n if (lastKnownConfig && lastKnownConfig.events_to_track && lastKnownConfig.events_to_track.length > 0) {\n this.log('Applying last-known config IMMEDIATELY (zero delay)', {\n eventsCount: lastKnownConfig.events_to_track.length\n });\n this.mergedConfig = {\n events_to_track: [...lastKnownConfig.events_to_track],\n tracking_config: lastKnownConfig.tracking_config\n };\n this.applyGeneratedConfig(lastKnownConfig);\n appliedFromCache = true;\n\n // Send config to worker\n if (this.config.useWebWorker && typeof Worker !== 'undefined') {\n this.worker.postMessage({ type: 'initConfig', config: lastKnownConfig });\n }\n }\n\n // BACKGROUND: Now do DOM analysis and fetch fresh config (non-blocking)\n this.setupAutoConfigurationBackground(appliedFromCache);\n\n } catch (error) {\n this.log('Auto-configuration failed with error', error);\n }\n }\n\n // Background DOM analysis and config fetching (doesn't block tracking)\n private async setupAutoConfigurationBackground(alreadyAppliedCache: boolean) {\n try {\n // Compute current DOM structure and hash\n const domStructure = await this.getDOMStructure();\n const domHash = this.computeDomHash(domStructure);\n this.lastDomHash = domHash;\n\n // Track all initial elements as known\n const elements = domStructure.elements || [];\n elements.forEach((el: any) => {\n if (el.selector) this.knownElementSelectors.add(el.selector);\n });\n this.log(`Tracking ${this.knownElementSelectors.size} initial element selectors`);\n\n // Check if we have a cached config for THIS specific DOM hash\n let cachedConfig = this.getCachedConfigForDomHash(domHash);\n let appliedFromCache = alreadyAppliedCache;\n\n if (!alreadyAppliedCache) {\n // Didn't apply last-known config, try domHash-specific or file config\n if (cachedConfig && cachedConfig.events_to_track) {\n this.log('Applying cached config for DOM hash:', domHash);\n this.mergedConfig = {\n events_to_track: [...cachedConfig.events_to_track],\n tracking_config: cachedConfig.tracking_config\n };\n this.applyGeneratedConfig(cachedConfig);\n appliedFromCache = true;\n\n if (this.config.useWebWorker && typeof Worker !== 'undefined') {\n this.worker.postMessage({ type: 'initConfig', config: cachedConfig });\n }\n } else {\n // Try to load config from file as fallback\n const fileConfig = await this.loadConfigFromFile();\n if (fileConfig && fileConfig.events_to_track) {\n this.log('Applying config from file');\n this.mergedConfig = {\n events_to_track: [...fileConfig.events_to_track],\n tracking_config: fileConfig.tracking_config\n };\n this.applyGeneratedConfig(fileConfig);\n appliedFromCache = true;\n }\n }\n }\n\n // BACKGROUND FETCH: Always fetch fresh config from API to get any updates\n this.fetchAndMergeFreshConfig(domStructure, domHash, appliedFromCache);\n\n } catch (error) {\n this.log('Background auto-configuration failed:', error);\n }\n }\n\n // Fetch fresh config from API and merge with existing config\n private async fetchAndMergeFreshConfig(domStructure: any, domHash: string, hadCachedConfig: boolean) {\n try {\n this.log('Fetching fresh config from backend (background)...');\n const freshConfig = await this.fetchGeneratedConfig(domStructure, domHash);\n\n if (!freshConfig || !freshConfig.events_to_track) {\n this.log('No valid config returned from API');\n return;\n }\n\n if (hadCachedConfig) {\n // Merge fresh config with existing (might have new events from server)\n const existingSelectors = new Set(\n this.mergedConfig.events_to_track.map(e => e.element_selector)\n );\n\n const newEvents = freshConfig.events_to_track.filter(\n (event: any) => !existingSelectors.has(event.element_selector)\n );\n\n if (newEvents.length > 0) {\n this.log(`Found ${newEvents.length} new events from fresh config, merging...`);\n this.mergedConfig.events_to_track.push(...newEvents);\n // Apply only new events (existing already have listeners)\n this.applyGeneratedConfig({ events_to_track: newEvents, tracking_config: freshConfig.tracking_config });\n } else {\n this.log('Fresh config has no new events, cache was up-to-date');\n }\n\n // Update tracking config if changed\n if (freshConfig.tracking_config) {\n this.mergedConfig.tracking_config = {\n ...this.mergedConfig.tracking_config,\n ...freshConfig.tracking_config\n };\n }\n } else {\n // No cached config was applied, apply fresh config fully\n this.mergedConfig = {\n events_to_track: [...freshConfig.events_to_track],\n tracking_config: freshConfig.tracking_config\n };\n this.applyGeneratedConfig(freshConfig);\n\n // Send config to worker\n if (this.config.useWebWorker && typeof Worker !== 'undefined') {\n this.worker.postMessage({ type: 'initConfig', config: freshConfig });\n }\n }\n\n // Cache the FINAL merged config in LocalStorage\n this.setCachedConfigForDomHash(domHash, this.mergedConfig);\n this.lastConfigHash = freshConfig.config_hash || '';\n\n // Also save as last-known config for INSTANT loading on next visit\n this.setLastKnownConfig(this.mergedConfig);\n\n this.log('Fresh config processed successfully', {\n totalEvents: this.mergedConfig.events_to_track.length,\n knownSelectors: this.knownElementSelectors.size\n });\n } catch (error) {\n this.log('Background config fetch failed:', error);\n // Silent failure - cached config is still working\n }\n }\n\n private async getDOMStructure(): Promise<any> {\n const getSelector = (el: Element): string => {\n if (el.id) {\n // Check for special characters that are invalid in CSS ID selectors\n // Spaces, special chars need escaping or use attribute selector\n if (/[\\s!\"#$%&'()*+,./:;<=>?@[\\\\\\]^`{|}~]/.test(el.id)) {\n // Use attribute selector for IDs with special characters\n return `[id=\"${el.id.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"]`;\n }\n return `#${el.id}`;\n }\n if (el.className && typeof el.className === 'string') {\n const classes = el.className.split(' ').filter(c => c.trim()).join('.');\n return classes ? `.${classes}` : el.tagName.toLowerCase();\n }\n return el.tagName.toLowerCase();\n };\n\n // Wait a bit for any dynamic content to load\n await new Promise(resolve => setTimeout(resolve, 500));\n\n // Comprehensive selector for all interactive and important elements\n const elements = Array.from(document.body.querySelectorAll(`\n button, a, input, select, textarea, form, img, h1, h2, h3, h4, h5, h6,\n [role=button], [role=link], [onclick], [tabindex], [data-analytics], [data-track],\n .card, .btn, .btn-primary, .btn-secondary, .card-title, .card-description, .card-price, .card-actions,\n [id*=\"card\"], [class*=\"card\"], [class*=\"btn\"], [class*=\"price\"], [class*=\"title\"],\n div, span, p\n `));\n\n // Filter and enhance elements with more comprehensive logic\n const filteredElements = elements.filter(el => {\n const style = window.getComputedStyle(el);\n const isVisible = style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0';\n const hasInteraction = el.tagName.toLowerCase() === 'button' || \n el.tagName.toLowerCase() === 'a' || \n el.hasAttribute('onclick') ||\n el.getAttribute('role') === 'button' ||\n el.classList.contains('btn') ||\n el.classList.contains('card');\n const isImportantElement = el.id === 'cardsContainer' || \n el.classList.contains('cards-grid') ||\n el.classList.contains('card') ||\n el.tagName.toLowerCase() === 'img' ||\n ['h1', 'h2', 'h3'].indexOf(el.tagName.toLowerCase()) !== -1;\n \n return (isVisible && (hasInteraction || isImportantElement)) || el.id === 'cardsContainer';\n });\n\n // Deduplicate and add stable metadata (exclude dynamic properties)\n const seen = new Set<string>();\n const structure = filteredElements.map(el => {\n // Only include stable attributes that don't change between page loads\n const stableAttributes: Record<string, string> = {};\n Array.from(el.attributes).forEach(attr => {\n // Exclude dynamic attributes that might change\n if (['style', 'data-timestamp', 'data-rendered'].indexOf(attr.name) === -1) {\n // Truncate attribute values > 25 chars to reduce payload size\n stableAttributes[attr.name] = attr.value.length > 25 ? attr.value.substring(0, 25) : attr.value;\n }\n });\n\n // Generate stable fingerprint for this element\n const fingerprint = this.generateElementFingerprint(el);\n\n const obj = {\n tagName: el.tagName.toLowerCase(),\n selector: getSelector(el),\n fingerprint, // NEW: Stable fingerprint for consistent event naming\n id: el.id || '',\n className: el.className || '',\n textContent: (el.textContent || '').trim().substring(0, 100),\n attributes: stableAttributes,\n // Remove position and computed styles as they can vary\n isInteractive: el.tagName.toLowerCase() === 'button' ||\n el.tagName.toLowerCase() === 'a' ||\n el.hasAttribute('onclick') ||\n el.getAttribute('role') === 'button' ||\n el.classList.contains('btn'),\n hasChildren: el.children.length > 0,\n childCount: el.children.length,\n // Add stable structural information\n parentTagName: el.parentElement?.tagName.toLowerCase() || '',\n index: Array.from(el.parentElement?.children || []).indexOf(el)\n };\n return obj;\n }).filter(obj => {\n // Deduplicate by fingerprint (more stable than selector)\n if (seen.has(obj.fingerprint)) return false;\n seen.add(obj.fingerprint);\n return true;\n });\n\n this.log('DOM structure analyzed', { elementCount: structure.length, elements: structure });\n return { elements: structure };\n }\n\n private async fetchGeneratedConfig(structure: any, domHash?: string): Promise<any> {\n try {\n if(structure && structure.elements && structure.elements.length === 0) {\n this.log('No elements found in DOM structure, skipping config fetch.');\n return null;\n }\n\n // Get authentication headers\n let headers: Record<string, string> = { 'Content-Type': 'application/json' };\n const authHeaders = await this.authManager.getAuthHeaders();\n headers = { ...headers, ...authHeaders };\n\n const requestBody: any = { structure };\n if (domHash) {\n requestBody.domHash = domHash;\n requestBody.lastConfigHash = this.lastConfigHash;\n }\n\n const response = await fetch(`${this.config.endpoint}/api/v1/sdk/config`, {\n method: 'POST',\n headers,\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n throw new Error(`Backend returned ${response.status}`);\n }\n return await response.json();\n } catch (error) {\n this.log('Error fetching generated config:', error);\n return null;\n }\n }\n\n // Helper to transform event names based on actual event type\n // e.g., \"simulasi_clicked\" + \"view\" → \"simulasi_viewed\"\n private transformEventNameForType(eventName: string, eventType: string): string {\n if (!eventName || !eventType) return eventName;\n\n // Common suffixes to replace\n const suffixMap: Record<string, Record<string, string>> = {\n 'view': {\n '_clicked': '_viewed',\n '_click': '_view'\n },\n 'focus': {\n '_clicked': '_focused',\n '_click': '_focus'\n },\n 'blur': {\n '_clicked': '_blurred',\n '_click': '_blur'\n }\n };\n\n const replacements = suffixMap[eventType];\n if (!replacements) return eventName;\n\n // Try each replacement\n for (const [from, to] of Object.entries(replacements)) {\n if (eventName.endsWith(from)) {\n return eventName.slice(0, -from.length) + to;\n }\n }\n\n // If no suffix match, append the event type\n // e.g., \"card_interaction\" + \"view\" → \"card_interaction_viewed\"\n if (eventType === 'view' && !eventName.endsWith('_viewed') && !eventName.endsWith('_view')) {\n return eventName + '_viewed';\n }\n\n return eventName;\n }\n\n // Helper to sanitize selectors that may have invalid characters (e.g., spaces in IDs)\n private sanitizeSelector(selector: string): string {\n if (!selector) return selector;\n\n // Check if it's an ID selector with spaces or special characters\n // Pattern: #someId with spaces or special chars\n if (selector.startsWith('#') && !selector.startsWith('[')) {\n const idPart = selector.substring(1);\n // If ID contains spaces or special CSS chars, convert to attribute selector\n if (/[\\s!\"#$%&'()*+,./:;<=>?@[\\\\\\]^`{|}~]/.test(idPart)) {\n const escapedId = idPart.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n return `[id=\"${escapedId}\"]`;\n }\n }\n\n return selector;\n }\n\n private applyGeneratedConfig(config: { events_to_track: any[], observe_mutations?: boolean, tracking_config?: any }) {\n // Apply tracking config if present\n if (config.tracking_config) {\n this.log('Applying tracking config:', config.tracking_config);\n }\n\n config.events_to_track.forEach(eventToTrack => {\n // Sanitize selector to handle IDs with spaces/special characters (outside try for catch access)\n const sanitizedSelector = this.sanitizeSelector(eventToTrack.element_selector);\n try {\n const elements = document.querySelectorAll(sanitizedSelector);\n const metadataRules = eventToTrack.metadata_rules || { extract_customdata: true, extract_text: true };\n\n if (elements.length > 0) {\n elements.forEach(element => {\n // Prevent multiple listeners for the same event type on the same element\n let eventSet = this.attachedListeners.get(element);\n if (!eventSet) {\n eventSet = new Set();\n this.attachedListeners.set(element, eventSet);\n }\n\n // Handle array of event types\n const eventTypes = Array.isArray(eventToTrack.event_type) ? eventToTrack.event_type : [eventToTrack.event_type];\n\n eventTypes.forEach((eventType: string) => {\n if (eventSet.has(eventType)) return;\n eventSet.add(eventType);\n\n // Click events\n if (eventType === 'click') {\n element.addEventListener('click', (event: Event) => {\n const clickTimestamp = Date.now();\n const isGenericEvent = eventToTrack.event_name === 'interactive_element_clicked';\n // List of generic HTML tags that shouldn't override specific selectors\n const genericTags = [\n 'div', 'span', 'p', 'section', 'article', 'header', 'footer',\n 'main', 'aside', 'nav', 'ul', 'ol', 'li', 'table', 'tr', 'td',\n 'th', 'tbody', 'thead', 'figure', 'figcaption', 'blockquote',\n 'pre', 'code', 'label', 'fieldset', 'legend', 'details', 'summary'\n ];\n const isGenericSelector = genericTags.includes(eventToTrack.element_selector?.toLowerCase());\n\n // For generic events, check if a specific event was already sent for this click\n if (isGenericEvent || isGenericSelector) {\n // Check recent clicks within dedup window\n const entries = Array.from(this.handledClicks.entries());\n for (let i = 0; i < entries.length; i++) {\n const ts = entries[i][0];\n if (Math.abs(clickTimestamp - ts) <= this.CLICK_DEDUP_WINDOW_MS) {\n // A specific event was already sent for this click, skip generic\n this.log(`Skipping generic event \"${eventToTrack.event_name}\" - specific event already sent`);\n return;\n }\n }\n }\n\n // Don't prevent default for this demo, let buttons work normally\n const target = event.target as HTMLElement;\n const elementData = this.extractElementData(target, metadataRules);\n\n // Mark this click as handled (for non-generic events)\n if (!isGenericEvent && !isGenericSelector) {\n this.handledClicks.set(clickTimestamp, new Set([eventToTrack.event_name]));\n // Clean up old entries (older than 1 second)\n const cutoff = clickTimestamp - 1000;\n const keys = Array.from(this.handledClicks.keys());\n for (let i = 0; i < keys.length; i++) {\n if (keys[i] < cutoff) this.handledClicks.delete(keys[i]);\n }\n }\n\n this.sendToWorker(eventToTrack.event_name, {\n selector: eventToTrack.element_selector,\n eventType: 'click',\n category: eventToTrack.category || 'uncategorized',\n element: elementData,\n // Include enriched data at top level for easy access\n itemName: elementData.itemName,\n section: elementData.section,\n timestamp: new Date().toISOString()\n });\n });\n this.log(`Attached click listener for \"${eventToTrack.event_name}\" on \"${eventToTrack.element_selector}\" (category: ${eventToTrack.category || 'uncategorized'})`);\n }\n\n // View events using IntersectionObserver\n if (eventType === 'view') {\n if ('IntersectionObserver' in window) {\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n const target = entry.target as HTMLElement;\n const elementData = this.extractElementData(target, metadataRules);\n\n // Transform event name: replace _clicked with _viewed for view events\n const viewEventName = this.transformEventNameForType(eventToTrack.event_name, 'view');\n\n this.sendToWorker(viewEventName, {\n selector: eventToTrack.element_selector,\n eventType: 'view',\n category: eventToTrack.category || 'uncategorized',\n element: elementData,\n itemName: elementData.itemName,\n section: elementData.section,\n intersectionRatio: entry.intersectionRatio,\n timestamp: new Date().toISOString()\n });\n }\n });\n }, { threshold: [0.1, 0.5, 1.0] });\n observer.observe(element);\n this.log(`Attached IntersectionObserver for \"${eventToTrack.event_name}\" (as \"${this.transformEventNameForType(eventToTrack.event_name, 'view')}\") on \"${eventToTrack.element_selector}\"`);\n }\n }\n\n // Focus/blur tracking\n if (eventType === 'focus' || eventType === 'blur') {\n element.addEventListener(eventType, () => {\n const target = element as HTMLElement;\n const elementData = this.extractElementData(target, metadataRules);\n\n // Transform event name for focus/blur events\n const transformedEventName = this.transformEventNameForType(eventToTrack.event_name, eventType);\n\n this.sendToWorker(transformedEventName, {\n selector: eventToTrack.element_selector,\n eventType: eventType,\n category: eventToTrack.category || 'uncategorized',\n element: elementData,\n timestamp: new Date().toISOString()\n });\n });\n this.log(`Attached ${eventType} listener for \"${eventToTrack.event_name}\" (as \"${this.transformEventNameForType(eventToTrack.event_name, eventType)}\") on \"${eventToTrack.element_selector}\"`);\n }\n });\n });\n } else {\n this.log(`No elements found for selector: \"${sanitizedSelector}\" (original: \"${eventToTrack.element_selector}\")`);\n }\n } catch (e) {\n this.log(`Error applying selector \"${sanitizedSelector}\" (original: \"${eventToTrack.element_selector}\"):`, e);\n }\n });\n\n // MutationObserver for DOM changes (if requested by config)\n if (config.observe_mutations) {\n if ('MutationObserver' in window) {\n const observer = new MutationObserver((mutations) => {\n mutations.forEach(mutation => {\n this.sendToWorker('dom_mutation', {\n type: mutation.type,\n target: (mutation.target as HTMLElement).outerHTML,\n timestamp: new Date().toISOString()\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n this.log('MutationObserver attached for DOM changes');\n }\n }\n }\n\n private extractElementData(element: HTMLElement, metadataRules?: Record<string, boolean>): any {\n const rect = element.getBoundingClientRect();\n const baseData: any = {\n tagName: element.tagName.toLowerCase(),\n id: element.id || '',\n className: element.className || '',\n textContent: (element.textContent || '').trim().substring(0, 100),\n position: {\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 href: (element as HTMLAnchorElement).href || undefined,\n value: (element as HTMLInputElement).value || undefined\n };\n\n // Smart enrichment: Extract data from customdata and other attributes\n if (metadataRules?.extract_customdata !== false) {\n const enrichedData = enrichEventWithCustomdata(element);\n if (Object.keys(enrichedData).length > 0) {\n baseData.enriched = enrichedData;\n\n // Promote key fields for easier access\n if (enrichedData.itemName) baseData.itemName = enrichedData.itemName;\n if (enrichedData.section) baseData.section = enrichedData.section;\n if (enrichedData.category) baseData.category = enrichedData.category;\n }\n }\n\n // Include raw attributes only if needed for debugging\n if (this.config.debug) {\n baseData.attributes = Array.from(element.attributes).reduce((acc, attr) => {\n acc[attr.name] = attr.value.length > 100 ? attr.value.substring(0, 100) + '...' : attr.value;\n return acc;\n }, {} as Record<string, string>);\n }\n\n return baseData;\n }\n\n // Helper to send events to worker for batching\n private sendToWorker(eventName: string, properties: Record<string, any>) {\n // Check if we should sample this event\n if (!this.shouldSampleEvents()) {\n this.log('Event skipped due to sampling:', eventName);\n return;\n }\n\n const now = new Date();\n const commonData = this.getCommonEventData();\n const eventData: any = {\n event: eventName,\n properties,\n timestamp: now.getTime(), // Milliseconds for backward compatibility\n created_at: now.toISOString(), // ISO timestamp for server-side time filtering\n userId: this.getUserId(),\n sessionId: this.sessionId,\n // Include both project_key (new) and client_id (legacy)\n project_key: this.config.projectKey || undefined,\n client_id: this.config.clientId || this.config.apiKey || undefined,\n project_id: this.projectSettings?.project_id || undefined,\n // Include page context and extraConfig with all events\n ...commonData\n };\n if (this.config.useWebWorker && typeof Worker !== 'undefined') {\n this.worker.postMessage({ type: 'track', payload: eventData });\n } else {\n this.eventQueue.push(eventData);\n }\n this.log('Event tracked:', eventData);\n }\n\n private async setupWebWorker() {\n // Get authentication headers\n const authHeaders = await this.authManager.getAuthHeaders();\n\n // Pass worker config to the worker\n this.worker.postMessage({\n type: 'config',\n payload: {\n apiUrl: this.config.apiDetails?.apiEndPoint || `${this.config.endpoint}/api/v1/events`,\n batchSize: this.config.workerConfig?.batchSize || 10,\n batchInterval: this.config.workerConfig?.batchInterval || 5000,\n headers: {\n 'Content-Type': 'application/json',\n ...authHeaders,\n ...(this.config.apiDetails?.headers || {})\n },\n }\n });\n this.worker.onmessage = (event) => {\n if (event.data.status === 'success') {\n this.log('Batch sent successfully by worker');\n // Don't re-queue failed events since we already cleared the queue\n } else if (event.data.status === 'debug') {\n this.log(event.data.message, event.data);\n } else if (event.data.status === 'error') {\n this.log('Worker failed to send batch', event.data.error);\n // Re-queue failed events only if we have them\n if (event.data.failedEvents && event.data.failedEvents.length > 0) {\n this.eventQueue.unshift(...event.data.failedEvents);\n }\n }\n };\n this.log('Web worker setup complete.');\n }\n\n public track(eventName: string, properties: Record<string, any> = {}) {\n // Check if we should sample this event\n if (!this.shouldSampleEvents()) {\n this.log('Event skipped due to sampling:', eventName);\n return;\n }\n\n // Track in journey tracker\n this.journeyTracker.trackEvent(eventName, properties);\n\n // Get journey context\n const journeyContext = this.journeyTracker.getContext();\n\n const now = new Date();\n const commonData = this.getCommonEventData();\n const eventData: any = {\n event: eventName,\n properties: {\n ...properties,\n journeyContext: {\n sequenceIndex: journeyContext.eventCount - 1,\n timeSinceLastEvent: journeyContext.timeSinceLastEvent,\n journeyDuration: Date.now() - journeyContext.journeyStartTime\n }\n },\n timestamp: now.getTime(), // Milliseconds for backward compatibility\n created_at: now.toISOString(), // ISO timestamp for server-side time filtering\n userId: this.userManager.getUserId(),\n userType: this.userManager.getUserType(),\n sessionId: this.sessionId,\n // Include both project_key (new) and client_id (legacy)\n project_key: this.config.projectKey || undefined,\n client_id: this.config.clientId || this.config.apiKey || undefined,\n // Include project_id if available from project settings\n project_id: this.projectSettings?.project_id || undefined,\n // Include page context and extraConfig with all events\n ...commonData\n };\n\n // Check if we should send journey for analysis\n if (this.journeyTracker.shouldAnalyzeJourney()) {\n this.sendJourneyForAnalysis();\n }\n\n // Use the same batching logic as sendToWorker\n if (this.config.useWebWorker && typeof Worker !== 'undefined') {\n this.worker.postMessage({ type: 'track', payload: eventData });\n } else {\n this.eventQueue.push(eventData);\n }\n this.log('Event tracked public:', eventData);\n }\n\n private startBatchTimer() {\n this.batchTimer = window.setInterval(() => {\n this.flushQueue();\n }, this.config.batchInterval);\n }\n\n private async flushQueue() {\n if (this.eventQueue.length === 0) {\n return;\n }\n\n const batch = [...this.eventQueue];\n // Clear the queue immediately to prevent duplicates\n this.eventQueue = [];\n\n if (this.config.useWebWorker && typeof Worker !== 'undefined') {\n this.worker.postMessage({\n type: 'batch',\n events: batch,\n endpoint: `${this.config.endpoint}/api/v1/events`,\n });\n } else {\n // Fallback send mechanism with retry logic\n await this.sendBatchWithRetry(batch);\n }\n }\n\n private async sendBatchWithRetry(batch: Map<string, any>[]) {\n if (this.batchRetryCount >= this.maxBatchRetries) {\n if (this.batchTimer) {\n clearInterval(this.batchTimer);\n this.batchTimer = undefined;\n this.log('Max batch retries reached. BatchTimer cancelled.');\n }\n return;\n }\n try {\n await this.sendBatch(batch);\n // On success, reset retry count (queue already cleared in flushQueue)\n this.batchRetryCount = 0;\n } catch (error) {\n this.batchRetryCount++;\n this.log(`Batch send failed. Retry attempt ${this.batchRetryCount} of ${this.maxBatchRetries}.`, error);\n // Re-queue the failed batch for retry\n this.eventQueue.unshift(...batch);\n if (this.batchRetryCount >= this.maxBatchRetries) {\n if (this.batchTimer) {\n clearInterval(this.batchTimer);\n this.batchTimer = undefined;\n this.log('Max batch retries reached. BatchTimer cancelled.');\n }\n }\n }\n }\n\n // Update sendBatch to support client db endpoint and headers\n private async sendBatch(batch: Map<string, any>[]) {\n let endpoint = `${this.config.endpoint}/api/v1/events`;\n let headers: Record<string, string> = { 'Content-Type': 'application/json' };\n\n // Get authentication headers\n const authHeaders = await this.authManager.getAuthHeaders();\n headers = { ...headers, ...authHeaders };\n\n if (this.config.apiDetails && this.config.apiDetails.apiEndPoint) {\n endpoint = this.config.apiDetails.apiEndPoint;\n if (this.config.apiDetails.headers) {\n headers = { ...headers, ...this.config.apiDetails.headers };\n }\n }\n // Transform batch to required format\n const clientId = this.config.clientId || '5288aa7d-1b7c-481e-958d-eb9b8e951f14';\n const events = batch.map((e: any) => ({\n event: e.event, // keep 'event' key\n userId: e.userId,\n client_id: clientId,\n timestamp: new Date(e.timestamp).toISOString(),\n ...(e.properties || {})\n }));\n try {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify({ events }),\n });\n if (!response.ok) {\n throw new Error(`Failed to send batch: ${response.status}`);\n }\n this.log('Batch sent successfully:', events);\n } catch (error) {\n this.log('Error sending batch:', error);\n throw error; // Let sendBatchWithRetry handle re-queuing\n }\n }\n\n private generateSessionId(): string {\n // Simple session ID generator (could be improved)\n return 'sess_' + Math.random().toString(36).substr(2, 9);\n }\n\n // Get page context including URL, path, query params, and referrer\n private getPageContext(): Record<string, any> {\n const url = window.location.href;\n const path = window.location.pathname;\n const hash = window.location.hash;\n const referrer = document.referrer;\n\n // Parse query params into object\n const queryParams: Record<string, string> = {};\n const searchParams = new URLSearchParams(window.location.search);\n searchParams.forEach((value, key) => {\n queryParams[key] = value;\n });\n\n return {\n url,\n path,\n hash: hash || undefined,\n referrer: referrer || undefined,\n queryParams: Object.keys(queryParams).length > 0 ? queryParams : undefined,\n title: document.title || undefined\n };\n }\n\n // Get common event data that should be included in all events\n private getCommonEventData(): Record<string, any> {\n return {\n pageContext: this.getPageContext(),\n // Spread extraConfig properties directly at top level (not nested)\n ...(this.config.extraConfig || {})\n };\n }\n\n private getUserId(): string {\n // Use UserManager for consistent user identification\n return this.userManager.getUserId();\n }\n\n // Public method to identify authenticated user\n public identifyUser(authenticatedUserId: string, userProperties?: Record<string, any>) {\n // Get identification event before updating\n const identificationEvent = this.userManager.getUserIdentificationEvent(authenticatedUserId);\n\n // Update user in UserManager\n this.userManager.identifyUser(authenticatedUserId, userProperties);\n\n // Track the identification event\n this.track('user_identified', identificationEvent);\n\n // Update error tracker if enabled\n if (this.errorTracker) {\n this.errorTracker.setUser(authenticatedUserId);\n }\n\n this.log('User identified:', { userId: authenticatedUserId, properties: userProperties });\n }\n\n /**\n * Update or set extra config data that will be included with all events\n * Use this to pass custom data like userId, deviceId, appVersion, etc.\n * Can be called after initialization to update values (e.g., after user login)\n *\n * @example\n * // Set extra config during initialization\n * const sdk = new AInamikaSDKPro({\n * projectKey: 'proj_xxx',\n * extraConfig: { appVersion: '1.0.0', environment: 'production' }\n * });\n *\n * // Update extra config after user login\n * sdk.setExtraConfig({ userId: 'user_123', plan: 'premium' });\n */\n public setExtraConfig(config: Record<string, any>, merge: boolean = true) {\n if (merge && this.config.extraConfig) {\n this.config.extraConfig = { ...this.config.extraConfig, ...config };\n } else {\n this.config.extraConfig = config;\n }\n this.log('Extra config updated:', this.config.extraConfig);\n }\n\n /**\n * Get the current extra config\n */\n public getExtraConfig(): Record<string, any> | undefined {\n return this.config.extraConfig;\n }\n\n // Public authentication methods\n public async isAuthenticated(): Promise<boolean> {\n const token = await this.authManager.getAccessToken();\n return token !== null;\n }\n\n public async authenticate(): Promise<boolean> {\n return await this.authManager.initialize();\n }\n\n public async logout(): Promise<void> {\n await this.authManager.logout();\n }\n\n // Send journey data for AI analysis\n private async sendJourneyForAnalysis() {\n try {\n const journeyData = this.journeyTracker.getJourneyForAnalysis();\n const endpoint = `${this.config.endpoint}/api/v1/journeys/analyze`;\n\n // Get authentication headers\n const authHeaders = await this.authManager.getAuthHeaders();\n\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...authHeaders\n },\n body: JSON.stringify({\n client_id: this.config.clientId,\n user_id: this.userManager.getUserId(),\n session_id: this.sessionId,\n journey: journeyData\n })\n });\n\n if (!response.ok) {\n console.error('[AInamika SDK] Failed to send journey for analysis:', response.statusText);\n }\n } catch (error) {\n console.error('[AInamika SDK] Error sending journey for analysis:', error);\n }\n }\n\n private log(message: string, data?: any) {\n if (this.config.debug) {\n console.log(`[AnalyticsPro SDK] ${message}`, data || '');\n }\n }\n\n// Load config from /AInamika_config.json in the project root (fallback)\nprivate async loadConfigFromFile(): Promise<any | null> {\n try {\n const response = await fetch('/AInamika_config.json', { cache: 'reload' });\n if (!response.ok) {\n return null;\n }\n const config = await response.json();\n return config;\n } catch (err) {\n return null;\n }\n}\n\n// --- Dynamic DOM Fingerprinting and Smart Debouncing ---\nprivate async setupDynamicDomTracking() {\n // Use MutationObserver to watch for DOM changes\n if ('MutationObserver' in window) {\n const observer = new MutationObserver(() => {\n if (this.mutationDebounceTimer) {\n clearTimeout(this.mutationDebounceTimer);\n }\n this.mutationDebounceTimer = window.setTimeout(() => {\n this.handleDomMutation();\n }, this.mutationDebounceMs);\n });\n observer.observe(document.body, { childList: true, subtree: true, attributes: true });\n this.log('Dynamic DOM MutationObserver attached');\n }\n}\n\nprivate computeDomHash(structure: any): string {\n // Simple hash: JSON.stringify, then a basic hash (FNV-1a or similar)\n const str = JSON.stringify(structure);\n let hash = 2166136261;\n for (let i = 0; i < str.length; i++) {\n hash ^= str.charCodeAt(i);\n hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);\n }\n return (hash >>> 0).toString(16);\n}\n\n/**\n * Generates a stable fingerprint for an element based on stable attributes.\n * This fingerprint is used to ensure consistent event naming across all users.\n *\n * Priority order for fingerprint generation:\n * 1. data-testid, data-track, data-analytics (explicit tracking attributes)\n * 2. id (if unique and stable)\n * 3. name attribute (for form elements)\n * 4. aria-label (accessibility attribute)\n * 5. Combination of tag + text + stable parent context\n */\nprivate generateElementFingerprint(el: Element): string {\n const factors: string[] = [];\n\n // Priority 1: Explicit tracking attributes (most stable)\n const dataTestId = el.getAttribute('data-testid');\n const dataTrack = el.getAttribute('data-track');\n const dataAnalytics = el.getAttribute('data-analytics');\n\n if (dataTestId) factors.push(`testid:${dataTestId}`);\n if (dataTrack) factors.push(`track:${dataTrack}`);\n if (dataAnalytics) factors.push(`analytics:${dataAnalytics}`);\n\n // Priority 2: ID (if not dynamically generated)\n const id = el.id;\n if (id && !id.match(/^(jsc|css|ember|react|ng)-|^\\d+$|^[a-f0-9]{8,}$/i)) {\n factors.push(`id:${id}`);\n }\n\n // Priority 3: Name attribute (for forms)\n const name = el.getAttribute('name');\n if (name) factors.push(`name:${name}`);\n\n // Priority 4: Aria-label\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) factors.push(`aria:${ariaLabel.substring(0, 50)}`);\n\n // Priority 5: Element type + role\n const tag = el.tagName.toLowerCase();\n const role = el.getAttribute('role');\n const type = el.getAttribute('type');\n factors.push(`tag:${tag}`);\n if (role) factors.push(`role:${role}`);\n if (type) factors.push(`type:${type}`);\n\n // Priority 6: Text content (truncated, for buttons/links)\n if (['button', 'a', 'span', 'div'].includes(tag)) {\n const text = (el.textContent || '').trim().substring(0, 30).toLowerCase().replace(/\\s+/g, '_');\n if (text) factors.push(`text:${text}`);\n }\n\n // Priority 7: Customdata attribute (common in apps)\n const customdata = el.getAttribute('customdata');\n if (customdata) {\n try {\n const parsed = JSON.parse(customdata);\n if (parsed.name) factors.push(`customname:${parsed.name}`);\n if (parsed.id) factors.push(`customid:${parsed.id}`);\n } catch {\n // If not valid JSON, use first 30 chars\n factors.push(`customdata:${customdata.substring(0, 30)}`);\n }\n }\n\n // Priority 8: Stable parent context\n const parent = el.closest('[data-testid], [id]:not([id^=\"jsc-\"]):not([id^=\"css-\"])');\n if (parent && parent !== el) {\n const parentId = parent.getAttribute('data-testid') || parent.id;\n if (parentId) factors.push(`parent:${parentId}`);\n }\n\n // Priority 9: Stable class names (exclude dynamic/generated ones)\n if (el.className && typeof el.className === 'string') {\n const stableClasses = el.className.split(' ')\n .filter(c => c.trim() && !c.match(/^(jsc|css|ember|react|ng|active|hover|focus|selected|open|closed)-|^[a-f0-9]{6,}$/i))\n .slice(0, 3)\n .join('.');\n if (stableClasses) factors.push(`class:${stableClasses}`);\n }\n\n // Generate hash from factors\n const factorString = factors.join('|');\n return this.hashString(factorString);\n}\n\n/**\n * Simple hash function for fingerprinting (MD5-like, but faster)\n */\nprivate hashString(str: string): string {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n // Convert to hex and ensure 8 characters\n const hexHash = Math.abs(hash).toString(16).padStart(8, '0');\n return hexHash.substring(0, 16); // 16 char fingerprint\n}\n\nprivate readonly MAX_CACHED_CONFIGS = 15;\n\n// Get last-known config for INSTANT tracking (not keyed by domHash)\n// This allows zero-delay tracking for returning users\nprivate getLastKnownConfig(): any | null {\n try {\n const stored = localStorage.getItem('ainamika_last_known_config');\n if (!stored) return null;\n\n const data = JSON.parse(stored);\n // Validate it has events\n if (data && data.events_to_track && data.events_to_track.length > 0) {\n return data;\n }\n return null;\n } catch {\n return null;\n }\n}\n\n// Save config as last-known for instant loading on next visit\nprivate setLastKnownConfig(config: any): void {\n try {\n if (config && config.events_to_track && config.events_to_track.length > 0) {\n localStorage.setItem('ainamika_last_known_config', JSON.stringify(config));\n }\n } catch {\n // Ignore storage errors\n }\n}\n\nprivate getCachedConfigForDomHash(domHash: string): any | null {\n try {\n const cache = JSON.parse(localStorage.getItem('ainamika_dom_config_cache') || '{}');\n const entry = cache[domHash];\n\n if (entry) {\n // Handle backward compatibility: old format stored config directly\n if (entry.events_to_track) {\n // Old format - migrate to new format\n cache[domHash] = {\n config: entry,\n lastAccessed: Date.now(),\n createdAt: Date.now()\n };\n localStorage.setItem('ainamika_dom_config_cache', JSON.stringify(cache));\n return entry;\n }\n\n // New format with wrapper\n entry.lastAccessed = Date.now();\n localStorage.setItem('ainamika_dom_config_cache', JSON.stringify(cache));\n return entry.config;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nprivate setCachedConfigForDomHash(domHash: string, config: any) {\n try {\n const cache = JSON.parse(localStorage.getItem('ainamika_dom_config_cache') || '{}');\n\n // Add new entry with timestamp\n cache[domHash] = {\n config: config,\n lastAccessed: Date.now(),\n createdAt: Date.now()\n };\n\n // Check if we exceed the limit\n const keys = Object.keys(cache);\n if (keys.length > this.MAX_CACHED_CONFIGS) {\n // Sort by lastAccessed (oldest first) and remove excess\n const sortedKeys = keys.sort((a, b) => {\n const aTime = cache[a].lastAccessed || cache[a].createdAt || 0;\n const bTime = cache[b].lastAccessed || cache[b].createdAt || 0;\n return aTime - bTime;\n });\n\n // Remove oldest entries until we're at the limit\n const keysToRemove = sortedKeys.slice(0, keys.length - this.MAX_CACHED_CONFIGS);\n keysToRemove.forEach(key => {\n delete cache[key];\n this.log(`Evicted old config cache: ${key}`);\n });\n }\n\n localStorage.setItem('ainamika_dom_config_cache', JSON.stringify(cache));\n } catch (e) {\n // If localStorage is full, clear old entries and retry\n this.log('Cache storage error, clearing old entries:', e);\n this.clearOldConfigCache();\n }\n}\n\nprivate clearOldConfigCache() {\n try {\n const cache = JSON.parse(localStorage.getItem('ainamika_dom_config_cache') || '{}');\n const keys = Object.keys(cache);\n\n if (keys.length === 0) return;\n\n // Keep only the 5 most recent configs\n const sortedKeys = keys.sort((a, b) => {\n const aTime = cache[a].lastAccessed || cache[a].createdAt || 0;\n const bTime = cache[b].lastAccessed || cache[b].createdAt || 0;\n return bTime - aTime; // Newest first\n });\n\n const newCache: Record<string, any> = {};\n sortedKeys.slice(0, 5).forEach(key => {\n newCache[key] = cache[key];\n });\n\n localStorage.setItem('ainamika_dom_config_cache', JSON.stringify(newCache));\n this.log(`Cleared config cache, kept ${Object.keys(newCache).length} entries`);\n } catch {\n // Last resort: clear everything\n localStorage.removeItem('ainamika_dom_config_cache');\n }\n}\n\nprivate async handleDomMutation() {\n const domStructure = await this.getDOMStructure();\n const domHash = this.computeDomHash(domStructure);\n\n if (domHash === this.lastDomHash) {\n this.log('DOM hash unchanged after mutation, skipping config fetch.');\n return;\n }\n\n this.log('DOM hash changed, detecting new elements...', { oldHash: this.lastDomHash, newHash: domHash });\n this.lastDomHash = domHash;\n\n // Filter to only NEW elements that we haven't seen before\n const allElements = domStructure.elements || [];\n const newElements = allElements.filter((el: any) => {\n const selector = el.selector || '';\n if (!selector || this.knownElementSelectors.has(selector)) {\n return false;\n }\n return true;\n });\n\n // If no new elements, just apply cached config if available\n if (newElements.length === 0) {\n this.log('No new elements detected, skipping config fetch.');\n return;\n }\n\n this.log(`Found ${newElements.length} new elements out of ${allElements.length} total`);\n\n // Check if we have a cached config for this exact DOM state\n const cachedConfig = this.getCachedConfigForDomHash(domHash);\n if (cachedConfig) {\n this.log('Reusing cached config for DOM hash', domHash);\n this.mergeAndApplyConfig(cachedConfig);\n // Mark all elements as known\n allElements.forEach((el: any) => {\n if (el.selector) this.knownElementSelectors.add(el.selector);\n });\n return;\n }\n\n // Send ONLY new elements to server for config generation\n const newDomStructure = { elements: newElements };\n this.log('Fetching config for new elements only:', newElements.length);\n\n const config = await this.fetchGeneratedConfig(newDomStructure, domHash);\n if (config && config.events_to_track) {\n // Merge new config with existing config\n this.mergeAndApplyConfig(config);\n\n // Cache the merged config\n this.setCachedConfigForDomHash(domHash, this.mergedConfig);\n this.lastConfigHash = config.config_hash || '';\n\n // Mark new elements as known\n newElements.forEach((el: any) => {\n if (el.selector) this.knownElementSelectors.add(el.selector);\n });\n\n this.log('Fetched and merged config for new elements', {\n newEvents: config.events_to_track.length,\n totalEvents: this.mergedConfig.events_to_track.length\n });\n } else {\n this.log('No valid config returned for new elements');\n }\n}\n\nprivate mergeAndApplyConfig(newConfig: { events_to_track: any[], tracking_config?: any }) {\n if (!newConfig || !newConfig.events_to_track) return;\n\n // Create a map of existing events by selector to avoid duplicates\n const existingSelectors = new Set(\n this.mergedConfig.events_to_track.map(e => e.element_selector)\n );\n\n // Add only new events that don't already exist\n const newEvents = newConfig.events_to_track.filter(\n event => !existingSelectors.has(event.element_selector)\n );\n\n if (newEvents.length > 0) {\n this.mergedConfig.events_to_track.push(...newEvents);\n this.log(`Merged ${newEvents.length} new events, total: ${this.mergedConfig.events_to_track.length}`);\n }\n\n // Merge tracking config\n if (newConfig.tracking_config) {\n this.mergedConfig.tracking_config = {\n ...this.mergedConfig.tracking_config,\n ...newConfig.tracking_config\n };\n }\n\n // Apply only the new events (existing ones already have listeners)\n if (newEvents.length > 0) {\n this.applyGeneratedConfig({ events_to_track: newEvents, tracking_config: newConfig.tracking_config });\n }\n}\n}\n\n// Make AnalyticsProSDK available globally for both classic and module scripts\nif (typeof window !== 'undefined') {\n (window as any).AInamikaSDKPro = AInamikaSDKPro;\n}\n\nexport default AInamikaSDKPro;\nexport { AInamikaSDKPro };\n\n// Export types for TypeScript users\nexport type { PerformanceMetrics, EngagementMetrics } from './advanced-tracker';\nexport { enrichEventWithCustomdata } from './advanced-tracker';"],"names":["root","factory","exports","module","define","amd","self","window","global","this","__webpack_require__","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","config","breadcrumbs","errorCount","errorDebounceMap","Map","html2canvasLoaded","html2canvasLoading","isCapturingScreenshot","captureScreenshots","captureDomSnapshots","maxStackTraceDepth","maxErrorsPerSession","debounceMs","enableNetworkTracking","enableConsoleCapture","authManager","sessionId","generateSessionId","originalConsole","console","initialize","loadHtml2Canvas","html2canvas","Promise","resolve","script","document","createElement","src","async","onload","log","onerror","error","head","appendChild","addEventListener","event","handleError","type","message","filename","line","lineno","column","colno","reason","promise","setupNetworkTracking","setupConsoleCapture","setupNavigationTracking","setupClickTracking","Date","now","Math","random","toString","substr","addBreadcrumb","breadcrumb","push","timestamp","length","slice","errorInfo","warn","errorKey","has","set","captureError","errorData","client_id","clientId","project_key","projectKey","error_type","stack_trace","extractStackTrace","url","location","href","user_agent","navigator","userAgent","error_metadata","userId","networkInfo","getNetworkInfo","performance","getPerformanceInfo","deviceInfo","getDeviceInfo","severity","assessSeverity","session_id","user_id","captureScreenshot","screen_snapshot","sendError","data","stack","split","maxDepth","join","toLowerCase","includes","captureDomSnapshot","snapshot","title","viewport","width","innerWidth","height","innerHeight","elements","extractDomElements","JSON","stringify","forEach","selector","els","querySelectorAll","Array","from","el","tagName","id","className","textContent","substring","attributes","getElementAttributes","e","element","attrs","attr","value","getAttribute","body","min","useCORS","logging","toDataURL","connection","mozConnection","webkitConnection","effectiveType","downlink","rtt","saveData","info","memory","usedJSHeapSize","totalJSHeapSize","jsHeapSizeLimit","timing","domContentLoaded","domContentLoadedEventEnd","navigationStart","load","loadEventEnd","getEntriesByType","entry","name","firstPaint","startTime","firstContentfulPaint","ua","deviceType","test","os","osVersion","match","replace","browser","browserVersion","screenWidth","screen","screenHeight","language","timezone","Intl","DateTimeFormat","resolvedOptions","timeZone","originalFetch","fetch","args","Request","String","response","status","duration","ok","statusText","originalXHROpen","XMLHttpRequest","open","originalXHRSend","send","method","username","password","_errorTracker","tracker","dispatchEvent","CustomEvent","detail","original","map","arg","consoleMethod","level","currentUrl","trackNavigation","newUrl","to","originalPushState","history","pushState","originalReplaceState","replaceState","apply","setTimeout","target","getElementSelector","text","trim","classes","filter","c","headers","getAuthHeaders","authHeaders","apiKey","endpoint","Error","storeErrorLocally","stored","localStorage","getItem","errors","parse","splice","setItem","captureException","context","setUser","addTag","flushStoredErrors","removeItem","STORAGE_KEY","METADATA_KEY","isProcessing","maxStorageSize","maxRetries","retryInterval","compressionEnabled","encryptionEnabled","cleanupOldErrors","startRetryTimer","setupStorageListener","processQueue","storeError","errorId","generateErrorId","storedError","compressData","retryCount","addToQueue","updateMetadata","getStoredErrors","decompressData","removeError","getQueueRaw","filteredErrors","clearAll","getStorageStats","totalSize","Blob","size","timestamps","sort","oldestError","newestError","lastRetry","incrementRetryCount","retryError","find","serialized","shift","errorIndex","findIndex","jsonString","btoa","compressedData","atob","cleanErrors","retryTimer","setInterval","stats","metadata","lastUpdate","exportErrors","exportData","version","importErrors","isArray","destroy","clearInterval","undefined","getAinamikaStorageUsage","errorSize","otherSize","startsWith","checkStorageSpace","requiredBytes","testKey","testData","repeat","cleanupAllAinamikaStorage","keysToRemove","generateStorageReport","storage","ErrorStorage","usage","ErrorStorageUtils","ENV_CONFIG","__AINAMIKA_CONFIG__","API_BASE_URL","APP_ENV","DEBUG","userProperties","initializeUser","getOrCreateUserId","generateAnonymousId","getUserId","getUserProperties","identifyUser","authenticatedUserId","properties","previousId","updateUserProperties","clearUser","getUserIdentificationEvent","previous_id","isAnonymousUser","getUserType","userJourney","lastEventTime","sequenceIndex","maxJourneyLength","journeyAnalysisThreshold","journeyStartTime","trackEvent","eventName","currentTime","timeSinceLastEvent","journeyEvent","journeyPosition","getContext","journeySequence","getJourneySequence","eventCount","getJourneyData","shouldAnalyzeJourney","getJourneyForAnalysis","journeyDuration","avgTimeBetweenEvents","calculateAverageTimeBetweenEvents","journey","journeyLength","endTime","totalTime","i","round","findPatterns","patterns","sequence","fromEntries","entries","clearJourney","getJourneySegment","count","detectPotentialFunnel","recentEvents","funnelName","apiEndpoint","debug","accessToken","refreshToken","tokenExpiry","loadTokens","isTokenValid","debugLog","refreshAccessToken","requestTokens","tokens","setTokens","json","refresh_token","clearTokens","getAccessToken","shouldRefreshToken","token","access_token","expires_in","saveTokens","scheduleTokenRefresh","refreshTimer","clearTimeout","refreshIn","max","tokenData","AuthManager","cleanupLegacyTokens","logout","onEvent","performanceMetrics","scrollDepthReached","Set","clickHistory","isPageVisible","visibilityChangeCount","trackPerformance","trackEngagement","trackScrollDepth","trackRageClicks","trackTimeOnPage","trackAPIResponses","scrollDepthThresholds","rageClickThreshold","rageClickWindow","apiTrackingPatterns","pageStartTime","lastActivityTime","bind","originalXHR","engagementMetrics","timeOnPage","scrollDepth","scrollDepthMilestones","rageClicks","totalClicks","activeTime","idleTime","pageVisibilityChanges","initPerformanceTracking","initEngagementTracking","initScrollTracking","initRageClickTracking","initTimeTracking","initAPITracking","trackPageExit","PerformanceObserver","entryList","getEntries","lastEntry","lcp","observe","buffered","firstEntry","fid","processingStart","eventType","hadRecentInput","cls","visibilityState","fcpEntry","fcp","ttfb","responseStart","pageLoad","resources","resourceCount","transferSize","reduce","acc","r","transferSizeKB","updateActiveTime","passive","ticking","updateScrollDepth","scrollTop","scrollY","documentElement","docHeight","scrollHeight","scrollPercent","threshold","add","depth","timeToReach","requestAnimationFrame","time","clickCount","position","x","clientX","y","clientY","totalRageClicks","timeSinceLastActivity","shouldTrackAPI","trackAPICall","success","some","pattern","RegExp","trackAPI","responseType","responseKeys","keys","hasData","dataCount","action","trackConversion","goalName","goal","timeToConvert","scrollDepthAtConversion","clicksBeforeConversion","getPerformanceMetrics","getEngagementMetrics","scrollMilestones","visibilityChanges","eventQueue","isInitialized","batchRetryCount","maxBatchRetries","lastDomHash","lastConfigHash","mutationDebounceTimer","mutationDebounceMs","attachedListeners","WeakMap","knownElementSelectors","handledClicks","CLICK_DEDUP_WINDOW_MS","mergedConfig","events_to_track","MAX_CACHED_CONFIGS","batchInterval","useWebWorker","errorTracking","enabled","advancedTracking","userIdentifier","getOrCreateUserIdentifier","userManager","UserManager","journeyTracker","JourneyTracker","blob","workerUrl","URL","createObjectURL","worker","Worker","initializeProjectSettings","initializeSamplingDecision","projectSettings","samplingDecision","shouldSampleErrors","initializeErrorTracking","initializeAdvancedTracking","autoConfig","setupAutoConfiguration","setupDynamicDomTracking","setupWebWorker","startBatchTimer","sampling","storageKey","identifier","user_identifier","cacheSamplingDecision","loadCachedSamplingDecision","cacheData","AInamikaSDKPro","SAMPLING_STORAGE_KEY","cleanupLegacySamplingKeys","cached","getDefaultSamplingDecision","samplingData","should_sample","events","session_replay","rates","decision","shouldSampleEvents","shouldSampleSessionReplay","getSamplingStatus","getProjectInfo","getTrackingStatus","totalEvents","knownSelectors","resetDomTracking","clear","clearAllCaches","clearUserIdentifier","getCacheStats","cache","domHashes","domConfigCacheSize","cachedDomHashes","hasSamplingCache","hasUserIdentifier","hasLastKnownConfig","errorStorage","errorConfig","errorTracker","ErrorTracker","advConfig","advancedTracker","AdvancedTracker","sendToWorker","track","appliedFromCache","lastKnownConfig","getLastKnownConfig","eventsCount","tracking_config","applyGeneratedConfig","postMessage","setupAutoConfigurationBackground","alreadyAppliedCache","getDOMStructure","domStructure","domHash","computeDomHash","cachedConfig","getCachedConfigForDomHash","loadConfigFromFile","fileConfig","fetchAndMergeFreshConfig","hadCachedConfig","fetchGeneratedConfig","freshConfig","element_selector","newEvents","setCachedConfigForDomHash","config_hash","setLastKnownConfig","getSelector","filteredElements","style","getComputedStyle","isVisible","display","visibility","opacity","hasInteraction","hasAttribute","classList","contains","isImportantElement","indexOf","seen","structure","stableAttributes","fingerprint","generateElementFingerprint","isInteractive","hasChildren","children","childCount","parentTagName","parentElement","index","elementCount","requestBody","transformEventNameForType","replacements","endsWith","sanitizeSelector","idPart","escapedId","eventToTrack","sanitizedSelector","metadata_rules","extract_customdata","extract_text","eventSet","event_type","clickTimestamp","isGenericEvent","event_name","isGenericSelector","ts","abs","elementData","extractElementData","cutoff","delete","category","itemName","section","toISOString","IntersectionObserver","isIntersecting","viewEventName","intersectionRatio","transformedEventName","observe_mutations","MutationObserver","mutations","mutation","outerHTML","childList","subtree","metadataRules","rect","getBoundingClientRect","baseData","enrichedData","customdata","dataset","parsed","displayedTitle","itemId","nameMatch","titleMatch","elementId","idParts","namePart","displayText","enrichEventWithCustomdata","enriched","commonData","getCommonEventData","eventData","getTime","created_at","project_id","payload","apiUrl","apiDetails","apiEndPoint","batchSize","workerConfig","onmessage","failedEvents","unshift","journeyContext","userType","sendJourneyForAnalysis","batchTimer","flushQueue","batch","sendBatchWithRetry","sendBatch","getPageContext","path","pathname","hash","referrer","queryParams","URLSearchParams","search","pageContext","extraConfig","identificationEvent","setExtraConfig","merge","getExtraConfig","isAuthenticated","authenticate","journeyData","handleDomMutation","str","charCodeAt","factors","dataTestId","dataTrack","dataAnalytics","ariaLabel","tag","role","parent","closest","parentId","stableClasses","factorString","hashString","padStart","lastAccessed","createdAt","a","b","clearOldConfigCache","sortedKeys","aTime","oldHash","newHash","allElements","newElements","mergeAndApplyConfig","newDomStructure","newConfig","existingSelectors"],"sourceRoot":""}
|
|
1
|
+
{"version":3,"file":"ainamika-sdk.js","mappings":"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","sources":["webpack://AInamikaSDKPro/webpack/universalModuleDefinition","webpack://AInamikaSDKPro/webpack/bootstrap","webpack://AInamikaSDKPro/webpack/runtime/define property getters","webpack://AInamikaSDKPro/webpack/runtime/hasOwnProperty shorthand","webpack://AInamikaSDKPro/./src/error-tracker.ts","webpack://AInamikaSDKPro/./src/error-storage.ts","webpack://AInamikaSDKPro/./src/config.ts","webpack://AInamikaSDKPro/./src/user-manager.ts","webpack://AInamikaSDKPro/./src/journey-tracker.ts","webpack://AInamikaSDKPro/./src/auth-manager.ts","webpack://AInamikaSDKPro/./src/advanced-tracker.ts","webpack://AInamikaSDKPro/./src/sdk.ts"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"AInamikaSDKPro\"] = factory();\n\telse\n\t\troot[\"AInamikaSDKPro\"] = factory();\n})((typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : typeof global !== \"undefined\" ? global : this), function() {\nreturn ","// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// error-tracker.ts - Advanced Error Tracking System for AInamika SDK\n\nimport { AuthManager } from './auth-manager';\n\nexport interface ErrorConfig {\n endpoint: string;\n clientId: string;\n apiKey?: string; // Made optional for backward compatibility\n authManager?: AuthManager; // New: pass authManager for JWT auth\n projectKey?: string; // Project key for project-based error tracking\n captureScreenshots?: boolean;\n captureDomSnapshots?: boolean;\n maxStackTraceDepth?: number;\n maxErrorsPerSession?: number;\n debounceMs?: number;\n enableNetworkTracking?: boolean;\n enableConsoleCapture?: boolean;\n}\n\nexport interface ErrorData {\n id?: string;\n client_id: string;\n project_key?: string; // Project key for project-based error tracking\n error_type: 'javascript' | 'network' | 'unhandled' | 'console' | 'custom';\n message: string;\n stack_trace?: string;\n url: string;\n user_agent: string;\n timestamp: number;\n error_metadata: {\n line?: number;\n column?: number;\n filename?: string;\n component?: string;\n props?: Record<string, any>;\n userId?: string;\n sessionId?: string;\n breadcrumbs?: ErrorBreadcrumb[];\n networkInfo?: NetworkInfo;\n performance?: PerformanceInfo;\n deviceInfo?: DeviceInfo;\n };\n dom_snapshot?: string;\n screen_snapshot?: string;\n severity: 'low' | 'medium' | 'high' | 'critical';\n session_id: string;\n user_id?: string;\n}\n\nexport interface ErrorBreadcrumb {\n timestamp: number;\n type: 'navigation' | 'click' | 'console' | 'network' | 'error';\n message: string;\n data?: Record<string, any>;\n}\n\nexport interface NetworkInfo {\n effectiveType?: string;\n downlink?: number;\n rtt?: number;\n saveData?: boolean;\n}\n\nexport interface PerformanceInfo {\n memory?: {\n usedJSHeapSize: number;\n totalJSHeapSize: number;\n jsHeapSizeLimit: number;\n };\n timing?: {\n domContentLoaded: number;\n load: number;\n firstPaint?: number;\n firstContentfulPaint?: number;\n };\n}\n\nexport interface DeviceInfo {\n deviceType: 'desktop' | 'mobile' | 'tablet';\n os: string;\n osVersion: string;\n browser: string;\n browserVersion: string;\n screenWidth: number;\n screenHeight: number;\n language: string;\n timezone: string;\n}\n\nexport class ErrorTracker {\n private config: ErrorConfig;\n private breadcrumbs: ErrorBreadcrumb[] = [];\n private errorCount = 0;\n private errorDebounceMap = new Map<string, number>();\n private originalConsole: Console;\n private sessionId: string;\n private userId?: string;\n private authManager?: AuthManager;\n\n constructor(config: ErrorConfig) {\n this.config = {\n captureScreenshots: false, // Disabled by default - loads html2canvas when enabled\n captureDomSnapshots: false, // Disabled - DOM snapshots are not used\n maxStackTraceDepth: 50,\n maxErrorsPerSession: 100,\n debounceMs: 1000,\n enableNetworkTracking: true,\n enableConsoleCapture: true,\n ...config\n };\n\n this.authManager = config.authManager;\n this.sessionId = this.generateSessionId();\n this.originalConsole = { ...console };\n this.initialize();\n }\n\n private html2canvasLoaded = false;\n private html2canvasLoading: Promise<boolean> | null = null;\n private isCapturingScreenshot = false; // Flag to prevent infinite loops during screenshot capture\n\n private async loadHtml2Canvas(): Promise<boolean> {\n // Return if already loaded\n if (this.html2canvasLoaded || typeof (window as any).html2canvas === 'function') {\n this.html2canvasLoaded = true;\n return true;\n }\n\n // Return existing loading promise if already loading\n if (this.html2canvasLoading) {\n return this.html2canvasLoading;\n }\n\n // Load html2canvas dynamically\n this.html2canvasLoading = new Promise<boolean>((resolve) => {\n const script = document.createElement('script');\n script.src = 'https://html2canvas.hertzen.com/dist/html2canvas.min.js';\n script.async = true;\n\n script.onload = () => {\n console.log('[AInamika Error Tracker] html2canvas loaded successfully');\n this.html2canvasLoaded = true;\n resolve(true);\n };\n\n script.onerror = () => {\n console.error('[AInamika Error Tracker] Failed to load html2canvas');\n resolve(false);\n };\n\n document.head.appendChild(script);\n });\n\n return this.html2canvasLoading;\n }\n\n private initialize() {\n // Global error handler\n window.addEventListener('error', (event) => {\n this.handleError({\n type: 'javascript',\n message: event.message,\n filename: event.filename,\n line: event.lineno,\n column: event.colno,\n error: event.error\n });\n });\n\n // Unhandled promise rejection handler\n window.addEventListener('unhandledrejection', (event) => {\n this.handleError({\n type: 'unhandled',\n message: event.reason?.message || 'Unhandled Promise Rejection',\n error: event.reason,\n promise: true\n });\n });\n\n // Network error tracking\n if (this.config.enableNetworkTracking) {\n this.setupNetworkTracking();\n }\n\n // Console capture\n if (this.config.enableConsoleCapture) {\n this.setupConsoleCapture();\n }\n\n // Navigation breadcrumbs\n this.setupNavigationTracking();\n\n // Click breadcrumbs\n this.setupClickTracking();\n\n // Preload html2canvas if screenshot capture is enabled\n if (this.config.captureScreenshots) {\n this.loadHtml2Canvas();\n }\n\n console.log('[AInamika Error Tracker] Initialized successfully');\n }\n\n private generateSessionId(): string {\n return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n }\n\n private addBreadcrumb(breadcrumb: Omit<ErrorBreadcrumb, 'timestamp'>) {\n this.breadcrumbs.push({\n ...breadcrumb,\n timestamp: Date.now()\n });\n\n // Keep only last 50 breadcrumbs\n if (this.breadcrumbs.length > 50) {\n this.breadcrumbs = this.breadcrumbs.slice(-50);\n }\n }\n\n private handleError(errorInfo: any) {\n if (this.errorCount >= this.config.maxErrorsPerSession!) {\n console.warn('[AInamika Error Tracker] Max errors per session reached');\n return;\n }\n\n const errorKey = `${errorInfo.message}_${errorInfo.filename}_${errorInfo.line}`;\n const now = Date.now();\n \n // Debounce duplicate errors\n if (this.errorDebounceMap.has(errorKey)) {\n const lastTime = this.errorDebounceMap.get(errorKey)!;\n if (now - lastTime < this.config.debounceMs!) {\n return;\n }\n }\n this.errorDebounceMap.set(errorKey, now);\n\n this.errorCount++;\n this.captureError(errorInfo);\n }\n\n private async captureError(errorInfo: any) {\n try {\n const errorData: ErrorData = {\n client_id: this.config.clientId,\n project_key: this.config.projectKey, // Include project_key for project-based tracking\n error_type: errorInfo.type || 'javascript',\n message: errorInfo.message || 'Unknown error',\n stack_trace: this.extractStackTrace(errorInfo.error),\n url: window.location.href,\n user_agent: navigator.userAgent,\n timestamp: Date.now(),\n error_metadata: {\n line: errorInfo.line,\n column: errorInfo.column,\n filename: errorInfo.filename,\n userId: this.userId,\n sessionId: this.sessionId,\n breadcrumbs: [...this.breadcrumbs],\n networkInfo: this.getNetworkInfo(),\n performance: this.getPerformanceInfo(),\n deviceInfo: this.getDeviceInfo()\n },\n severity: this.assessSeverity(errorInfo),\n session_id: this.sessionId,\n user_id: this.userId\n };\n\n // DOM snapshot capture disabled - not used in dashboard\n\n // Capture screenshot\n if (this.config.captureScreenshots) {\n errorData.screen_snapshot = await this.captureScreenshot();\n }\n\n // Send error to backend\n await this.sendError(errorData);\n\n // Add error breadcrumb\n this.addBreadcrumb({\n type: 'error',\n message: `${errorData.error_type}: ${errorData.message}`,\n data: { severity: errorData.severity }\n });\n\n } catch (captureError) {\n console.error('[AInamika Error Tracker] Failed to capture error:', captureError);\n }\n }\n\n private extractStackTrace(error: Error): string {\n if (!error || !error.stack) return '';\n \n const stack = error.stack.split('\\n');\n const maxDepth = this.config.maxStackTraceDepth!;\n \n return stack.slice(0, maxDepth).join('\\n');\n }\n\n private assessSeverity(errorInfo: any): 'low' | 'medium' | 'high' | 'critical' {\n const message = errorInfo.message?.toLowerCase() || '';\n \n // Critical errors\n if (message.includes('out of memory') || \n message.includes('security') ||\n message.includes('permission denied') ||\n errorInfo.type === 'unhandled') {\n return 'critical';\n }\n \n // High severity\n if (message.includes('network') || \n message.includes('timeout') ||\n message.includes('failed to fetch') ||\n message.includes('cors')) {\n return 'high';\n }\n \n // Medium severity\n if (message.includes('undefined') || \n message.includes('null') ||\n message.includes('cannot read property')) {\n return 'medium';\n }\n \n return 'low';\n }\n\n private captureDomSnapshot(): string {\n try {\n // Create a simplified DOM snapshot\n const snapshot = {\n url: window.location.href,\n title: document.title,\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight\n },\n elements: this.extractDomElements()\n };\n \n return JSON.stringify(snapshot);\n } catch (error) {\n console.error('[AInamika Error Tracker] Failed to capture DOM snapshot:', error);\n return '';\n }\n }\n\n private extractDomElements(): any[] {\n const elements: any[] = [];\n const maxElements = 100;\n \n // Get key elements\n const selectors = [\n 'body > *',\n '[id]',\n '[class*=\"error\"]',\n '[class*=\"modal\"]',\n 'form',\n 'button',\n 'input[type=\"submit\"]'\n ];\n \n selectors.forEach(selector => {\n try {\n const els = document.querySelectorAll(selector);\n Array.from(els).slice(0, maxElements - elements.length).forEach(el => {\n elements.push({\n tagName: el.tagName,\n id: el.id,\n className: el.className,\n textContent: el.textContent?.substring(0, 100),\n attributes: this.getElementAttributes(el)\n });\n });\n } catch (e) {\n // Ignore selector errors\n }\n });\n \n return elements;\n }\n\n private getElementAttributes(element: Element): Record<string, string> {\n const attrs: Record<string, string> = {};\n const importantAttrs = ['id', 'class', 'type', 'name', 'value', 'href', 'src'];\n \n importantAttrs.forEach(attr => {\n const value = element.getAttribute(attr);\n if (value) attrs[attr] = value;\n });\n \n return attrs;\n }\n\n private async captureScreenshot(): Promise<string> {\n // Prevent recursive screenshot capture (html2canvas makes network calls that could trigger errors)\n if (this.isCapturingScreenshot) {\n return '';\n }\n\n this.isCapturingScreenshot = true;\n\n try {\n // Dynamically load html2canvas if not already loaded\n const loaded = await this.loadHtml2Canvas();\n if (!loaded) {\n console.warn('[AInamika Error Tracker] html2canvas not available, skipping screenshot');\n return '';\n }\n\n // Use html2canvas to capture screenshot\n if (typeof (window as any).html2canvas === 'function') {\n const canvas = await (window as any).html2canvas(document.body, {\n height: Math.min(window.innerHeight, 1000),\n width: Math.min(window.innerWidth, 1000),\n useCORS: true,\n logging: false // Disable html2canvas logging\n });\n return canvas.toDataURL('image/jpeg', 0.7);\n }\n return '';\n } catch (error) {\n console.error('[AInamika Error Tracker] Failed to capture screenshot:', error);\n return '';\n } finally {\n this.isCapturingScreenshot = false;\n }\n }\n\n private getNetworkInfo(): NetworkInfo {\n const connection = (navigator as any).connection || \n (navigator as any).mozConnection || \n (navigator as any).webkitConnection;\n \n if (!connection) return {};\n \n return {\n effectiveType: connection.effectiveType,\n downlink: connection.downlink,\n rtt: connection.rtt,\n saveData: connection.saveData\n };\n }\n\n private getPerformanceInfo(): PerformanceInfo {\n const info: PerformanceInfo = {};\n \n // Memory info\n if ((performance as any).memory) {\n info.memory = {\n usedJSHeapSize: (performance as any).memory.usedJSHeapSize,\n totalJSHeapSize: (performance as any).memory.totalJSHeapSize,\n jsHeapSizeLimit: (performance as any).memory.jsHeapSizeLimit\n };\n }\n \n // Timing info\n if (performance.timing) {\n const timing = performance.timing;\n info.timing = {\n domContentLoaded: timing.domContentLoadedEventEnd - timing.navigationStart,\n load: timing.loadEventEnd - timing.navigationStart\n };\n \n // Paint timings\n if (performance.getEntriesByType) {\n const paintEntries = performance.getEntriesByType('paint');\n paintEntries.forEach((entry: any) => {\n if (entry.name === 'first-paint') {\n info.timing!.firstPaint = entry.startTime;\n } else if (entry.name === 'first-contentful-paint') {\n info.timing!.firstContentfulPaint = entry.startTime;\n }\n });\n }\n }\n \n return info;\n }\n\n private getDeviceInfo(): DeviceInfo {\n const ua = navigator.userAgent;\n\n // Detect device type\n let deviceType: 'desktop' | 'mobile' | 'tablet' = 'desktop';\n if (/tablet|ipad|playbook|silk/i.test(ua)) {\n deviceType = 'tablet';\n } else if (/mobile|iphone|ipod|android|blackberry|opera mini|iemobile/i.test(ua)) {\n deviceType = 'mobile';\n }\n\n // Detect OS\n let os = 'Unknown';\n let osVersion = '';\n if (/windows/i.test(ua)) {\n os = 'Windows';\n const match = ua.match(/Windows NT (\\d+\\.\\d+)/);\n if (match) osVersion = match[1];\n } else if (/macintosh|mac os x/i.test(ua)) {\n os = 'macOS';\n const match = ua.match(/Mac OS X (\\d+[._]\\d+)/);\n if (match) osVersion = match[1].replace('_', '.');\n } else if (/android/i.test(ua)) {\n os = 'Android';\n const match = ua.match(/Android (\\d+(\\.\\d+)?)/);\n if (match) osVersion = match[1];\n } else if (/iphone|ipad|ipod/i.test(ua)) {\n os = 'iOS';\n const match = ua.match(/OS (\\d+[._]\\d+)/);\n if (match) osVersion = match[1].replace('_', '.');\n } else if (/linux/i.test(ua)) {\n os = 'Linux';\n }\n\n // Detect browser\n let browser = 'Unknown';\n let browserVersion = '';\n if (/edg/i.test(ua)) {\n browser = 'Edge';\n const match = ua.match(/Edg\\/(\\d+(\\.\\d+)?)/);\n if (match) browserVersion = match[1];\n } else if (/chrome/i.test(ua) && !/edg/i.test(ua)) {\n browser = 'Chrome';\n const match = ua.match(/Chrome\\/(\\d+(\\.\\d+)?)/);\n if (match) browserVersion = match[1];\n } else if (/safari/i.test(ua) && !/chrome/i.test(ua)) {\n browser = 'Safari';\n const match = ua.match(/Version\\/(\\d+(\\.\\d+)?)/);\n if (match) browserVersion = match[1];\n } else if (/firefox/i.test(ua)) {\n browser = 'Firefox';\n const match = ua.match(/Firefox\\/(\\d+(\\.\\d+)?)/);\n if (match) browserVersion = match[1];\n }\n\n return {\n deviceType,\n os,\n osVersion,\n browser,\n browserVersion,\n screenWidth: window.screen.width,\n screenHeight: window.screen.height,\n language: navigator.language || '',\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || ''\n };\n }\n\n private setupNetworkTracking() {\n // Override fetch\n const originalFetch = window.fetch;\n window.fetch = async (...args) => {\n const startTime = Date.now();\n const url = args[0] instanceof Request ? args[0].url : String(args[0]);\n \n try {\n const response = await originalFetch(...args);\n \n this.addBreadcrumb({\n type: 'network',\n message: `Fetch ${response.status} ${url}`,\n data: {\n url,\n status: response.status,\n duration: Date.now() - startTime\n }\n });\n \n if (!response.ok) {\n this.handleError({\n type: 'network',\n message: `Network request failed: ${response.status} ${response.statusText}`,\n url,\n status: response.status\n });\n }\n \n return response;\n } catch (error: any) {\n this.addBreadcrumb({\n type: 'network',\n message: `Fetch failed ${url}`,\n data: { url, error: error?.message || 'Unknown error' }\n });\n \n this.handleError({\n type: 'network',\n message: `Network request failed: ${error?.message || 'Unknown error'}`,\n url,\n error\n });\n \n throw error;\n }\n };\n\n // Override XMLHttpRequest\n const originalXHROpen = XMLHttpRequest.prototype.open;\n const originalXHRSend = XMLHttpRequest.prototype.send;\n \n XMLHttpRequest.prototype.open = function(method: string, url: string | URL, async?: boolean, username?: string | null, password?: string | null) {\n (this as any)._errorTracker = { method, url, startTime: Date.now() };\n return originalXHROpen.call(this, method, url, async || true, username, password);\n };\n \n XMLHttpRequest.prototype.send = function(...args) {\n const tracker = (this as any)._errorTracker;\n \n this.addEventListener('loadend', () => {\n if (tracker) {\n const duration = Date.now() - tracker.startTime;\n \n if (this.status >= 400) {\n this.dispatchEvent(new CustomEvent('networkerror', {\n detail: {\n type: 'network',\n message: `XHR request failed: ${this.status} ${this.statusText}`,\n url: tracker.url,\n status: this.status\n }\n }));\n }\n \n this.dispatchEvent(new CustomEvent('networkbreadcrumb', {\n detail: {\n type: 'network',\n message: `XHR ${this.status} ${tracker.url}`,\n data: {\n method: tracker.method,\n url: tracker.url,\n status: this.status,\n duration\n }\n }\n }));\n }\n });\n \n return originalXHRSend.call(this, ...args);\n };\n \n // Listen for custom events\n document.addEventListener('networkerror', (event: any) => {\n this.handleError(event.detail);\n });\n \n document.addEventListener('networkbreadcrumb', (event: any) => {\n this.addBreadcrumb(event.detail);\n });\n }\n\n private setupConsoleCapture() {\n // Override console methods\n ['error', 'warn'].forEach(method => {\n const original = this.originalConsole[method as keyof Console] as Function;\n (console as any)[method] = (...args: any[]) => {\n if (typeof original === 'function') {\n original.call(console, ...args);\n }\n \n if (method === 'error') {\n this.handleError({\n type: 'console',\n message: args.map(arg => String(arg)).join(' '),\n consoleMethod: method\n });\n }\n \n this.addBreadcrumb({\n type: 'console',\n message: `Console ${method}: ${args.map(arg => String(arg)).join(' ')}`,\n data: { level: method }\n });\n };\n });\n }\n\n private setupNavigationTracking() {\n // Track page changes\n let currentUrl = window.location.href;\n \n const trackNavigation = () => {\n const newUrl = window.location.href;\n if (newUrl !== currentUrl) {\n this.addBreadcrumb({\n type: 'navigation',\n message: `Navigation from ${currentUrl} to ${newUrl}`,\n data: { from: currentUrl, to: newUrl }\n });\n currentUrl = newUrl;\n }\n };\n \n // Listen for various navigation events\n window.addEventListener('popstate', trackNavigation);\n window.addEventListener('hashchange', trackNavigation);\n \n // Override pushState and replaceState\n const originalPushState = history.pushState;\n const originalReplaceState = history.replaceState;\n \n history.pushState = function(...args) {\n originalPushState.apply(this, args);\n setTimeout(trackNavigation, 0);\n };\n \n history.replaceState = function(...args) {\n originalReplaceState.apply(this, args);\n setTimeout(trackNavigation, 0);\n };\n }\n\n private setupClickTracking() {\n document.addEventListener('click', (event) => {\n const target = event.target as Element;\n if (!target) return;\n \n const selector = this.getElementSelector(target);\n const text = target.textContent?.trim().substring(0, 50) || '';\n \n this.addBreadcrumb({\n type: 'click',\n message: `Clicked ${selector}${text ? `: ${text}` : ''}`,\n data: {\n selector,\n text,\n tagName: target.tagName,\n id: target.id,\n className: target.className\n }\n });\n });\n }\n\n private getElementSelector(element: Element): string {\n if (element.id) return `#${element.id}`;\n if (element.className) {\n const classes = element.className.split(' ').filter(c => c).slice(0, 2);\n if (classes.length) return `.${classes.join('.')}`;\n }\n return element.tagName.toLowerCase();\n }\n\n private async sendError(errorData: ErrorData) {\n try {\n let headers: Record<string, string> = { 'Content-Type': 'application/json' };\n\n // Use authManager if available, otherwise fall back to apiKey\n if (this.authManager) {\n const authHeaders = await this.authManager.getAuthHeaders();\n headers = { ...headers, ...authHeaders };\n } else if (this.config.apiKey) {\n headers['Authorization'] = `Bearer ${this.config.apiKey}`;\n }\n\n const response = await fetch(`${this.config.endpoint}/api/v1/errors`, {\n method: 'POST',\n headers,\n body: JSON.stringify(errorData)\n });\n\n if (!response.ok) {\n throw new Error(`Failed to send error: ${response.status} ${response.statusText}`);\n }\n\n console.log('[AInamika Error Tracker] Error sent successfully');\n } catch (error) {\n console.error('[AInamika Error Tracker] Failed to send error:', error);\n // Store error locally for retry\n this.storeErrorLocally(errorData);\n }\n }\n\n private storeErrorLocally(errorData: ErrorData) {\n try {\n const stored = localStorage.getItem('ainamika_errors') || '[]';\n const errors = JSON.parse(stored);\n errors.push(errorData);\n \n // Keep only last 50 errors\n if (errors.length > 50) {\n errors.splice(0, errors.length - 50);\n }\n \n localStorage.setItem('ainamika_errors', JSON.stringify(errors));\n } catch (error) {\n console.error('[AInamika Error Tracker] Failed to store error locally:', error);\n }\n }\n\n // Public methods\n public captureException(error: Error, context?: Record<string, any>) {\n this.handleError({\n type: 'custom',\n message: error.message,\n error,\n context\n });\n }\n\n public setUser(userId: string) {\n this.userId = userId;\n }\n\n public addTag(key: string, value: string) {\n // Add custom tags to error metadata\n if (!this.config.clientId) {\n this.config.clientId += `_${key}:${value}`;\n }\n }\n\n public async flushStoredErrors() {\n try {\n const stored = localStorage.getItem('ainamika_errors');\n if (!stored) return;\n \n const errors = JSON.parse(stored);\n if (errors.length === 0) return;\n \n console.log(`[AInamika Error Tracker] Flushing ${errors.length} stored errors`);\n \n for (const error of errors) {\n await this.sendError(error);\n }\n \n localStorage.removeItem('ainamika_errors');\n } catch (error) {\n console.error('[AInamika Error Tracker] Failed to flush stored errors:', error);\n }\n }\n}\n","// error-storage.ts - Offline Storage and Queue Management for Error Tracking\n\nexport interface StoredError {\n id: string;\n errorData: any;\n timestamp: number;\n retryCount: number;\n lastRetry?: number;\n}\n\nexport interface StorageConfig {\n maxStorageSize: number;\n maxRetries: number;\n retryInterval: number;\n compressionEnabled: boolean;\n encryptionEnabled: boolean;\n endpoint?: string; // Base API endpoint URL\n}\n\nexport class ErrorStorage {\n private config: StorageConfig;\n private readonly STORAGE_KEY = 'ainamika_error_queue';\n private readonly METADATA_KEY = 'ainamika_error_metadata';\n private retryTimer?: number;\n private isProcessing = false;\n\n constructor(config: Partial<StorageConfig> = {}) {\n this.config = {\n maxStorageSize: 5 * 1024 * 1024, // 5MB\n maxRetries: 5,\n retryInterval: 30000, // 30 seconds\n compressionEnabled: true,\n encryptionEnabled: false,\n ...config\n };\n\n this.initialize();\n }\n\n private initialize() {\n this.cleanupOldErrors();\n this.startRetryTimer();\n this.setupStorageListener();\n \n // Process any existing errors on initialization\n setTimeout(() => this.processQueue(), 1000);\n }\n\n /**\n * Store error data with automatic compression and queue management\n */\n public async storeError(errorData: any): Promise<string> {\n try {\n const errorId = this.generateErrorId();\n const storedError: StoredError = {\n id: errorId,\n errorData: this.config.compressionEnabled ? this.compressData(errorData) : errorData,\n timestamp: Date.now(),\n retryCount: 0\n };\n\n await this.addToQueue(storedError);\n this.updateMetadata();\n \n // Trigger immediate processing\n setTimeout(() => this.processQueue(), 100);\n \n return errorId;\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to store error:', error);\n throw error;\n }\n }\n\n /**\n * Get all stored errors\n */\n public getStoredErrors(): StoredError[] {\n try {\n const stored = localStorage.getItem(this.STORAGE_KEY);\n if (!stored) return [];\n \n const errors = JSON.parse(stored) as StoredError[];\n return errors.map(error => ({\n ...error,\n errorData: this.config.compressionEnabled ? this.decompressData(error.errorData) : error.errorData\n }));\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to get stored errors:', error);\n return [];\n }\n }\n\n /**\n * Remove error from storage\n */\n public removeError(errorId: string): boolean {\n try {\n const errors = this.getQueueRaw();\n const filteredErrors = errors.filter(error => error.id !== errorId);\n \n if (filteredErrors.length !== errors.length) {\n localStorage.setItem(this.STORAGE_KEY, JSON.stringify(filteredErrors));\n this.updateMetadata();\n return true;\n }\n return false;\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to remove error:', error);\n return false;\n }\n }\n\n /**\n * Clear all stored errors\n */\n public clearAll(): void {\n try {\n localStorage.removeItem(this.STORAGE_KEY);\n localStorage.removeItem(this.METADATA_KEY);\n console.log('[AInamika Error Storage] All errors cleared');\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to clear errors:', error);\n }\n }\n\n /**\n * Get storage statistics\n */\n public getStorageStats(): {\n errorCount: number;\n totalSize: number;\n oldestError?: number;\n newestError?: number;\n } {\n try {\n const errors = this.getQueueRaw();\n const totalSize = new Blob([localStorage.getItem(this.STORAGE_KEY) || '']).size;\n \n const timestamps = errors.map(e => e.timestamp).sort();\n \n return {\n errorCount: errors.length,\n totalSize,\n oldestError: timestamps[0],\n newestError: timestamps[timestamps.length - 1]\n };\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to get storage stats:', error);\n return { errorCount: 0, totalSize: 0 };\n }\n }\n\n /**\n * Process the error queue - attempt to send stored errors\n */\n public async processQueue(): Promise<void> {\n if (this.isProcessing) return;\n \n this.isProcessing = true;\n \n try {\n const errors = this.getQueueRaw();\n if (errors.length === 0) return;\n \n console.log(`[AInamika Error Storage] Processing ${errors.length} queued errors`);\n \n for (const storedError of errors) {\n if (storedError.retryCount >= this.config.maxRetries) {\n console.warn(`[AInamika Error Storage] Max retries reached for error ${storedError.id}`);\n this.removeError(storedError.id);\n continue;\n }\n\n // Check retry interval\n if (storedError.lastRetry && \n Date.now() - storedError.lastRetry < this.config.retryInterval) {\n continue;\n }\n\n try {\n const success = await this.sendError(storedError);\n if (success) {\n this.removeError(storedError.id);\n console.log(`[AInamika Error Storage] Successfully sent error ${storedError.id}`);\n } else {\n this.incrementRetryCount(storedError.id);\n }\n } catch (error) {\n console.error(`[AInamika Error Storage] Failed to send error ${storedError.id}:`, error);\n this.incrementRetryCount(storedError.id);\n }\n }\n } finally {\n this.isProcessing = false;\n }\n }\n\n /**\n * Force retry of a specific error\n */\n public async retryError(errorId: string): Promise<boolean> {\n const errors = this.getQueueRaw();\n const error = errors.find(e => e.id === errorId);\n \n if (!error) return false;\n \n try {\n const success = await this.sendError(error);\n if (success) {\n this.removeError(errorId);\n return true;\n } else {\n this.incrementRetryCount(errorId);\n return false;\n }\n } catch (err) {\n console.error(`[AInamika Error Storage] Failed to retry error ${errorId}:`, err);\n this.incrementRetryCount(errorId);\n return false;\n }\n }\n\n private async addToQueue(storedError: StoredError): Promise<void> {\n const errors = this.getQueueRaw();\n errors.push(storedError);\n \n // Check storage size limit\n const serialized = JSON.stringify(errors);\n if (new Blob([serialized]).size > this.config.maxStorageSize) {\n // Remove oldest errors until under limit\n while (errors.length > 0 && new Blob([JSON.stringify(errors)]).size > this.config.maxStorageSize) {\n errors.shift();\n console.warn('[AInamika Error Storage] Removed old error due to size limit');\n }\n }\n \n localStorage.setItem(this.STORAGE_KEY, JSON.stringify(errors));\n }\n\n private getQueueRaw(): StoredError[] {\n try {\n const stored = localStorage.getItem(this.STORAGE_KEY);\n return stored ? JSON.parse(stored) : [];\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to parse stored errors:', error);\n return [];\n }\n }\n\n private incrementRetryCount(errorId: string): void {\n try {\n const errors = this.getQueueRaw();\n const errorIndex = errors.findIndex(e => e.id === errorId);\n \n if (errorIndex !== -1) {\n errors[errorIndex].retryCount++;\n errors[errorIndex].lastRetry = Date.now();\n localStorage.setItem(this.STORAGE_KEY, JSON.stringify(errors));\n }\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to increment retry count:', error);\n }\n }\n\n private async sendError(storedError: StoredError): Promise<boolean> {\n try {\n const errorData = this.config.compressionEnabled ?\n this.decompressData(storedError.errorData) :\n storedError.errorData;\n\n // Use endpoint from config (passed during initialization) or from stored error data\n const endpoint = this.config.endpoint || errorData.endpoint;\n if (!endpoint) {\n console.error('[AInamika Error Storage] No endpoint configured for sending errors');\n return false;\n }\n\n const apiKey = errorData.apiKey || '';\n\n const response = await fetch(`${endpoint}/api/v1/errors`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': apiKey ? `Bearer ${apiKey}` : ''\n },\n body: JSON.stringify(errorData)\n });\n\n return response.ok;\n } catch (error) {\n console.error('[AInamika Error Storage] Network error sending stored error:', error);\n return false;\n }\n }\n\n private compressData(data: any): string {\n try {\n // Simple compression using JSON + base64\n const jsonString = JSON.stringify(data);\n return btoa(jsonString);\n } catch (error) {\n console.warn('[AInamika Error Storage] Compression failed, storing uncompressed:', error);\n return data;\n }\n }\n\n private decompressData(compressedData: any): any {\n try {\n if (typeof compressedData === 'string' && compressedData.length > 0) {\n const jsonString = atob(compressedData);\n return JSON.parse(jsonString);\n }\n return compressedData;\n } catch (error) {\n console.warn('[AInamika Error Storage] Decompression failed, returning raw data:', error);\n return compressedData;\n }\n }\n\n private generateErrorId(): string {\n return `error_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n }\n\n private cleanupOldErrors(): void {\n try {\n const errors = this.getQueueRaw();\n const cutoffTime = Date.now() - (7 * 24 * 60 * 60 * 1000); // 7 days\n \n const cleanErrors = errors.filter(error => error.timestamp > cutoffTime);\n \n if (cleanErrors.length !== errors.length) {\n localStorage.setItem(this.STORAGE_KEY, JSON.stringify(cleanErrors));\n console.log(`[AInamika Error Storage] Cleaned up ${errors.length - cleanErrors.length} old errors`);\n }\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to cleanup old errors:', error);\n }\n }\n\n private startRetryTimer(): void {\n this.retryTimer = window.setInterval(() => {\n this.processQueue();\n }, this.config.retryInterval);\n }\n\n private setupStorageListener(): void {\n // Listen for storage changes from other tabs\n window.addEventListener('storage', (event) => {\n if (event.key === this.STORAGE_KEY) {\n console.log('[AInamika Error Storage] Storage updated from another tab');\n setTimeout(() => this.processQueue(), 1000);\n }\n });\n\n // Listen for online/offline events\n window.addEventListener('online', () => {\n console.log('[AInamika Error Storage] Network back online, processing queue');\n setTimeout(() => this.processQueue(), 1000);\n });\n\n window.addEventListener('offline', () => {\n console.log('[AInamika Error Storage] Network offline, errors will be queued');\n });\n }\n\n private updateMetadata(): void {\n try {\n const stats = this.getStorageStats();\n const metadata = {\n lastUpdate: Date.now(),\n ...stats\n };\n localStorage.setItem(this.METADATA_KEY, JSON.stringify(metadata));\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to update metadata:', error);\n }\n }\n\n /**\n * Export stored errors for debugging\n */\n public exportErrors(): string {\n try {\n const errors = this.getStoredErrors();\n const exportData = {\n timestamp: Date.now(),\n version: '1.0',\n stats: this.getStorageStats(),\n errors: errors\n };\n return JSON.stringify(exportData, null, 2);\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to export errors:', error);\n return '{}';\n }\n }\n\n /**\n * Import errors from export\n */\n public importErrors(exportData: string): boolean {\n try {\n const data = JSON.parse(exportData);\n if (!data.errors || !Array.isArray(data.errors)) {\n throw new Error('Invalid export format');\n }\n\n this.clearAll();\n \n for (const errorData of data.errors) {\n this.storeError(errorData.errorData);\n }\n \n console.log(`[AInamika Error Storage] Imported ${data.errors.length} errors`);\n return true;\n } catch (error) {\n console.error('[AInamika Error Storage] Failed to import errors:', error);\n return false;\n }\n }\n\n /**\n * Cleanup and destroy the storage instance\n */\n public destroy(): void {\n if (this.retryTimer) {\n clearInterval(this.retryTimer);\n this.retryTimer = undefined;\n }\n \n // Final attempt to process queue\n this.processQueue();\n \n console.log('[AInamika Error Storage] Storage instance destroyed');\n }\n}\n\n/**\n * Utility functions for error storage management\n */\nexport class ErrorStorageUtils {\n /**\n * Get total localStorage usage for AInamika\n */\n static getAinamikaStorageUsage(): { \n totalSize: number; \n errorSize: number; \n otherSize: number; \n } {\n let totalSize = 0;\n let errorSize = 0;\n let otherSize = 0;\n\n for (let key in localStorage) {\n if (localStorage.hasOwnProperty(key)) {\n const size = new Blob([localStorage.getItem(key) || '']).size;\n totalSize += size;\n \n if (key.startsWith('ainamika_error')) {\n errorSize += size;\n } else if (key.startsWith('ainamika_')) {\n otherSize += size;\n }\n }\n }\n\n return { totalSize, errorSize, otherSize };\n }\n\n /**\n * Check if localStorage has enough space\n */\n static checkStorageSpace(requiredBytes: number): boolean {\n try {\n const testKey = 'ainamika_storage_test';\n const testData = 'x'.repeat(Math.min(requiredBytes, 1024 * 1024));\n \n localStorage.setItem(testKey, testData);\n localStorage.removeItem(testKey);\n \n return true;\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Clean up all AInamika storage\n */\n static cleanupAllAinamikaStorage(): void {\n const keysToRemove: string[] = [];\n \n for (let key in localStorage) {\n if (key.startsWith('ainamika_')) {\n keysToRemove.push(key);\n }\n }\n \n keysToRemove.forEach(key => localStorage.removeItem(key));\n console.log(`[AInamika Storage Utils] Cleaned up ${keysToRemove.length} storage keys`);\n }\n\n /**\n * Generate storage report\n */\n static generateStorageReport(): {\n usage: ReturnType<typeof ErrorStorageUtils.getAinamikaStorageUsage>;\n errors: any[];\n metadata: any;\n } {\n const storage = new ErrorStorage();\n \n return {\n usage: ErrorStorageUtils.getAinamikaStorageUsage(),\n errors: storage.getStoredErrors(),\n metadata: storage.getStorageStats()\n };\n }\n}\n","// config.ts - Environment-based configuration for Ainamika SDK\n\nexport interface EnvironmentConfig {\n API_BASE_URL: string;\n APP_ENV: 'development' | 'production';\n DEBUG: boolean;\n}\n\n// Environment configuration with fallbacks\ndeclare global {\n interface Window {\n __AINAMIKA_CONFIG__?: EnvironmentConfig;\n }\n}\n\n// Production API URL - using proxy that routes to Kubernetes backend\nconst PRODUCTION_API_URL = 'https://ainamika-webhook-proxy-366651516847.asia-south1.run.app';\n\n// Get environment configuration\nfunction getEnvironmentConfig(): EnvironmentConfig {\n // Check for explicitly set configuration (allows override via apiDetails)\n if (typeof window !== 'undefined' && window.__AINAMIKA_CONFIG__) {\n return window.__AINAMIKA_CONFIG__;\n }\n\n // Always use production URLs for npm package\n // Users can override via apiDetails config option if needed\n return {\n API_BASE_URL: PRODUCTION_API_URL,\n APP_ENV: 'production',\n DEBUG: false\n };\n}\n\nexport const ENV_CONFIG = getEnvironmentConfig();\n\n// API endpoint configuration\nexport const API_ENDPOINTS = {\n EVENTS: `${ENV_CONFIG.API_BASE_URL}/api/v1/events`,\n ERRORS: `${ENV_CONFIG.API_BASE_URL}/api/errors/report`,\n CONFIG: `${ENV_CONFIG.API_BASE_URL}/api/v1/sdk/config`,\n DEBUG_EVENTS: `${ENV_CONFIG.API_BASE_URL}/api/v1/debug/events`,\n // Project-based endpoints\n PROJECTS_LOOKUP: `${ENV_CONFIG.API_BASE_URL}/api/v1/projects/lookup`,\n SAMPLING_CHECK: `${ENV_CONFIG.API_BASE_URL}/api/v1/projects/sampling/check`\n};\n\n// Configuration helper function\nexport function configureSDK(config: Partial<EnvironmentConfig>) {\n if (typeof window !== 'undefined') {\n window.__AINAMIKA_CONFIG__ = { ...ENV_CONFIG, ...config };\n }\n}\n\n","/**\n * User Manager Module\n * Handles user identification for hybrid tracking (anonymous + authenticated)\n */\n\nexport class UserManager {\n private userId: string | null = null;\n private userProperties: Record<string, any> = {};\n\n constructor() {\n this.initializeUser();\n }\n\n /**\n * Initialize user on module load\n */\n private initializeUser(): void {\n this.userId = this.getOrCreateUserId();\n }\n\n /**\n * Generate or retrieve persistent anonymous user ID\n */\n private getOrCreateUserId(): string {\n try {\n let userId = localStorage.getItem('ainamika_user_id');\n\n if (!userId) {\n userId = this.generateAnonymousId();\n localStorage.setItem('ainamika_user_id', userId);\n }\n\n return userId;\n } catch (error) {\n // Fallback for environments without localStorage\n console.warn('[UserManager] localStorage not available, using session ID');\n return this.generateAnonymousId();\n }\n }\n\n /**\n * Generate a new anonymous user ID\n */\n private generateAnonymousId(): string {\n return 'anon_' + Math.random().toString(36).substr(2, 9) + '_' + Date.now();\n }\n\n /**\n * Get current user ID\n */\n public getUserId(): string {\n if (!this.userId) {\n this.userId = this.getOrCreateUserId();\n }\n return this.userId;\n }\n\n /**\n * Get user properties\n */\n public getUserProperties(): Record<string, any> {\n return { ...this.userProperties };\n }\n\n /**\n * Identify user with authenticated ID\n * Merges anonymous session with authenticated user\n */\n public identifyUser(authenticatedUserId: string, properties?: Record<string, any>): void {\n const previousId = this.getUserId();\n\n try {\n // Update stored user ID\n localStorage.setItem('ainamika_user_id', authenticatedUserId);\n this.userId = authenticatedUserId;\n\n // Merge properties\n if (properties) {\n this.userProperties = {\n ...this.userProperties,\n ...properties\n };\n }\n\n console.log(`[UserManager] User identified: ${previousId} → ${authenticatedUserId}`);\n } catch (error) {\n console.error('[UserManager] Error identifying user:', error);\n }\n }\n\n /**\n * Update user properties\n */\n public updateUserProperties(properties: Record<string, any>): void {\n this.userProperties = {\n ...this.userProperties,\n ...properties\n };\n }\n\n /**\n * Clear user data (logout)\n */\n public clearUser(): void {\n try {\n localStorage.removeItem('ainamika_user_id');\n this.userId = null;\n this.userProperties = {};\n\n // Generate new anonymous ID for next session\n this.initializeUser();\n } catch (error) {\n console.error('[UserManager] Error clearing user:', error);\n }\n }\n\n /**\n * Get user identification event data\n * Used when upgrading from anonymous to authenticated\n */\n public getUserIdentificationEvent(authenticatedUserId: string): Record<string, any> {\n return {\n event: 'user_identified',\n previous_id: this.getUserId(),\n user_id: authenticatedUserId,\n timestamp: Date.now(),\n properties: this.userProperties\n };\n }\n\n /**\n * Check if current user is anonymous\n */\n public isAnonymousUser(): boolean {\n const userId = this.getUserId();\n return userId.startsWith('anon_');\n }\n\n /**\n * Get user type (anonymous or authenticated)\n */\n public getUserType(): 'anonymous' | 'authenticated' {\n return this.isAnonymousUser() ? 'anonymous' : 'authenticated';\n }\n}","/**\n * Journey Tracker Module\n * Tracks user journeys for funnel analysis\n */\n\ninterface JourneyEvent {\n eventName: string;\n timestamp: number;\n properties: Record<string, any>;\n sequenceIndex: number;\n}\n\ninterface JourneyContext {\n journeySequence: string[];\n eventCount: number;\n lastEventTime: number;\n journeyStartTime: number;\n timeSinceLastEvent: number;\n}\n\nexport class JourneyTracker {\n private userJourney: JourneyEvent[] = [];\n private journeyStartTime: number;\n private lastEventTime: number = 0;\n private sequenceIndex: number = 0;\n private maxJourneyLength: number = 50; // Limit journey size for performance\n private journeyAnalysisThreshold: number = 5; // Send for analysis after 5 events\n\n constructor() {\n this.journeyStartTime = Date.now();\n }\n\n /**\n * Add event to user journey\n */\n public trackEvent(eventName: string, properties: Record<string, any>): void {\n const currentTime = Date.now();\n const timeSinceLastEvent = this.lastEventTime ? currentTime - this.lastEventTime : 0;\n\n const journeyEvent: JourneyEvent = {\n eventName,\n timestamp: currentTime,\n properties: {\n ...properties,\n timeSinceLastEvent,\n journeyPosition: this.sequenceIndex\n },\n sequenceIndex: this.sequenceIndex++\n };\n\n this.userJourney.push(journeyEvent);\n this.lastEventTime = currentTime;\n\n // Maintain journey size limit\n if (this.userJourney.length > this.maxJourneyLength) {\n this.userJourney = this.userJourney.slice(-this.maxJourneyLength);\n }\n\n // Log journey progress\n console.log(`[JourneyTracker] Event tracked: ${eventName} (position: ${journeyEvent.sequenceIndex})`);\n }\n\n /**\n * Get current journey context\n */\n public getContext(): JourneyContext {\n const currentTime = Date.now();\n\n return {\n journeySequence: this.getJourneySequence(),\n eventCount: this.userJourney.length,\n lastEventTime: this.lastEventTime,\n journeyStartTime: this.journeyStartTime,\n timeSinceLastEvent: this.lastEventTime ? currentTime - this.lastEventTime : 0\n };\n }\n\n /**\n * Get journey as sequence of event names\n */\n public getJourneySequence(): string[] {\n return this.userJourney.map(event => event.eventName);\n }\n\n /**\n * Get full journey data\n */\n public getJourneyData(): JourneyEvent[] {\n return [...this.userJourney];\n }\n\n /**\n * Check if journey should be sent for analysis\n */\n public shouldAnalyzeJourney(): boolean {\n return this.userJourney.length >= this.journeyAnalysisThreshold &&\n this.userJourney.length % this.journeyAnalysisThreshold === 0;\n }\n\n /**\n * Get journey data for analysis\n */\n public getJourneyForAnalysis(): Record<string, any> {\n const journeyDuration = Date.now() - this.journeyStartTime;\n const avgTimeBetweenEvents = this.calculateAverageTimeBetweenEvents();\n\n return {\n journey: this.userJourney.map(event => ({\n name: event.eventName,\n timestamp: event.timestamp,\n properties: event.properties\n })),\n metadata: {\n journeyLength: this.userJourney.length,\n journeyDuration,\n avgTimeBetweenEvents,\n startTime: this.journeyStartTime,\n endTime: this.lastEventTime\n }\n };\n }\n\n /**\n * Calculate average time between events\n */\n private calculateAverageTimeBetweenEvents(): number {\n if (this.userJourney.length < 2) return 0;\n\n let totalTime = 0;\n for (let i = 1; i < this.userJourney.length; i++) {\n totalTime += this.userJourney[i].timestamp - this.userJourney[i - 1].timestamp;\n }\n\n return Math.round(totalTime / (this.userJourney.length - 1));\n }\n\n /**\n * Find patterns in journey (e.g., repeated sequences)\n */\n public findPatterns(): Record<string, number> {\n const patterns: Record<string, number> = {};\n const sequenceLength = 3; // Look for patterns of 3 events\n\n if (this.userJourney.length < sequenceLength) return patterns;\n\n for (let i = 0; i <= this.userJourney.length - sequenceLength; i++) {\n const sequence = this.userJourney\n .slice(i, i + sequenceLength)\n .map(e => e.eventName)\n .join(' → ');\n\n patterns[sequence] = (patterns[sequence] || 0) + 1;\n }\n\n // Filter out single occurrences\n return Object.fromEntries(\n Object.entries(patterns).filter(([_, count]) => count > 1)\n );\n }\n\n /**\n * Clear journey (for new session)\n */\n public clearJourney(): void {\n this.userJourney = [];\n this.sequenceIndex = 0;\n this.lastEventTime = 0;\n this.journeyStartTime = Date.now();\n }\n\n /**\n * Get journey segment (last N events)\n */\n public getJourneySegment(count: number): JourneyEvent[] {\n return this.userJourney.slice(-count);\n }\n\n /**\n * Check if user is in a potential funnel\n * Based on common funnel patterns\n */\n public detectPotentialFunnel(): string | null {\n const recentEvents = this.getJourneySequence().slice(-5);\n\n // Common funnel patterns\n const funnelPatterns: Record<string, string[]> = {\n 'signup_flow': ['view_pricing', 'click_signup', 'enter_email'],\n 'purchase_flow': ['view_product', 'add_to_cart', 'view_cart'],\n 'onboarding_flow': ['user_signup', 'profile_setup', 'tutorial_start']\n };\n\n for (const [funnelName, pattern] of Object.entries(funnelPatterns)) {\n const matchCount = pattern.filter(event =>\n recentEvents.includes(event)\n ).length;\n\n if (matchCount >= 2) {\n return funnelName;\n }\n }\n\n return null;\n }\n}","/**\n * Authentication Manager for Ainamika SDK\n *\n * Handles token generation, storage, and refresh for API authentication\n */\n\nexport interface AuthTokens {\n access_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n}\n\nexport class AuthManager {\n private accessToken: string | null = null;\n private refreshToken: string | null = null;\n private tokenExpiry: number | null = null;\n private clientId: string;\n private apiEndpoint: string;\n private refreshTimer?: NodeJS.Timeout;\n private debug: boolean;\n\n // Fixed storage key for auth tokens (no longer includes clientId)\n private static readonly STORAGE_KEY = 'ainamika_auth_token';\n\n constructor(clientId: string, apiEndpoint: string, debug: boolean = false) {\n this.clientId = clientId;\n this.apiEndpoint = apiEndpoint;\n this.debug = debug;\n\n // Load tokens from storage (validates clientId match)\n this.loadTokens();\n }\n\n /**\n * Initialize authentication by requesting tokens\n */\n async initialize(): Promise<boolean> {\n try {\n // Check if we have valid tokens\n if (this.isTokenValid()) {\n this.debugLog('Using existing valid token');\n return true;\n }\n\n // Try to refresh if we have a refresh token\n if (this.refreshToken) {\n const refreshed = await this.refreshAccessToken();\n if (refreshed) {\n return true;\n }\n }\n\n // Request new tokens\n const tokens = await this.requestTokens();\n if (tokens) {\n this.setTokens(tokens);\n return true;\n }\n\n return false;\n } catch (error) {\n this.debugLog('Authentication initialization failed:', error);\n return false;\n }\n }\n\n /**\n * Request new tokens from the server\n */\n private async requestTokens(): Promise<AuthTokens | null> {\n try {\n const response = await fetch(`${this.apiEndpoint}/api/v1/auth/token`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ client_id: this.clientId }),\n });\n\n if (!response.ok) {\n throw new Error(`Token request failed: ${response.status}`);\n }\n\n const tokens: AuthTokens = await response.json();\n return tokens;\n } catch (error) {\n this.debugLog('Token request error:', error);\n return null;\n }\n }\n\n /**\n * Refresh the access token using refresh token\n */\n async refreshAccessToken(): Promise<boolean> {\n if (!this.refreshToken) {\n return false;\n }\n\n try {\n const response = await fetch(`${this.apiEndpoint}/api/v1/auth/refresh`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ refresh_token: this.refreshToken }),\n });\n\n if (!response.ok) {\n // Refresh token is invalid, clear tokens\n this.clearTokens();\n return false;\n }\n\n const tokens: AuthTokens = await response.json();\n this.setTokens(tokens);\n return true;\n } catch (error) {\n this.debugLog('Token refresh error:', error);\n return false;\n }\n }\n\n /**\n * Get the current access token, refreshing if needed\n */\n async getAccessToken(): Promise<string | null> {\n // If token is expiring soon (within 5 minutes), refresh it\n if (this.shouldRefreshToken()) {\n await this.refreshAccessToken();\n }\n\n // If still no valid token, try to initialize\n if (!this.isTokenValid()) {\n const initialized = await this.initialize();\n if (!initialized) {\n return null;\n }\n }\n\n return this.accessToken;\n }\n\n /**\n * Get authorization headers for API requests\n */\n async getAuthHeaders(): Promise<Record<string, string>> {\n const token = await this.getAccessToken();\n\n if (token) {\n return {\n 'Authorization': `Bearer ${token}`,\n };\n }\n\n // Fallback to X-Client-ID for backward compatibility\n return {\n 'X-Client-ID': this.clientId,\n };\n }\n\n /**\n * Check if the current token is valid\n */\n private isTokenValid(): boolean {\n if (!this.accessToken || !this.tokenExpiry) {\n return false;\n }\n\n // Check if token has expired\n return Date.now() < this.tokenExpiry;\n }\n\n /**\n * Check if token should be refreshed (5 minutes before expiry)\n */\n private shouldRefreshToken(): boolean {\n if (!this.tokenExpiry || !this.refreshToken) {\n return false;\n }\n\n const fiveMinutes = 5 * 60 * 1000;\n return Date.now() > (this.tokenExpiry - fiveMinutes);\n }\n\n /**\n * Set tokens and schedule refresh\n */\n private setTokens(tokens: AuthTokens): void {\n this.accessToken = tokens.access_token;\n this.refreshToken = tokens.refresh_token || this.refreshToken;\n this.tokenExpiry = Date.now() + (tokens.expires_in * 1000);\n\n // Save to storage\n this.saveTokens();\n\n // Schedule token refresh\n this.scheduleTokenRefresh();\n\n this.debugLog('Tokens set successfully');\n }\n\n /**\n * Schedule automatic token refresh\n */\n private scheduleTokenRefresh(): void {\n // Clear existing timer\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer);\n }\n\n // Schedule refresh 5 minutes before expiry\n const refreshIn = Math.max(0, this.tokenExpiry! - Date.now() - (5 * 60 * 1000));\n\n this.refreshTimer = setTimeout(() => {\n this.refreshAccessToken();\n }, refreshIn);\n }\n\n /**\n * Save tokens to localStorage with fixed key\n */\n private saveTokens(): void {\n if (typeof window !== 'undefined' && window.localStorage) {\n const tokenData = {\n clientId: this.clientId, // Store clientId to validate on load\n accessToken: this.accessToken,\n refreshToken: this.refreshToken,\n tokenExpiry: this.tokenExpiry,\n };\n\n localStorage.setItem(AuthManager.STORAGE_KEY, JSON.stringify(tokenData));\n\n // Clean up any old dynamic keys from previous SDK versions\n this.cleanupLegacyTokens();\n }\n }\n\n /**\n * Remove old tokens stored with dynamic key format (ainamika_auth_<clientId>)\n */\n private cleanupLegacyTokens(): void {\n if (typeof window !== 'undefined' && window.localStorage) {\n const keysToRemove: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith('ainamika_auth_') && key !== AuthManager.STORAGE_KEY) {\n keysToRemove.push(key);\n }\n }\n keysToRemove.forEach(key => {\n localStorage.removeItem(key);\n this.debugLog('Removed legacy token key:', key);\n });\n }\n }\n\n /**\n * Load tokens from localStorage with clientId validation\n */\n private loadTokens(): void {\n if (typeof window !== 'undefined' && window.localStorage) {\n // Clean up legacy tokens first\n this.cleanupLegacyTokens();\n\n const stored = localStorage.getItem(AuthManager.STORAGE_KEY);\n\n if (stored) {\n try {\n const tokenData = JSON.parse(stored);\n\n // Validate clientId - if different, clear stored token\n if (tokenData.clientId && tokenData.clientId !== this.clientId) {\n this.debugLog('Stored token is for different clientId, clearing');\n localStorage.removeItem(AuthManager.STORAGE_KEY);\n return;\n }\n\n this.accessToken = tokenData.accessToken;\n this.refreshToken = tokenData.refreshToken;\n this.tokenExpiry = tokenData.tokenExpiry;\n\n // Schedule refresh if token is valid\n if (this.isTokenValid()) {\n this.scheduleTokenRefresh();\n }\n } catch (error) {\n this.debugLog('Failed to load stored tokens:', error);\n }\n }\n }\n }\n\n /**\n * Clear tokens\n */\n clearTokens(): void {\n this.accessToken = null;\n this.refreshToken = null;\n this.tokenExpiry = null;\n\n // Clear from storage (fixed key)\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.removeItem(AuthManager.STORAGE_KEY);\n // Also clean up any legacy keys\n this.cleanupLegacyTokens();\n }\n\n // Clear refresh timer\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer);\n this.refreshTimer = undefined;\n }\n }\n\n /**\n * Logout and clear authentication\n */\n async logout(): Promise<void> {\n try {\n if (this.accessToken) {\n await fetch(`${this.apiEndpoint}/api/v1/auth/logout`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.accessToken}`,\n },\n });\n }\n } catch (error) {\n this.debugLog('Logout error:', error);\n } finally {\n this.clearTokens();\n }\n }\n\n /**\n * Debug logging\n */\n private debugLog(...args: any[]): void {\n if (this.debug) {\n console.log('[Ainamika Auth]', ...args);\n }\n }\n}","// advanced-tracker.ts - Advanced Analytics Tracking for AInamika SDK\n// Provides: Performance tracking, Engagement metrics, API tracking, Smart event enrichment\n\nexport interface AdvancedTrackingConfig {\n trackPerformance?: boolean;\n trackEngagement?: boolean;\n trackScrollDepth?: boolean;\n trackRageClicks?: boolean;\n trackTimeOnPage?: boolean;\n trackAPIResponses?: boolean;\n scrollDepthThresholds?: number[];\n rageClickThreshold?: number;\n rageClickWindow?: number;\n apiTrackingPatterns?: string[];\n}\n\nexport interface PerformanceMetrics {\n // Core Web Vitals\n lcp?: number; // Largest Contentful Paint\n fid?: number; // First Input Delay\n cls?: number; // Cumulative Layout Shift\n fcp?: number; // First Contentful Paint\n ttfb?: number; // Time to First Byte\n // Page Load Timing\n domContentLoaded?: number;\n pageLoad?: number;\n // Resource Metrics\n resourceCount?: number;\n transferSize?: number;\n}\n\nexport interface EngagementMetrics {\n timeOnPage: number;\n scrollDepth: number;\n scrollDepthMilestones: number[];\n rageClicks: number;\n totalClicks: number;\n activeTime: number;\n idleTime: number;\n pageVisibilityChanges: number;\n}\n\nexport interface APITrackingEvent {\n url: string;\n method: string;\n status: number;\n duration: number;\n requestSize?: number;\n responseSize?: number;\n success: boolean;\n error?: string;\n timestamp: number;\n}\n\ntype EventCallback = (eventName: string, properties: Record<string, any>) => void;\n\nexport class AdvancedTracker {\n private config: AdvancedTrackingConfig;\n private onEvent: EventCallback;\n private performanceMetrics: PerformanceMetrics = {};\n private engagementMetrics: EngagementMetrics;\n private pageStartTime: number;\n private lastActivityTime: number;\n private scrollDepthReached: Set<number> = new Set();\n private clickHistory: number[] = [];\n private isPageVisible: boolean = true;\n private visibilityChangeCount: number = 0;\n private originalFetch: typeof fetch;\n private originalXHR: typeof XMLHttpRequest.prototype.open;\n\n constructor(config: AdvancedTrackingConfig, onEvent: EventCallback) {\n this.config = {\n trackPerformance: true,\n trackEngagement: true,\n trackScrollDepth: true,\n trackRageClicks: true,\n trackTimeOnPage: true,\n trackAPIResponses: false, // Opt-in for API tracking\n scrollDepthThresholds: [25, 50, 75, 90, 100],\n rageClickThreshold: 3,\n rageClickWindow: 1000, // 3 clicks within 1 second\n apiTrackingPatterns: [],\n ...config\n };\n\n this.onEvent = onEvent;\n this.pageStartTime = Date.now();\n this.lastActivityTime = Date.now();\n this.originalFetch = window.fetch.bind(window);\n this.originalXHR = XMLHttpRequest.prototype.open;\n\n this.engagementMetrics = {\n timeOnPage: 0,\n scrollDepth: 0,\n scrollDepthMilestones: [],\n rageClicks: 0,\n totalClicks: 0,\n activeTime: 0,\n idleTime: 0,\n pageVisibilityChanges: 0\n };\n\n this.initialize();\n }\n\n private initialize() {\n if (this.config.trackPerformance) {\n this.initPerformanceTracking();\n }\n\n if (this.config.trackEngagement) {\n this.initEngagementTracking();\n }\n\n if (this.config.trackScrollDepth) {\n this.initScrollTracking();\n }\n\n if (this.config.trackRageClicks) {\n this.initRageClickTracking();\n }\n\n if (this.config.trackTimeOnPage) {\n this.initTimeTracking();\n }\n\n if (this.config.trackAPIResponses) {\n this.initAPITracking();\n }\n\n // Track page unload\n window.addEventListener('beforeunload', () => {\n this.trackPageExit();\n });\n\n console.log('[AInamika Advanced Tracker] Initialized');\n }\n\n // ============= Performance Tracking =============\n\n private initPerformanceTracking() {\n // Track Core Web Vitals using PerformanceObserver\n if ('PerformanceObserver' in window) {\n // LCP - Largest Contentful Paint\n try {\n const lcpObserver = new PerformanceObserver((entryList) => {\n const entries = entryList.getEntries();\n const lastEntry = entries[entries.length - 1] as any;\n this.performanceMetrics.lcp = lastEntry.startTime;\n this.onEvent('performance_lcp', {\n value: lastEntry.startTime,\n element: lastEntry.element?.tagName\n });\n });\n lcpObserver.observe({ type: 'largest-contentful-paint', buffered: true });\n } catch (e) {\n console.debug('[Advanced Tracker] LCP not supported');\n }\n\n // FID - First Input Delay\n try {\n const fidObserver = new PerformanceObserver((entryList) => {\n const entries = entryList.getEntries();\n const firstEntry = entries[0] as any;\n this.performanceMetrics.fid = firstEntry.processingStart - firstEntry.startTime;\n this.onEvent('performance_fid', {\n value: this.performanceMetrics.fid,\n eventType: firstEntry.name\n });\n });\n fidObserver.observe({ type: 'first-input', buffered: true });\n } catch (e) {\n console.debug('[Advanced Tracker] FID not supported');\n }\n\n // CLS - Cumulative Layout Shift\n try {\n let clsValue = 0;\n const clsObserver = new PerformanceObserver((entryList) => {\n for (const entry of entryList.getEntries() as any[]) {\n if (!entry.hadRecentInput) {\n clsValue += entry.value;\n }\n }\n this.performanceMetrics.cls = clsValue;\n });\n clsObserver.observe({ type: 'layout-shift', buffered: true });\n\n // Report CLS on page hide\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') {\n this.onEvent('performance_cls', { value: clsValue });\n }\n });\n } catch (e) {\n console.debug('[Advanced Tracker] CLS not supported');\n }\n\n // FCP - First Contentful Paint\n try {\n const fcpObserver = new PerformanceObserver((entryList) => {\n const entries = entryList.getEntries();\n const fcpEntry = entries.find(e => e.name === 'first-contentful-paint');\n if (fcpEntry) {\n this.performanceMetrics.fcp = fcpEntry.startTime;\n this.onEvent('performance_fcp', { value: fcpEntry.startTime });\n }\n });\n fcpObserver.observe({ type: 'paint', buffered: true });\n } catch (e) {\n console.debug('[Advanced Tracker] FCP not supported');\n }\n }\n\n // Track page load timing\n window.addEventListener('load', () => {\n setTimeout(() => {\n const timing = performance.timing;\n this.performanceMetrics.ttfb = timing.responseStart - timing.navigationStart;\n this.performanceMetrics.domContentLoaded = timing.domContentLoadedEventEnd - timing.navigationStart;\n this.performanceMetrics.pageLoad = timing.loadEventEnd - timing.navigationStart;\n\n // Count resources\n const resources = performance.getEntriesByType('resource');\n this.performanceMetrics.resourceCount = resources.length;\n this.performanceMetrics.transferSize = resources.reduce((acc, r: any) => acc + (r.transferSize || 0), 0);\n\n this.onEvent('performance_page_load', {\n ttfb: this.performanceMetrics.ttfb,\n domContentLoaded: this.performanceMetrics.domContentLoaded,\n pageLoad: this.performanceMetrics.pageLoad,\n resourceCount: this.performanceMetrics.resourceCount,\n transferSizeKB: Math.round((this.performanceMetrics.transferSize || 0) / 1024)\n });\n }, 0);\n });\n }\n\n // ============= Engagement Tracking =============\n\n private initEngagementTracking() {\n // Track page visibility changes\n document.addEventListener('visibilitychange', () => {\n this.isPageVisible = document.visibilityState === 'visible';\n this.visibilityChangeCount++;\n this.engagementMetrics.pageVisibilityChanges = this.visibilityChangeCount;\n\n if (this.isPageVisible) {\n this.lastActivityTime = Date.now();\n } else {\n this.updateActiveTime();\n }\n });\n\n // Track user activity\n ['mousemove', 'keydown', 'touchstart', 'scroll'].forEach(eventType => {\n document.addEventListener(eventType, () => {\n this.lastActivityTime = Date.now();\n }, { passive: true });\n });\n\n // Track all clicks for engagement\n document.addEventListener('click', () => {\n this.engagementMetrics.totalClicks++;\n });\n }\n\n // ============= Scroll Depth Tracking =============\n\n private initScrollTracking() {\n let ticking = false;\n\n const updateScrollDepth = () => {\n const scrollTop = window.scrollY || document.documentElement.scrollTop;\n const docHeight = Math.max(\n document.body.scrollHeight,\n document.documentElement.scrollHeight\n ) - window.innerHeight;\n\n const scrollPercent = docHeight > 0 ? Math.round((scrollTop / docHeight) * 100) : 0;\n this.engagementMetrics.scrollDepth = Math.max(this.engagementMetrics.scrollDepth, scrollPercent);\n\n // Check milestones\n for (const threshold of this.config.scrollDepthThresholds!) {\n if (scrollPercent >= threshold && !this.scrollDepthReached.has(threshold)) {\n this.scrollDepthReached.add(threshold);\n this.engagementMetrics.scrollDepthMilestones.push(threshold);\n\n this.onEvent('engagement_scroll_depth', {\n depth: threshold,\n maxDepth: this.engagementMetrics.scrollDepth,\n timeToReach: Date.now() - this.pageStartTime\n });\n }\n }\n\n ticking = false;\n };\n\n window.addEventListener('scroll', () => {\n if (!ticking) {\n requestAnimationFrame(updateScrollDepth);\n ticking = true;\n }\n }, { passive: true });\n }\n\n // ============= Rage Click Tracking =============\n\n private initRageClickTracking() {\n document.addEventListener('click', (event) => {\n const now = Date.now();\n this.clickHistory.push(now);\n\n // Remove old clicks outside the window\n this.clickHistory = this.clickHistory.filter(\n time => now - time < this.config.rageClickWindow!\n );\n\n // Check for rage clicks\n if (this.clickHistory.length >= this.config.rageClickThreshold!) {\n this.engagementMetrics.rageClicks++;\n\n const target = event.target as HTMLElement;\n this.onEvent('engagement_rage_click', {\n clickCount: this.clickHistory.length,\n element: {\n tagName: target.tagName,\n id: target.id,\n className: target.className,\n textContent: target.textContent?.substring(0, 50)\n },\n position: { x: event.clientX, y: event.clientY },\n totalRageClicks: this.engagementMetrics.rageClicks\n });\n\n // Reset history after detecting rage click\n this.clickHistory = [];\n }\n });\n }\n\n // ============= Time on Page Tracking =============\n\n private initTimeTracking() {\n // Update time metrics every 30 seconds\n setInterval(() => {\n this.updateActiveTime();\n }, 30000);\n }\n\n private updateActiveTime() {\n const now = Date.now();\n const timeSinceLastActivity = now - this.lastActivityTime;\n\n this.engagementMetrics.timeOnPage = now - this.pageStartTime;\n\n // If last activity was within 30 seconds, count as active time\n if (timeSinceLastActivity < 30000) {\n this.engagementMetrics.activeTime += Math.min(timeSinceLastActivity, 30000);\n } else {\n this.engagementMetrics.idleTime += timeSinceLastActivity;\n }\n }\n\n // ============= API Response Tracking =============\n\n private initAPITracking() {\n // Intercept fetch\n window.fetch = async (...args) => {\n const startTime = Date.now();\n const url = args[0] instanceof Request ? args[0].url : String(args[0]);\n const method = args[1]?.method || 'GET';\n\n // Check if URL matches tracking patterns\n if (!this.shouldTrackAPI(url)) {\n return this.originalFetch(...args);\n }\n\n try {\n const response = await this.originalFetch(...args);\n const duration = Date.now() - startTime;\n\n this.trackAPICall({\n url,\n method,\n status: response.status,\n duration,\n success: response.ok,\n timestamp: Date.now()\n });\n\n return response;\n } catch (error: any) {\n const duration = Date.now() - startTime;\n\n this.trackAPICall({\n url,\n method,\n status: 0,\n duration,\n success: false,\n error: error?.message || 'Network error',\n timestamp: Date.now()\n });\n\n throw error;\n }\n };\n\n console.log('[Advanced Tracker] API tracking initialized');\n }\n\n private shouldTrackAPI(url: string): boolean {\n if (!this.config.apiTrackingPatterns || this.config.apiTrackingPatterns.length === 0) {\n // Track all APIs if no patterns specified\n return true;\n }\n\n return this.config.apiTrackingPatterns.some(pattern => {\n try {\n const regex = new RegExp(pattern);\n return regex.test(url);\n } catch {\n return url.includes(pattern);\n }\n });\n }\n\n private trackAPICall(event: APITrackingEvent) {\n this.onEvent('api_call', {\n url: event.url,\n method: event.method,\n status: event.status,\n duration: event.duration,\n success: event.success,\n error: event.error\n });\n }\n\n // ============= Public Methods =============\n\n /**\n * Manually track an API response with custom data\n * Use this when you need to track specific API data that's important for analytics\n */\n public trackAPI(\n endpoint: string,\n method: string,\n response: any,\n metadata?: Record<string, any>\n ) {\n this.onEvent('api_response_tracked', {\n endpoint,\n method,\n responseType: typeof response,\n responseKeys: response && typeof response === 'object' ? Object.keys(response) : [],\n hasData: !!response,\n dataCount: Array.isArray(response) ? response.length : undefined,\n ...metadata\n });\n }\n\n /**\n * Track custom engagement event\n */\n public trackEngagement(action: string, properties?: Record<string, any>) {\n this.onEvent(`engagement_${action}`, {\n ...properties,\n timeOnPage: Date.now() - this.pageStartTime,\n scrollDepth: this.engagementMetrics.scrollDepth\n });\n }\n\n /**\n * Track conversion/goal completion\n */\n public trackConversion(goalName: string, value?: number, properties?: Record<string, any>) {\n this.onEvent('conversion', {\n goal: goalName,\n value,\n ...properties,\n timeToConvert: Date.now() - this.pageStartTime,\n scrollDepthAtConversion: this.engagementMetrics.scrollDepth,\n clicksBeforeConversion: this.engagementMetrics.totalClicks\n });\n }\n\n /**\n * Get current performance metrics\n */\n public getPerformanceMetrics(): PerformanceMetrics {\n return { ...this.performanceMetrics };\n }\n\n /**\n * Get current engagement metrics\n */\n public getEngagementMetrics(): EngagementMetrics {\n this.updateActiveTime();\n return {\n ...this.engagementMetrics,\n timeOnPage: Date.now() - this.pageStartTime\n };\n }\n\n /**\n * Track page exit - called automatically on beforeunload\n */\n private trackPageExit() {\n this.updateActiveTime();\n\n this.onEvent('page_exit', {\n timeOnPage: Date.now() - this.pageStartTime,\n activeTime: this.engagementMetrics.activeTime,\n idleTime: this.engagementMetrics.idleTime,\n scrollDepth: this.engagementMetrics.scrollDepth,\n scrollMilestones: this.engagementMetrics.scrollDepthMilestones,\n totalClicks: this.engagementMetrics.totalClicks,\n rageClicks: this.engagementMetrics.rageClicks,\n visibilityChanges: this.engagementMetrics.pageVisibilityChanges,\n performance: this.performanceMetrics\n });\n }\n}\n\n/**\n * Smart Event Enrichment - Parse customdata and enrich event properties\n */\nexport function enrichEventWithCustomdata(element: HTMLElement): Record<string, any> {\n const enrichedData: Record<string, any> = {};\n\n // Get customdata attribute\n const customdata = element.getAttribute('customdata') || element.dataset.customdata;\n\n if (customdata) {\n try {\n // Try to parse as JSON\n const parsed = JSON.parse(customdata);\n enrichedData.customdata = parsed;\n\n // Extract common fields\n if (parsed.name) enrichedData.itemName = parsed.name;\n if (parsed.displayedTitle) enrichedData.section = parsed.displayedTitle;\n if (parsed.title) enrichedData.title = parsed.title;\n if (parsed.category) enrichedData.category = parsed.category;\n if (parsed.id) enrichedData.itemId = parsed.id;\n } catch {\n // Try regex extraction for truncated JSON\n const nameMatch = customdata.match(/\"name\"\\s*:\\s*\"([^\"]+)\"/);\n if (nameMatch) enrichedData.itemName = nameMatch[1];\n\n const titleMatch = customdata.match(/\"(?:displayedTitle|title)\"\\s*:\\s*\"([^\"]+)\"/);\n if (titleMatch) enrichedData.section = titleMatch[1];\n }\n }\n\n // Extract from element ID\n const elementId = element.id;\n if (elementId) {\n enrichedData.elementId = elementId;\n\n // Extract game/item name from ID pattern like \"uuid_GameName\"\n const idParts = elementId.split('_');\n if (idParts.length >= 2) {\n const namePart = idParts.slice(1).join('_');\n if (!enrichedData.itemName && namePart) {\n enrichedData.itemName = namePart;\n }\n }\n }\n\n // Extract text content\n const textContent = element.textContent?.trim();\n if (textContent && textContent.length < 100) {\n enrichedData.displayText = textContent;\n }\n\n // Get data attributes\n const dataset = element.dataset;\n for (const [key, value] of Object.entries(dataset)) {\n if (!enrichedData[key] && value) {\n enrichedData[`data_${key}`] = value;\n }\n }\n\n return enrichedData;\n}\n","// src/sdk.ts - Main SDK entry point\nimport { ErrorTracker, ErrorConfig } from './error-tracker';\nimport { ErrorStorage } from './error-storage';\nimport { ENV_CONFIG } from './config';\nimport { UserManager } from './user-manager';\nimport { JourneyTracker } from './journey-tracker';\nimport { AuthManager } from './auth-manager';\nimport { AdvancedTracker, AdvancedTrackingConfig, enrichEventWithCustomdata, PerformanceMetrics, EngagementMetrics } from './advanced-tracker';\n\ninterface AnalyticsConfig {\n // NEW: Project-based authentication (preferred)\n projectKey?: string; // Public project key (e.g., 'proj_a1b2c3d4e5f6')\n\n // LEGACY: Client-based authentication (for backward compatibility)\n apiKey?: string;\n clientId?: string;\n\n endpoint?: string;\n autoConfig?: boolean;\n batchInterval?: number;\n useWebWorker?: boolean;\n workerPath?: string;\n debug?: boolean;\n apiDetails?: {\n apiEndPoint: string;\n headers?: Record<string, string>;\n };\n workerConfig?: {\n batchSize?: number;\n batchInterval?: number;\n };\n errorTracking?: {\n enabled?: boolean;\n captureScreenshots?: boolean;\n captureDomSnapshots?: boolean;\n maxStackTraceDepth?: number;\n maxErrorsPerSession?: number;\n debounceMs?: number;\n enableNetworkTracking?: boolean;\n enableConsoleCapture?: boolean;\n };\n // NEW: Advanced tracking configuration\n advancedTracking?: {\n enabled?: boolean;\n trackPerformance?: boolean;\n trackEngagement?: boolean;\n trackScrollDepth?: boolean;\n trackRageClicks?: boolean;\n trackTimeOnPage?: boolean;\n trackAPIResponses?: boolean;\n scrollDepthThresholds?: number[];\n apiTrackingPatterns?: string[];\n };\n // Optional extra config - passed as-is with all events\n // Use this to pass custom data like userId, deviceId, appVersion, etc.\n extraConfig?: Record<string, any>;\n}\n\n// Sampling decision from server\ninterface SamplingDecision {\n should_sample: {\n events: boolean;\n errors: boolean;\n session_replay: boolean;\n };\n rates: {\n events: number;\n errors: number;\n session_replay: number;\n };\n decision: 'new' | 'existing';\n}\n\n// Project settings from server\ninterface ProjectSettings {\n project_id: number;\n name: string;\n settings: Record<string, any>;\n features: Record<string, boolean>;\n sampling: {\n events: number;\n errors: number;\n session_replay: number;\n };\n}\n\ninterface EventData {\n event: string;\n properties?: Record<string, any>;\n timestamp?: number;\n userId?: string;\n sessionId?: string;\n}\n\nclass AInamikaSDKPro {\n private config: AnalyticsConfig;\n private worker: Worker;\n private sessionId: string;\n private batchTimer?: number;\n private eventQueue: Map<string, any>[] = [];\n private isInitialized = false;\n private batchRetryCount: number = 0;\n private maxBatchRetries: number = 5;\n\n // --- Project-based Configuration ---\n private projectSettings?: ProjectSettings;\n private samplingDecision?: SamplingDecision;\n private userIdentifier: string; // Persistent user identifier for sampling\n\n // --- Error Tracking Components ---\n private errorTracker?: ErrorTracker;\n private errorStorage?: ErrorStorage;\n\n // --- User & Journey Tracking Components ---\n private userManager: UserManager;\n private journeyTracker: JourneyTracker;\n\n // --- Authentication Manager ---\n private authManager: AuthManager;\n\n // --- Advanced Tracking ---\n private advancedTracker?: AdvancedTracker;\n\n // --- Dynamic DOM Fingerprinting and Smart Debouncing ---\n private lastDomHash: string = '';\n private lastConfigHash: string = '';\n private mutationDebounceTimer: number | null = null;\n private mutationDebounceMs: number = 2000; // 2s debounce for dynamic DOM\n\n // Track attached event types per element to prevent duplicate listeners\n private attachedListeners: WeakMap<Element, Set<string>> = new WeakMap();\n\n // Track known element selectors to avoid sending duplicates to server\n private knownElementSelectors: Set<string> = new Set();\n\n // Track handled clicks to prevent generic events when specific ones are sent\n // Key: timestamp, Value: Set of event names sent for that click\n private handledClicks: Map<number, Set<string>> = new Map();\n private readonly CLICK_DEDUP_WINDOW_MS = 50; // 50ms window for same click\n\n // Track viewed elements to prevent duplicate view events\n // Key: unique identifier (selector + element index/id), Value: timestamp when viewed\n private viewedElements: Set<string> = new Set();\n\n // Store active IntersectionObservers for cleanup\n private viewObservers: Map<string, IntersectionObserver> = new Map();\n\n // Store merged config for all tracked events\n private mergedConfig: { events_to_track: any[], tracking_config?: any } = { events_to_track: [] };\n\n constructor(config: AnalyticsConfig) {\n // Validate that either projectKey or clientId is provided\n if (!config.projectKey && !config.clientId && !config.apiKey) {\n throw new Error('[AInamika SDK] Either projectKey or clientId is required for initialization');\n }\n\n this.config = {\n endpoint: ENV_CONFIG.API_BASE_URL,\n batchInterval: 5000,\n useWebWorker: true,\n debug: ENV_CONFIG.DEBUG,\n errorTracking: {\n enabled: true,\n captureScreenshots: true,\n captureDomSnapshots: true,\n maxStackTraceDepth: 50,\n maxErrorsPerSession: 100,\n debounceMs: 1000,\n enableNetworkTracking: true,\n enableConsoleCapture: true\n },\n advancedTracking: {\n enabled: true,\n trackPerformance: true,\n trackEngagement: true,\n trackScrollDepth: true,\n trackRageClicks: true,\n trackTimeOnPage: true,\n trackAPIResponses: false, // Opt-in\n scrollDepthThresholds: [25, 50, 75, 90, 100]\n },\n ...config\n };\n\n this.sessionId = this.generateSessionId();\n\n // Initialize or retrieve persistent user identifier for sampling\n this.userIdentifier = this.getOrCreateUserIdentifier();\n\n // Initialize user and journey tracking\n this.userManager = new UserManager();\n this.journeyTracker = new JourneyTracker();\n\n // Initialize authentication manager (use clientId for legacy, or we'll get it from project lookup)\n this.authManager = new AuthManager(\n this.config.clientId || this.config.apiKey || '',\n this.config.endpoint!,\n this.config.debug\n );\n // Inline the worker code as a Blob to avoid cross-origin issues\n const workerCode = `\n self.eventQueue = [];\n self.config = {\n apiUrl: '',\n batchSize: 10,\n batchInterval: 5000,\n headers: { 'Content-Type': 'application/json' }\n };\n let batchTimer = null;\n function flushQueue() {\n self.postMessage({ status: 'debug', message: '[AInamika Worker] flushQueue called', eventQueue: self.eventQueue, config: self.config });\n if (self.eventQueue.length === 0) return;\n const batch = self.eventQueue.splice(0, self.config.batchSize);\n fetch(self.config.apiUrl, {\n method: 'POST',\n headers: self.config.headers,\n body: JSON.stringify({ events: batch })\n }).then(r => {\n if (r.ok) {\n self.postMessage({ status: 'success' });\n } else {\n self.postMessage({ status: 'error', error: r.statusText, failedEvents: batch });\n }\n }).catch(e => {\n self.postMessage({ status: 'error', error: e.message, failedEvents: batch });\n });\n }\n self.onmessage = function(e) {\n self.postMessage({ status: 'debug', message: '[AInamika Worker] onmessage', data: e.data });\n if (e.data.type === 'config') {\n self.config = { ...self.config, ...e.data.payload };\n if (batchTimer) clearInterval(batchTimer);\n batchTimer = setInterval(flushQueue, self.config.batchInterval);\n self.postMessage({ status: 'debug', message: '[AInamika Worker] config set', config: self.config });\n } else if (e.data.type === 'track') {\n self.eventQueue.push(e.data.payload);\n // Only send when timer triggers, not when batch size is reached\n // This ensures true batching behavior\n } else if (e.data.type === 'batch') {\n // Handle batch flush from main thread\n self.postMessage({ status: 'debug', message: '[AInamika Worker] Received batch from main thread', events: e.data.events });\n self.eventQueue.push(...e.data.events);\n flushQueue();\n } else if (e.data.type === 'initConfig') {\n // No-op for now, can be used for advanced config\n }\n };\n `;\n const blob = new Blob([workerCode], { type: 'application/javascript' });\n const workerUrl = URL.createObjectURL(blob);\n this.worker = new Worker(workerUrl);\n this.initialize();\n }\n\n private async initialize() {\n if (this.isInitialized) return;\n this.isInitialized = true;\n\n // If using projectKey, fetch project settings and sampling decision first\n if (this.config.projectKey) {\n try {\n await this.initializeProjectSettings();\n await this.initializeSamplingDecision();\n this.log('Project-based initialization complete', {\n projectKey: this.config.projectKey,\n projectSettings: this.projectSettings,\n samplingDecision: this.samplingDecision\n });\n } catch (error) {\n this.log('Project initialization failed:', error);\n console.warn('[AInamika SDK] Failed to initialize project settings. Some features may be limited.');\n }\n }\n\n // Initialize authentication (only for legacy clientId-based auth)\n if (this.config.clientId || this.config.apiKey) {\n try {\n await this.authManager.initialize();\n this.log('Authentication initialized');\n } catch (error) {\n this.log('Authentication initialization failed:', error);\n // Continue without authentication in development mode\n if (!this.config.debug) {\n console.warn('[Ainamika] Running without authentication. Some features may be limited.');\n }\n }\n }\n\n // Initialize Error Tracking (respecting sampling decision)\n if (this.config.errorTracking?.enabled && this.shouldSampleErrors()) {\n this.initializeErrorTracking();\n } else if (this.config.errorTracking?.enabled && !this.shouldSampleErrors()) {\n this.log('Error tracking disabled due to sampling decision');\n }\n\n // Initialize Advanced Tracking\n if (this.config.advancedTracking?.enabled) {\n this.initializeAdvancedTracking();\n }\n\n if (this.config.autoConfig) {\n await this.setupAutoConfiguration();\n\n // Enable dynamic DOM tracking only when autoConfig is enabled\n // This watches for DOM changes and fetches config for new elements\n this.setupDynamicDomTracking();\n }\n\n if (this.config.useWebWorker && typeof Worker !== 'undefined') {\n await this.setupWebWorker();\n } else {\n // Fallback for environments without web workers\n this.startBatchTimer();\n }\n this.log('AnalyticsPro SDK initialized', {\n config: this.config,\n projectKey: this.config.projectKey,\n sampling: this.samplingDecision\n });\n }\n\n // --- Project Initialization Methods ---\n\n private getOrCreateUserIdentifier(): string {\n const storageKey = 'ainamika_user_identifier';\n let identifier = localStorage.getItem(storageKey);\n\n if (!identifier) {\n // Generate anonymous user identifier\n identifier = 'anon_' + Math.random().toString(36).substr(2, 16) + Date.now().toString(36);\n localStorage.setItem(storageKey, identifier);\n this.log('Created new user identifier:', identifier);\n }\n\n return identifier;\n }\n\n private async initializeProjectSettings(): Promise<void> {\n if (!this.config.projectKey) return;\n\n try {\n const response = await fetch(`${this.config.endpoint}/api/v1/projects/lookup`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ project_key: this.config.projectKey })\n });\n\n if (!response.ok) {\n throw new Error(`Project lookup failed: ${response.status}`);\n }\n\n this.projectSettings = await response.json();\n this.log('Project settings loaded:', this.projectSettings);\n } catch (error) {\n this.log('Failed to load project settings:', error);\n throw error;\n }\n }\n\n private async initializeSamplingDecision(): Promise<void> {\n if (!this.config.projectKey) return;\n\n try {\n const response = await fetch(`${this.config.endpoint}/api/v1/projects/sampling/check`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n project_key: this.config.projectKey,\n user_identifier: this.userIdentifier\n })\n });\n\n if (!response.ok) {\n throw new Error(`Sampling check failed: ${response.status}`);\n }\n\n this.samplingDecision = await response.json();\n this.log('Sampling decision received:', this.samplingDecision);\n\n // Store sampling decision locally for offline access\n this.cacheSamplingDecision();\n } catch (error) {\n this.log('Failed to get sampling decision, using cached or defaults:', error);\n this.loadCachedSamplingDecision();\n }\n }\n\n // Fixed storage key for sampling decision (no longer includes projectKey)\n private static readonly SAMPLING_STORAGE_KEY = 'ainamika_sampling';\n\n private cacheSamplingDecision(): void {\n if (this.samplingDecision) {\n const cacheData = {\n projectKey: this.config.projectKey, // Store projectKey for validation\n ...this.samplingDecision\n };\n localStorage.setItem(AInamikaSDKPro.SAMPLING_STORAGE_KEY, JSON.stringify(cacheData));\n // Clean up legacy dynamic keys\n this.cleanupLegacySamplingKeys();\n }\n }\n\n private loadCachedSamplingDecision(): void {\n // Clean up legacy keys first\n this.cleanupLegacySamplingKeys();\n\n const cached = localStorage.getItem(AInamikaSDKPro.SAMPLING_STORAGE_KEY);\n\n if (cached) {\n try {\n const cacheData = JSON.parse(cached);\n\n // Validate projectKey - if different, clear and use defaults\n if (cacheData.projectKey && cacheData.projectKey !== this.config.projectKey) {\n this.log('Cached sampling is for different projectKey, clearing');\n localStorage.removeItem(AInamikaSDKPro.SAMPLING_STORAGE_KEY);\n this.samplingDecision = this.getDefaultSamplingDecision();\n return;\n }\n\n // Extract sampling decision (exclude projectKey from the decision object)\n const { projectKey, ...samplingData } = cacheData;\n this.samplingDecision = samplingData as SamplingDecision;\n this.log('Loaded cached sampling decision:', this.samplingDecision);\n } catch {\n // Use default (sample everything)\n this.samplingDecision = this.getDefaultSamplingDecision();\n }\n } else {\n // Default to sampling everything when no cached decision\n this.samplingDecision = this.getDefaultSamplingDecision();\n }\n }\n\n private getDefaultSamplingDecision(): SamplingDecision {\n return {\n should_sample: { events: true, errors: true, session_replay: false },\n rates: { events: 100, errors: 100, session_replay: 0 },\n decision: 'existing'\n };\n }\n\n private cleanupLegacySamplingKeys(): void {\n if (typeof window !== 'undefined' && window.localStorage) {\n const keysToRemove: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith('ainamika_sampling_') && key !== AInamikaSDKPro.SAMPLING_STORAGE_KEY) {\n keysToRemove.push(key);\n }\n }\n keysToRemove.forEach(key => {\n localStorage.removeItem(key);\n this.log('Removed legacy sampling key:', key);\n });\n }\n }\n\n // --- Sampling Check Methods ---\n\n private shouldSampleEvents(): boolean {\n // If no sampling decision (legacy mode), sample everything\n if (!this.samplingDecision) return true;\n return this.samplingDecision.should_sample.events;\n }\n\n private shouldSampleErrors(): boolean {\n // If no sampling decision (legacy mode), sample everything\n if (!this.samplingDecision) return true;\n return this.samplingDecision.should_sample.errors;\n }\n\n private shouldSampleSessionReplay(): boolean {\n // If no sampling decision (legacy mode), don't sample replay\n if (!this.samplingDecision) return false;\n return this.samplingDecision.should_sample.session_replay;\n }\n\n // Public method to check sampling status\n public getSamplingStatus(): SamplingDecision | null {\n return this.samplingDecision || null;\n }\n\n // Public method to get project info\n public getProjectInfo(): ProjectSettings | null {\n return this.projectSettings || null;\n }\n\n // Public method to get current tracking config status\n public getTrackingStatus(): {\n totalEvents: number;\n knownSelectors: number;\n mergedConfig: { events_to_track: any[], tracking_config?: any };\n } {\n return {\n totalEvents: this.mergedConfig.events_to_track.length,\n knownSelectors: this.knownElementSelectors.size,\n mergedConfig: this.mergedConfig\n };\n }\n\n // Public method to reset DOM tracking (useful for SPA route changes)\n public resetDomTracking(): void {\n this.knownElementSelectors.clear();\n this.mergedConfig = { events_to_track: [] };\n this.lastDomHash = '';\n this.attachedListeners = new WeakMap();\n this.log('DOM tracking reset - will re-analyze on next mutation');\n }\n\n /**\n * Clears all SDK caches from LocalStorage.\n * Call this method to force fresh config generation from the server.\n *\n * This clears:\n * - DOM config cache (ainamika_dom_config_cache)\n * - Sampling decision cache\n * - User identifier (optional)\n *\n * @param clearUserIdentifier - If true, also clears user identifier (default: false)\n */\n public clearAllCaches(clearUserIdentifier: boolean = false): void {\n try {\n // Clear DOM config cache\n localStorage.removeItem('ainamika_dom_config_cache');\n this.log('Cleared DOM config cache');\n\n // Clear last-known config (for instant loading)\n localStorage.removeItem('ainamika_last_known_config');\n this.log('Cleared last-known config cache');\n\n // Clear sampling decision cache (fixed key)\n localStorage.removeItem(AInamikaSDKPro.SAMPLING_STORAGE_KEY);\n // Also clean up any legacy dynamic keys\n this.cleanupLegacySamplingKeys();\n this.log('Cleared sampling decision cache');\n\n // Optionally clear user identifier\n if (clearUserIdentifier) {\n localStorage.removeItem('ainamika_user_identifier');\n this.log('Cleared user identifier');\n }\n\n // Reset in-memory state\n this.resetDomTracking();\n this.samplingDecision = undefined;\n\n this.log('All caches cleared successfully');\n } catch (error) {\n console.error('[AInamika SDK] Error clearing caches:', error);\n }\n }\n\n /**\n * Gets cache statistics for debugging\n */\n public getCacheStats(): {\n domConfigCacheSize: number;\n cachedDomHashes: string[];\n hasSamplingCache: boolean;\n hasUserIdentifier: boolean;\n hasLastKnownConfig: boolean;\n } {\n try {\n const cache = JSON.parse(localStorage.getItem('ainamika_dom_config_cache') || '{}');\n const domHashes = Object.keys(cache);\n\n return {\n domConfigCacheSize: domHashes.length,\n cachedDomHashes: domHashes,\n hasSamplingCache: !!localStorage.getItem(AInamikaSDKPro.SAMPLING_STORAGE_KEY),\n hasUserIdentifier: !!localStorage.getItem('ainamika_user_identifier'),\n hasLastKnownConfig: !!localStorage.getItem('ainamika_last_known_config')\n };\n } catch {\n return {\n domConfigCacheSize: 0,\n cachedDomHashes: [],\n hasSamplingCache: false,\n hasUserIdentifier: false,\n hasLastKnownConfig: false\n };\n }\n }\n\n // --- Error Tracking Initialization ---\n private initializeErrorTracking() {\n try {\n // Initialize error storage with endpoint from config\n this.errorStorage = new ErrorStorage({\n maxStorageSize: 5 * 1024 * 1024, // 5MB\n maxRetries: 5,\n retryInterval: 30000, // 30 seconds\n compressionEnabled: true,\n encryptionEnabled: false,\n endpoint: this.config.endpoint // Pass endpoint for retrying stored errors\n });\n\n // Initialize error tracker with endpoint from config\n const errorConfig: ErrorConfig = {\n endpoint: this.config.endpoint!,\n clientId: this.config.clientId || \"\",\n apiKey: this.config.apiKey, // Keep for backward compatibility\n authManager: this.authManager, // Pass authManager for JWT auth\n projectKey: this.config.projectKey, // Pass projectKey for project-based error tracking\n captureScreenshots: this.config.errorTracking?.captureScreenshots ?? true,\n captureDomSnapshots: this.config.errorTracking?.captureDomSnapshots ?? true,\n maxStackTraceDepth: this.config.errorTracking?.maxStackTraceDepth ?? 50,\n maxErrorsPerSession: this.config.errorTracking?.maxErrorsPerSession ?? 100,\n debounceMs: this.config.errorTracking?.debounceMs ?? 1000,\n enableNetworkTracking: this.config.errorTracking?.enableNetworkTracking ?? true,\n enableConsoleCapture: this.config.errorTracking?.enableConsoleCapture ?? true\n };\n\n this.errorTracker = new ErrorTracker(errorConfig);\n \n // Set user for error tracking if available\n const userId = this.getUserId();\n if (userId && this.errorTracker) {\n this.errorTracker.setUser(userId);\n }\n\n this.log('Error tracking initialized successfully');\n } catch (error) {\n console.error('[AInamika SDK] Failed to initialize error tracking:', error);\n }\n }\n\n // Public method to capture custom exceptions\n public captureException(error: Error, context?: Record<string, any>) {\n if (this.errorTracker) {\n this.errorTracker.captureException(error, context);\n }\n }\n\n // Public method to set user for error tracking (deprecated - use identifyUser instead)\n public setUser(userId: string) {\n console.warn('[AInamika SDK] setUser is deprecated. Please use identifyUser() instead.');\n this.identifyUser(userId);\n }\n\n // Public method to flush stored errors\n public async flushStoredErrors() {\n if (this.errorStorage) {\n await this.errorStorage.processQueue();\n }\n if (this.errorTracker) {\n await this.errorTracker.flushStoredErrors();\n }\n }\n\n // --- Advanced Tracking Initialization ---\n private initializeAdvancedTracking() {\n try {\n const advConfig: AdvancedTrackingConfig = {\n trackPerformance: this.config.advancedTracking?.trackPerformance ?? true,\n trackEngagement: this.config.advancedTracking?.trackEngagement ?? true,\n trackScrollDepth: this.config.advancedTracking?.trackScrollDepth ?? true,\n trackRageClicks: this.config.advancedTracking?.trackRageClicks ?? true,\n trackTimeOnPage: this.config.advancedTracking?.trackTimeOnPage ?? true,\n trackAPIResponses: this.config.advancedTracking?.trackAPIResponses ?? false,\n scrollDepthThresholds: this.config.advancedTracking?.scrollDepthThresholds || [25, 50, 75, 90, 100],\n apiTrackingPatterns: this.config.advancedTracking?.apiTrackingPatterns || []\n };\n\n this.advancedTracker = new AdvancedTracker(advConfig, (eventName, properties) => {\n this.sendToWorker(eventName, properties);\n });\n\n this.log('Advanced tracking initialized successfully');\n } catch (error) {\n console.error('[AInamika SDK] Failed to initialize advanced tracking:', error);\n }\n }\n\n // --- Public API Tracking Methods ---\n\n /**\n * Track an API response with custom data\n * Use this to track important API calls and their responses\n *\n * @example\n * // Track a game data API response\n * sdk.trackAPI('/api/games', 'GET', gamesData, { category: 'games' });\n *\n * // Track a user action API\n * sdk.trackAPI('/api/purchase', 'POST', purchaseResult, {\n * gameId: 'swing-monkey',\n * amount: 9.99\n * });\n */\n public trackAPI(endpoint: string, method: string, response: any, metadata?: Record<string, any>) {\n if (this.advancedTracker) {\n this.advancedTracker.trackAPI(endpoint, method, response, metadata);\n } else {\n // Fallback if advanced tracker not initialized\n this.track('api_response_tracked', {\n endpoint,\n method,\n responseType: typeof response,\n hasData: !!response,\n ...metadata\n });\n }\n }\n\n /**\n * Track a custom engagement event\n *\n * @example\n * sdk.trackEngagement('video_watched', { videoId: '123', duration: 120 });\n * sdk.trackEngagement('level_completed', { level: 5, score: 1000 });\n */\n public trackEngagement(action: string, properties?: Record<string, any>) {\n if (this.advancedTracker) {\n this.advancedTracker.trackEngagement(action, properties);\n } else {\n this.track(`engagement_${action}`, properties || {});\n }\n }\n\n /**\n * Track a conversion or goal completion\n *\n * @example\n * sdk.trackConversion('purchase', 9.99, { productId: 'game-123' });\n * sdk.trackConversion('signup', undefined, { source: 'organic' });\n */\n public trackConversion(goalName: string, value?: number, properties?: Record<string, any>) {\n if (this.advancedTracker) {\n this.advancedTracker.trackConversion(goalName, value, properties);\n } else {\n this.track('conversion', { goal: goalName, value, ...properties });\n }\n }\n\n /**\n * Get current performance metrics (Web Vitals, page load timing)\n */\n public getPerformanceMetrics(): PerformanceMetrics | null {\n return this.advancedTracker?.getPerformanceMetrics() || null;\n }\n\n /**\n * Get current engagement metrics (scroll depth, time on page, clicks)\n */\n public getEngagementMetrics(): EngagementMetrics | null {\n return this.advancedTracker?.getEngagementMetrics() || null;\n }\n\n private async setupAutoConfiguration() {\n try {\n this.log('Starting auto-configuration...');\n\n // IMMEDIATE TRACKING: Apply last-known config BEFORE DOM analysis (zero delay)\n // This ensures returning users get instant tracking\n let appliedFromCache = false;\n const lastKnownConfig = this.getLastKnownConfig();\n\n if (lastKnownConfig && lastKnownConfig.events_to_track && lastKnownConfig.events_to_track.length > 0) {\n this.log('Applying last-known config IMMEDIATELY (zero delay)', {\n eventsCount: lastKnownConfig.events_to_track.length\n });\n this.mergedConfig = {\n events_to_track: [...lastKnownConfig.events_to_track],\n tracking_config: lastKnownConfig.tracking_config\n };\n this.applyGeneratedConfig(lastKnownConfig);\n appliedFromCache = true;\n\n // Send config to worker\n if (this.config.useWebWorker && typeof Worker !== 'undefined') {\n this.worker.postMessage({ type: 'initConfig', config: lastKnownConfig });\n }\n }\n\n // BACKGROUND: Now do DOM analysis and fetch fresh config (non-blocking)\n this.setupAutoConfigurationBackground(appliedFromCache);\n\n } catch (error) {\n this.log('Auto-configuration failed with error', error);\n }\n }\n\n // Background DOM analysis and config fetching (doesn't block tracking)\n private async setupAutoConfigurationBackground(alreadyAppliedCache: boolean) {\n try {\n // Compute current DOM structure and hash\n const domStructure = await this.getDOMStructure();\n const domHash = this.computeDomHash(domStructure);\n this.lastDomHash = domHash;\n\n // Track all initial elements as known\n const elements = domStructure.elements || [];\n elements.forEach((el: any) => {\n if (el.selector) this.knownElementSelectors.add(el.selector);\n });\n this.log(`Tracking ${this.knownElementSelectors.size} initial element selectors`);\n\n // Check if we have a cached config for THIS specific DOM hash\n let cachedConfig = this.getCachedConfigForDomHash(domHash);\n let appliedFromCache = alreadyAppliedCache;\n\n if (!alreadyAppliedCache) {\n // Didn't apply last-known config, try domHash-specific or file config\n if (cachedConfig && cachedConfig.events_to_track) {\n this.log('Applying cached config for DOM hash:', domHash);\n this.mergedConfig = {\n events_to_track: [...cachedConfig.events_to_track],\n tracking_config: cachedConfig.tracking_config\n };\n this.applyGeneratedConfig(cachedConfig);\n appliedFromCache = true;\n\n if (this.config.useWebWorker && typeof Worker !== 'undefined') {\n this.worker.postMessage({ type: 'initConfig', config: cachedConfig });\n }\n } else {\n // Try to load config from file as fallback\n const fileConfig = await this.loadConfigFromFile();\n if (fileConfig && fileConfig.events_to_track) {\n this.log('Applying config from file');\n this.mergedConfig = {\n events_to_track: [...fileConfig.events_to_track],\n tracking_config: fileConfig.tracking_config\n };\n this.applyGeneratedConfig(fileConfig);\n appliedFromCache = true;\n }\n }\n }\n\n // BACKGROUND FETCH: Always fetch fresh config from API to get any updates\n this.fetchAndMergeFreshConfig(domStructure, domHash, appliedFromCache);\n\n } catch (error) {\n this.log('Background auto-configuration failed:', error);\n }\n }\n\n // Fetch fresh config from API and merge with existing config\n private async fetchAndMergeFreshConfig(domStructure: any, domHash: string, hadCachedConfig: boolean) {\n try {\n this.log('Fetching fresh config from backend (background)...');\n const freshConfig = await this.fetchGeneratedConfig(domStructure, domHash);\n\n if (!freshConfig || !freshConfig.events_to_track) {\n this.log('No valid config returned from API');\n return;\n }\n\n if (hadCachedConfig) {\n // Merge fresh config with existing (might have new events from server)\n const existingSelectors = new Set(\n this.mergedConfig.events_to_track.map(e => e.element_selector)\n );\n\n const newEvents = freshConfig.events_to_track.filter(\n (event: any) => !existingSelectors.has(event.element_selector)\n );\n\n if (newEvents.length > 0) {\n this.log(`Found ${newEvents.length} new events from fresh config, merging...`);\n this.mergedConfig.events_to_track.push(...newEvents);\n // Apply only new events (existing already have listeners)\n this.applyGeneratedConfig({ events_to_track: newEvents, tracking_config: freshConfig.tracking_config });\n } else {\n this.log('Fresh config has no new events, cache was up-to-date');\n }\n\n // Update tracking config if changed\n if (freshConfig.tracking_config) {\n this.mergedConfig.tracking_config = {\n ...this.mergedConfig.tracking_config,\n ...freshConfig.tracking_config\n };\n }\n } else {\n // No cached config was applied, apply fresh config fully\n this.mergedConfig = {\n events_to_track: [...freshConfig.events_to_track],\n tracking_config: freshConfig.tracking_config\n };\n this.applyGeneratedConfig(freshConfig);\n\n // Send config to worker\n if (this.config.useWebWorker && typeof Worker !== 'undefined') {\n this.worker.postMessage({ type: 'initConfig', config: freshConfig });\n }\n }\n\n // Cache the FINAL merged config in LocalStorage\n this.setCachedConfigForDomHash(domHash, this.mergedConfig);\n this.lastConfigHash = freshConfig.config_hash || '';\n\n // Also save as last-known config for INSTANT loading on next visit\n this.setLastKnownConfig(this.mergedConfig);\n\n this.log('Fresh config processed successfully', {\n totalEvents: this.mergedConfig.events_to_track.length,\n knownSelectors: this.knownElementSelectors.size\n });\n } catch (error) {\n this.log('Background config fetch failed:', error);\n // Silent failure - cached config is still working\n }\n }\n\n private async getDOMStructure(): Promise<any> {\n const getSelector = (el: Element): string => {\n if (el.id) {\n // Check for special characters that are invalid in CSS ID selectors\n // Spaces and special chars need attribute selector format\n if (/[\\s!\"#$%&'()*+,./:;<=>?@[\\\\\\]^`{|}~]/.test(el.id)) {\n // Use attribute selector for IDs with special characters\n // Note: Don't escape here - the value is wrapped in quotes which handles most cases\n // Only escape actual quote characters if present in the ID\n const escapedId = el.id.includes('\"') ? el.id.replace(/\"/g, '\\\\\"') : el.id;\n return `[id=\"${escapedId}\"]`;\n }\n return `#${el.id}`;\n }\n if (el.className && typeof el.className === 'string') {\n const classes = el.className.split(' ').filter(c => c.trim()).join('.');\n return classes ? `.${classes}` : el.tagName.toLowerCase();\n }\n return el.tagName.toLowerCase();\n };\n\n // Wait a bit for any dynamic content to load\n await new Promise(resolve => setTimeout(resolve, 500));\n\n // Comprehensive selector for all interactive and important elements\n const elements = Array.from(document.body.querySelectorAll(`\n button, a, input, select, textarea, form, img, h1, h2, h3, h4, h5, h6,\n [role=button], [role=link], [onclick], [tabindex], [data-analytics], [data-track],\n .card, .btn, .btn-primary, .btn-secondary, .card-title, .card-description, .card-price, .card-actions,\n [id*=\"card\"], [class*=\"card\"], [class*=\"btn\"], [class*=\"price\"], [class*=\"title\"],\n div, span, p\n `));\n\n // Filter and enhance elements with more comprehensive logic\n const filteredElements = elements.filter(el => {\n const style = window.getComputedStyle(el);\n const isVisible = style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0';\n const hasInteraction = el.tagName.toLowerCase() === 'button' || \n el.tagName.toLowerCase() === 'a' || \n el.hasAttribute('onclick') ||\n el.getAttribute('role') === 'button' ||\n el.classList.contains('btn') ||\n el.classList.contains('card');\n const isImportantElement = el.id === 'cardsContainer' || \n el.classList.contains('cards-grid') ||\n el.classList.contains('card') ||\n el.tagName.toLowerCase() === 'img' ||\n ['h1', 'h2', 'h3'].indexOf(el.tagName.toLowerCase()) !== -1;\n \n return (isVisible && (hasInteraction || isImportantElement)) || el.id === 'cardsContainer';\n });\n\n // Deduplicate and add stable metadata (exclude dynamic properties)\n const seen = new Set<string>();\n const structure = filteredElements.map(el => {\n // Only include stable attributes that don't change between page loads\n const stableAttributes: Record<string, string> = {};\n Array.from(el.attributes).forEach(attr => {\n // Exclude dynamic attributes that might change\n if (['style', 'data-timestamp', 'data-rendered'].indexOf(attr.name) === -1) {\n // Truncate attribute values > 25 chars to reduce payload size\n stableAttributes[attr.name] = attr.value.length > 25 ? attr.value.substring(0, 25) : attr.value;\n }\n });\n\n // Generate stable fingerprint for this element\n const fingerprint = this.generateElementFingerprint(el);\n\n const obj = {\n tagName: el.tagName.toLowerCase(),\n selector: getSelector(el),\n fingerprint, // NEW: Stable fingerprint for consistent event naming\n id: el.id || '',\n className: el.className || '',\n textContent: (el.textContent || '').trim().substring(0, 100),\n attributes: stableAttributes,\n // Remove position and computed styles as they can vary\n isInteractive: el.tagName.toLowerCase() === 'button' ||\n el.tagName.toLowerCase() === 'a' ||\n el.hasAttribute('onclick') ||\n el.getAttribute('role') === 'button' ||\n el.classList.contains('btn'),\n hasChildren: el.children.length > 0,\n childCount: el.children.length,\n // Add stable structural information\n parentTagName: el.parentElement?.tagName.toLowerCase() || '',\n index: Array.from(el.parentElement?.children || []).indexOf(el)\n };\n return obj;\n }).filter(obj => {\n // Deduplicate by fingerprint (more stable than selector)\n if (seen.has(obj.fingerprint)) return false;\n seen.add(obj.fingerprint);\n return true;\n });\n\n this.log('DOM structure analyzed', { elementCount: structure.length, elements: structure });\n return { elements: structure };\n }\n\n private async fetchGeneratedConfig(structure: any, domHash?: string): Promise<any> {\n try {\n if(structure && structure.elements && structure.elements.length === 0) {\n this.log('No elements found in DOM structure, skipping config fetch.');\n return null;\n }\n\n // Get authentication headers\n let headers: Record<string, string> = { 'Content-Type': 'application/json' };\n const authHeaders = await this.authManager.getAuthHeaders();\n headers = { ...headers, ...authHeaders };\n\n const requestBody: any = { structure };\n if (domHash) {\n requestBody.domHash = domHash;\n requestBody.lastConfigHash = this.lastConfigHash;\n }\n\n const response = await fetch(`${this.config.endpoint}/api/v1/sdk/config`, {\n method: 'POST',\n headers,\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n throw new Error(`Backend returned ${response.status}`);\n }\n return await response.json();\n } catch (error) {\n this.log('Error fetching generated config:', error);\n return null;\n }\n }\n\n // Helper to transform event names based on actual event type\n // e.g., \"simulasi_clicked\" + \"view\" → \"simulasi_viewed\"\n private transformEventNameForType(eventName: string, eventType: string): string {\n if (!eventName || !eventType) return eventName;\n\n // Common suffixes to replace\n const suffixMap: Record<string, Record<string, string>> = {\n 'view': {\n '_clicked': '_viewed',\n '_click': '_view'\n },\n 'focus': {\n '_clicked': '_focused',\n '_click': '_focus'\n },\n 'blur': {\n '_clicked': '_blurred',\n '_click': '_blur'\n }\n };\n\n const replacements = suffixMap[eventType];\n if (!replacements) return eventName;\n\n // Try each replacement\n for (const [from, to] of Object.entries(replacements)) {\n if (eventName.endsWith(from)) {\n return eventName.slice(0, -from.length) + to;\n }\n }\n\n // If no suffix match, append the event type\n // e.g., \"card_interaction\" + \"view\" → \"card_interaction_viewed\"\n if (eventType === 'view' && !eventName.endsWith('_viewed') && !eventName.endsWith('_view')) {\n return eventName + '_viewed';\n }\n\n return eventName;\n }\n\n // Helper to sanitize selectors that may have invalid characters (e.g., spaces in IDs)\n private sanitizeSelector(selector: string): string {\n if (!selector) return selector;\n\n // Check if it's an ID selector with spaces or special characters\n // Pattern: #someId with spaces or special chars\n if (selector.startsWith('#') && !selector.startsWith('[')) {\n const idPart = selector.substring(1);\n // If ID contains spaces or special CSS chars, convert to attribute selector\n if (/[\\s!\"#$%&'()*+,./:;<=>?@[\\\\\\]^`{|}~]/.test(idPart)) {\n // Only escape actual quote characters if present\n const escapedId = idPart.includes('\"') ? idPart.replace(/\"/g, '\\\\\"') : idPart;\n return `[id=\"${escapedId}\"]`;\n }\n }\n\n return selector;\n }\n\n private applyGeneratedConfig(config: { events_to_track: any[], observe_mutations?: boolean, tracking_config?: any }) {\n // Apply tracking config if present\n if (config.tracking_config) {\n this.log('Applying tracking config:', config.tracking_config);\n }\n\n config.events_to_track.forEach(eventToTrack => {\n // Sanitize selector to handle IDs with spaces/special characters (outside try for catch access)\n const sanitizedSelector = this.sanitizeSelector(eventToTrack.element_selector);\n try {\n const elements = document.querySelectorAll(sanitizedSelector);\n const metadataRules = eventToTrack.metadata_rules || { extract_customdata: true, extract_text: true };\n\n if (elements.length > 0) {\n elements.forEach(element => {\n // Prevent multiple listeners for the same event type on the same element\n let eventSet = this.attachedListeners.get(element);\n if (!eventSet) {\n eventSet = new Set();\n this.attachedListeners.set(element, eventSet);\n }\n\n // Handle array of event types\n const eventTypes = Array.isArray(eventToTrack.event_type) ? eventToTrack.event_type : [eventToTrack.event_type];\n\n eventTypes.forEach((eventType: string) => {\n if (eventSet.has(eventType)) return;\n eventSet.add(eventType);\n\n // Click events\n if (eventType === 'click') {\n element.addEventListener('click', (event: Event) => {\n const clickTimestamp = Date.now();\n const isGenericEvent = eventToTrack.event_name === 'interactive_element_clicked';\n // List of generic HTML tags that shouldn't override specific selectors\n const genericTags = [\n 'div', 'span', 'p', 'section', 'article', 'header', 'footer',\n 'main', 'aside', 'nav', 'ul', 'ol', 'li', 'table', 'tr', 'td',\n 'th', 'tbody', 'thead', 'figure', 'figcaption', 'blockquote',\n 'pre', 'code', 'label', 'fieldset', 'legend', 'details', 'summary'\n ];\n const isGenericSelector = genericTags.includes(eventToTrack.element_selector?.toLowerCase());\n\n // For generic events, check if a specific event was already sent for this click\n if (isGenericEvent || isGenericSelector) {\n // Check recent clicks within dedup window\n const entries = Array.from(this.handledClicks.entries());\n for (let i = 0; i < entries.length; i++) {\n const ts = entries[i][0];\n if (Math.abs(clickTimestamp - ts) <= this.CLICK_DEDUP_WINDOW_MS) {\n // A specific event was already sent for this click, skip generic\n this.log(`Skipping generic event \"${eventToTrack.event_name}\" - specific event already sent`);\n return;\n }\n }\n }\n\n // Don't prevent default for this demo, let buttons work normally\n const target = event.target as HTMLElement;\n const elementData = this.extractElementData(target, metadataRules);\n\n // Mark this click as handled (for non-generic events)\n if (!isGenericEvent && !isGenericSelector) {\n this.handledClicks.set(clickTimestamp, new Set([eventToTrack.event_name]));\n // Clean up old entries (older than 1 second)\n const cutoff = clickTimestamp - 1000;\n const keys = Array.from(this.handledClicks.keys());\n for (let i = 0; i < keys.length; i++) {\n if (keys[i] < cutoff) this.handledClicks.delete(keys[i]);\n }\n }\n\n this.sendToWorker(eventToTrack.event_name, {\n selector: eventToTrack.element_selector,\n eventType: 'click',\n category: eventToTrack.category || 'uncategorized',\n element: elementData,\n // Include enriched data at top level for easy access\n itemName: elementData.itemName,\n section: elementData.section,\n timestamp: new Date().toISOString()\n });\n });\n this.log(`Attached click listener for \"${eventToTrack.event_name}\" on \"${eventToTrack.element_selector}\" (category: ${eventToTrack.category || 'uncategorized'})`);\n }\n\n // View events using IntersectionObserver\n if (eventType === 'view') {\n if ('IntersectionObserver' in window) {\n // Create unique identifier for this element to prevent duplicate view events\n const elementIndex = Array.from(elements).indexOf(element);\n const elementId = element.id || element.getAttribute('data-id') || '';\n const viewKey = `${eventToTrack.element_selector}::${elementIndex}::${elementId}`;\n\n // Skip if already being observed or already viewed\n if (this.viewedElements.has(viewKey)) {\n this.log(`Skipping already viewed element: \"${viewKey}\"`);\n return;\n }\n\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {\n const target = entry.target as HTMLElement;\n\n // Double-check: prevent duplicate events for this element\n if (this.viewedElements.has(viewKey)) {\n return;\n }\n\n // Mark as viewed BEFORE sending to prevent race conditions\n this.viewedElements.add(viewKey);\n\n const elementData = this.extractElementData(target, metadataRules);\n\n // Transform event name: replace _clicked with _viewed for view events\n const viewEventName = this.transformEventNameForType(eventToTrack.event_name, 'view');\n\n this.sendToWorker(viewEventName, {\n selector: eventToTrack.element_selector,\n eventType: 'view',\n category: eventToTrack.category || 'uncategorized',\n element: elementData,\n itemName: elementData.itemName,\n section: elementData.section,\n intersectionRatio: entry.intersectionRatio,\n timestamp: new Date().toISOString()\n });\n\n // Unobserve after first view to prevent further events\n observer.unobserve(target);\n this.log(`View event sent and unobserved: \"${viewEventName}\" for \"${viewKey}\"`);\n }\n });\n }, { threshold: 0.5 }); // Single threshold: fire when 50% visible\n\n observer.observe(element);\n // Store observer reference for potential cleanup\n this.viewObservers.set(viewKey, observer);\n this.log(`Attached IntersectionObserver for \"${eventToTrack.event_name}\" (as \"${this.transformEventNameForType(eventToTrack.event_name, 'view')}\") on \"${eventToTrack.element_selector}\"`);\n }\n }\n\n // Focus/blur tracking\n if (eventType === 'focus' || eventType === 'blur') {\n element.addEventListener(eventType, () => {\n const target = element as HTMLElement;\n const elementData = this.extractElementData(target, metadataRules);\n\n // Transform event name for focus/blur events\n const transformedEventName = this.transformEventNameForType(eventToTrack.event_name, eventType);\n\n this.sendToWorker(transformedEventName, {\n selector: eventToTrack.element_selector,\n eventType: eventType,\n category: eventToTrack.category || 'uncategorized',\n element: elementData,\n timestamp: new Date().toISOString()\n });\n });\n this.log(`Attached ${eventType} listener for \"${eventToTrack.event_name}\" (as \"${this.transformEventNameForType(eventToTrack.event_name, eventType)}\") on \"${eventToTrack.element_selector}\"`);\n }\n });\n });\n } else {\n this.log(`No elements found for selector: \"${sanitizedSelector}\" (original: \"${eventToTrack.element_selector}\")`);\n }\n } catch (e) {\n this.log(`Error applying selector \"${sanitizedSelector}\" (original: \"${eventToTrack.element_selector}\"):`, e);\n }\n });\n\n // MutationObserver for DOM changes (if requested by config)\n if (config.observe_mutations) {\n if ('MutationObserver' in window) {\n const observer = new MutationObserver((mutations) => {\n mutations.forEach(mutation => {\n this.sendToWorker('dom_mutation', {\n type: mutation.type,\n target: (mutation.target as HTMLElement).outerHTML,\n timestamp: new Date().toISOString()\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n this.log('MutationObserver attached for DOM changes');\n }\n }\n }\n\n private extractElementData(element: HTMLElement, metadataRules?: Record<string, boolean>): any {\n const rect = element.getBoundingClientRect();\n const baseData: any = {\n tagName: element.tagName.toLowerCase(),\n id: element.id || '',\n className: element.className || '',\n textContent: (element.textContent || '').trim().substring(0, 100),\n position: {\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 href: (element as HTMLAnchorElement).href || undefined,\n value: (element as HTMLInputElement).value || undefined\n };\n\n // Smart enrichment: Extract data from customdata and other attributes\n if (metadataRules?.extract_customdata !== false) {\n const enrichedData = enrichEventWithCustomdata(element);\n if (Object.keys(enrichedData).length > 0) {\n baseData.enriched = enrichedData;\n\n // Promote key fields for easier access\n if (enrichedData.itemName) baseData.itemName = enrichedData.itemName;\n if (enrichedData.section) baseData.section = enrichedData.section;\n if (enrichedData.category) baseData.category = enrichedData.category;\n }\n }\n\n // Include raw attributes only if needed for debugging\n if (this.config.debug) {\n baseData.attributes = Array.from(element.attributes).reduce((acc, attr) => {\n acc[attr.name] = attr.value.length > 100 ? attr.value.substring(0, 100) + '...' : attr.value;\n return acc;\n }, {} as Record<string, string>);\n }\n\n return baseData;\n }\n\n // Helper to send events to worker for batching\n private sendToWorker(eventName: string, properties: Record<string, any>) {\n // Check if we should sample this event\n if (!this.shouldSampleEvents()) {\n this.log('Event skipped due to sampling:', eventName);\n return;\n }\n\n const now = new Date();\n const commonData = this.getCommonEventData();\n const eventData: any = {\n event: eventName,\n properties,\n timestamp: now.getTime(), // Milliseconds for backward compatibility\n created_at: now.toISOString(), // ISO timestamp for server-side time filtering\n userId: this.getUserId(),\n sessionId: this.sessionId,\n // Include both project_key (new) and client_id (legacy)\n project_key: this.config.projectKey || undefined,\n client_id: this.config.clientId || this.config.apiKey || undefined,\n project_id: this.projectSettings?.project_id || undefined,\n // Include page context and extraConfig with all events\n ...commonData\n };\n if (this.config.useWebWorker && typeof Worker !== 'undefined') {\n this.worker.postMessage({ type: 'track', payload: eventData });\n } else {\n this.eventQueue.push(eventData);\n }\n this.log('Event tracked:', eventData);\n }\n\n private async setupWebWorker() {\n // Get authentication headers\n const authHeaders = await this.authManager.getAuthHeaders();\n\n // Pass worker config to the worker\n this.worker.postMessage({\n type: 'config',\n payload: {\n apiUrl: this.config.apiDetails?.apiEndPoint || `${this.config.endpoint}/api/v1/events`,\n batchSize: this.config.workerConfig?.batchSize || 10,\n batchInterval: this.config.workerConfig?.batchInterval || 5000,\n headers: {\n 'Content-Type': 'application/json',\n ...authHeaders,\n ...(this.config.apiDetails?.headers || {})\n },\n }\n });\n this.worker.onmessage = (event) => {\n if (event.data.status === 'success') {\n this.log('Batch sent successfully by worker');\n // Don't re-queue failed events since we already cleared the queue\n } else if (event.data.status === 'debug') {\n this.log(event.data.message, event.data);\n } else if (event.data.status === 'error') {\n this.log('Worker failed to send batch', event.data.error);\n // Re-queue failed events only if we have them\n if (event.data.failedEvents && event.data.failedEvents.length > 0) {\n this.eventQueue.unshift(...event.data.failedEvents);\n }\n }\n };\n this.log('Web worker setup complete.');\n }\n\n public track(eventName: string, properties: Record<string, any> = {}) {\n // Check if we should sample this event\n if (!this.shouldSampleEvents()) {\n this.log('Event skipped due to sampling:', eventName);\n return;\n }\n\n // Track in journey tracker\n this.journeyTracker.trackEvent(eventName, properties);\n\n // Get journey context\n const journeyContext = this.journeyTracker.getContext();\n\n const now = new Date();\n const commonData = this.getCommonEventData();\n const eventData: any = {\n event: eventName,\n properties: {\n ...properties,\n journeyContext: {\n sequenceIndex: journeyContext.eventCount - 1,\n timeSinceLastEvent: journeyContext.timeSinceLastEvent,\n journeyDuration: Date.now() - journeyContext.journeyStartTime\n }\n },\n timestamp: now.getTime(), // Milliseconds for backward compatibility\n created_at: now.toISOString(), // ISO timestamp for server-side time filtering\n userId: this.userManager.getUserId(),\n userType: this.userManager.getUserType(),\n sessionId: this.sessionId,\n // Include both project_key (new) and client_id (legacy)\n project_key: this.config.projectKey || undefined,\n client_id: this.config.clientId || this.config.apiKey || undefined,\n // Include project_id if available from project settings\n project_id: this.projectSettings?.project_id || undefined,\n // Include page context and extraConfig with all events\n ...commonData\n };\n\n // Check if we should send journey for analysis\n if (this.journeyTracker.shouldAnalyzeJourney()) {\n this.sendJourneyForAnalysis();\n }\n\n // Use the same batching logic as sendToWorker\n if (this.config.useWebWorker && typeof Worker !== 'undefined') {\n this.worker.postMessage({ type: 'track', payload: eventData });\n } else {\n this.eventQueue.push(eventData);\n }\n this.log('Event tracked public:', eventData);\n }\n\n private startBatchTimer() {\n this.batchTimer = window.setInterval(() => {\n this.flushQueue();\n }, this.config.batchInterval);\n }\n\n private async flushQueue() {\n if (this.eventQueue.length === 0) {\n return;\n }\n\n const batch = [...this.eventQueue];\n // Clear the queue immediately to prevent duplicates\n this.eventQueue = [];\n\n if (this.config.useWebWorker && typeof Worker !== 'undefined') {\n this.worker.postMessage({\n type: 'batch',\n events: batch,\n endpoint: `${this.config.endpoint}/api/v1/events`,\n });\n } else {\n // Fallback send mechanism with retry logic\n await this.sendBatchWithRetry(batch);\n }\n }\n\n private async sendBatchWithRetry(batch: Map<string, any>[]) {\n if (this.batchRetryCount >= this.maxBatchRetries) {\n if (this.batchTimer) {\n clearInterval(this.batchTimer);\n this.batchTimer = undefined;\n this.log('Max batch retries reached. BatchTimer cancelled.');\n }\n return;\n }\n try {\n await this.sendBatch(batch);\n // On success, reset retry count (queue already cleared in flushQueue)\n this.batchRetryCount = 0;\n } catch (error) {\n this.batchRetryCount++;\n this.log(`Batch send failed. Retry attempt ${this.batchRetryCount} of ${this.maxBatchRetries}.`, error);\n // Re-queue the failed batch for retry\n this.eventQueue.unshift(...batch);\n if (this.batchRetryCount >= this.maxBatchRetries) {\n if (this.batchTimer) {\n clearInterval(this.batchTimer);\n this.batchTimer = undefined;\n this.log('Max batch retries reached. BatchTimer cancelled.');\n }\n }\n }\n }\n\n // Update sendBatch to support client db endpoint and headers\n private async sendBatch(batch: Map<string, any>[]) {\n let endpoint = `${this.config.endpoint}/api/v1/events`;\n let headers: Record<string, string> = { 'Content-Type': 'application/json' };\n\n // Get authentication headers\n const authHeaders = await this.authManager.getAuthHeaders();\n headers = { ...headers, ...authHeaders };\n\n if (this.config.apiDetails && this.config.apiDetails.apiEndPoint) {\n endpoint = this.config.apiDetails.apiEndPoint;\n if (this.config.apiDetails.headers) {\n headers = { ...headers, ...this.config.apiDetails.headers };\n }\n }\n // Transform batch to required format\n const clientId = this.config.clientId || '5288aa7d-1b7c-481e-958d-eb9b8e951f14';\n const events = batch.map((e: any) => ({\n event: e.event, // keep 'event' key\n userId: e.userId,\n client_id: clientId,\n timestamp: new Date(e.timestamp).toISOString(),\n ...(e.properties || {})\n }));\n try {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify({ events }),\n });\n if (!response.ok) {\n throw new Error(`Failed to send batch: ${response.status}`);\n }\n this.log('Batch sent successfully:', events);\n } catch (error) {\n this.log('Error sending batch:', error);\n throw error; // Let sendBatchWithRetry handle re-queuing\n }\n }\n\n private generateSessionId(): string {\n // Simple session ID generator (could be improved)\n return 'sess_' + Math.random().toString(36).substr(2, 9);\n }\n\n // Get page context including URL, path, query params, and referrer\n private getPageContext(): Record<string, any> {\n const url = window.location.href;\n const path = window.location.pathname;\n const hash = window.location.hash;\n const referrer = document.referrer;\n\n // Parse query params into object\n const queryParams: Record<string, string> = {};\n const searchParams = new URLSearchParams(window.location.search);\n searchParams.forEach((value, key) => {\n queryParams[key] = value;\n });\n\n return {\n url,\n path,\n hash: hash || undefined,\n referrer: referrer || undefined,\n queryParams: Object.keys(queryParams).length > 0 ? queryParams : undefined,\n title: document.title || undefined\n };\n }\n\n // Get common event data that should be included in all events\n private getCommonEventData(): Record<string, any> {\n return {\n pageContext: this.getPageContext(),\n // Spread extraConfig properties directly at top level (not nested)\n ...(this.config.extraConfig || {})\n };\n }\n\n private getUserId(): string {\n // Use UserManager for consistent user identification\n return this.userManager.getUserId();\n }\n\n // Public method to identify authenticated user\n public identifyUser(authenticatedUserId: string, userProperties?: Record<string, any>) {\n // Get identification event before updating\n const identificationEvent = this.userManager.getUserIdentificationEvent(authenticatedUserId);\n\n // Update user in UserManager\n this.userManager.identifyUser(authenticatedUserId, userProperties);\n\n // Track the identification event\n this.track('user_identified', identificationEvent);\n\n // Update error tracker if enabled\n if (this.errorTracker) {\n this.errorTracker.setUser(authenticatedUserId);\n }\n\n this.log('User identified:', { userId: authenticatedUserId, properties: userProperties });\n }\n\n /**\n * Update or set extra config data that will be included with all events\n * Use this to pass custom data like userId, deviceId, appVersion, etc.\n * Can be called after initialization to update values (e.g., after user login)\n *\n * @example\n * // Set extra config during initialization\n * const sdk = new AInamikaSDKPro({\n * projectKey: 'proj_xxx',\n * extraConfig: { appVersion: '1.0.0', environment: 'production' }\n * });\n *\n * // Update extra config after user login\n * sdk.setExtraConfig({ userId: 'user_123', plan: 'premium' });\n */\n public setExtraConfig(config: Record<string, any>, merge: boolean = true) {\n if (merge && this.config.extraConfig) {\n this.config.extraConfig = { ...this.config.extraConfig, ...config };\n } else {\n this.config.extraConfig = config;\n }\n this.log('Extra config updated:', this.config.extraConfig);\n }\n\n /**\n * Get the current extra config\n */\n public getExtraConfig(): Record<string, any> | undefined {\n return this.config.extraConfig;\n }\n\n // Public authentication methods\n public async isAuthenticated(): Promise<boolean> {\n const token = await this.authManager.getAccessToken();\n return token !== null;\n }\n\n public async authenticate(): Promise<boolean> {\n return await this.authManager.initialize();\n }\n\n public async logout(): Promise<void> {\n await this.authManager.logout();\n }\n\n // Send journey data for AI analysis\n private async sendJourneyForAnalysis() {\n try {\n const journeyData = this.journeyTracker.getJourneyForAnalysis();\n const endpoint = `${this.config.endpoint}/api/v1/journeys/analyze`;\n\n // Get authentication headers\n const authHeaders = await this.authManager.getAuthHeaders();\n\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...authHeaders\n },\n body: JSON.stringify({\n client_id: this.config.clientId,\n user_id: this.userManager.getUserId(),\n session_id: this.sessionId,\n journey: journeyData\n })\n });\n\n if (!response.ok) {\n console.error('[AInamika SDK] Failed to send journey for analysis:', response.statusText);\n }\n } catch (error) {\n console.error('[AInamika SDK] Error sending journey for analysis:', error);\n }\n }\n\n private log(message: string, data?: any) {\n if (this.config.debug) {\n console.log(`[AnalyticsPro SDK] ${message}`, data || '');\n }\n }\n\n// Load config from /AInamika_config.json in the project root (fallback)\nprivate async loadConfigFromFile(): Promise<any | null> {\n try {\n const response = await fetch('/AInamika_config.json', { cache: 'reload' });\n if (!response.ok) {\n return null;\n }\n const config = await response.json();\n return config;\n } catch (err) {\n return null;\n }\n}\n\n// --- Dynamic DOM Fingerprinting and Smart Debouncing ---\nprivate async setupDynamicDomTracking() {\n // Use MutationObserver to watch for DOM changes\n if ('MutationObserver' in window) {\n const observer = new MutationObserver(() => {\n if (this.mutationDebounceTimer) {\n clearTimeout(this.mutationDebounceTimer);\n }\n this.mutationDebounceTimer = window.setTimeout(() => {\n this.handleDomMutation();\n }, this.mutationDebounceMs);\n });\n observer.observe(document.body, { childList: true, subtree: true, attributes: true });\n this.log('Dynamic DOM MutationObserver attached');\n }\n}\n\nprivate computeDomHash(structure: any): string {\n // Simple hash: JSON.stringify, then a basic hash (FNV-1a or similar)\n const str = JSON.stringify(structure);\n let hash = 2166136261;\n for (let i = 0; i < str.length; i++) {\n hash ^= str.charCodeAt(i);\n hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);\n }\n return (hash >>> 0).toString(16);\n}\n\n/**\n * Generates a stable fingerprint for an element based on stable attributes.\n * This fingerprint is used to ensure consistent event naming across all users.\n *\n * Priority order for fingerprint generation:\n * 1. data-testid, data-track, data-analytics (explicit tracking attributes)\n * 2. id (if unique and stable)\n * 3. name attribute (for form elements)\n * 4. aria-label (accessibility attribute)\n * 5. Combination of tag + text + stable parent context\n */\nprivate generateElementFingerprint(el: Element): string {\n const factors: string[] = [];\n\n // Priority 1: Explicit tracking attributes (most stable)\n const dataTestId = el.getAttribute('data-testid');\n const dataTrack = el.getAttribute('data-track');\n const dataAnalytics = el.getAttribute('data-analytics');\n\n if (dataTestId) factors.push(`testid:${dataTestId}`);\n if (dataTrack) factors.push(`track:${dataTrack}`);\n if (dataAnalytics) factors.push(`analytics:${dataAnalytics}`);\n\n // Priority 2: ID (if not dynamically generated)\n const id = el.id;\n if (id && !id.match(/^(jsc|css|ember|react|ng)-|^\\d+$|^[a-f0-9]{8,}$/i)) {\n factors.push(`id:${id}`);\n }\n\n // Priority 3: Name attribute (for forms)\n const name = el.getAttribute('name');\n if (name) factors.push(`name:${name}`);\n\n // Priority 4: Aria-label\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) factors.push(`aria:${ariaLabel.substring(0, 50)}`);\n\n // Priority 5: Element type + role\n const tag = el.tagName.toLowerCase();\n const role = el.getAttribute('role');\n const type = el.getAttribute('type');\n factors.push(`tag:${tag}`);\n if (role) factors.push(`role:${role}`);\n if (type) factors.push(`type:${type}`);\n\n // Priority 6: Text content (truncated, for buttons/links)\n if (['button', 'a', 'span', 'div'].includes(tag)) {\n const text = (el.textContent || '').trim().substring(0, 30).toLowerCase().replace(/\\s+/g, '_');\n if (text) factors.push(`text:${text}`);\n }\n\n // Priority 7: Customdata attribute (common in apps)\n const customdata = el.getAttribute('customdata');\n if (customdata) {\n try {\n const parsed = JSON.parse(customdata);\n if (parsed.name) factors.push(`customname:${parsed.name}`);\n if (parsed.id) factors.push(`customid:${parsed.id}`);\n } catch {\n // If not valid JSON, use first 30 chars\n factors.push(`customdata:${customdata.substring(0, 30)}`);\n }\n }\n\n // Priority 8: Stable parent context\n const parent = el.closest('[data-testid], [id]:not([id^=\"jsc-\"]):not([id^=\"css-\"])');\n if (parent && parent !== el) {\n const parentId = parent.getAttribute('data-testid') || parent.id;\n if (parentId) factors.push(`parent:${parentId}`);\n }\n\n // Priority 9: Stable class names (exclude dynamic/generated ones)\n if (el.className && typeof el.className === 'string') {\n const stableClasses = el.className.split(' ')\n .filter(c => c.trim() && !c.match(/^(jsc|css|ember|react|ng|active|hover|focus|selected|open|closed)-|^[a-f0-9]{6,}$/i))\n .slice(0, 3)\n .join('.');\n if (stableClasses) factors.push(`class:${stableClasses}`);\n }\n\n // Generate hash from factors\n const factorString = factors.join('|');\n return this.hashString(factorString);\n}\n\n/**\n * Simple hash function for fingerprinting (MD5-like, but faster)\n */\nprivate hashString(str: string): string {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n // Convert to hex and ensure 8 characters\n const hexHash = Math.abs(hash).toString(16).padStart(8, '0');\n return hexHash.substring(0, 16); // 16 char fingerprint\n}\n\nprivate readonly MAX_CACHED_CONFIGS = 15;\n\n// Get last-known config for INSTANT tracking (not keyed by domHash)\n// This allows zero-delay tracking for returning users\nprivate getLastKnownConfig(): any | null {\n try {\n const stored = localStorage.getItem('ainamika_last_known_config');\n if (!stored) return null;\n\n const data = JSON.parse(stored);\n // Validate it has events\n if (data && data.events_to_track && data.events_to_track.length > 0) {\n return data;\n }\n return null;\n } catch {\n return null;\n }\n}\n\n// Save config as last-known for instant loading on next visit\nprivate setLastKnownConfig(config: any): void {\n try {\n if (config && config.events_to_track && config.events_to_track.length > 0) {\n localStorage.setItem('ainamika_last_known_config', JSON.stringify(config));\n }\n } catch {\n // Ignore storage errors\n }\n}\n\nprivate getCachedConfigForDomHash(domHash: string): any | null {\n try {\n const cache = JSON.parse(localStorage.getItem('ainamika_dom_config_cache') || '{}');\n const entry = cache[domHash];\n\n if (entry) {\n // Handle backward compatibility: old format stored config directly\n if (entry.events_to_track) {\n // Old format - migrate to new format\n cache[domHash] = {\n config: entry,\n lastAccessed: Date.now(),\n createdAt: Date.now()\n };\n localStorage.setItem('ainamika_dom_config_cache', JSON.stringify(cache));\n return entry;\n }\n\n // New format with wrapper\n entry.lastAccessed = Date.now();\n localStorage.setItem('ainamika_dom_config_cache', JSON.stringify(cache));\n return entry.config;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nprivate setCachedConfigForDomHash(domHash: string, config: any) {\n try {\n const cache = JSON.parse(localStorage.getItem('ainamika_dom_config_cache') || '{}');\n\n // Add new entry with timestamp\n cache[domHash] = {\n config: config,\n lastAccessed: Date.now(),\n createdAt: Date.now()\n };\n\n // Check if we exceed the limit\n const keys = Object.keys(cache);\n if (keys.length > this.MAX_CACHED_CONFIGS) {\n // Sort by lastAccessed (oldest first) and remove excess\n const sortedKeys = keys.sort((a, b) => {\n const aTime = cache[a].lastAccessed || cache[a].createdAt || 0;\n const bTime = cache[b].lastAccessed || cache[b].createdAt || 0;\n return aTime - bTime;\n });\n\n // Remove oldest entries until we're at the limit\n const keysToRemove = sortedKeys.slice(0, keys.length - this.MAX_CACHED_CONFIGS);\n keysToRemove.forEach(key => {\n delete cache[key];\n this.log(`Evicted old config cache: ${key}`);\n });\n }\n\n localStorage.setItem('ainamika_dom_config_cache', JSON.stringify(cache));\n } catch (e) {\n // If localStorage is full, clear old entries and retry\n this.log('Cache storage error, clearing old entries:', e);\n this.clearOldConfigCache();\n }\n}\n\nprivate clearOldConfigCache() {\n try {\n const cache = JSON.parse(localStorage.getItem('ainamika_dom_config_cache') || '{}');\n const keys = Object.keys(cache);\n\n if (keys.length === 0) return;\n\n // Keep only the 5 most recent configs\n const sortedKeys = keys.sort((a, b) => {\n const aTime = cache[a].lastAccessed || cache[a].createdAt || 0;\n const bTime = cache[b].lastAccessed || cache[b].createdAt || 0;\n return bTime - aTime; // Newest first\n });\n\n const newCache: Record<string, any> = {};\n sortedKeys.slice(0, 5).forEach(key => {\n newCache[key] = cache[key];\n });\n\n localStorage.setItem('ainamika_dom_config_cache', JSON.stringify(newCache));\n this.log(`Cleared config cache, kept ${Object.keys(newCache).length} entries`);\n } catch {\n // Last resort: clear everything\n localStorage.removeItem('ainamika_dom_config_cache');\n }\n}\n\nprivate async handleDomMutation() {\n const domStructure = await this.getDOMStructure();\n const domHash = this.computeDomHash(domStructure);\n\n if (domHash === this.lastDomHash) {\n this.log('DOM hash unchanged after mutation, skipping config fetch.');\n return;\n }\n\n this.log('DOM hash changed, detecting new elements...', { oldHash: this.lastDomHash, newHash: domHash });\n this.lastDomHash = domHash;\n\n // Filter to only NEW elements that we haven't seen before\n const allElements = domStructure.elements || [];\n const newElements = allElements.filter((el: any) => {\n const selector = el.selector || '';\n if (!selector || this.knownElementSelectors.has(selector)) {\n return false;\n }\n return true;\n });\n\n // If no new elements, just apply cached config if available\n if (newElements.length === 0) {\n this.log('No new elements detected, skipping config fetch.');\n return;\n }\n\n this.log(`Found ${newElements.length} new elements out of ${allElements.length} total`);\n\n // Check if we have a cached config for this exact DOM state\n const cachedConfig = this.getCachedConfigForDomHash(domHash);\n if (cachedConfig) {\n this.log('Reusing cached config for DOM hash', domHash);\n this.mergeAndApplyConfig(cachedConfig);\n // Mark all elements as known\n allElements.forEach((el: any) => {\n if (el.selector) this.knownElementSelectors.add(el.selector);\n });\n return;\n }\n\n // Send ONLY new elements to server for config generation\n const newDomStructure = { elements: newElements };\n this.log('Fetching config for new elements only:', newElements.length);\n\n const config = await this.fetchGeneratedConfig(newDomStructure, domHash);\n if (config && config.events_to_track) {\n // Merge new config with existing config\n this.mergeAndApplyConfig(config);\n\n // Cache the merged config\n this.setCachedConfigForDomHash(domHash, this.mergedConfig);\n this.lastConfigHash = config.config_hash || '';\n\n // Mark new elements as known\n newElements.forEach((el: any) => {\n if (el.selector) this.knownElementSelectors.add(el.selector);\n });\n\n this.log('Fetched and merged config for new elements', {\n newEvents: config.events_to_track.length,\n totalEvents: this.mergedConfig.events_to_track.length\n });\n } else {\n this.log('No valid config returned for new elements');\n }\n}\n\n/**\n * Reset view tracking - call this when navigating to a new page (for SPAs)\n * This allows elements to be tracked again on the new \"page\"\n */\npublic resetViewTracking(): void {\n // Clear viewed elements set\n this.viewedElements.clear();\n\n // Disconnect all view observers\n this.viewObservers.forEach((observer, key) => {\n observer.disconnect();\n });\n this.viewObservers.clear();\n\n this.log('View tracking reset - elements can be tracked again');\n}\n\n/**\n * Cleanup all SDK resources - call this when unmounting/destroying the SDK\n */\npublic destroy(): void {\n // Disconnect all view observers\n this.viewObservers.forEach((observer) => {\n observer.disconnect();\n });\n this.viewObservers.clear();\n this.viewedElements.clear();\n\n // Clear event queue\n this.eventQueue = [];\n\n // Stop batch timer\n if (this.batchTimer) {\n clearInterval(this.batchTimer);\n this.batchTimer = undefined;\n }\n\n // Terminate web worker\n if (this.worker) {\n this.worker.terminate();\n }\n\n this.log('SDK destroyed and all resources cleaned up');\n}\n\n/**\n * Flush pending events immediately (e.g., before page unload)\n */\npublic flush(): void {\n if (this.config.useWebWorker && this.worker) {\n this.worker.postMessage({ type: 'flush' });\n } else {\n this.flushQueue();\n }\n this.log('Flush requested');\n}\n\nprivate mergeAndApplyConfig(newConfig: { events_to_track: any[], tracking_config?: any }) {\n if (!newConfig || !newConfig.events_to_track) return;\n\n // Create a map of existing events by selector to avoid duplicates\n const existingSelectors = new Set(\n this.mergedConfig.events_to_track.map(e => e.element_selector)\n );\n\n // Add only new events that don't already exist\n const newEvents = newConfig.events_to_track.filter(\n event => !existingSelectors.has(event.element_selector)\n );\n\n if (newEvents.length > 0) {\n this.mergedConfig.events_to_track.push(...newEvents);\n this.log(`Merged ${newEvents.length} new events, total: ${this.mergedConfig.events_to_track.length}`);\n }\n\n // Merge tracking config\n if (newConfig.tracking_config) {\n this.mergedConfig.tracking_config = {\n ...this.mergedConfig.tracking_config,\n ...newConfig.tracking_config\n };\n }\n\n // Apply only the new events (existing ones already have listeners)\n if (newEvents.length > 0) {\n this.applyGeneratedConfig({ events_to_track: newEvents, tracking_config: newConfig.tracking_config });\n }\n}\n}\n\n// Make AnalyticsProSDK available globally for both classic and module scripts\nif (typeof window !== 'undefined') {\n (window as any).AInamikaSDKPro = AInamikaSDKPro;\n}\n\nexport default AInamikaSDKPro;\nexport { AInamikaSDKPro };\n\n// Export types for TypeScript users\nexport type { PerformanceMetrics, EngagementMetrics } from './advanced-tracker';\nexport { enrichEventWithCustomdata } from './advanced-tracker';"],"names":["root","factory","exports","module","define","amd","self","window","global","this","__webpack_require__","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","config","breadcrumbs","errorCount","errorDebounceMap","Map","html2canvasLoaded","html2canvasLoading","isCapturingScreenshot","captureScreenshots","captureDomSnapshots","maxStackTraceDepth","maxErrorsPerSession","debounceMs","enableNetworkTracking","enableConsoleCapture","authManager","sessionId","generateSessionId","originalConsole","console","initialize","loadHtml2Canvas","html2canvas","Promise","resolve","script","document","createElement","src","async","onload","log","onerror","error","head","appendChild","addEventListener","event","handleError","type","message","filename","line","lineno","column","colno","reason","promise","setupNetworkTracking","setupConsoleCapture","setupNavigationTracking","setupClickTracking","Date","now","Math","random","toString","substr","addBreadcrumb","breadcrumb","push","timestamp","length","slice","errorInfo","warn","errorKey","has","set","captureError","errorData","client_id","clientId","project_key","projectKey","error_type","stack_trace","extractStackTrace","url","location","href","user_agent","navigator","userAgent","error_metadata","userId","networkInfo","getNetworkInfo","performance","getPerformanceInfo","deviceInfo","getDeviceInfo","severity","assessSeverity","session_id","user_id","captureScreenshot","screen_snapshot","sendError","data","stack","split","maxDepth","join","toLowerCase","includes","captureDomSnapshot","snapshot","title","viewport","width","innerWidth","height","innerHeight","elements","extractDomElements","JSON","stringify","forEach","selector","els","querySelectorAll","Array","from","el","tagName","id","className","textContent","substring","attributes","getElementAttributes","e","element","attrs","attr","value","getAttribute","body","min","useCORS","logging","toDataURL","connection","mozConnection","webkitConnection","effectiveType","downlink","rtt","saveData","info","memory","usedJSHeapSize","totalJSHeapSize","jsHeapSizeLimit","timing","domContentLoaded","domContentLoadedEventEnd","navigationStart","load","loadEventEnd","getEntriesByType","entry","name","firstPaint","startTime","firstContentfulPaint","ua","deviceType","test","os","osVersion","match","replace","browser","browserVersion","screenWidth","screen","screenHeight","language","timezone","Intl","DateTimeFormat","resolvedOptions","timeZone","originalFetch","fetch","args","Request","String","response","status","duration","ok","statusText","originalXHROpen","XMLHttpRequest","open","originalXHRSend","send","method","username","password","_errorTracker","tracker","dispatchEvent","CustomEvent","detail","original","map","arg","consoleMethod","level","currentUrl","trackNavigation","newUrl","to","originalPushState","history","pushState","originalReplaceState","replaceState","apply","setTimeout","target","getElementSelector","text","trim","classes","filter","c","headers","getAuthHeaders","authHeaders","apiKey","endpoint","Error","storeErrorLocally","stored","localStorage","getItem","errors","parse","splice","setItem","captureException","context","setUser","addTag","flushStoredErrors","removeItem","STORAGE_KEY","METADATA_KEY","isProcessing","maxStorageSize","maxRetries","retryInterval","compressionEnabled","encryptionEnabled","cleanupOldErrors","startRetryTimer","setupStorageListener","processQueue","storeError","errorId","generateErrorId","storedError","compressData","retryCount","addToQueue","updateMetadata","getStoredErrors","decompressData","removeError","getQueueRaw","filteredErrors","clearAll","getStorageStats","totalSize","Blob","size","timestamps","sort","oldestError","newestError","lastRetry","incrementRetryCount","retryError","find","serialized","shift","errorIndex","findIndex","jsonString","btoa","compressedData","atob","cleanErrors","retryTimer","setInterval","stats","metadata","lastUpdate","exportErrors","exportData","version","importErrors","isArray","destroy","clearInterval","undefined","getAinamikaStorageUsage","errorSize","otherSize","startsWith","checkStorageSpace","requiredBytes","testKey","testData","repeat","cleanupAllAinamikaStorage","keysToRemove","generateStorageReport","storage","ErrorStorage","usage","ErrorStorageUtils","ENV_CONFIG","__AINAMIKA_CONFIG__","API_BASE_URL","APP_ENV","DEBUG","userProperties","initializeUser","getOrCreateUserId","generateAnonymousId","getUserId","getUserProperties","identifyUser","authenticatedUserId","properties","previousId","updateUserProperties","clearUser","getUserIdentificationEvent","previous_id","isAnonymousUser","getUserType","userJourney","lastEventTime","sequenceIndex","maxJourneyLength","journeyAnalysisThreshold","journeyStartTime","trackEvent","eventName","currentTime","timeSinceLastEvent","journeyEvent","journeyPosition","getContext","journeySequence","getJourneySequence","eventCount","getJourneyData","shouldAnalyzeJourney","getJourneyForAnalysis","journeyDuration","avgTimeBetweenEvents","calculateAverageTimeBetweenEvents","journey","journeyLength","endTime","totalTime","i","round","findPatterns","patterns","sequence","fromEntries","entries","clearJourney","getJourneySegment","count","detectPotentialFunnel","recentEvents","funnelName","apiEndpoint","debug","accessToken","refreshToken","tokenExpiry","loadTokens","isTokenValid","debugLog","refreshAccessToken","requestTokens","tokens","setTokens","json","refresh_token","clearTokens","getAccessToken","shouldRefreshToken","token","access_token","expires_in","saveTokens","scheduleTokenRefresh","refreshTimer","clearTimeout","refreshIn","max","tokenData","AuthManager","cleanupLegacyTokens","logout","onEvent","performanceMetrics","scrollDepthReached","Set","clickHistory","isPageVisible","visibilityChangeCount","trackPerformance","trackEngagement","trackScrollDepth","trackRageClicks","trackTimeOnPage","trackAPIResponses","scrollDepthThresholds","rageClickThreshold","rageClickWindow","apiTrackingPatterns","pageStartTime","lastActivityTime","bind","originalXHR","engagementMetrics","timeOnPage","scrollDepth","scrollDepthMilestones","rageClicks","totalClicks","activeTime","idleTime","pageVisibilityChanges","initPerformanceTracking","initEngagementTracking","initScrollTracking","initRageClickTracking","initTimeTracking","initAPITracking","trackPageExit","PerformanceObserver","entryList","getEntries","lastEntry","lcp","observe","buffered","firstEntry","fid","processingStart","eventType","hadRecentInput","cls","visibilityState","fcpEntry","fcp","ttfb","responseStart","pageLoad","resources","resourceCount","transferSize","reduce","acc","r","transferSizeKB","updateActiveTime","passive","ticking","updateScrollDepth","scrollTop","scrollY","documentElement","docHeight","scrollHeight","scrollPercent","threshold","add","depth","timeToReach","requestAnimationFrame","time","clickCount","position","x","clientX","y","clientY","totalRageClicks","timeSinceLastActivity","shouldTrackAPI","trackAPICall","success","some","pattern","RegExp","trackAPI","responseType","responseKeys","keys","hasData","dataCount","action","trackConversion","goalName","goal","timeToConvert","scrollDepthAtConversion","clicksBeforeConversion","getPerformanceMetrics","getEngagementMetrics","scrollMilestones","visibilityChanges","eventQueue","isInitialized","batchRetryCount","maxBatchRetries","lastDomHash","lastConfigHash","mutationDebounceTimer","mutationDebounceMs","attachedListeners","WeakMap","knownElementSelectors","handledClicks","CLICK_DEDUP_WINDOW_MS","viewedElements","viewObservers","mergedConfig","events_to_track","MAX_CACHED_CONFIGS","batchInterval","useWebWorker","errorTracking","enabled","advancedTracking","userIdentifier","getOrCreateUserIdentifier","userManager","UserManager","journeyTracker","JourneyTracker","blob","workerUrl","URL","createObjectURL","worker","Worker","initializeProjectSettings","initializeSamplingDecision","projectSettings","samplingDecision","shouldSampleErrors","initializeErrorTracking","initializeAdvancedTracking","autoConfig","setupAutoConfiguration","setupDynamicDomTracking","setupWebWorker","startBatchTimer","sampling","storageKey","identifier","user_identifier","cacheSamplingDecision","loadCachedSamplingDecision","cacheData","AInamikaSDKPro","SAMPLING_STORAGE_KEY","cleanupLegacySamplingKeys","cached","getDefaultSamplingDecision","samplingData","should_sample","events","session_replay","rates","decision","shouldSampleEvents","shouldSampleSessionReplay","getSamplingStatus","getProjectInfo","getTrackingStatus","totalEvents","knownSelectors","resetDomTracking","clear","clearAllCaches","clearUserIdentifier","getCacheStats","cache","domHashes","domConfigCacheSize","cachedDomHashes","hasSamplingCache","hasUserIdentifier","hasLastKnownConfig","errorStorage","errorConfig","errorTracker","ErrorTracker","advConfig","advancedTracker","AdvancedTracker","sendToWorker","track","appliedFromCache","lastKnownConfig","getLastKnownConfig","eventsCount","tracking_config","applyGeneratedConfig","postMessage","setupAutoConfigurationBackground","alreadyAppliedCache","getDOMStructure","domStructure","domHash","computeDomHash","cachedConfig","getCachedConfigForDomHash","loadConfigFromFile","fileConfig","fetchAndMergeFreshConfig","hadCachedConfig","fetchGeneratedConfig","freshConfig","element_selector","newEvents","setCachedConfigForDomHash","config_hash","setLastKnownConfig","getSelector","escapedId","filteredElements","style","getComputedStyle","isVisible","display","visibility","opacity","hasInteraction","hasAttribute","classList","contains","isImportantElement","indexOf","seen","structure","stableAttributes","fingerprint","generateElementFingerprint","isInteractive","hasChildren","children","childCount","parentTagName","parentElement","index","elementCount","requestBody","transformEventNameForType","replacements","endsWith","sanitizeSelector","idPart","eventToTrack","sanitizedSelector","metadata_rules","extract_customdata","extract_text","eventSet","event_type","clickTimestamp","isGenericEvent","event_name","isGenericSelector","ts","abs","elementData","extractElementData","cutoff","delete","category","itemName","section","toISOString","elementIndex","elementId","IntersectionObserver","isIntersecting","intersectionRatio","viewEventName","unobserve","transformedEventName","observe_mutations","MutationObserver","mutations","mutation","outerHTML","childList","subtree","metadataRules","rect","getBoundingClientRect","baseData","enrichedData","customdata","dataset","parsed","displayedTitle","itemId","nameMatch","titleMatch","idParts","namePart","displayText","enrichEventWithCustomdata","enriched","commonData","getCommonEventData","eventData","getTime","created_at","project_id","payload","apiUrl","apiDetails","apiEndPoint","batchSize","workerConfig","onmessage","failedEvents","unshift","journeyContext","userType","sendJourneyForAnalysis","batchTimer","flushQueue","batch","sendBatchWithRetry","sendBatch","getPageContext","path","pathname","hash","referrer","queryParams","URLSearchParams","search","pageContext","extraConfig","identificationEvent","setExtraConfig","merge","getExtraConfig","isAuthenticated","authenticate","journeyData","handleDomMutation","str","charCodeAt","factors","dataTestId","dataTrack","dataAnalytics","ariaLabel","tag","role","parent","closest","parentId","stableClasses","factorString","hashString","padStart","lastAccessed","createdAt","a","b","clearOldConfigCache","sortedKeys","aTime","oldHash","newHash","allElements","newElements","mergeAndApplyConfig","newDomStructure","resetViewTracking","observer","disconnect","terminate","flush","newConfig","existingSelectors"],"sourceRoot":""}
|