@active-reach/web-sdk 1.0.0

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.
Files changed (80) hide show
  1. package/README.md +576 -0
  2. package/dist/aegis-sw.js +1 -0
  3. package/dist/aegis.min.js +2 -0
  4. package/dist/aegis.min.js.map +1 -0
  5. package/dist/analytics-B11keZ55.mjs +1854 -0
  6. package/dist/analytics-B11keZ55.mjs.map +1 -0
  7. package/dist/cdn.d.ts +18 -0
  8. package/dist/cdn.d.ts.map +1 -0
  9. package/dist/core/analytics.d.ts +47 -0
  10. package/dist/core/analytics.d.ts.map +1 -0
  11. package/dist/core/queue.d.ts +35 -0
  12. package/dist/core/queue.d.ts.map +1 -0
  13. package/dist/core/sdk-config-poller.d.ts +59 -0
  14. package/dist/core/sdk-config-poller.d.ts.map +1 -0
  15. package/dist/core/session.d.ts +41 -0
  16. package/dist/core/session.d.ts.map +1 -0
  17. package/dist/core/transport.d.ts +50 -0
  18. package/dist/core/transport.d.ts.map +1 -0
  19. package/dist/inapp/AegisInAppManager.d.ts +126 -0
  20. package/dist/inapp/AegisInAppManager.d.ts.map +1 -0
  21. package/dist/inapp/index.d.ts +4 -0
  22. package/dist/inapp/index.d.ts.map +1 -0
  23. package/dist/inapp/renderPreview.d.ts +25 -0
  24. package/dist/inapp/renderPreview.d.ts.map +1 -0
  25. package/dist/index.d.ts +23 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +4296 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/integrations/react.d.ts +19 -0
  30. package/dist/integrations/react.d.ts.map +1 -0
  31. package/dist/placements/AegisPlacementManager.d.ts +88 -0
  32. package/dist/placements/AegisPlacementManager.d.ts.map +1 -0
  33. package/dist/plugins/registry.d.ts +13 -0
  34. package/dist/plugins/registry.d.ts.map +1 -0
  35. package/dist/push/AegisWebPush.d.ts +51 -0
  36. package/dist/push/AegisWebPush.d.ts.map +1 -0
  37. package/dist/push/AegisWebPush.js +203 -0
  38. package/dist/push/AegisWebPush.js.map +1 -0
  39. package/dist/react.js +70 -0
  40. package/dist/react.js.map +1 -0
  41. package/dist/snippet.min.js +1 -0
  42. package/dist/triggers/TriggerEngine.d.ts +114 -0
  43. package/dist/triggers/TriggerEngine.d.ts.map +1 -0
  44. package/dist/triggers/index.d.ts +3 -0
  45. package/dist/triggers/index.d.ts.map +1 -0
  46. package/dist/types/config.d.ts +73 -0
  47. package/dist/types/config.d.ts.map +1 -0
  48. package/dist/types/events.d.ts +127 -0
  49. package/dist/types/events.d.ts.map +1 -0
  50. package/dist/types/index.d.ts +5 -0
  51. package/dist/types/index.d.ts.map +1 -0
  52. package/dist/types/plugin.d.ts +21 -0
  53. package/dist/types/plugin.d.ts.map +1 -0
  54. package/dist/types/type-safe-events.d.ts +14 -0
  55. package/dist/types/type-safe-events.d.ts.map +1 -0
  56. package/dist/utils/canonical-identity.d.ts +29 -0
  57. package/dist/utils/canonical-identity.d.ts.map +1 -0
  58. package/dist/utils/consent.d.ts +40 -0
  59. package/dist/utils/consent.d.ts.map +1 -0
  60. package/dist/utils/debounce.d.ts +3 -0
  61. package/dist/utils/debounce.d.ts.map +1 -0
  62. package/dist/utils/device.d.ts +6 -0
  63. package/dist/utils/device.d.ts.map +1 -0
  64. package/dist/utils/identity.d.ts +27 -0
  65. package/dist/utils/identity.d.ts.map +1 -0
  66. package/dist/utils/index.d.ts +7 -0
  67. package/dist/utils/index.d.ts.map +1 -0
  68. package/dist/utils/logger.d.ts +15 -0
  69. package/dist/utils/logger.d.ts.map +1 -0
  70. package/dist/utils/storage.d.ts +20 -0
  71. package/dist/utils/storage.d.ts.map +1 -0
  72. package/dist/utils/url-parser.d.ts +23 -0
  73. package/dist/utils/url-parser.d.ts.map +1 -0
  74. package/dist/utils/uuid.d.ts +4 -0
  75. package/dist/utils/uuid.d.ts.map +1 -0
  76. package/dist/widgets/AegisWidgetManager.d.ts +194 -0
  77. package/dist/widgets/AegisWidgetManager.d.ts.map +1 -0
  78. package/dist/widgets/index.d.ts +3 -0
  79. package/dist/widgets/index.d.ts.map +1 -0
  80. package/package.json +73 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aegis.min.js","sources":["../src/types/config.ts","../src/utils/uuid.ts","../src/utils/logger.ts","../src/utils/identity.ts","../src/core/session.ts","../src/core/queue.ts","../src/core/transport.ts","../src/utils/storage.ts","../src/utils/device.ts","../src/utils/url-parser.ts","../src/plugins/registry.ts","../src/utils/consent.ts","../src/core/analytics.ts","../src/cdn.ts","../src/inapp/AegisInAppManager.ts","../src/placements/AegisPlacementManager.ts","../src/widgets/AegisWidgetManager.ts","../src/triggers/TriggerEngine.ts"],"sourcesContent":["export type CellRegion = 'us-east' | 'us-west' | 'eu-central' | 'ap-south' | 'ap-southeast';\n\nexport interface CellEndpoint {\n region: CellRegion;\n url: string;\n priority: number;\n healthy: boolean;\n}\n\nexport interface AegisConfig {\n write_key: string;\n\n workspace_id?: string;\n \n api_host?: string;\n \n cell_endpoints?: CellEndpoint[];\n \n preferred_region?: CellRegion;\n \n auto_region_detection?: boolean;\n \n batch_size?: number;\n \n batch_interval?: number;\n \n capture_utm?: boolean;\n \n capture_referrer?: boolean;\n \n auto_page_view?: boolean;\n \n session_timeout?: number;\n \n debug?: boolean;\n \n respect_dnt?: boolean;\n \n cross_domain_tracking?: boolean;\n \n cookie_domain?: string;\n \n secure_cookie?: boolean;\n \n enable_offline_mode?: boolean;\n \n max_offline_events?: number;\n \n retry_failed_requests?: boolean;\n \n max_retries?: number;\n \n retry_backoff_multiplier?: number;\n \n request_timeout?: number;\n \n plugins?: string[];\n\n wait_for_consent?: boolean;\n\n default_consent?: {\n analytics?: boolean;\n marketing?: boolean;\n functional?: boolean;\n };\n\n enable_consent_mode?: boolean;\n\n integrate_onetrust?: boolean;\n\n integrate_cookiebot?: boolean;\n\n integrate_google_consent_mode?: boolean;\n\n /** Push notification configuration. When provided, AegisWebPush is initialized. */\n push?: {\n /** VAPID public key for Web Push subscription. */\n vapidPublicKey: string;\n /** Automatically prompt for push permission after SDK init. Default: false. */\n autoPrompt?: boolean;\n /** Delay in ms before showing auto-prompt. Default: 5000. */\n promptDelay?: number;\n /** Path to the service worker file. Default: '/aegis-sw.js'. */\n serviceWorkerPath?: string;\n /** Scope for the service worker registration. Default: '/'. Critical for e-commerce platforms. */\n serviceWorkerScope?: string;\n };\n}\n\nexport interface AegisConfigInternal extends Required<Omit<AegisConfig, 'api_host' | 'cell_endpoints' | 'preferred_region' | 'cookie_domain' | 'plugins' | 'default_consent' | 'workspace_id'>> {\n initialized: boolean;\n workspace_id: string | null;\n api_host: string | null;\n cell_endpoints: CellEndpoint[];\n preferred_region: CellRegion | null;\n cookie_domain: string | null;\n plugins: string[];\n active_cell: CellEndpoint | null;\n default_consent: {\n analytics: boolean;\n marketing: boolean;\n functional: boolean;\n };\n}\n\nexport const DEFAULT_CONFIG: Partial<AegisConfigInternal> = {\n workspace_id: null,\n batch_size: 10,\n batch_interval: 1000,\n capture_utm: true,\n capture_referrer: true,\n auto_page_view: false,\n session_timeout: 30,\n debug: false,\n respect_dnt: true,\n cross_domain_tracking: false,\n secure_cookie: true,\n enable_offline_mode: true,\n max_offline_events: 100,\n retry_failed_requests: true,\n max_retries: 3,\n retry_backoff_multiplier: 2,\n request_timeout: 5000,\n auto_region_detection: true,\n wait_for_consent: false,\n enable_consent_mode: false,\n integrate_onetrust: false,\n integrate_cookiebot: false,\n integrate_google_consent_mode: false,\n default_consent: {\n analytics: false,\n marketing: false,\n functional: true,\n },\n initialized: false,\n api_host: null,\n cell_endpoints: [],\n preferred_region: null,\n cookie_domain: null,\n plugins: [],\n active_cell: null,\n};\n","export function generateUUID(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nexport function generateSessionId(): string {\n return `sess_${Date.now()}_${generateUUID().slice(0, 8)}`;\n}\n\nexport function generateMessageId(): string {\n return `msg_${Date.now()}_${generateUUID().slice(0, 8)}`;\n}\n","export type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nclass Logger {\n private enabled: boolean = false;\n private prefix: string = '[Aegis SDK]';\n\n enable(): void {\n this.enabled = true;\n }\n\n disable(): void {\n this.enabled = false;\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n debug(message: string, ...args: any[]): void {\n if (!this.enabled) return;\n console.debug(`${this.prefix} ${message}`, ...args);\n }\n\n info(message: string, ...args: any[]): void {\n if (!this.enabled) return;\n console.info(`${this.prefix} ${message}`, ...args);\n }\n\n warn(message: string, ...args: any[]): void {\n console.warn(`${this.prefix} ${message}`, ...args);\n }\n\n error(message: string, ...args: any[]): void {\n console.error(`${this.prefix} ${message}`, ...args);\n }\n}\n\nexport const logger = new Logger();\n","import { generateUUID } from './uuid';\nimport { Storage } from './storage';\nimport { logger } from './logger';\n\nexport interface IdentityState {\n anonymousId: string;\n userId: string | null;\n traits: Record<string, any>;\n}\n\nexport class Identity {\n private storage: Storage;\n private anonymousId: string;\n private userId: string | null = null;\n private traits: Record<string, any> = {};\n\n constructor(storage: Storage) {\n this.storage = storage;\n this.anonymousId = this.getOrCreateAnonymousId();\n this.loadUserIdentity();\n }\n\n private getOrCreateAnonymousId(): string {\n let id = this.storage.get('anon_id');\n\n if (!id) {\n id = generateUUID();\n this.storage.set('anon_id', id, 365);\n logger.debug('Created new anonymous ID:', id);\n } else {\n logger.debug('Loaded existing anonymous ID:', id);\n }\n\n return id;\n }\n\n private loadUserIdentity(): void {\n const storedUserId = this.storage.get('user_id');\n const storedTraits = this.storage.get('user_traits');\n\n if (storedUserId) {\n this.userId = storedUserId;\n logger.debug('Loaded user ID:', storedUserId);\n }\n\n if (storedTraits) {\n try {\n this.traits = JSON.parse(storedTraits);\n logger.debug('Loaded user traits:', this.traits);\n } catch (error) {\n logger.warn('Failed to parse stored traits:', error);\n this.traits = {};\n }\n }\n }\n\n getAnonymousId(): string {\n return this.anonymousId;\n }\n\n setUserId(userId: string, traits?: Record<string, any>): void {\n this.userId = userId;\n this.storage.set('user_id', userId, 365);\n logger.info('User identified:', userId);\n\n if (traits) {\n this.setTraits(traits);\n }\n }\n\n getUserId(): string | null {\n return this.userId;\n }\n\n setTraits(traits: Record<string, any>): void {\n this.traits = { ...this.traits, ...traits };\n this.storage.set('user_traits', JSON.stringify(this.traits), 365);\n logger.debug('User traits updated:', this.traits);\n }\n\n getTraits(): Record<string, any> {\n return { ...this.traits };\n }\n\n reset(): void {\n this.userId = null;\n this.traits = {};\n this.anonymousId = generateUUID();\n\n this.storage.remove('user_id');\n this.storage.remove('user_traits');\n this.storage.set('anon_id', this.anonymousId, 365);\n\n logger.info('Identity reset, new anonymous ID:', this.anonymousId);\n }\n\n alias(newUserId: string): { previousId: string; newUserId: string } {\n const previousId = this.userId || this.anonymousId;\n\n this.setUserId(newUserId);\n\n logger.info('User aliased:', { previousId, newUserId });\n\n return { previousId, newUserId };\n }\n\n getState(): IdentityState {\n return {\n anonymousId: this.anonymousId,\n userId: this.userId,\n traits: this.getTraits(),\n };\n }\n}\n","import { Storage } from '../utils/storage';\nimport { generateSessionId } from '../utils/uuid';\nimport { logger } from '../utils/logger';\nimport { AdClickIDs } from '../utils/url-parser';\n\nexport interface SessionState {\n sessionId: string;\n startTime: number;\n lastActivityTime: number;\n eventCount: number;\n adClickIDs?: AdClickIDs;\n landingPage?: string;\n}\n\nexport class SessionManager {\n private storage: Storage;\n private sessionId: string;\n private sessionTimeout: number;\n private lastActivityTime: number;\n private sessionStartTime: number;\n private eventCount: number = 0;\n private checkInterval: number | null = null;\n private activityThrottle: number = 1000;\n private lastActivityUpdate: number = 0;\n private adClickIDs: AdClickIDs = {};\n private landingPage?: string;\n\n constructor(storage: Storage, sessionTimeoutMinutes: number = 30) {\n this.storage = storage;\n this.sessionTimeout = sessionTimeoutMinutes * 60 * 1000;\n this.lastActivityTime = Date.now();\n this.sessionStartTime = Date.now();\n\n const session = this.loadSession();\n if (session) {\n this.sessionId = session.sessionId;\n this.sessionStartTime = session.startTime;\n this.lastActivityTime = session.lastActivityTime;\n this.eventCount = session.eventCount;\n this.adClickIDs = session.adClickIDs || {};\n this.landingPage = session.landingPage;\n logger.debug('Session loaded:', session);\n } else {\n this.sessionId = this.createNewSession();\n }\n\n this.startActivityTracking();\n this.startExpiryCheck();\n }\n\n private loadSession(): SessionState | null {\n const sessionData = this.storage.get('session');\n\n if (!sessionData) {\n return null;\n }\n\n try {\n const session: SessionState = JSON.parse(sessionData);\n const elapsed = Date.now() - session.lastActivityTime;\n\n if (elapsed < this.sessionTimeout) {\n return session;\n } else {\n logger.debug('Session expired, creating new session');\n this.storage.remove('session');\n return null;\n }\n } catch (error) {\n logger.warn('Failed to parse session data:', error);\n this.storage.remove('session');\n return null;\n }\n }\n\n private createNewSession(): string {\n const newSessionId = generateSessionId();\n this.sessionStartTime = Date.now();\n this.lastActivityTime = Date.now();\n this.eventCount = 0;\n\n this.persistSession();\n logger.info('New session created:', newSessionId);\n\n return newSessionId;\n }\n\n private persistSession(): void {\n const sessionData: SessionState = {\n sessionId: this.sessionId,\n startTime: this.sessionStartTime,\n lastActivityTime: this.lastActivityTime,\n eventCount: this.eventCount,\n adClickIDs: this.adClickIDs,\n landingPage: this.landingPage,\n };\n\n this.storage.set('session', JSON.stringify(sessionData));\n }\n\n private startActivityTracking(): void {\n const events = ['click', 'scroll', 'keypress', 'mousemove', 'touchstart'];\n\n const activityHandler = () => this.onActivity();\n\n events.forEach((event) => {\n window.addEventListener(event, activityHandler, { passive: true });\n });\n\n window.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'visible') {\n this.onActivity();\n }\n });\n }\n\n private startExpiryCheck(): void {\n this.checkInterval = window.setInterval(() => {\n this.checkSessionExpiry();\n }, 60000);\n }\n\n private onActivity(): void {\n const now = Date.now();\n const timeSinceLastUpdate = now - this.lastActivityUpdate;\n\n if (timeSinceLastUpdate < this.activityThrottle) {\n return;\n }\n\n this.lastActivityUpdate = now;\n const timeSinceLastActivity = now - this.lastActivityTime;\n\n if (timeSinceLastActivity > this.sessionTimeout) {\n logger.info('Session expired due to inactivity, creating new session');\n this.sessionId = this.createNewSession();\n } else {\n this.lastActivityTime = now;\n this.persistSession();\n }\n }\n\n private checkSessionExpiry(): void {\n const elapsed = Date.now() - this.lastActivityTime;\n\n if (elapsed > this.sessionTimeout) {\n logger.info('Session expired during check, creating new session');\n this.sessionId = this.createNewSession();\n }\n }\n\n getSessionId(): string {\n return this.sessionId;\n }\n\n incrementEventCount(): void {\n this.eventCount++;\n this.lastActivityTime = Date.now();\n this.persistSession();\n }\n\n getSessionDuration(): number {\n return Date.now() - this.sessionStartTime;\n }\n\n getEventCount(): number {\n return this.eventCount;\n }\n\n getState(): SessionState {\n return {\n sessionId: this.sessionId,\n startTime: this.sessionStartTime,\n lastActivityTime: this.lastActivityTime,\n eventCount: this.eventCount,\n adClickIDs: this.adClickIDs,\n landingPage: this.landingPage,\n };\n }\n\n setAdClickIDs(adClickIDs: AdClickIDs, landingPage?: string): void {\n if (Object.keys(adClickIDs).length > 0) {\n this.adClickIDs = { ...this.adClickIDs, ...adClickIDs };\n if (landingPage) {\n this.landingPage = landingPage;\n }\n this.persistSession();\n logger.info('Ad click IDs stored in session:', this.adClickIDs);\n }\n }\n\n getAdClickIDs(): AdClickIDs {\n return this.adClickIDs;\n }\n\n getLandingPage(): string | undefined {\n return this.landingPage;\n }\n\n destroy(): void {\n if (this.checkInterval) {\n clearInterval(this.checkInterval);\n this.checkInterval = null;\n }\n }\n}\n","import { AegisEvent } from '../types/events';\nimport { Transport } from './transport';\nimport { Storage } from '../utils/storage';\nimport { logger } from '../utils/logger';\n\nexport interface QueueConfig {\n batchSize: number;\n batchInterval: number;\n enableOfflineMode: boolean;\n maxOfflineEvents: number;\n}\n\nexport class EventQueue {\n private buffer: AegisEvent[] = [];\n private config: QueueConfig;\n private transport: Transport;\n private storage: Storage;\n private flushInterval: number | null = null;\n private isFlushing: boolean = false;\n private offlineQueue: AegisEvent[] = [];\n private isOnline: boolean = navigator.onLine;\n\n constructor(config: QueueConfig, transport: Transport, storage: Storage) {\n this.config = config;\n this.transport = transport;\n this.storage = storage;\n\n if (config.enableOfflineMode) {\n this.loadOfflineQueue();\n this.setupOnlineListener();\n }\n\n this.startFlushTimer();\n this.setupUnloadHandlers();\n }\n\n private loadOfflineQueue(): void {\n const offlineData = this.storage.get('offline_queue');\n\n if (!offlineData) {\n return;\n }\n\n try {\n const events = JSON.parse(offlineData) as AegisEvent[];\n\n if (Array.isArray(events) && events.length > 0) {\n this.offlineQueue = events.slice(0, this.config.maxOfflineEvents);\n logger.info(`Loaded ${this.offlineQueue.length} offline events`);\n\n if (this.isOnline) {\n this.flushOfflineQueue();\n }\n }\n } catch (error) {\n logger.warn('Failed to load offline queue:', error);\n this.storage.remove('offline_queue');\n }\n }\n\n private saveOfflineQueue(): void {\n if (this.offlineQueue.length === 0) {\n this.storage.remove('offline_queue');\n return;\n }\n\n try {\n const data = JSON.stringify(this.offlineQueue);\n this.storage.set('offline_queue', data);\n logger.debug(`Saved ${this.offlineQueue.length} events to offline queue`);\n } catch (error) {\n logger.warn('Failed to save offline queue:', error);\n }\n }\n\n private setupOnlineListener(): void {\n window.addEventListener('online', () => {\n logger.info('Connection restored');\n this.isOnline = true;\n this.flushOfflineQueue();\n this.flush();\n });\n\n window.addEventListener('offline', () => {\n logger.warn('Connection lost, entering offline mode');\n this.isOnline = false;\n });\n }\n\n private async flushOfflineQueue(): Promise<void> {\n if (this.offlineQueue.length === 0) {\n return;\n }\n\n logger.info(`Flushing ${this.offlineQueue.length} offline events`);\n\n const events = [...this.offlineQueue];\n this.offlineQueue = [];\n this.storage.remove('offline_queue');\n\n const result = await this.transport.send(events);\n\n if (!result.success) {\n logger.warn('Failed to send offline events, re-queueing');\n this.offlineQueue = [...events, ...this.offlineQueue].slice(\n 0,\n this.config.maxOfflineEvents\n );\n this.saveOfflineQueue();\n } else {\n logger.info('Offline events sent successfully');\n }\n }\n\n push(event: AegisEvent): void {\n if (!this.isOnline && this.config.enableOfflineMode) {\n this.addToOfflineQueue(event);\n return;\n }\n\n this.buffer.push(event);\n logger.debug('Event queued:', event.type, event);\n\n if (this.buffer.length >= this.config.batchSize) {\n this.flush();\n }\n }\n\n private addToOfflineQueue(event: AegisEvent): void {\n if (this.offlineQueue.length >= this.config.maxOfflineEvents) {\n logger.warn('Offline queue full, dropping oldest event');\n this.offlineQueue.shift();\n }\n\n this.offlineQueue.push(event);\n this.saveOfflineQueue();\n logger.debug('Event added to offline queue');\n }\n\n async flush(): Promise<void> {\n if (this.isFlushing) {\n logger.debug('Flush already in progress, skipping');\n return;\n }\n\n if (this.buffer.length === 0) {\n return;\n }\n\n this.isFlushing = true;\n\n const events = [...this.buffer];\n this.buffer = [];\n\n logger.info(`Flushing ${events.length} events`);\n\n try {\n const result = await this.transport.send(events);\n\n if (!result.success) {\n logger.error('Failed to send events:', result.error);\n\n if (this.config.enableOfflineMode) {\n this.offlineQueue = [...this.offlineQueue, ...events].slice(\n 0,\n this.config.maxOfflineEvents\n );\n this.saveOfflineQueue();\n logger.info('Events saved to offline queue');\n } else {\n this.buffer.unshift(...events);\n logger.warn('Events re-queued for retry');\n }\n } else {\n logger.info('Events sent successfully');\n }\n } catch (error) {\n logger.error('Flush error:', error);\n\n if (this.config.enableOfflineMode) {\n this.offlineQueue = [...this.offlineQueue, ...events].slice(\n 0,\n this.config.maxOfflineEvents\n );\n this.saveOfflineQueue();\n }\n } finally {\n this.isFlushing = false;\n }\n }\n\n private startFlushTimer(): void {\n if (this.flushInterval) {\n clearInterval(this.flushInterval);\n }\n\n this.flushInterval = window.setInterval(() => {\n this.flush();\n }, this.config.batchInterval);\n\n logger.debug(\n `Flush timer started with interval: ${this.config.batchInterval}ms`\n );\n }\n\n private setupUnloadHandlers(): void {\n const flushBeforeUnload = () => {\n if (this.buffer.length > 0 || this.offlineQueue.length > 0) {\n this.persistBufferToOfflineQueue();\n this.flush();\n }\n };\n\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') {\n flushBeforeUnload();\n }\n });\n\n window.addEventListener('beforeunload', flushBeforeUnload);\n\n window.addEventListener('pagehide', flushBeforeUnload);\n }\n\n private persistBufferToOfflineQueue(): void {\n if (this.buffer.length === 0) {\n return;\n }\n\n if (this.config.enableOfflineMode) {\n this.offlineQueue = [...this.offlineQueue, ...this.buffer].slice(\n 0,\n this.config.maxOfflineEvents\n );\n this.saveOfflineQueue();\n logger.debug('Buffer persisted to offline queue before unload');\n }\n }\n\n getQueueSize(): number {\n return this.buffer.length;\n }\n\n getOfflineQueueSize(): number {\n return this.offlineQueue.length;\n }\n\n clear(): void {\n this.buffer = [];\n this.offlineQueue = [];\n this.storage.remove('offline_queue');\n logger.info('Queue cleared');\n }\n\n destroy(): void {\n if (this.flushInterval) {\n clearInterval(this.flushInterval);\n this.flushInterval = null;\n }\n\n this.flush();\n }\n}\n","import { AegisEvent, BatchPayload, BatchResponse } from '../types/events';\nimport { CellEndpoint, CellRegion } from '../types/config';\nimport { logger } from '../utils/logger';\nimport { Storage } from '../utils/storage';\n\nexport interface TransportConfig {\n writeKey: string;\n apiHost: string | null;\n cellEndpoints: CellEndpoint[];\n preferredRegion: CellRegion | null;\n autoRegionDetection: boolean;\n requestTimeout: number;\n retryFailedRequests: boolean;\n maxRetries: number;\n retryBackoffMultiplier: number;\n}\n\nexport interface SendResult {\n success: boolean;\n response?: BatchResponse;\n error?: Error;\n endpoint?: string;\n}\n\nexport class Transport {\n private config: TransportConfig;\n private storage: Storage;\n private activeCell: CellEndpoint | null = null;\n private healthCheckInterval: number | null = null;\n private regionLatencyMap: Map<string, number> = new Map();\n\n constructor(config: TransportConfig, storage: Storage) {\n this.config = config;\n this.storage = storage;\n\n if (config.cellEndpoints.length > 0) {\n this.initializeCellularArchitecture();\n }\n }\n\n private async initializeCellularArchitecture(): Promise<void> {\n const cachedCell = this.loadCachedCell();\n\n if (cachedCell && this.isCellHealthy(cachedCell)) {\n this.activeCell = cachedCell;\n logger.info('Using cached cell:', cachedCell);\n } else {\n await this.selectOptimalCell();\n }\n\n this.startHealthChecks();\n }\n\n private loadCachedCell(): CellEndpoint | null {\n const cached = this.storage.get('active_cell');\n\n if (!cached) {\n return null;\n }\n\n try {\n return JSON.parse(cached) as CellEndpoint;\n } catch (error) {\n logger.warn('Failed to parse cached cell:', error);\n return null;\n }\n }\n\n private saveCachedCell(cell: CellEndpoint): void {\n this.storage.set('active_cell', JSON.stringify(cell), 7);\n }\n\n private isCellHealthy(cell: CellEndpoint): boolean {\n return (\n cell.healthy &&\n this.config.cellEndpoints.some(\n (c) => c.region === cell.region && c.url === cell.url\n )\n );\n }\n\n private async selectOptimalCell(): Promise<void> {\n logger.info('Selecting optimal cell...');\n\n if (this.config.preferredRegion) {\n const preferredCell = this.config.cellEndpoints.find(\n (cell) => cell.region === this.config.preferredRegion && cell.healthy\n );\n\n if (preferredCell) {\n this.activeCell = preferredCell;\n this.saveCachedCell(preferredCell);\n logger.info('Using preferred region cell:', preferredCell);\n return;\n }\n }\n\n if (this.config.autoRegionDetection) {\n await this.detectOptimalRegion();\n } else {\n this.selectCellByPriority();\n }\n }\n\n private async detectOptimalRegion(): Promise<void> {\n const healthyCells = this.config.cellEndpoints.filter((cell) => cell.healthy);\n\n if (healthyCells.length === 0) {\n logger.error('No healthy cells available');\n return;\n }\n\n const latencyPromises = healthyCells.map(async (cell) => {\n const latency = await this.measureLatency(cell);\n this.regionLatencyMap.set(cell.region, latency);\n return { cell, latency };\n });\n\n const results = await Promise.all(latencyPromises);\n results.sort((a, b) => a.latency - b.latency);\n\n const optimalCell = results[0].cell;\n this.activeCell = optimalCell;\n this.saveCachedCell(optimalCell);\n\n logger.info('Optimal cell selected:', {\n region: optimalCell.region,\n latency: results[0].latency,\n });\n }\n\n private async measureLatency(cell: CellEndpoint): Promise<number> {\n const startTime = performance.now();\n\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 2000);\n\n const response = await fetch(`${cell.url}/health`, {\n method: 'GET',\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (response.ok) {\n return performance.now() - startTime;\n } else {\n return Infinity;\n }\n } catch (error) {\n logger.warn(`Health check failed for ${cell.region}:`, error);\n return Infinity;\n }\n }\n\n private selectCellByPriority(): void {\n const sortedCells = [...this.config.cellEndpoints]\n .filter((cell) => cell.healthy)\n .sort((a, b) => a.priority - b.priority);\n\n if (sortedCells.length > 0) {\n this.activeCell = sortedCells[0];\n this.saveCachedCell(sortedCells[0]);\n logger.info('Cell selected by priority:', sortedCells[0]);\n } else {\n logger.error('No healthy cells available');\n }\n }\n\n private startHealthChecks(): void {\n this.healthCheckInterval = window.setInterval(() => {\n this.performHealthChecks();\n }, 60000);\n }\n\n private async performHealthChecks(): Promise<void> {\n const healthPromises = this.config.cellEndpoints.map(async (cell) => {\n const isHealthy = await this.checkCellHealth(cell);\n cell.healthy = isHealthy;\n return { cell, isHealthy };\n });\n\n const results = await Promise.all(healthPromises);\n\n if (this.activeCell && !this.activeCell.healthy) {\n logger.warn('Active cell unhealthy, selecting new cell');\n await this.selectOptimalCell();\n }\n\n logger.debug('Health check results:', results);\n }\n\n private async checkCellHealth(cell: CellEndpoint): Promise<boolean> {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 3000);\n\n const response = await fetch(`${cell.url}/health`, {\n method: 'GET',\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n return response.ok;\n } catch (error) {\n return false;\n }\n }\n\n async send(events: AegisEvent[]): Promise<SendResult> {\n if (events.length === 0) {\n return { success: true };\n }\n\n const endpoint = this.getActiveEndpoint();\n const payload = this.buildPayload(events);\n\n logger.debug('Sending batch:', { endpoint, eventCount: events.length });\n\n if (document.visibilityState === 'hidden' && typeof navigator.sendBeacon === 'function') {\n const result = this.sendViaBeacon(endpoint, payload);\n return Promise.resolve(result);\n } else {\n return this.sendViaFetch(endpoint, payload);\n }\n }\n\n private getActiveEndpoint(): string {\n if (this.activeCell) {\n return `${this.activeCell.url}/v1/batch`;\n }\n\n if (this.config.apiHost) {\n return `${this.config.apiHost}/v1/batch`;\n }\n\n throw new Error('No active endpoint available');\n }\n\n private buildPayload(events: AegisEvent[]): BatchPayload {\n return {\n batch: events,\n sentAt: new Date().toISOString(),\n writeKey: this.config.writeKey,\n context: this.activeCell\n ? {\n cell: {\n region: this.activeCell.region,\n endpoint: this.activeCell.url,\n },\n }\n : undefined,\n };\n }\n\n private sendViaBeacon(endpoint: string, payload: BatchPayload): SendResult | Promise<SendResult> {\n try {\n const blob = new Blob([JSON.stringify(payload)], {\n type: 'application/json',\n });\n\n const sent = navigator.sendBeacon(endpoint, blob);\n\n if (sent) {\n logger.debug('Batch sent via Beacon');\n return { success: true, endpoint };\n } else {\n logger.warn('Beacon send failed, falling back to fetch');\n return this.sendViaFetch(endpoint, payload);\n }\n } catch (error) {\n logger.error('Beacon send error:', error);\n return {\n success: false,\n error: error as Error,\n endpoint,\n };\n }\n }\n\n private async sendViaFetch(\n endpoint: string,\n payload: BatchPayload,\n attempt: number = 1\n ): Promise<SendResult> {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(),\n this.config.requestTimeout\n );\n\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.config.writeKey}`,\n },\n body: JSON.stringify(payload),\n keepalive: true,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (response.ok) {\n const result: BatchResponse = await response.json();\n logger.debug('Batch sent successfully:', result);\n return { success: true, response: result, endpoint };\n } else {\n const errorText = await response.text();\n const error = new Error(\n `HTTP ${response.status}: ${errorText || response.statusText}`\n );\n\n logger.error('Batch send failed:', error);\n\n if (this.shouldRetry(response.status, attempt)) {\n return this.retryRequest(endpoint, payload, attempt);\n }\n\n return { success: false, error, endpoint };\n }\n } catch (error) {\n logger.error('Fetch error:', error);\n\n if (this.shouldRetry(0, attempt)) {\n return this.retryRequest(endpoint, payload, attempt);\n }\n\n return {\n success: false,\n error: error as Error,\n endpoint,\n };\n }\n }\n\n private shouldRetry(statusCode: number, attempt: number): boolean {\n if (!this.config.retryFailedRequests) {\n return false;\n }\n\n if (attempt >= this.config.maxRetries) {\n return false;\n }\n\n if (statusCode === 0) {\n return true;\n }\n\n return statusCode >= 500 || statusCode === 429;\n }\n\n private async retryRequest(\n endpoint: string,\n payload: BatchPayload,\n attempt: number\n ): Promise<SendResult> {\n const delay =\n Math.pow(this.config.retryBackoffMultiplier, attempt) * 1000;\n\n logger.info(`Retrying request in ${delay}ms (attempt ${attempt + 1})`);\n\n await new Promise((resolve) => setTimeout(resolve, delay));\n\n return this.sendViaFetch(endpoint, payload, attempt + 1);\n }\n\n getActiveCell(): CellEndpoint | null {\n return this.activeCell;\n }\n\n getRegionLatencies(): Map<string, number> {\n return new Map(this.regionLatencyMap);\n }\n\n destroy(): void {\n if (this.healthCheckInterval) {\n clearInterval(this.healthCheckInterval);\n this.healthCheckInterval = null;\n }\n }\n}\n","const STORAGE_PREFIX = 'aegis_';\n\nexport interface StorageOptions {\n cookieDomain?: string | null;\n secureCookie?: boolean;\n crossDomain?: boolean;\n}\n\nexport class Storage {\n private useLocalStorage: boolean;\n private options: StorageOptions;\n\n constructor(options: StorageOptions = {}) {\n this.options = options;\n this.useLocalStorage = this.isLocalStorageAvailable();\n }\n\n private isLocalStorageAvailable(): boolean {\n try {\n const test = '__aegis_test__';\n localStorage.setItem(test, test);\n localStorage.removeItem(test);\n return true;\n } catch {\n return false;\n }\n }\n\n set(key: string, value: string, expiryDays: number = 365): void {\n const fullKey = STORAGE_PREFIX + key;\n\n if (this.useLocalStorage) {\n try {\n const item = {\n value,\n expiry: Date.now() + expiryDays * 24 * 60 * 60 * 1000,\n };\n localStorage.setItem(fullKey, JSON.stringify(item));\n } catch (error) {\n console.warn('[Aegis Storage] localStorage.setItem failed:', error);\n }\n }\n\n this.setCookie(fullKey, value, expiryDays);\n }\n\n get(key: string): string | null {\n const fullKey = STORAGE_PREFIX + key;\n\n if (this.useLocalStorage) {\n try {\n const itemStr = localStorage.getItem(fullKey);\n if (itemStr) {\n const item = JSON.parse(itemStr);\n if (Date.now() < item.expiry) {\n return item.value;\n } else {\n localStorage.removeItem(fullKey);\n }\n }\n } catch (error) {\n console.warn('[Aegis Storage] localStorage.getItem failed:', error);\n }\n }\n\n return this.getCookie(fullKey);\n }\n\n remove(key: string): void {\n const fullKey = STORAGE_PREFIX + key;\n\n if (this.useLocalStorage) {\n try {\n localStorage.removeItem(fullKey);\n } catch (error) {\n console.warn('[Aegis Storage] localStorage.removeItem failed:', error);\n }\n }\n\n this.deleteCookie(fullKey);\n }\n\n clear(): void {\n if (this.useLocalStorage) {\n try {\n const keys = Object.keys(localStorage);\n keys.forEach((key) => {\n if (key.startsWith(STORAGE_PREFIX)) {\n localStorage.removeItem(key);\n }\n });\n } catch (error) {\n console.warn('[Aegis Storage] localStorage.clear failed:', error);\n }\n }\n\n const cookies = document.cookie.split(';');\n cookies.forEach((cookie) => {\n const key = cookie.split('=')[0].trim();\n if (key.startsWith(STORAGE_PREFIX)) {\n this.deleteCookie(key);\n }\n });\n }\n\n private setCookie(name: string, value: string, days: number): void {\n try {\n const date = new Date();\n date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);\n const expires = `expires=${date.toUTCString()}`;\n \n let cookieStr = `${name}=${value};${expires};path=/`;\n \n if (this.options.secureCookie && window.location.protocol === 'https:') {\n cookieStr += ';Secure';\n }\n \n cookieStr += ';SameSite=Lax';\n \n if (this.options.cookieDomain) {\n cookieStr += `;domain=${this.options.cookieDomain}`;\n } else if (this.options.crossDomain) {\n const domain = this.getRootDomain();\n if (domain) {\n cookieStr += `;domain=${domain}`;\n }\n }\n \n document.cookie = cookieStr;\n } catch (error) {\n console.warn('[Aegis Storage] setCookie failed:', error);\n }\n }\n\n private getCookie(name: string): string | null {\n try {\n const nameEQ = name + '=';\n const ca = document.cookie.split(';');\n \n for (let i = 0; i < ca.length; i++) {\n let c = ca[i];\n while (c.charAt(0) === ' ') {\n c = c.substring(1, c.length);\n }\n if (c.indexOf(nameEQ) === 0) {\n return c.substring(nameEQ.length, c.length);\n }\n }\n } catch (error) {\n console.warn('[Aegis Storage] getCookie failed:', error);\n }\n \n return null;\n }\n\n private deleteCookie(name: string): void {\n try {\n let cookieStr = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/`;\n \n if (this.options.cookieDomain) {\n cookieStr += `;domain=${this.options.cookieDomain}`;\n } else if (this.options.crossDomain) {\n const domain = this.getRootDomain();\n if (domain) {\n cookieStr += `;domain=${domain}`;\n }\n }\n \n document.cookie = cookieStr;\n } catch (error) {\n console.warn('[Aegis Storage] deleteCookie failed:', error);\n }\n }\n\n private getRootDomain(): string | null {\n try {\n const hostname = window.location.hostname;\n \n if (/^(\\d{1,3}\\.){3}\\d{1,3}$/.test(hostname)) {\n return null;\n }\n \n if (hostname === 'localhost') {\n return null;\n }\n \n const parts = hostname.split('.');\n \n if (parts.length <= 2) {\n return `.${hostname}`;\n }\n \n return `.${parts.slice(-2).join('.')}`;\n } catch (error) {\n console.warn('[Aegis Storage] getRootDomain failed:', error);\n return null;\n }\n }\n}\n","import { EventContext } from '../types/events';\nimport { parseUTMParameters } from './url-parser';\nimport { AegisConfigInternal } from '../types/config';\nimport type { SessionManager } from '../core/session';\n\nexport function buildContext(config: AegisConfigInternal, session?: SessionManager): EventContext {\n const utm = config.capture_utm ? parseUTMParameters() : undefined;\n const device = detectDevice();\n const os = detectOS();\n const browser = detectBrowser();\n const network = detectNetworkInfo();\n\n const adClickIDs = session?.getAdClickIDs();\n const landingPage = session?.getLandingPage();\n\n return {\n library: {\n name: '@aegis/web-sdk',\n version: '1.0.0',\n },\n page: {\n path: window.location.pathname,\n referrer: config.capture_referrer ? document.referrer : '',\n search: window.location.search,\n title: document.title,\n url: window.location.href,\n hash: window.location.hash,\n },\n userAgent: navigator.userAgent,\n locale: navigator.language,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n screen: {\n width: window.screen.width,\n height: window.screen.height,\n density: window.devicePixelRatio || 1,\n },\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight,\n },\n ...(utm && Object.keys(utm).length > 0 && { campaign: utm }),\n ...(adClickIDs && Object.keys(adClickIDs).length > 0 && { adClickIDs }),\n ...(landingPage && { landingPage }),\n ...(network && { network }),\n ...(device && { device }),\n ...(os && { os }),\n ...(browser && { browser }),\n ...(config.active_cell && {\n cell: {\n region: config.active_cell.region,\n endpoint: config.active_cell.url,\n },\n }),\n };\n}\n\nfunction detectDevice(): EventContext['device'] {\n const ua = navigator.userAgent;\n\n if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(ua)) {\n return { type: 'tablet' };\n }\n\n if (/Mobile|Android|iP(hone|od)|IEMobile|BlackBerry|Kindle|Silk-Accelerated|(hpw|web)OS|Opera M(obi|ini)/.test(ua)) {\n return { type: 'mobile' };\n }\n\n return { type: 'desktop' };\n}\n\nfunction detectOS(): EventContext['os'] {\n const ua = navigator.userAgent;\n\n if (/Windows NT 10/i.test(ua)) return { name: 'Windows', version: '10' };\n if (/Windows NT 6.3/i.test(ua)) return { name: 'Windows', version: '8.1' };\n if (/Windows NT 6.2/i.test(ua)) return { name: 'Windows', version: '8' };\n if (/Windows NT 6.1/i.test(ua)) return { name: 'Windows', version: '7' };\n if (/Windows/i.test(ua)) return { name: 'Windows', version: 'Unknown' };\n\n if (/Mac OS X (\\d+)[._](\\d+)/.test(ua)) {\n const match = ua.match(/Mac OS X (\\d+)[._](\\d+)/);\n return { name: 'macOS', version: `${match![1]}.${match![2]}` };\n }\n if (/Mac/i.test(ua)) return { name: 'macOS', version: 'Unknown' };\n\n if (/Android (\\d+\\.\\d+)/.test(ua)) {\n const match = ua.match(/Android (\\d+\\.\\d+)/);\n return { name: 'Android', version: match![1] };\n }\n if (/Android/i.test(ua)) return { name: 'Android', version: 'Unknown' };\n\n if (/iPhone OS (\\d+)_(\\d+)/.test(ua)) {\n const match = ua.match(/iPhone OS (\\d+)_(\\d+)/);\n return { name: 'iOS', version: `${match![1]}.${match![2]}` };\n }\n if (/iPad.*OS (\\d+)_(\\d+)/.test(ua)) {\n const match = ua.match(/iPad.*OS (\\d+)_(\\d+)/);\n return { name: 'iOS', version: `${match![1]}.${match![2]}` };\n }\n if (/iPhone|iPad/i.test(ua)) return { name: 'iOS', version: 'Unknown' };\n\n if (/Linux/i.test(ua)) return { name: 'Linux', version: 'Unknown' };\n\n return { name: 'Unknown', version: 'Unknown' };\n}\n\nfunction detectBrowser(): EventContext['browser'] {\n const ua = navigator.userAgent;\n\n if (/Edg\\/(\\d+\\.\\d+)/.test(ua)) {\n const match = ua.match(/Edg\\/(\\d+\\.\\d+)/);\n return { name: 'Edge', version: match![1] };\n }\n\n if (/Chrome\\/(\\d+\\.\\d+)/.test(ua) && !/Edg/.test(ua)) {\n const match = ua.match(/Chrome\\/(\\d+\\.\\d+)/);\n return { name: 'Chrome', version: match![1] };\n }\n\n if (/Firefox\\/(\\d+\\.\\d+)/.test(ua)) {\n const match = ua.match(/Firefox\\/(\\d+\\.\\d+)/);\n return { name: 'Firefox', version: match![1] };\n }\n\n if (/Safari\\/(\\d+\\.\\d+)/.test(ua) && !/Chrome/.test(ua)) {\n const match = ua.match(/Version\\/(\\d+\\.\\d+)/);\n return { name: 'Safari', version: match ? match[1] : 'Unknown' };\n }\n\n if (/MSIE (\\d+\\.\\d+)/.test(ua) || /Trident\\//.test(ua)) {\n const match = ua.match(/MSIE (\\d+\\.\\d+)/) || ua.match(/rv:(\\d+\\.\\d+)/);\n return { name: 'Internet Explorer', version: match ? match[1] : 'Unknown' };\n }\n\n return { name: 'Unknown', version: 'Unknown' };\n}\n\nfunction detectNetworkInfo(): EventContext['network'] | undefined {\n try {\n const connection =\n (navigator as any).connection ||\n (navigator as any).mozConnection ||\n (navigator as any).webkitConnection;\n\n if (connection) {\n return {\n effectiveType: connection.effectiveType,\n downlink: connection.downlink,\n rtt: connection.rtt,\n };\n }\n } catch (error) {\n console.warn('[Aegis Device] detectNetworkInfo failed:', error);\n }\n\n return undefined;\n}\n\nexport function isBot(): boolean {\n const ua = navigator.userAgent.toLowerCase();\n const botPatterns = [\n 'bot',\n 'crawl',\n 'spider',\n 'slurp',\n 'mediapartners',\n 'googlebot',\n 'bingbot',\n 'yahoo',\n 'duckduckbot',\n 'baiduspider',\n 'yandex',\n 'facebookexternalhit',\n 'linkedinbot',\n 'twitterbot',\n 'slackbot',\n 'telegrambot',\n 'whatsapp',\n 'pingdom',\n 'uptimerobot',\n ];\n\n return botPatterns.some((pattern) => ua.includes(pattern));\n}\n","export interface UTMParams {\n source?: string;\n medium?: string;\n campaign?: string;\n term?: string;\n content?: string;\n name?: string;\n}\n\nexport function parseUTMParameters(url?: string): UTMParams {\n try {\n const searchParams = url\n ? new URL(url).searchParams\n : new URLSearchParams(window.location.search);\n\n const utm: UTMParams = {};\n\n const utmKeys: Array<keyof UTMParams> = [\n 'source',\n 'medium',\n 'campaign',\n 'term',\n 'content',\n 'name',\n ];\n\n utmKeys.forEach((key) => {\n const value = searchParams.get(`utm_${key}`);\n if (value) {\n utm[key] = value;\n }\n });\n\n return utm;\n } catch (error) {\n console.warn('[Aegis URL Parser] parseUTMParameters failed:', error);\n return {};\n }\n}\n\nexport function parseQueryParameters(url?: string): Record<string, string> {\n try {\n const searchParams = url\n ? new URL(url).searchParams\n : new URLSearchParams(window.location.search);\n\n const params: Record<string, string> = {};\n\n searchParams.forEach((value, key) => {\n params[key] = value;\n });\n\n return params;\n } catch (error) {\n console.warn('[Aegis URL Parser] parseQueryParameters failed:', error);\n return {};\n }\n}\n\nexport function getCanonicalURL(): string {\n try {\n const canonical = document.querySelector('link[rel=\"canonical\"]');\n if (canonical && canonical.getAttribute('href')) {\n return canonical.getAttribute('href')!;\n }\n \n return window.location.href;\n } catch (error) {\n console.warn('[Aegis URL Parser] getCanonicalURL failed:', error);\n return window.location.href;\n }\n}\n\nexport function stripQueryParameters(url: string): string {\n try {\n const urlObj = new URL(url);\n return `${urlObj.protocol}//${urlObj.host}${urlObj.pathname}`;\n } catch (error) {\n console.warn('[Aegis URL Parser] stripQueryParameters failed:', error);\n return url;\n }\n}\n\nexport interface AdClickIDs {\n gclid?: string;\n fbclid?: string;\n msclkid?: string;\n ctwa_clid?: string;\n ttclid?: string;\n li_fat_id?: string;\n}\n\nexport function parseAdClickIDs(url?: string): AdClickIDs {\n try {\n const searchParams = url\n ? new URL(url).searchParams\n : new URLSearchParams(window.location.search);\n\n const adClickIDs: AdClickIDs = {};\n\n const clickIDKeys: Array<keyof AdClickIDs> = [\n 'gclid',\n 'fbclid',\n 'msclkid',\n 'ctwa_clid',\n 'ttclid',\n 'li_fat_id',\n ];\n\n clickIDKeys.forEach((key) => {\n const value = searchParams.get(key);\n if (value) {\n adClickIDs[key] = value;\n }\n });\n\n return adClickIDs;\n } catch (error) {\n console.warn('[Aegis URL Parser] parseAdClickIDs failed:', error);\n return {};\n }\n}\n\nexport function hasAdClickIDs(adClickIDs: AdClickIDs): boolean {\n return Object.keys(adClickIDs).length > 0;\n}\n","import { Plugin } from '../types/plugin';\nimport { logger } from '../utils/logger';\n\nexport class PluginRegistry {\n private plugins: Map<string, Plugin> = new Map();\n\n register(plugin: Plugin): void {\n if (this.plugins.has(plugin.name)) {\n logger.warn(`Plugin \"${plugin.name}\" already registered, skipping`);\n return;\n }\n\n this.plugins.set(plugin.name, plugin);\n logger.info(`Plugin registered: ${plugin.name} v${plugin.version}`);\n }\n\n unregister(pluginName: string): void {\n const plugin = this.plugins.get(pluginName);\n\n if (!plugin) {\n logger.warn(`Plugin \"${pluginName}\" not found`);\n return;\n }\n\n if (plugin.destroy) {\n try {\n plugin.destroy();\n } catch (error) {\n logger.error(`Error destroying plugin \"${pluginName}\":`, error);\n }\n }\n\n this.plugins.delete(pluginName);\n logger.info(`Plugin unregistered: ${pluginName}`);\n }\n\n get(pluginName: string): Plugin | undefined {\n return this.plugins.get(pluginName);\n }\n\n getAll(): Plugin[] {\n return Array.from(this.plugins.values());\n }\n\n async executeHook<T = any>(\n hookName: keyof Plugin,\n ...args: any[]\n ): Promise<T | undefined> {\n for (const plugin of this.plugins.values()) {\n const hook = plugin[hookName];\n\n if (typeof hook === 'function') {\n try {\n const result = await (hook as Function).apply(plugin, args);\n\n if (result !== undefined) {\n return result as T;\n }\n } catch (error) {\n logger.error(\n `Error executing ${String(hookName)} in plugin \"${plugin.name}\":`,\n error\n );\n\n if (plugin.onError) {\n try {\n plugin.onError(error as Error, { hookName, args });\n } catch (onErrorError) {\n logger.error(\n `Error in onError handler for plugin \"${plugin.name}\":`,\n onErrorError\n );\n }\n }\n }\n }\n }\n\n return undefined;\n }\n\n async executeHookChain<T = any>(\n hookName: keyof Plugin,\n initialValue: T,\n ...additionalArgs: any[]\n ): Promise<T> {\n let value = initialValue;\n\n for (const plugin of this.plugins.values()) {\n const hook = plugin[hookName];\n\n if (typeof hook === 'function') {\n try {\n const result = await (hook as Function).apply(plugin, [\n value,\n ...additionalArgs,\n ]);\n\n if (result !== undefined && result !== null) {\n value = result;\n }\n } catch (error) {\n logger.error(\n `Error executing ${String(hookName)} in plugin \"${plugin.name}\":`,\n error\n );\n\n if (plugin.onError) {\n try {\n plugin.onError(error as Error, { hookName, value, additionalArgs });\n } catch (onErrorError) {\n logger.error(\n `Error in onError handler for plugin \"${plugin.name}\":`,\n onErrorError\n );\n }\n }\n }\n }\n }\n\n return value;\n }\n\n async executeHookParallel<T = any>(\n hookName: keyof Plugin,\n ...args: any[]\n ): Promise<T[]> {\n const promises: Promise<T>[] = [];\n\n for (const plugin of this.plugins.values()) {\n const hook = plugin[hookName];\n\n if (typeof hook === 'function') {\n const promise = (async () => {\n try {\n return await (hook as Function).apply(plugin, args);\n } catch (error) {\n logger.error(\n `Error executing ${String(hookName)} in plugin \"${plugin.name}\":`,\n error\n );\n\n if (plugin.onError) {\n try {\n plugin.onError(error as Error, { hookName, args });\n } catch (onErrorError) {\n logger.error(\n `Error in onError handler for plugin \"${plugin.name}\":`,\n onErrorError\n );\n }\n }\n\n return undefined;\n }\n })();\n\n promises.push(promise);\n }\n }\n\n const results = await Promise.all(promises);\n return results.filter((r) => r !== undefined) as T[];\n }\n\n clear(): void {\n for (const plugin of this.plugins.values()) {\n if (plugin.destroy) {\n try {\n plugin.destroy();\n } catch (error) {\n logger.error(`Error destroying plugin \"${plugin.name}\":`, error);\n }\n }\n }\n\n this.plugins.clear();\n logger.info('All plugins cleared');\n }\n}\n","import { Storage } from './storage';\nimport { logger } from './logger';\n\nexport type ConsentCategory =\n | 'analytics'\n | 'marketing'\n | 'functional'\n | 'necessary';\n\nexport interface ConsentPreferences {\n analytics: boolean;\n marketing: boolean;\n functional: boolean;\n necessary: boolean;\n}\n\nexport type ConsentStatus = 'granted' | 'denied' | 'pending';\n\nexport interface ConsentManagerConfig {\n defaultConsent?: Partial<ConsentPreferences>;\n waitForConsent?: boolean;\n consentStorageKey?: string;\n}\n\nexport class ConsentManager {\n private storage: Storage;\n private config: Required<ConsentManagerConfig>;\n private preferences: ConsentPreferences;\n private listeners: Array<(preferences: ConsentPreferences) => void> = [];\n\n constructor(storage: Storage, config: ConsentManagerConfig = {}) {\n this.storage = storage;\n this.config = {\n defaultConsent: config.defaultConsent || {},\n waitForConsent: config.waitForConsent ?? false,\n consentStorageKey: config.consentStorageKey || 'aegis_consent',\n };\n\n this.preferences = this.loadPreferences();\n }\n\n private loadPreferences(): ConsentPreferences {\n const stored = this.storage.get(this.config.consentStorageKey);\n\n if (stored) {\n try {\n const parsed = JSON.parse(stored);\n logger.info('Loaded consent preferences:', parsed);\n return this.mergeWithDefaults(parsed);\n } catch (error) {\n logger.warn('Failed to parse consent preferences:', error);\n }\n }\n\n return this.getDefaultPreferences();\n }\n\n private getDefaultPreferences(): ConsentPreferences {\n return {\n analytics: this.config.defaultConsent.analytics ?? false,\n marketing: this.config.defaultConsent.marketing ?? false,\n functional: this.config.defaultConsent.functional ?? true,\n necessary: true,\n };\n }\n\n private mergeWithDefaults(\n preferences: Partial<ConsentPreferences>\n ): ConsentPreferences {\n return {\n necessary: true,\n analytics: preferences.analytics ?? this.config.defaultConsent.analytics ?? false,\n marketing: preferences.marketing ?? this.config.defaultConsent.marketing ?? false,\n functional: preferences.functional ?? this.config.defaultConsent.functional ?? true,\n };\n }\n\n private savePreferences(): void {\n try {\n this.storage.set(\n this.config.consentStorageKey,\n JSON.stringify(this.preferences),\n 365\n );\n logger.info('Saved consent preferences:', this.preferences);\n } catch (error) {\n logger.error('Failed to save consent preferences:', error);\n }\n }\n\n setConsent(preferences: Partial<ConsentPreferences>): void {\n const updated = { ...this.preferences, ...preferences };\n updated.necessary = true;\n\n this.preferences = updated;\n this.savePreferences();\n this.notifyListeners();\n\n logger.info('Consent updated:', this.preferences);\n }\n\n grantAll(): void {\n this.setConsent({\n analytics: true,\n marketing: true,\n functional: true,\n necessary: true,\n });\n }\n\n denyAll(): void {\n this.setConsent({\n analytics: false,\n marketing: false,\n functional: false,\n necessary: true,\n });\n }\n\n hasConsent(category: ConsentCategory): boolean {\n return this.preferences[category];\n }\n\n getPreferences(): ConsentPreferences {\n return { ...this.preferences };\n }\n\n getStatus(category: ConsentCategory): ConsentStatus {\n if (this.hasConsent(category)) {\n return 'granted';\n }\n\n const stored = this.storage.get(this.config.consentStorageKey);\n if (!stored && this.config.waitForConsent) {\n return 'pending';\n }\n\n return 'denied';\n }\n\n isAnalyticsEnabled(): boolean {\n return this.hasConsent('analytics');\n }\n\n isMarketingEnabled(): boolean {\n return this.hasConsent('marketing');\n }\n\n onChange(callback: (preferences: ConsentPreferences) => void): () => void {\n this.listeners.push(callback);\n\n return () => {\n const index = this.listeners.indexOf(callback);\n if (index > -1) {\n this.listeners.splice(index, 1);\n }\n };\n }\n\n private notifyListeners(): void {\n this.listeners.forEach((listener) => {\n try {\n listener(this.getPreferences());\n } catch (error) {\n logger.error('Consent listener error:', error);\n }\n });\n }\n\n reset(): void {\n this.storage.remove(this.config.consentStorageKey);\n this.preferences = this.getDefaultPreferences();\n this.notifyListeners();\n logger.info('Consent preferences reset');\n }\n\n integrateOneTrust(): void {\n if (typeof window === 'undefined') return;\n\n const oneTrust = (window as any).OneTrust;\n if (!oneTrust) {\n logger.warn('OneTrust not detected');\n return;\n }\n\n const syncWithOneTrust = () => {\n const activeGroups = (window as any).OnetrustActiveGroups || '';\n\n this.setConsent({\n necessary: true,\n functional: activeGroups.includes('C0003'),\n analytics: activeGroups.includes('C0002'),\n marketing: activeGroups.includes('C0004'),\n });\n\n logger.info('Synced with OneTrust consent');\n };\n\n if ((window as any).OptanonWrapper) {\n const originalWrapper = (window as any).OptanonWrapper;\n (window as any).OptanonWrapper = function () {\n originalWrapper();\n syncWithOneTrust();\n };\n } else {\n (window as any).OptanonWrapper = syncWithOneTrust;\n }\n\n syncWithOneTrust();\n }\n\n integrateCookiebot(): void {\n if (typeof window === 'undefined') return;\n\n const cookiebot = (window as any).Cookiebot;\n if (!cookiebot) {\n logger.warn('Cookiebot not detected');\n return;\n }\n\n const syncWithCookiebot = () => {\n const consent = cookiebot.consent || {};\n\n this.setConsent({\n necessary: true,\n functional: consent.preferences || false,\n analytics: consent.statistics || false,\n marketing: consent.marketing || false,\n });\n\n logger.info('Synced with Cookiebot consent');\n };\n\n window.addEventListener('CookiebotOnAccept', syncWithCookiebot);\n window.addEventListener('CookiebotOnDecline', syncWithCookiebot);\n\n if (cookiebot.consent) {\n syncWithCookiebot();\n }\n }\n\n integrateGoogleConsentMode(): void {\n if (typeof window === 'undefined') return;\n\n const gtag = (window as any).gtag;\n if (!gtag) {\n logger.warn('Google Tag Manager not detected');\n return;\n }\n\n const updateGoogleConsent = () => {\n gtag('consent', 'update', {\n ad_storage: this.preferences.marketing ? 'granted' : 'denied',\n analytics_storage: this.preferences.analytics ? 'granted' : 'denied',\n ad_user_data: this.preferences.marketing ? 'granted' : 'denied',\n ad_personalization: this.preferences.marketing ? 'granted' : 'denied',\n functionality_storage: this.preferences.functional ? 'granted' : 'denied',\n personalization_storage: this.preferences.functional ? 'granted' : 'denied',\n security_storage: 'granted',\n });\n\n logger.info('Updated Google Consent Mode');\n };\n\n this.onChange(updateGoogleConsent);\n updateGoogleConsent();\n }\n}\n","import {\n AegisConfig,\n AegisConfigInternal,\n DEFAULT_CONFIG,\n CellEndpoint,\n} from '../types/config';\nimport {\n TrackEvent,\n IdentifyEvent,\n PageEvent,\n GroupEvent,\n AliasEvent,\n AegisEvent,\n} from '../types/events';\nimport { Plugin } from '../types/plugin';\nimport { Identity } from '../utils/identity';\nimport { SessionManager } from './session';\nimport { EventQueue } from './queue';\nimport { Transport } from './transport';\nimport { Storage } from '../utils/storage';\nimport { buildContext, isBot } from '../utils/device';\nimport { generateMessageId } from '../utils/uuid';\nimport { logger } from '../utils/logger';\nimport { PluginRegistry } from '../plugins/registry';\nimport { ConsentManager, ConsentPreferences, ConsentCategory } from '../utils/consent';\nimport { parseAdClickIDs, hasAdClickIDs } from '../utils/url-parser';\n\nexport class Aegis {\n private config: AegisConfigInternal | null = null;\n private storage!: Storage;\n private identity!: Identity;\n private session: SessionManager | null = null;\n private queue: EventQueue | null = null;\n private transport: Transport | null = null;\n private plugins: PluginRegistry = new PluginRegistry();\n private initPromise: Promise<void> | null = null;\n private consent: ConsentManager | null = null;\n\n async init(\n writeKey: string,\n config?: Partial<AegisConfig>\n ): Promise<void> {\n if (this.initPromise) {\n return this.initPromise;\n }\n\n this.initPromise = this._init(writeKey, config);\n return this.initPromise;\n }\n\n private async _init(\n writeKey: string,\n config?: Partial<AegisConfig>\n ): Promise<void> {\n if (this.config?.initialized) {\n logger.warn('SDK already initialized');\n return;\n }\n\n if (this.shouldRespectDNT(config)) {\n logger.info('Do Not Track is enabled, SDK disabled');\n return;\n }\n\n if (isBot()) {\n logger.info('Bot detected, SDK disabled');\n return;\n }\n\n this.config = this.buildConfig(writeKey, config);\n\n if (this.config.debug) {\n logger.enable();\n }\n\n logger.info('Initializing Aegis SDK...', this.config);\n\n this.storage = new Storage({\n cookieDomain: this.config.cookie_domain,\n secureCookie: this.config.secure_cookie,\n crossDomain: this.config.cross_domain_tracking,\n });\n\n this.identity = new Identity(this.storage);\n\n this.consent = new ConsentManager(this.storage, {\n defaultConsent: this.config.default_consent,\n waitForConsent: this.config.wait_for_consent,\n });\n\n if (this.config.integrate_onetrust) {\n this.consent.integrateOneTrust();\n }\n\n if (this.config.integrate_cookiebot) {\n this.consent.integrateCookiebot();\n }\n\n if (this.config.integrate_google_consent_mode) {\n this.consent.integrateGoogleConsentMode();\n }\n\n this.session = new SessionManager(\n this.storage,\n this.config.session_timeout\n );\n\n this.captureAdClickIDsOnInit();\n\n this.transport = new Transport(\n {\n writeKey: this.config.write_key,\n apiHost: this.config.api_host,\n cellEndpoints: this.config.cell_endpoints,\n preferredRegion: this.config.preferred_region,\n autoRegionDetection: this.config.auto_region_detection,\n requestTimeout: this.config.request_timeout,\n retryFailedRequests: this.config.retry_failed_requests,\n maxRetries: this.config.max_retries,\n retryBackoffMultiplier: this.config.retry_backoff_multiplier,\n },\n this.storage\n );\n\n this.config.active_cell = this.transport.getActiveCell();\n\n this.queue = new EventQueue(\n {\n batchSize: this.config.batch_size,\n batchInterval: this.config.batch_interval,\n enableOfflineMode: this.config.enable_offline_mode,\n maxOfflineEvents: this.config.max_offline_events,\n },\n this.transport,\n this.storage\n );\n\n await this.initializePlugins();\n\n if (this.config.auto_page_view) {\n this.page();\n }\n\n logger.info('Aegis SDK initialized successfully');\n }\n\n private buildConfig(\n writeKey: string,\n config?: Partial<AegisConfig>\n ): AegisConfigInternal {\n return {\n ...DEFAULT_CONFIG,\n ...config,\n write_key: writeKey,\n initialized: true,\n } as AegisConfigInternal;\n }\n\n private shouldRespectDNT(config?: Partial<AegisConfig>): boolean {\n const respectDNT = config?.respect_dnt !== false;\n if (!respectDNT) return false;\n\n const dnt =\n navigator.doNotTrack ||\n (window as any).doNotTrack ||\n (navigator as any).msDoNotTrack;\n\n return dnt === '1' || dnt === 'yes';\n }\n\n private captureAdClickIDsOnInit(): void {\n if (!this.session) return;\n\n const adClickIDs = parseAdClickIDs();\n\n if (hasAdClickIDs(adClickIDs)) {\n this.session.setAdClickIDs(adClickIDs, window.location.href);\n logger.info('Ad click IDs captured on page load:', adClickIDs);\n }\n }\n\n private async initializePlugins(): Promise<void> {\n if (!this.config) return;\n\n for (const pluginName of this.config.plugins) {\n logger.debug(`Initializing plugin: ${pluginName}`);\n }\n\n await this.plugins.executeHook('init', this.config);\n }\n\n use(plugin: Plugin): void {\n this.plugins.register(plugin);\n\n if (this.config?.initialized && plugin.init) {\n Promise.resolve(plugin.init(this.config)).catch((error: any) => {\n logger.error(`Failed to initialize plugin \"${plugin.name}\":`, error);\n });\n }\n }\n\n track(eventName: string, properties?: Record<string, any>): void {\n if (!this.assertInitialized()) return;\n\n const event: TrackEvent = {\n type: 'track',\n event: eventName,\n properties: properties || {},\n messageId: generateMessageId(),\n timestamp: new Date().toISOString(),\n anonymousId: this.identity.getAnonymousId(),\n userId: this.identity.getUserId() || undefined,\n sessionId: this.session!.getSessionId(),\n context: buildContext(this.config!, this.session!),\n };\n\n this.captureEvent(event);\n }\n\n identify(userId: string, traits?: Record<string, any>): void {\n if (!this.assertInitialized()) return;\n\n this.identity.setUserId(userId, traits);\n\n const event: IdentifyEvent = {\n type: 'identify',\n traits: traits || {},\n messageId: generateMessageId(),\n timestamp: new Date().toISOString(),\n anonymousId: this.identity.getAnonymousId(),\n userId: userId,\n sessionId: this.session!.getSessionId(),\n context: buildContext(this.config!, this.session!),\n };\n\n this.captureEvent(event);\n }\n\n page(name?: string, properties?: Record<string, any>): void {\n if (!this.assertInitialized()) return;\n\n const event: PageEvent = {\n type: 'page',\n name: name || document.title,\n properties: properties || {},\n messageId: generateMessageId(),\n timestamp: new Date().toISOString(),\n anonymousId: this.identity.getAnonymousId(),\n userId: this.identity.getUserId() || undefined,\n sessionId: this.session!.getSessionId(),\n context: buildContext(this.config!, this.session!),\n };\n\n this.captureEvent(event);\n }\n\n group(groupId: string, traits?: Record<string, any>): void {\n if (!this.assertInitialized()) return;\n\n const event: GroupEvent = {\n type: 'group',\n groupId,\n traits: traits || {},\n messageId: generateMessageId(),\n timestamp: new Date().toISOString(),\n anonymousId: this.identity.getAnonymousId(),\n userId: this.identity.getUserId() || undefined,\n sessionId: this.session!.getSessionId(),\n context: buildContext(this.config!, this.session!),\n };\n\n this.captureEvent(event);\n }\n\n alias(newUserId: string): void {\n if (!this.assertInitialized()) return;\n\n const { previousId } = this.identity.alias(newUserId);\n\n const event: AliasEvent = {\n type: 'alias',\n previousId,\n messageId: generateMessageId(),\n timestamp: new Date().toISOString(),\n anonymousId: this.identity.getAnonymousId(),\n userId: newUserId,\n sessionId: this.session!.getSessionId(),\n context: buildContext(this.config!, this.session!),\n };\n\n this.captureEvent(event);\n }\n\n private async captureEvent(event: AegisEvent): Promise<void> {\n if (this.config?.enable_consent_mode && this.consent) {\n if (event.type === 'track' || event.type === 'page') {\n if (!this.consent.hasConsent('analytics')) {\n logger.debug('Event blocked: analytics consent not granted');\n return;\n }\n }\n }\n\n logger.debug('Capturing event:', event);\n\n const transformedEvent = await this.plugins.executeHookChain(\n 'beforeEventCapture',\n event\n );\n\n if (!transformedEvent) {\n logger.debug('Event cancelled by plugin');\n return;\n }\n\n this.queue!.push(transformedEvent);\n this.session!.incrementEventCount();\n\n await this.plugins.executeHook('afterEventCapture', transformedEvent);\n }\n\n reset(): void {\n if (!this.assertInitialized()) return;\n\n this.identity.reset();\n logger.info('User identity reset');\n }\n\n async flush(): Promise<void> {\n if (!this.assertInitialized()) return;\n\n await this.queue!.flush();\n }\n\n getAnonymousId(): string | null {\n if (!this.identity) return null;\n return this.identity.getAnonymousId();\n }\n\n getUserId(): string | null {\n if (!this.identity) return null;\n return this.identity.getUserId();\n }\n\n getSessionId(): string | null {\n if (!this.session) return null;\n return this.session.getSessionId();\n }\n\n debug(enable: boolean = true): void {\n if (enable) {\n logger.enable();\n } else {\n logger.disable();\n }\n\n if (this.config) {\n this.config.debug = enable;\n }\n }\n\n setCell(cellEndpoint: CellEndpoint): void {\n if (!this.config) {\n logger.warn('SDK not initialized');\n return;\n }\n\n const existingCell = this.config.cell_endpoints.find(\n (c) => c.region === cellEndpoint.region\n );\n\n if (existingCell) {\n Object.assign(existingCell, cellEndpoint);\n } else {\n this.config.cell_endpoints.push(cellEndpoint);\n }\n\n logger.info('Cell endpoint configured:', cellEndpoint);\n }\n\n getCellInfo() {\n if (!this.transport) return null;\n\n return {\n activeCell: this.transport.getActiveCell(),\n latencies: this.transport.getRegionLatencies(),\n };\n }\n\n setConsent(preferences: Partial<ConsentPreferences>): void {\n if (!this.consent) {\n logger.warn('Consent manager not initialized');\n return;\n }\n\n this.consent.setConsent(preferences);\n logger.info('Consent preferences updated');\n }\n\n grantConsent(category?: ConsentCategory): void {\n if (!this.consent) {\n logger.warn('Consent manager not initialized');\n return;\n }\n\n if (category) {\n this.consent.setConsent({ [category]: true });\n } else {\n this.consent.grantAll();\n }\n }\n\n denyConsent(category?: ConsentCategory): void {\n if (!this.consent) {\n logger.warn('Consent manager not initialized');\n return;\n }\n\n if (category) {\n this.consent.setConsent({ [category]: false });\n } else {\n this.consent.denyAll();\n }\n }\n\n hasConsent(category: ConsentCategory): boolean {\n if (!this.consent) {\n return true;\n }\n\n return this.consent.hasConsent(category);\n }\n\n getConsentPreferences(): ConsentPreferences | null {\n if (!this.consent) {\n return null;\n }\n\n return this.consent.getPreferences();\n }\n\n onConsentChange(callback: (preferences: ConsentPreferences) => void): () => void {\n if (!this.consent) {\n logger.warn('Consent manager not initialized');\n return () => {};\n }\n\n return this.consent.onChange(callback);\n }\n\n private assertInitialized(): boolean {\n if (!this.config?.initialized) {\n logger.warn('SDK not initialized. Call aegis.init() first.');\n return false;\n }\n return true;\n }\n\n destroy(): void {\n if (this.queue) {\n this.queue.destroy();\n }\n\n if (this.session) {\n this.session.destroy();\n }\n\n if (this.transport) {\n this.transport.destroy();\n }\n\n this.plugins.clear();\n\n logger.info('SDK destroyed');\n }\n}\n","import { Aegis } from './core/analytics';\nimport { AegisInAppManager } from './inapp';\nimport { AegisPlacementManager } from './placements/AegisPlacementManager';\nimport { AegisWidgetManager } from './widgets';\nimport { TriggerEngine } from './triggers';\n\ndeclare global {\n interface Window {\n aegis: any;\n Aegis: typeof Aegis;\n AegisInAppManager: typeof AegisInAppManager;\n AegisPlacementManager: typeof AegisPlacementManager;\n AegisWidgetManager: typeof AegisWidgetManager;\n TriggerEngine: typeof TriggerEngine;\n }\n}\n\nconst globalName = 'aegis';\nconst existingQueue: any = window[globalName] || [];\n\nconst instance = new Aegis();\n\nif (Array.isArray(existingQueue)) {\n const loadOptions = (existingQueue as any)._loadOptions;\n\n existingQueue.forEach((item: any) => {\n if (!Array.isArray(item)) {\n return;\n }\n\n const [method, ...args] = item;\n\n if (typeof instance[method as keyof Aegis] === 'function') {\n try {\n (instance[method as keyof Aegis] as Function).apply(instance, args);\n } catch (error) {\n console.error(`[Aegis SDK] Error executing queued method \"${method}\":`, error);\n }\n } else {\n console.warn(`[Aegis SDK] Unknown method \"${method}\"`);\n }\n });\n\n if (loadOptions?.key) {\n instance.init(loadOptions.key, loadOptions.options).catch((error) => {\n console.error('[Aegis SDK] Initialization failed:', error);\n });\n }\n}\n\nwindow[globalName] = instance;\nwindow.Aegis = Aegis;\nwindow.AegisInAppManager = AegisInAppManager;\nwindow.AegisPlacementManager = AegisPlacementManager;\nwindow.AegisWidgetManager = AegisWidgetManager;\nwindow.TriggerEngine = TriggerEngine;\n\nexport default instance;\n","/**\n * AegisInAppManager - Web SDK In-App Messaging Module\n * \n * Real-time SSE architecture with client-side evaluation.\n * \n * Security:\n * - XSS Protection: Uses DOM APIs (createElement, textContent) instead of innerHTML\n * - URL Validation: Prevents javascript: protocol injection\n * - CSP Compatible: No inline styles in HTML strings\n * \n * Architecture:\n * - Connects to SSE endpoint for real-time campaign updates\n * - Initial fetch on load, then SSE for updates\n * - Caches campaigns locally in memory\n * - Evaluates trigger rules client-side\n * - Tracks events (impression, click, dismiss) asynchronously\n */\n\nexport interface InAppCampaign {\n id: string;\n type: 'modal' | 'banner' | 'tooltip' | 'full_screen' | 'half_interstitial' | 'alert' | 'pip';\n sub_type?: string;\n title: string;\n body: string;\n image_url?: string;\n video_url?: string;\n action_url?: string;\n button_text?: string;\n background_color?: string;\n text_color?: string;\n priority: number;\n expires_at?: string;\n frequency?: {\n max_impressions?: number;\n max_impressions_per_day?: number;\n cooldown_seconds?: number;\n };\n interactive_config?: Record<string, unknown>;\n client_trigger?: {\n type: string;\n config?: Record<string, unknown>;\n };\n assigned_variant_id?: string;\n}\n\nexport interface AegisInAppConfig {\n writeKey: string;\n apiHost?: string;\n userId?: string;\n contactId?: string;\n organizationId?: string;\n debugMode?: boolean;\n enableSSE?: boolean;\n}\n\nexport class AegisInAppManager {\n private writeKey: string;\n private apiHost: string;\n private userId?: string;\n private contactId?: string;\n private organizationId?: string;\n private debugMode: boolean;\n private enableSSE: boolean;\n \n private campaigns: InAppCampaign[] = [];\n private displayedCampaigns = new Set<string>();\n private eventSource?: EventSource;\n private isInitialized = false;\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n \n constructor(config: AegisInAppConfig) {\n this.writeKey = config.writeKey;\n this.apiHost = config.apiHost || 'https://api.aegis.ai';\n this.userId = config.userId;\n this.contactId = config.contactId;\n this.organizationId = config.organizationId;\n this.debugMode = config.debugMode || false;\n this.enableSSE = config.enableSSE !== false;\n }\n \n async initialize(): Promise<void> {\n if (this.isInitialized) {\n this.log('AegisInApp already initialized');\n return;\n }\n\n // Mark user as returning for subsequent visits\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem('aegis_returning_user', '1');\n }\n\n await this.refreshCampaigns();\n\n if (this.enableSSE && this.organizationId) {\n this.connectSSE();\n }\n \n this.isInitialized = true;\n this.log('AegisInApp initialized successfully');\n }\n \n updateUserId(userId: string): void {\n this.userId = userId;\n this.refreshCampaigns();\n }\n \n updateContactId(contactId: string): void {\n this.contactId = contactId;\n this.disconnectSSE();\n if (this.enableSSE && this.organizationId) {\n this.connectSSE();\n }\n this.refreshCampaigns();\n }\n \n private connectSSE(): void {\n if (this.eventSource) {\n this.disconnectSSE();\n }\n \n if (!this.organizationId) {\n this.log('Cannot connect SSE without organization ID', 'warn');\n return;\n }\n \n const url = new URL('/v1/stream/realtime', this.apiHost);\n \n const headers: Record<string, string> = {\n 'X-Aegis-Write-Key': this.writeKey,\n 'X-Organization-ID': this.organizationId,\n };\n \n if (this.contactId) {\n headers['X-Contact-ID'] = this.contactId;\n }\n \n const queryParams = new URLSearchParams();\n Object.entries(headers).forEach(([key, value]) => {\n queryParams.append(key, value);\n });\n \n this.eventSource = new EventSource(`${url}?${queryParams.toString()}`);\n \n this.eventSource.addEventListener('open', () => {\n this.log('SSE connection established');\n this.reconnectAttempts = 0;\n });\n \n this.eventSource.addEventListener('in_app_campaign_updated', (event: MessageEvent) => {\n try {\n const data = JSON.parse(event.data);\n this.log(`Received in-app campaign update: ${data.campaign_id}`);\n this.refreshCampaigns();\n } catch (error) {\n this.log(`Error parsing SSE event: ${error}`, 'error');\n }\n });\n \n this.eventSource.addEventListener('heartbeat', (event: MessageEvent) => {\n this.log('SSE heartbeat received');\n });\n \n this.eventSource.addEventListener('error', (error) => {\n this.log('SSE connection error', 'error');\n \n if (this.eventSource?.readyState === EventSource.CLOSED) {\n this.attemptReconnect();\n }\n });\n }\n \n private disconnectSSE(): void {\n if (this.eventSource) {\n this.eventSource.close();\n this.eventSource = undefined;\n this.log('SSE connection closed');\n }\n }\n \n private attemptReconnect(): void {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n this.log('Max reconnect attempts reached, giving up', 'warn');\n return;\n }\n \n this.reconnectAttempts++;\n const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);\n \n this.log(`Reconnecting SSE in ${delay}ms (attempt ${this.reconnectAttempts})`);\n \n setTimeout(() => {\n if (this.isInitialized && this.enableSSE && this.organizationId) {\n this.connectSSE();\n }\n }, delay);\n }\n \n private async refreshCampaigns(): Promise<void> {\n try {\n // Build URL with client context for server-side targeting (Critical Fix B)\n const context = new URLSearchParams({\n device_type: this.detectDeviceType(),\n page_url: typeof window !== 'undefined' ? window.location.pathname : '/',\n });\n\n // Geo is resolved server-side from IP — no need to send\n context.set('is_new_user', this.isNewUser() ? 'true' : 'false');\n\n const url = `${this.apiHost}/v1/in-app/active?${context.toString()}`;\n\n const headers: Record<string, string> = {\n 'X-Aegis-Write-Key': this.writeKey,\n 'Content-Type': 'application/json'\n };\n\n if (this.userId) {\n headers['X-User-ID'] = this.userId;\n }\n\n if (this.contactId) {\n headers['X-Contact-ID'] = this.contactId;\n }\n\n if (this.organizationId) {\n headers['X-Organization-ID'] = this.organizationId;\n }\n\n // Send cached A/B assignments so server can skip re-evaluation (Critical Fix C)\n const abAssignments = this.getABAssignments();\n if (Object.keys(abAssignments).length > 0) {\n headers['X-AB-Assignments'] = btoa(JSON.stringify(abAssignments));\n }\n\n const response = await fetch(url, {\n method: 'GET',\n headers\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch campaigns: ${response.status}`);\n }\n\n this.campaigns = await response.json();\n\n // Process A/B assignments from server response (Critical Fix C)\n this.processABAssignments(this.campaigns);\n\n this.log(`Fetched ${this.campaigns.length} campaigns`);\n\n this.tryDisplayNextCampaign();\n\n } catch (error) {\n this.log(`Error refreshing campaigns: ${error}`, 'error');\n }\n }\n\n // --- Client Context Helpers (Critical Fix B) ---\n\n private detectDeviceType(): 'mobile' | 'desktop' | 'tablet' {\n if (typeof navigator === 'undefined') return 'desktop';\n const ua = navigator.userAgent;\n if (/Mobi|Android/i.test(ua)) return 'mobile';\n if (/iPad|Tablet/i.test(ua)) return 'tablet';\n return 'desktop';\n }\n\n private isNewUser(): boolean {\n if (typeof localStorage === 'undefined') return true;\n return !localStorage.getItem('aegis_returning_user');\n }\n\n // --- A/B Assignment Persistence (Critical Fix C) ---\n\n private getABAssignments(): Record<string, string> {\n if (typeof localStorage === 'undefined') return {};\n try {\n return JSON.parse(localStorage.getItem('aegis_ab_assignments') || '{}');\n } catch {\n return {};\n }\n }\n\n private processABAssignments(campaigns: InAppCampaign[]): void {\n if (typeof localStorage === 'undefined') return;\n const stored = this.getABAssignments();\n for (const campaign of campaigns) {\n if (campaign.assigned_variant_id) {\n stored[campaign.id] = campaign.assigned_variant_id;\n }\n }\n localStorage.setItem('aegis_ab_assignments', JSON.stringify(stored));\n }\n\n private getVariantId(campaignId: string): string | undefined {\n const assignments = this.getABAssignments();\n return assignments[campaignId] ?? undefined;\n }\n \n private tryDisplayNextCampaign(): void {\n const campaign = this.campaigns.find(c => !this.displayedCampaigns.has(c.id));\n \n if (campaign) {\n this.displayCampaign(campaign);\n }\n }\n \n private displayCampaign(campaign: InAppCampaign): void {\n this.displayedCampaigns.add(campaign.id);\n\n // Sub-type routing: interactive types are handled by dedicated renderers\n const interactiveSubTypes = new Set([\n 'spin_wheel', 'scratch_card', 'nps_survey', 'quiz',\n 'countdown_offer', 'star_rating', 'quick_poll',\n ]);\n\n if (campaign.sub_type && interactiveSubTypes.has(campaign.sub_type)) {\n this.renderInteractive(campaign);\n this.trackEvent(campaign.id, 'impression');\n return;\n }\n\n switch (campaign.type) {\n case 'modal':\n this.renderModal(campaign);\n break;\n case 'banner':\n this.renderBanner(campaign);\n break;\n case 'full_screen':\n this.renderFullScreen(campaign);\n break;\n case 'half_interstitial':\n this.renderHalfInterstitial(campaign);\n break;\n case 'alert':\n this.renderAlert(campaign);\n break;\n case 'pip':\n this.renderPIP(campaign);\n break;\n case 'tooltip':\n this.renderTooltip(campaign);\n break;\n }\n\n this.trackEvent(campaign.id, 'impression');\n }\n\n /**\n * Renders interactive sub-type campaigns (spin wheel, NPS, quiz, etc.)\n * using DOM-safe rendering. These sub-types use the campaign's\n * interactive_config payload for type-specific behavior.\n */\n private renderInteractive(campaign: InAppCampaign): void {\n const ic = (campaign.interactive_config || {}) as Record<string, unknown>;\n const bg = this.sanitizeColor(campaign.background_color || '#4169e1');\n const text = this.sanitizeColor(campaign.text_color || '#ffffff');\n\n switch (campaign.sub_type) {\n case 'nps_survey':\n this.renderNPSSurvey(campaign, ic, bg, text);\n break;\n case 'countdown_offer':\n this.renderCountdownOffer(campaign, ic, bg, text);\n break;\n case 'star_rating':\n this.renderStarRating(campaign, ic, bg, text);\n break;\n case 'quick_poll':\n this.renderQuickPoll(campaign, ic, bg, text);\n break;\n case 'quiz':\n this.renderQuiz(campaign, ic, bg, text);\n break;\n case 'spin_wheel':\n case 'scratch_card':\n // These are handled by AegisWidgetManager — emit event for bridge\n this.log(`${campaign.sub_type} delegated to AegisWidgetManager`);\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new CustomEvent('aegis:render-widget', {\n detail: { campaign, sub_type: campaign.sub_type },\n }));\n }\n break;\n default:\n this.log(`Unknown interactive sub_type: ${campaign.sub_type}`, 'warn');\n this.renderModal(campaign);\n }\n }\n\n // --- Interactive Renderers ---\n\n private renderNPSSurvey(\n campaign: InAppCampaign,\n ic: Record<string, unknown>,\n bg: string,\n text: string\n ): void {\n const overlay = this.createOverlay('aegis-in-app-nps-overlay');\n const modal = document.createElement('div');\n modal.style.cssText = `\n max-width: 360px; width: 90%; border-radius: 16px; overflow: hidden;\n background: ${bg}; color: ${text}; animation: aegisScaleIn 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.15);\n `;\n\n const body = document.createElement('div');\n body.style.cssText = 'padding: 24px; text-align: center;';\n\n const question = document.createElement('div');\n question.style.cssText = 'font-size: 16px; font-weight: 700; margin-bottom: 16px;';\n question.textContent = (ic.nps_question as string) || 'How likely are you to recommend us?';\n body.appendChild(question);\n\n const scale = document.createElement('div');\n scale.style.cssText = 'display: flex; gap: 4px; justify-content: center; flex-wrap: wrap; margin-bottom: 12px;';\n for (let i = 0; i <= 10; i++) {\n const btn = document.createElement('span');\n btn.style.cssText = `\n width: 28px; height: 28px; border-radius: 6px; display: flex;\n align-items: center; justify-content: center; font-size: 11px;\n font-weight: 600; cursor: pointer; background: ${text}33; color: ${text};\n transition: transform 0.1s;\n `;\n btn.textContent = String(i);\n btn.addEventListener('click', () => {\n this.trackEvent(campaign.id, 'clicked');\n });\n scale.appendChild(btn);\n }\n body.appendChild(scale);\n\n const labels = document.createElement('div');\n labels.style.cssText = 'display: flex; justify-content: space-between; font-size: 11px; opacity: 0.6; margin-bottom: 16px;';\n const notLikely = document.createElement('span');\n notLikely.textContent = 'Not likely';\n const veryLikely = document.createElement('span');\n veryLikely.textContent = 'Very likely';\n labels.appendChild(notLikely);\n labels.appendChild(veryLikely);\n body.appendChild(labels);\n\n this.addCloseButton(body, overlay, campaign.id);\n modal.appendChild(body);\n overlay.appendChild(modal);\n this.addAnimationStyles();\n document.body.appendChild(overlay);\n }\n\n private renderCountdownOffer(\n campaign: InAppCampaign,\n ic: Record<string, unknown>,\n bg: string,\n text: string\n ): void {\n const overlay = this.createOverlay('aegis-in-app-countdown-overlay');\n const modal = document.createElement('div');\n modal.style.cssText = `\n max-width: 320px; width: 90%; border-radius: 16px; overflow: hidden;\n background: ${bg}; color: ${text}; animation: aegisScaleIn 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.15);\n `;\n\n const body = document.createElement('div');\n body.style.cssText = 'padding: 24px; text-align: center;';\n\n const title = document.createElement('div');\n title.style.cssText = 'font-size: 20px; font-weight: 700; margin-bottom: 8px;';\n title.textContent = campaign.title || 'Flash Sale';\n body.appendChild(title);\n\n const label = document.createElement('div');\n label.style.cssText = 'font-size: 13px; opacity: 0.8; margin-bottom: 12px;';\n label.textContent = (ic.countdown_label as string) || 'Sale ends in:';\n body.appendChild(label);\n\n // Countdown digits\n const digits = document.createElement('div');\n digits.style.cssText = 'display: flex; gap: 8px; justify-content: center; margin-bottom: 16px;';\n const digitStyle = `padding: 8px 12px; border-radius: 8px; font-size: 24px; font-weight: 700; font-family: monospace; background: ${text}22;`;\n for (const val of ['00', ':', '00', ':', '00']) {\n const el = document.createElement('span');\n if (val === ':') {\n el.style.cssText = 'font-size: 24px; font-weight: 700; align-self: center;';\n } else {\n el.style.cssText = digitStyle;\n }\n el.textContent = val;\n digits.appendChild(el);\n }\n body.appendChild(digits);\n\n // Start countdown from target or 2h default\n const targetStr = ic.countdown_target as string | undefined;\n if (targetStr) {\n const target = new Date(targetStr).getTime();\n const update = () => {\n const diff = Math.max(0, target - Date.now());\n const h = String(Math.floor(diff / 3600000)).padStart(2, '0');\n const m = String(Math.floor((diff % 3600000) / 60000)).padStart(2, '0');\n const s = String(Math.floor((diff % 60000) / 1000)).padStart(2, '0');\n const spans = digits.querySelectorAll('span');\n if (spans.length >= 5) {\n spans[0].textContent = h;\n spans[2].textContent = m;\n spans[4].textContent = s;\n }\n if (diff > 0) requestAnimationFrame(update);\n };\n update();\n }\n\n if (campaign.body) {\n const desc = document.createElement('div');\n desc.style.cssText = 'font-size: 14px; opacity: 0.85; margin-bottom: 16px;';\n desc.textContent = campaign.body;\n body.appendChild(desc);\n }\n\n if (campaign.button_text) {\n const btn = this.createCTAButton(campaign, bg, text);\n body.appendChild(btn);\n }\n\n this.addCloseButton(body, overlay, campaign.id);\n modal.appendChild(body);\n overlay.appendChild(modal);\n this.addAnimationStyles();\n document.body.appendChild(overlay);\n }\n\n private renderStarRating(\n campaign: InAppCampaign,\n ic: Record<string, unknown>,\n bg: string,\n text: string\n ): void {\n const overlay = this.createOverlay('aegis-in-app-rating-overlay');\n const modal = document.createElement('div');\n modal.style.cssText = `\n max-width: 320px; width: 90%; border-radius: 16px; overflow: hidden;\n background: ${bg}; color: ${text}; animation: aegisScaleIn 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.15);\n `;\n\n const body = document.createElement('div');\n body.style.cssText = 'padding: 24px; text-align: center;';\n\n const title = document.createElement('div');\n title.style.cssText = 'font-size: 18px; font-weight: 700; margin-bottom: 16px;';\n title.textContent = campaign.title || 'Rate your experience';\n body.appendChild(title);\n\n const stars = document.createElement('div');\n stars.style.cssText = 'display: flex; gap: 8px; justify-content: center; margin-bottom: 16px;';\n const maxStars = (ic.rating_scale as number) || 5;\n for (let i = 1; i <= maxStars; i++) {\n const star = document.createElement('span');\n star.style.cssText = 'font-size: 32px; cursor: pointer; transition: transform 0.1s;';\n star.textContent = '\\u2606'; // ☆\n star.addEventListener('click', () => {\n this.trackEvent(campaign.id, 'clicked');\n });\n star.addEventListener('mouseenter', () => { star.style.transform = 'scale(1.2)'; });\n star.addEventListener('mouseleave', () => { star.style.transform = 'scale(1)'; });\n stars.appendChild(star);\n }\n body.appendChild(stars);\n\n this.addCloseButton(body, overlay, campaign.id);\n modal.appendChild(body);\n overlay.appendChild(modal);\n this.addAnimationStyles();\n document.body.appendChild(overlay);\n }\n\n private renderQuickPoll(\n campaign: InAppCampaign,\n ic: Record<string, unknown>,\n bg: string,\n text: string\n ): void {\n const overlay = this.createOverlay('aegis-in-app-poll-overlay');\n const modal = document.createElement('div');\n modal.style.cssText = `\n max-width: 320px; width: 90%; border-radius: 16px; overflow: hidden;\n background: ${bg}; color: ${text}; animation: aegisScaleIn 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.15);\n `;\n\n const body = document.createElement('div');\n body.style.cssText = 'padding: 24px; text-align: center;';\n\n const title = document.createElement('div');\n title.style.cssText = 'font-size: 16px; font-weight: 700; margin-bottom: 16px;';\n title.textContent = campaign.title || 'Quick question';\n body.appendChild(title);\n\n const options = (ic.poll_options as string[]) || [];\n const optionsList = document.createElement('div');\n optionsList.style.cssText = 'display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px;';\n for (const opt of options) {\n const optBtn = document.createElement('button');\n optBtn.style.cssText = `\n padding: 10px 16px; border-radius: 10px; border: 1px solid ${text}33;\n background: transparent; color: ${text}; font-size: 14px; cursor: pointer;\n text-align: left; transition: background 0.15s;\n `;\n optBtn.textContent = opt;\n optBtn.addEventListener('click', () => {\n this.trackEvent(campaign.id, 'clicked');\n });\n optionsList.appendChild(optBtn);\n }\n body.appendChild(optionsList);\n\n this.addCloseButton(body, overlay, campaign.id);\n modal.appendChild(body);\n overlay.appendChild(modal);\n this.addAnimationStyles();\n document.body.appendChild(overlay);\n }\n\n private renderQuiz(\n campaign: InAppCampaign,\n ic: Record<string, unknown>,\n bg: string,\n text: string\n ): void {\n const overlay = this.createOverlay('aegis-in-app-quiz-overlay');\n const modal = document.createElement('div');\n modal.style.cssText = `\n max-width: 360px; width: 90%; border-radius: 16px; overflow: hidden;\n background: ${bg}; color: ${text}; animation: aegisScaleIn 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.15);\n `;\n\n const body = document.createElement('div');\n body.style.cssText = 'padding: 24px; text-align: center;';\n\n const title = document.createElement('div');\n title.style.cssText = 'font-size: 18px; font-weight: 700; margin-bottom: 8px;';\n title.textContent = campaign.title || 'Quiz';\n body.appendChild(title);\n\n const questions = (ic.questions as Array<{ question: string; options: string[] }>) || [];\n let currentQ = 0;\n\n const renderQuestion = () => {\n // Clear previous content except title\n while (body.childNodes.length > 1) {\n body.removeChild(body.lastChild!);\n }\n\n if (currentQ >= questions.length) {\n const result = document.createElement('div');\n result.style.cssText = 'font-size: 16px; margin: 16px 0;';\n result.textContent = (ic.thank_you_message as string) || 'Thanks for completing the quiz!';\n body.appendChild(result);\n this.trackEvent(campaign.id, 'clicked');\n this.addCloseButton(body, overlay, campaign.id);\n return;\n }\n\n const q = questions[currentQ];\n const progress = document.createElement('div');\n progress.style.cssText = 'font-size: 12px; opacity: 0.6; margin-bottom: 12px;';\n progress.textContent = `Question ${currentQ + 1} of ${questions.length}`;\n body.appendChild(progress);\n\n const questionText = document.createElement('div');\n questionText.style.cssText = 'font-size: 14px; font-weight: 600; margin-bottom: 16px;';\n questionText.textContent = q.question;\n body.appendChild(questionText);\n\n const optionsDiv = document.createElement('div');\n optionsDiv.style.cssText = 'display: flex; flex-direction: column; gap: 8px;';\n for (const opt of q.options) {\n const optBtn = document.createElement('button');\n optBtn.style.cssText = `\n padding: 10px 16px; border-radius: 10px; border: 1px solid ${text}33;\n background: transparent; color: ${text}; font-size: 14px; cursor: pointer;\n text-align: left; transition: background 0.15s;\n `;\n optBtn.textContent = opt;\n optBtn.addEventListener('click', () => {\n currentQ++;\n renderQuestion();\n });\n optionsDiv.appendChild(optBtn);\n }\n body.appendChild(optionsDiv);\n this.addCloseButton(body, overlay, campaign.id);\n };\n\n renderQuestion();\n modal.appendChild(body);\n overlay.appendChild(modal);\n this.addAnimationStyles();\n document.body.appendChild(overlay);\n }\n\n // --- Shared Rendering Helpers ---\n\n private createOverlay(className: string): HTMLElement {\n const overlay = document.createElement('div');\n overlay.className = className;\n overlay.style.cssText = `\n position: fixed; top: 0; left: 0; right: 0; bottom: 0;\n background: rgba(0,0,0,0.5); display: flex; align-items: center;\n justify-content: center; z-index: 99999; animation: aegisFadeIn 0.3s ease;\n `;\n return overlay;\n }\n\n private createCTAButton(campaign: InAppCampaign, bg: string, text: string): HTMLElement {\n const btn = document.createElement('button');\n btn.style.cssText = `\n display: inline-block; padding: 10px 28px; border-radius: 999px;\n font-size: 14px; font-weight: 600; cursor: pointer; border: none;\n background: ${text}; color: ${bg}; transition: transform 0.15s;\n `;\n btn.textContent = campaign.button_text || 'OK';\n btn.addEventListener('click', () => {\n this.trackEvent(campaign.id, 'clicked');\n if (campaign.action_url) {\n const safeUrl = this.sanitizeUrl(campaign.action_url);\n if (safeUrl) window.open(safeUrl, '_blank');\n }\n });\n return btn;\n }\n\n private addCloseButton(container: HTMLElement, overlay: HTMLElement, campaignId: string): void {\n const close = document.createElement('div');\n close.style.cssText = 'margin-top: 12px; font-size: 12px; opacity: 0.6; cursor: pointer;';\n close.textContent = 'Close';\n close.addEventListener('click', () => {\n this.trackEvent(campaignId, 'dismissed');\n this.removeModal(overlay);\n });\n container.appendChild(close);\n }\n \n private renderBanner(campaign: InAppCampaign): void {\n const banner = document.createElement('div');\n banner.className = 'aegis-in-app-banner';\n banner.setAttribute('data-campaign-id', campaign.id);\n \n banner.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n background: ${this.sanitizeColor(campaign.background_color || '#1a73e8')};\n color: ${this.sanitizeColor(campaign.text_color || '#ffffff')};\n padding: 16px;\n z-index: 999999;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1);\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n animation: aegisSlideDown 0.3s ease-out;\n `;\n \n const contentContainer = document.createElement('div');\n contentContainer.style.cssText = 'flex: 1; display: flex; align-items: center; gap: 12px;';\n \n if (campaign.image_url) {\n const img = document.createElement('img');\n const safeUrl = this.sanitizeUrl(campaign.image_url);\n if (safeUrl) {\n img.src = safeUrl;\n img.alt = '';\n img.style.cssText = 'width: 40px; height: 40px; border-radius: 4px; object-fit: cover;';\n contentContainer.appendChild(img);\n }\n }\n \n const textContainer = document.createElement('div');\n textContainer.style.cssText = 'flex: 1;';\n \n const title = document.createElement('div');\n title.textContent = campaign.title;\n title.style.cssText = 'font-weight: 600; font-size: 14px; margin-bottom: 4px;';\n textContainer.appendChild(title);\n \n const body = document.createElement('div');\n body.textContent = campaign.body;\n body.style.cssText = 'font-size: 13px; opacity: 0.9;';\n textContainer.appendChild(body);\n \n contentContainer.appendChild(textContainer);\n \n const actionsContainer = document.createElement('div');\n actionsContainer.style.cssText = 'display: flex; align-items: center; gap: 12px; margin-left: 16px;';\n \n if (campaign.action_url && campaign.button_text) {\n const ctaButton = document.createElement('button');\n ctaButton.textContent = campaign.button_text;\n ctaButton.style.cssText = `\n background: white;\n color: ${this.sanitizeColor(campaign.background_color || '#1a73e8')};\n border: none;\n padding: 8px 16px;\n border-radius: 4px;\n font-weight: 600;\n cursor: pointer;\n font-size: 13px;\n white-space: nowrap;\n `;\n \n ctaButton.addEventListener('click', () => {\n this.trackEvent(campaign.id, 'clicked');\n const safeUrl = this.sanitizeUrl(campaign.action_url!);\n if (safeUrl) {\n window.location.href = safeUrl;\n }\n this.removeBanner(banner);\n });\n \n actionsContainer.appendChild(ctaButton);\n }\n \n const closeButton = document.createElement('button');\n closeButton.textContent = '✕';\n closeButton.setAttribute('aria-label', 'Close');\n closeButton.style.cssText = `\n background: transparent;\n border: none;\n color: inherit;\n font-size: 20px;\n cursor: pointer;\n padding: 0;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0.7;\n `;\n \n closeButton.addEventListener('click', () => {\n this.trackEvent(campaign.id, 'dismissed');\n this.removeBanner(banner);\n });\n \n actionsContainer.appendChild(closeButton);\n \n banner.appendChild(contentContainer);\n banner.appendChild(actionsContainer);\n \n this.addAnimationStyles();\n document.body.appendChild(banner);\n }\n \n private renderModal(campaign: InAppCampaign): void {\n const overlay = document.createElement('div');\n overlay.className = 'aegis-in-app-modal-overlay';\n overlay.setAttribute('data-campaign-id', campaign.id);\n \n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 1000000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: aegisFadeIn 0.3s ease-out;\n `;\n \n const modal = document.createElement('div');\n modal.className = 'aegis-in-app-modal';\n modal.style.cssText = `\n background: white;\n border-radius: 8px;\n max-width: 500px;\n width: 90%;\n max-height: 80vh;\n overflow: auto;\n box-shadow: 0 10px 40px rgba(0,0,0,0.2);\n animation: aegisScaleIn 0.3s ease-out;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n `;\n \n if (campaign.image_url) {\n const img = document.createElement('img');\n const safeUrl = this.sanitizeUrl(campaign.image_url);\n if (safeUrl) {\n img.src = safeUrl;\n img.alt = '';\n img.style.cssText = 'width: 100%; height: 200px; object-fit: cover; border-radius: 8px 8px 0 0;';\n modal.appendChild(img);\n }\n }\n \n const content = document.createElement('div');\n content.style.cssText = 'padding: 24px;';\n \n const title = document.createElement('h2');\n title.textContent = campaign.title;\n title.style.cssText = 'margin: 0 0 12px 0; font-size: 20px; font-weight: 600; color: #1a1a1a;';\n content.appendChild(title);\n \n const body = document.createElement('p');\n body.textContent = campaign.body;\n body.style.cssText = 'margin: 0 0 20px 0; font-size: 15px; line-height: 1.5; color: #4a4a4a;';\n content.appendChild(body);\n \n const actions = document.createElement('div');\n actions.style.cssText = 'display: flex; gap: 12px; justify-content: flex-end;';\n \n if (campaign.action_url && campaign.button_text) {\n const ctaButton = document.createElement('button');\n ctaButton.textContent = campaign.button_text;\n ctaButton.style.cssText = `\n background: ${this.sanitizeColor(campaign.background_color || '#1a73e8')};\n color: ${this.sanitizeColor(campaign.text_color || '#ffffff')};\n border: none;\n padding: 10px 24px;\n border-radius: 6px;\n font-weight: 600;\n cursor: pointer;\n font-size: 14px;\n `;\n \n ctaButton.addEventListener('click', () => {\n this.trackEvent(campaign.id, 'clicked');\n const safeUrl = this.sanitizeUrl(campaign.action_url!);\n if (safeUrl) {\n window.location.href = safeUrl;\n }\n this.removeModal(overlay);\n });\n \n actions.appendChild(ctaButton);\n }\n \n const closeButton = document.createElement('button');\n closeButton.textContent = 'Close';\n closeButton.style.cssText = `\n background: transparent;\n border: 1px solid #d0d0d0;\n color: #4a4a4a;\n padding: 10px 24px;\n border-radius: 6px;\n font-weight: 600;\n cursor: pointer;\n font-size: 14px;\n `;\n \n closeButton.addEventListener('click', () => {\n this.trackEvent(campaign.id, 'dismissed');\n this.removeModal(overlay);\n });\n \n actions.appendChild(closeButton);\n \n content.appendChild(actions);\n modal.appendChild(content);\n overlay.appendChild(modal);\n \n this.addAnimationStyles();\n document.body.appendChild(overlay);\n }\n \n private renderFullScreen(campaign: InAppCampaign): void {\n const overlay = document.createElement('div');\n overlay.className = 'aegis-in-app-fullscreen-overlay';\n overlay.setAttribute('data-campaign-id', campaign.id);\n \n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: ${this.sanitizeColor(campaign.background_color || '#ffffff')};\n color: ${this.sanitizeColor(campaign.text_color || '#1a1a1a')};\n z-index: 1000001;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n animation: aegisFadeIn 0.3s ease-out;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n overflow-y: auto;\n `;\n \n if (campaign.image_url) {\n const img = document.createElement('img');\n const safeUrl = this.sanitizeUrl(campaign.image_url);\n if (safeUrl) {\n img.src = safeUrl;\n img.alt = '';\n img.style.cssText = 'max-width: 100%; max-height: 40vh; object-fit: contain; margin-bottom: 32px;';\n overlay.appendChild(img);\n }\n }\n \n const contentContainer = document.createElement('div');\n contentContainer.style.cssText = 'max-width: 600px; text-align: center;';\n \n const title = document.createElement('h1');\n title.textContent = campaign.title;\n title.style.cssText = 'margin: 0 0 16px 0; font-size: 32px; font-weight: 700;';\n contentContainer.appendChild(title);\n \n const body = document.createElement('p');\n body.textContent = campaign.body;\n body.style.cssText = 'margin: 0 0 32px 0; font-size: 18px; line-height: 1.6; opacity: 0.9;';\n contentContainer.appendChild(body);\n \n if (campaign.action_url && campaign.button_text) {\n const ctaButton = document.createElement('button');\n ctaButton.textContent = campaign.button_text;\n ctaButton.style.cssText = `\n background: ${this.sanitizeColor(campaign.text_color || '#1a73e8')};\n color: ${this.sanitizeColor(campaign.background_color || '#ffffff')};\n border: none;\n padding: 16px 48px;\n border-radius: 8px;\n font-weight: 700;\n font-size: 18px;\n cursor: pointer;\n margin-bottom: 16px;\n `;\n \n ctaButton.addEventListener('click', () => {\n this.trackEvent(campaign.id, 'clicked');\n const safeUrl = this.sanitizeUrl(campaign.action_url!);\n if (safeUrl) {\n window.location.href = safeUrl;\n }\n this.removeModal(overlay);\n });\n \n contentContainer.appendChild(ctaButton);\n }\n \n overlay.appendChild(contentContainer);\n \n const closeButton = document.createElement('button');\n closeButton.textContent = '✕';\n closeButton.setAttribute('aria-label', 'Close');\n closeButton.style.cssText = `\n position: absolute;\n top: 20px;\n right: 20px;\n background: transparent;\n border: none;\n color: inherit;\n font-size: 32px;\n cursor: pointer;\n padding: 0;\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0.6;\n `;\n \n closeButton.addEventListener('click', () => {\n this.trackEvent(campaign.id, 'dismissed');\n this.removeModal(overlay);\n });\n \n overlay.appendChild(closeButton);\n \n this.addAnimationStyles();\n document.body.appendChild(overlay);\n }\n \n private renderHalfInterstitial(campaign: InAppCampaign): void {\n const overlay = document.createElement('div');\n overlay.className = 'aegis-in-app-half-interstitial-overlay';\n overlay.setAttribute('data-campaign-id', campaign.id);\n \n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 1000000;\n display: flex;\n align-items: flex-end;\n justify-content: center;\n animation: aegisFadeIn 0.3s ease-out;\n `;\n \n const modal = document.createElement('div');\n modal.className = 'aegis-in-app-half-interstitial';\n modal.style.cssText = `\n background: white;\n border-radius: 16px 16px 0 0;\n width: 100%;\n max-width: 600px;\n max-height: 60vh;\n overflow: auto;\n box-shadow: 0 -4px 20px rgba(0,0,0,0.2);\n animation: aegisSlideUp 0.3s ease-out;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n `;\n \n if (campaign.image_url) {\n const img = document.createElement('img');\n const safeUrl = this.sanitizeUrl(campaign.image_url);\n if (safeUrl) {\n img.src = safeUrl;\n img.alt = '';\n img.style.cssText = 'width: 100%; height: 200px; object-fit: cover;';\n modal.appendChild(img);\n }\n }\n \n const content = document.createElement('div');\n content.style.cssText = 'padding: 32px 24px;';\n \n const title = document.createElement('h2');\n title.textContent = campaign.title;\n title.style.cssText = 'margin: 0 0 12px 0; font-size: 24px; font-weight: 700; color: #1a1a1a;';\n content.appendChild(title);\n \n const body = document.createElement('p');\n body.textContent = campaign.body;\n body.style.cssText = 'margin: 0 0 24px 0; font-size: 16px; line-height: 1.5; color: #4a4a4a;';\n content.appendChild(body);\n \n if (campaign.action_url && campaign.button_text) {\n const ctaButton = document.createElement('button');\n ctaButton.textContent = campaign.button_text;\n ctaButton.style.cssText = `\n background: ${this.sanitizeColor(campaign.background_color || '#1a73e8')};\n color: ${this.sanitizeColor(campaign.text_color || '#ffffff')};\n border: none;\n padding: 14px 32px;\n border-radius: 8px;\n font-weight: 700;\n font-size: 16px;\n cursor: pointer;\n width: 100%;\n `;\n \n ctaButton.addEventListener('click', () => {\n this.trackEvent(campaign.id, 'clicked');\n const safeUrl = this.sanitizeUrl(campaign.action_url!);\n if (safeUrl) {\n window.location.href = safeUrl;\n }\n this.removeModal(overlay);\n });\n \n content.appendChild(ctaButton);\n }\n \n modal.appendChild(content);\n \n const closeButton = document.createElement('button');\n closeButton.textContent = '✕';\n closeButton.setAttribute('aria-label', 'Close');\n closeButton.style.cssText = `\n position: absolute;\n top: 16px;\n right: 16px;\n background: rgba(255,255,255,0.9);\n border: none;\n color: #333;\n font-size: 24px;\n cursor: pointer;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 2px 8px rgba(0,0,0,0.2);\n `;\n \n closeButton.addEventListener('click', () => {\n this.trackEvent(campaign.id, 'dismissed');\n this.removeModal(overlay);\n });\n \n modal.style.position = 'relative';\n modal.appendChild(closeButton);\n \n overlay.appendChild(modal);\n \n this.addAnimationStyles();\n document.body.appendChild(overlay);\n }\n \n private renderAlert(campaign: InAppCampaign): void {\n const overlay = document.createElement('div');\n overlay.className = 'aegis-in-app-alert-overlay';\n overlay.setAttribute('data-campaign-id', campaign.id);\n \n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.6);\n z-index: 1000000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: aegisFadeIn 0.2s ease-out;\n `;\n \n const alert = document.createElement('div');\n alert.className = 'aegis-in-app-alert';\n alert.style.cssText = `\n background: white;\n border-radius: 12px;\n max-width: 320px;\n width: 85%;\n box-shadow: 0 10px 40px rgba(0,0,0,0.3);\n animation: aegisScaleIn 0.2s ease-out;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n overflow: hidden;\n `;\n \n const content = document.createElement('div');\n content.style.cssText = 'padding: 24px 20px; text-align: center;';\n \n const title = document.createElement('h3');\n title.textContent = campaign.title;\n title.style.cssText = 'margin: 0 0 8px 0; font-size: 18px; font-weight: 700; color: #1a1a1a;';\n content.appendChild(title);\n \n const body = document.createElement('p');\n body.textContent = campaign.body;\n body.style.cssText = 'margin: 0; font-size: 14px; line-height: 1.4; color: #666;';\n content.appendChild(body);\n \n alert.appendChild(content);\n \n const buttonContainer = document.createElement('div');\n buttonContainer.style.cssText = 'display: flex; border-top: 1px solid #e0e0e0;';\n \n if (campaign.action_url && campaign.button_text) {\n const ctaButton = document.createElement('button');\n ctaButton.textContent = campaign.button_text;\n ctaButton.style.cssText = `\n flex: 1;\n background: transparent;\n border: none;\n border-right: 1px solid #e0e0e0;\n color: #1a73e8;\n padding: 14px;\n font-weight: 600;\n font-size: 16px;\n cursor: pointer;\n `;\n \n ctaButton.addEventListener('click', () => {\n this.trackEvent(campaign.id, 'clicked');\n const safeUrl = this.sanitizeUrl(campaign.action_url!);\n if (safeUrl) {\n window.location.href = safeUrl;\n }\n this.removeModal(overlay);\n });\n \n buttonContainer.appendChild(ctaButton);\n }\n \n const cancelButton = document.createElement('button');\n cancelButton.textContent = 'Cancel';\n cancelButton.style.cssText = `\n flex: 1;\n background: transparent;\n border: none;\n color: #666;\n padding: 14px;\n font-weight: 600;\n font-size: 16px;\n cursor: pointer;\n `;\n \n cancelButton.addEventListener('click', () => {\n this.trackEvent(campaign.id, 'dismissed');\n this.removeModal(overlay);\n });\n \n buttonContainer.appendChild(cancelButton);\n \n alert.appendChild(buttonContainer);\n overlay.appendChild(alert);\n \n this.addAnimationStyles();\n document.body.appendChild(overlay);\n }\n \n private renderPIP(campaign: InAppCampaign): void {\n const pip = document.createElement('div');\n pip.className = 'aegis-in-app-pip';\n pip.setAttribute('data-campaign-id', campaign.id);\n \n pip.style.cssText = `\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 320px;\n background: black;\n border-radius: 12px;\n overflow: hidden;\n box-shadow: 0 8px 24px rgba(0,0,0,0.3);\n z-index: 999999;\n animation: aegisSlideUp 0.3s ease-out;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n `;\n \n if (campaign.video_url) {\n const video = document.createElement('video');\n const safeUrl = this.sanitizeUrl(campaign.video_url);\n if (safeUrl) {\n video.src = safeUrl;\n video.controls = true;\n video.autoplay = true;\n video.muted = true;\n video.style.cssText = 'width: 100%; display: block;';\n pip.appendChild(video);\n }\n } else if (campaign.image_url) {\n const img = document.createElement('img');\n const safeUrl = this.sanitizeUrl(campaign.image_url);\n if (safeUrl) {\n img.src = safeUrl;\n img.alt = '';\n img.style.cssText = 'width: 100%; display: block;';\n pip.appendChild(img);\n }\n }\n \n const overlay = document.createElement('div');\n overlay.style.cssText = `\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n background: linear-gradient(to top, rgba(0,0,0,0.9), transparent);\n padding: 40px 16px 16px;\n color: white;\n `;\n \n const title = document.createElement('div');\n title.textContent = campaign.title;\n title.style.cssText = 'font-size: 14px; font-weight: 600; margin-bottom: 4px;';\n overlay.appendChild(title);\n \n const body = document.createElement('div');\n body.textContent = campaign.body;\n body.style.cssText = 'font-size: 12px; opacity: 0.9;';\n overlay.appendChild(body);\n \n pip.appendChild(overlay);\n \n const closeButton = document.createElement('button');\n closeButton.textContent = '✕';\n closeButton.setAttribute('aria-label', 'Close');\n closeButton.style.cssText = `\n position: absolute;\n top: 8px;\n right: 8px;\n background: rgba(0,0,0,0.6);\n border: none;\n color: white;\n font-size: 18px;\n cursor: pointer;\n width: 28px;\n height: 28px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n `;\n \n closeButton.addEventListener('click', () => {\n this.trackEvent(campaign.id, 'dismissed');\n pip.style.animation = 'aegisSlideDown 0.3s ease-out';\n setTimeout(() => {\n if (pip.parentNode) {\n pip.parentNode.removeChild(pip);\n }\n }, 300);\n });\n \n pip.appendChild(closeButton);\n \n if (campaign.action_url) {\n pip.style.cursor = 'pointer';\n pip.addEventListener('click', (e) => {\n if (e.target !== closeButton) {\n this.trackEvent(campaign.id, 'clicked');\n const safeUrl = this.sanitizeUrl(campaign.action_url!);\n if (safeUrl) {\n window.open(safeUrl, '_blank');\n }\n }\n });\n }\n \n this.addAnimationStyles();\n document.body.appendChild(pip);\n }\n \n private removeBanner(banner: HTMLElement): void {\n banner.style.animation = 'aegisSlideUp 0.3s ease-out';\n setTimeout(() => {\n if (banner.parentNode) {\n banner.parentNode.removeChild(banner);\n }\n }, 300);\n }\n \n private removeModal(overlay: HTMLElement): void {\n overlay.style.animation = 'aegisFadeOut 0.3s ease-out';\n setTimeout(() => {\n if (overlay.parentNode) {\n overlay.parentNode.removeChild(overlay);\n }\n }, 300);\n }\n \n private renderTooltip(campaign: InAppCampaign): void {\n const ic = (campaign.interactive_config || {}) as Record<string, unknown>;\n const anchorSelector = (ic.tooltip_anchor_selector as string) || '[data-aegis-tooltip]';\n const preferredPosition = (ic.tooltip_position as string) || 'bottom'; // top | bottom | left | right\n\n const anchor = document.querySelector(anchorSelector);\n if (!anchor) {\n this.log(`Tooltip anchor not found: ${anchorSelector}`, 'warn');\n return;\n }\n\n const bg = this.sanitizeColor(campaign.background_color || '#1a1a1a');\n const textColor = this.sanitizeColor(campaign.text_color || '#ffffff');\n\n // Tooltip container (positioned absolute to body)\n const tooltip = document.createElement('div');\n tooltip.className = 'aegis-in-app-tooltip';\n tooltip.setAttribute('data-campaign-id', campaign.id);\n tooltip.style.cssText = `\n position: absolute; z-index: 1000001; max-width: 280px; width: max-content;\n background: ${bg}; color: ${textColor}; border-radius: 10px; padding: 14px 16px;\n box-shadow: 0 8px 24px rgba(0,0,0,0.18); font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n animation: aegisScaleIn 0.2s ease-out; pointer-events: auto;\n `;\n\n // Arrow\n const arrow = document.createElement('div');\n arrow.className = 'aegis-tooltip-arrow';\n arrow.style.cssText = `\n position: absolute; width: 10px; height: 10px; background: ${bg};\n transform: rotate(45deg);\n `;\n\n // Close button\n const closeBtn = document.createElement('button');\n closeBtn.textContent = '\\u00d7';\n closeBtn.style.cssText = `\n position: absolute; top: 6px; right: 8px; background: none; border: none;\n color: ${textColor}; opacity: 0.6; font-size: 16px; cursor: pointer; padding: 0; line-height: 1;\n `;\n\n const dismiss = () => {\n tooltip.style.animation = 'aegisFadeOut 0.2s ease-out';\n setTimeout(() => { tooltip.parentNode?.removeChild(tooltip); }, 200);\n this.trackEvent(campaign.id, 'dismissed');\n };\n\n closeBtn.addEventListener('click', (e) => { e.stopPropagation(); dismiss(); });\n\n // Title\n if (campaign.title) {\n const title = document.createElement('div');\n title.textContent = campaign.title;\n title.style.cssText = 'font-size: 13px; font-weight: 700; margin-bottom: 4px; padding-right: 16px;';\n tooltip.appendChild(title);\n }\n\n // Body\n const body = document.createElement('div');\n body.textContent = campaign.body;\n body.style.cssText = 'font-size: 12px; line-height: 1.4; opacity: 0.9;';\n tooltip.appendChild(body);\n\n // CTA button\n if (campaign.button_text && campaign.action_url) {\n const cta = document.createElement('a');\n cta.textContent = campaign.button_text;\n cta.href = campaign.action_url;\n cta.style.cssText = `\n display: inline-block; margin-top: 8px; font-size: 12px; font-weight: 600;\n color: ${textColor}; text-decoration: underline; cursor: pointer;\n `;\n cta.addEventListener('click', () => { this.trackEvent(campaign.id, 'clicked'); });\n tooltip.appendChild(cta);\n }\n\n tooltip.appendChild(closeBtn);\n tooltip.appendChild(arrow);\n document.body.appendChild(tooltip);\n\n // Position relative to anchor\n const anchorRect = anchor.getBoundingClientRect();\n const tooltipRect = tooltip.getBoundingClientRect();\n const scrollX = window.scrollX;\n const scrollY = window.scrollY;\n const gap = 10;\n\n let top = 0;\n let left = 0;\n let arrowTop = '';\n let arrowLeft = '';\n let arrowBottom = '';\n let arrowRight = '';\n\n switch (preferredPosition) {\n case 'top':\n top = anchorRect.top + scrollY - tooltipRect.height - gap;\n left = anchorRect.left + scrollX + (anchorRect.width - tooltipRect.width) / 2;\n arrowBottom = '-5px';\n arrowLeft = `${tooltipRect.width / 2 - 5}px`;\n break;\n case 'left':\n top = anchorRect.top + scrollY + (anchorRect.height - tooltipRect.height) / 2;\n left = anchorRect.left + scrollX - tooltipRect.width - gap;\n arrowRight = '-5px';\n arrowTop = `${tooltipRect.height / 2 - 5}px`;\n break;\n case 'right':\n top = anchorRect.top + scrollY + (anchorRect.height - tooltipRect.height) / 2;\n left = anchorRect.right + scrollX + gap;\n arrowLeft = '-5px';\n arrowTop = `${tooltipRect.height / 2 - 5}px`;\n break;\n default: // bottom\n top = anchorRect.bottom + scrollY + gap;\n left = anchorRect.left + scrollX + (anchorRect.width - tooltipRect.width) / 2;\n arrowTop = '-5px';\n arrowLeft = `${tooltipRect.width / 2 - 5}px`;\n break;\n }\n\n // Clamp to viewport\n left = Math.max(8, Math.min(left, window.innerWidth + scrollX - tooltipRect.width - 8));\n top = Math.max(8, top);\n\n tooltip.style.top = `${top}px`;\n tooltip.style.left = `${left}px`;\n arrow.style.top = arrowTop || '';\n arrow.style.left = arrowLeft || '';\n arrow.style.bottom = arrowBottom || '';\n arrow.style.right = arrowRight || '';\n\n // Dismiss on outside click\n const outsideClickHandler = (e: MouseEvent) => {\n if (!tooltip.contains(e.target as Node) && !anchor.contains(e.target as Node)) {\n document.removeEventListener('click', outsideClickHandler);\n dismiss();\n }\n };\n setTimeout(() => document.addEventListener('click', outsideClickHandler), 100);\n }\n\n private addAnimationStyles(): void {\n if (document.getElementById('aegis-in-app-styles')) {\n return;\n }\n \n const style = document.createElement('style');\n style.id = 'aegis-in-app-styles';\n style.textContent = `\n @keyframes aegisSlideDown {\n from { transform: translateY(-100%); opacity: 0; }\n to { transform: translateY(0); opacity: 1; }\n }\n \n @keyframes aegisSlideUp {\n from { transform: translateY(0); opacity: 1; }\n to { transform: translateY(-100%); opacity: 0; }\n }\n \n @keyframes aegisFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n \n @keyframes aegisFadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n }\n \n @keyframes aegisScaleIn {\n from { transform: scale(0.9); opacity: 0; }\n to { transform: scale(1); opacity: 1; }\n }\n `;\n \n document.head.appendChild(style);\n }\n \n private sanitizeUrl(url: string): string | null {\n try {\n const parsedUrl = new URL(url, window.location.origin);\n \n if (parsedUrl.protocol === 'javascript:' || parsedUrl.protocol === 'data:') {\n this.log(`Blocked unsafe URL: ${url}`, 'error');\n return null;\n }\n \n return parsedUrl.href;\n } catch (error) {\n this.log(`Invalid URL: ${url}`, 'error');\n return null;\n }\n }\n \n private sanitizeColor(color: string): string {\n if (/^#[0-9A-Fa-f]{3,6}$/.test(color)) {\n return color;\n }\n \n if (/^rgb\\(\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*\\d+\\s*\\)$/.test(color)) {\n return color;\n }\n \n if (/^rgba\\(\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*[\\d.]+\\s*\\)$/.test(color)) {\n return color;\n }\n \n const namedColors = ['white', 'black', 'red', 'green', 'blue', 'yellow', 'orange', 'purple', 'pink', 'gray', 'transparent'];\n if (namedColors.includes(color.toLowerCase())) {\n return color;\n }\n \n return '#000000';\n }\n \n /**\n * Track in-app event via the standard Event Ingress pipeline.\n *\n * Events flow: SDK → Event Ingress → Kafka → Governance Consumer\n * → Event Engine → ClickHouse (in_app_events + events_with_ttl)\n *\n * The event_type uses the canonical prefix `in_app.` so the event\n * switchboard maps it to the correct canonical form:\n * in_app.impression → engagement.view\n * in_app.clicked → engagement.click\n * in_app.dismissed → engagement.dismiss\n */\n private async trackEvent(campaignId: string, eventType: 'impression' | 'clicked' | 'dismissed'): Promise<void> {\n try {\n const url = `${this.apiHost}/api/v1/events`;\n const now = new Date().toISOString();\n const externalEventId = `inapp_${campaignId}_${eventType}_${Date.now()}`;\n\n const ingressEvent = {\n tenant_id: this.organizationId || 'unknown',\n source: 'in_app_sdk',\n external_event_id: externalEventId,\n event_type: `in_app.${eventType}`,\n timestamp: now,\n payload: {\n campaign_id: campaignId,\n event_type: eventType,\n user_id: this.userId,\n contact_id: this.contactId,\n platform: 'web',\n variant_id: this.getVariantId(campaignId) ?? undefined,\n },\n trace_id: externalEventId,\n metadata: {\n write_key: this.writeKey,\n },\n };\n\n fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Aegis-Write-Key': this.writeKey,\n },\n body: JSON.stringify(ingressEvent),\n }).catch(error => {\n this.log(`Error tracking event: ${error}`, 'error');\n });\n\n this.log(`Tracked ${eventType} event for campaign ${campaignId}`);\n } catch (error) {\n this.log(`Error tracking event: ${error}`, 'error');\n }\n }\n \n private log(message: string, level: 'log' | 'warn' | 'error' = 'log'): void {\n if (this.debugMode) {\n console[level](`[AegisInApp] ${message}`);\n }\n }\n \n destroy(options?: { clearABState?: boolean }): void {\n this.disconnectSSE();\n\n document.querySelectorAll(\n '.aegis-in-app-banner, .aegis-in-app-modal-overlay, .aegis-in-app-fullscreen-overlay, ' +\n '.aegis-in-app-half-interstitial-overlay, .aegis-in-app-alert-overlay, .aegis-in-app-pip, ' +\n '.aegis-in-app-nps-overlay, .aegis-in-app-countdown-overlay, .aegis-in-app-rating-overlay, ' +\n '.aegis-in-app-poll-overlay, .aegis-in-app-quiz-overlay'\n ).forEach(el => {\n if (el.parentNode) {\n el.parentNode.removeChild(el);\n }\n });\n\n const styles = document.getElementById('aegis-in-app-styles');\n if (styles && styles.parentNode) {\n styles.parentNode.removeChild(styles);\n }\n\n // Optionally clear A/B assignment state\n if (options?.clearABState && typeof localStorage !== 'undefined') {\n localStorage.removeItem('aegis_ab_assignments');\n }\n\n this.isInitialized = false;\n this.log('AegisInApp destroyed');\n }\n}\n","/**\n * AegisPlacementManager - Web SDK Placement Module\n * \n * Real-time SSE architecture for inline content placements.\n * \n * Security:\n * - XSS Protection: Uses DOM APIs (createElement, textContent) instead of innerHTML\n * - URL Validation: Prevents javascript: protocol injection\n * - CSP Compatible: No inline styles in HTML strings\n * \n * Architecture:\n * - Connects to SSE endpoint for real-time placement updates\n * - Initial fetch on load, then SSE for updates\n * - Caches placement content locally in memory\n * - Renders content into pre-defined UI slots (inline, not overlay)\n * - Tracks events (impression, click, conversion) asynchronously\n * \n * Key Differences from In-App Messages:\n * - INLINE content (part of layout), not overlays\n * - Content rendered immediately on slot registration\n * - No trigger rules (shown when slot loads)\n * - Supports banner, card, carousel, video, HTML content types\n */\n\nexport interface PlacementContent {\n placement_id: string;\n variant_id: string;\n content_type: 'banner' | 'card' | 'carousel' | 'video' | 'html' | 'dynamic_injection';\n content: Record<string, any>;\n css_selector?: string;\n injection_mode?: 'replace' | 'append' | 'prepend';\n}\n\nexport interface PlacementSlot {\n placementId: string;\n containerId: string;\n fallbackContent?: string;\n onRender?: (content: PlacementContent) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface AegisPlacementConfig {\n writeKey: string;\n apiHost?: string;\n userId?: string;\n contactId?: string;\n organizationId?: string;\n debugMode?: boolean;\n enableSSE?: boolean;\n}\n\nexport class AegisPlacementManager {\n private writeKey: string;\n private apiHost: string;\n private userId?: string;\n private contactId?: string;\n private organizationId?: string;\n private debugMode: boolean;\n private enableSSE: boolean;\n \n private placements: Map<string, PlacementContent> = new Map();\n private slots: Map<string, PlacementSlot> = new Map();\n private renderedSlots = new Set<string>();\n private eventSource?: EventSource;\n private isInitialized = false;\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n \n constructor(config: AegisPlacementConfig) {\n this.writeKey = config.writeKey;\n this.apiHost = config.apiHost || 'https://api.aegis.ai';\n this.userId = config.userId;\n this.contactId = config.contactId;\n this.organizationId = config.organizationId;\n this.debugMode = config.debugMode || false;\n this.enableSSE = config.enableSSE !== false;\n }\n \n async initialize(): Promise<void> {\n if (this.isInitialized) {\n this.log('AegisPlacements already initialized');\n return;\n }\n \n await this.refreshPlacements();\n \n if (this.enableSSE && this.organizationId) {\n this.connectSSE();\n }\n \n this.isInitialized = true;\n this.log('AegisPlacements initialized successfully');\n }\n \n register(placementId: string, options: Omit<PlacementSlot, 'placementId'>): void {\n const slot: PlacementSlot = {\n placementId,\n ...options\n };\n \n this.slots.set(placementId, slot);\n this.log(`Registered placement slot: ${placementId}`);\n \n const existingContent = this.placements.get(placementId);\n if (existingContent) {\n this.renderSlot(slot, existingContent);\n } else if (options.fallbackContent) {\n this.renderFallback(slot);\n }\n }\n \n unregister(placementId: string): void {\n this.slots.delete(placementId);\n this.renderedSlots.delete(placementId);\n this.log(`Unregistered placement slot: ${placementId}`);\n }\n \n async refreshPlacements(): Promise<void> {\n try {\n const placementIds = Array.from(this.slots.keys());\n \n if (placementIds.length === 0) {\n this.log('No registered slots, skipping refresh');\n return;\n }\n \n const url = `${this.apiHost}/v1/placements/content?placement_ids=${placementIds.join(',')}`;\n \n const headers: Record<string, string> = {\n 'X-Aegis-Write-Key': this.writeKey,\n 'X-Device-Type': this.getDeviceType(),\n 'X-Platform': 'web'\n };\n \n if (this.userId) headers['X-User-ID'] = this.userId;\n if (this.contactId) headers['X-Contact-ID'] = this.contactId;\n if (this.organizationId) headers['X-Organization-ID'] = this.organizationId;\n \n const response = await fetch(url, { headers });\n \n if (!response.ok) {\n throw new Error(`Failed to fetch placements: ${response.status}`);\n }\n \n const data = await response.json();\n \n this.placements.clear();\n \n for (const placement of data.placements || []) {\n this.placements.set(placement.placement_id, placement);\n }\n \n this.renderAllSlots();\n \n this.log(`Refreshed ${this.placements.size} placements`);\n \n } catch (error) {\n this.log(`Error refreshing placements: ${error}`, true);\n }\n }\n \n private renderAllSlots(): void {\n for (const [placementId, slot] of this.slots.entries()) {\n const content = this.placements.get(placementId);\n \n if (content) {\n this.renderSlot(slot, content);\n } else if (slot.fallbackContent) {\n this.renderFallback(slot);\n }\n }\n }\n \n private renderSlot(slot: PlacementSlot, content: PlacementContent): void {\n try {\n if (content.content_type === 'dynamic_injection') {\n this.renderDynamicInjection(content);\n } else {\n const container = document.getElementById(slot.containerId);\n \n if (!container) {\n this.log(`Container not found: ${slot.containerId}`, true);\n return;\n }\n \n container.innerHTML = '';\n \n switch (content.content_type) {\n case 'banner':\n this.renderBanner(container, content);\n break;\n case 'card':\n this.renderCard(container, content);\n break;\n case 'carousel':\n this.renderCarousel(container, content);\n break;\n case 'video':\n this.renderVideo(container, content);\n break;\n case 'html':\n this.renderHTML(container, content);\n break;\n default:\n this.log(`Unknown content type: ${content.content_type}`, true);\n return;\n }\n }\n \n if (!this.renderedSlots.has(slot.placementId)) {\n this.trackEvent(content.placement_id, content.variant_id, 'impression');\n this.renderedSlots.add(slot.placementId);\n }\n \n if (slot.onRender) {\n slot.onRender(content);\n }\n \n this.log(`Rendered placement: ${content.placement_id} (${content.content_type})`);\n \n } catch (error) {\n this.log(`Error rendering placement: ${error}`, true);\n \n if (slot.onError) {\n slot.onError(error as Error);\n }\n }\n }\n \n private renderBanner(container: HTMLElement, content: PlacementContent): void {\n const { title, body, image_url, cta_text, cta_url, background_color, text_color } = content.content;\n \n const banner = document.createElement('div');\n banner.className = 'aegis-placement-banner';\n banner.style.cssText = `\n background: ${this.sanitizeColor(background_color || '#1a73e8')};\n color: ${this.sanitizeColor(text_color || '#ffffff')};\n padding: 24px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n gap: 16px;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n `;\n \n if (image_url) {\n const img = document.createElement('img');\n const safeUrl = this.sanitizeUrl(image_url);\n if (safeUrl) {\n img.src = safeUrl;\n img.alt = '';\n img.style.cssText = 'width: 80px; height: 80px; border-radius: 8px; object-fit: cover;';\n banner.appendChild(img);\n }\n }\n \n const textContainer = document.createElement('div');\n textContainer.style.cssText = 'flex: 1;';\n \n if (title) {\n const titleEl = document.createElement('div');\n titleEl.textContent = title;\n titleEl.style.cssText = 'font-size: 18px; font-weight: 600; margin-bottom: 8px;';\n textContainer.appendChild(titleEl);\n }\n \n if (body) {\n const bodyEl = document.createElement('div');\n bodyEl.textContent = body;\n bodyEl.style.cssText = 'font-size: 14px; opacity: 0.9;';\n textContainer.appendChild(bodyEl);\n }\n \n banner.appendChild(textContainer);\n \n if (cta_text && cta_url) {\n const ctaButton = document.createElement('button');\n ctaButton.textContent = cta_text;\n ctaButton.style.cssText = `\n background: white;\n color: ${this.sanitizeColor(background_color || '#1a73e8')};\n border: none;\n padding: 12px 24px;\n border-radius: 6px;\n font-weight: 600;\n cursor: pointer;\n font-size: 14px;\n white-space: nowrap;\n `;\n \n ctaButton.addEventListener('click', () => {\n this.trackEvent(content.placement_id, content.variant_id, 'click');\n const safeUrl = this.sanitizeUrl(cta_url);\n if (safeUrl) {\n window.location.href = safeUrl;\n }\n });\n \n banner.appendChild(ctaButton);\n }\n \n container.appendChild(banner);\n }\n \n private renderCard(container: HTMLElement, content: PlacementContent): void {\n const { title, body, image_url, cta_text, cta_url } = content.content;\n \n const card = document.createElement('div');\n card.className = 'aegis-placement-card';\n card.style.cssText = `\n background: white;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1);\n overflow: hidden;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n `;\n \n if (image_url) {\n const img = document.createElement('img');\n const safeUrl = this.sanitizeUrl(image_url);\n if (safeUrl) {\n img.src = safeUrl;\n img.alt = title || '';\n img.style.cssText = 'width: 100%; height: 200px; object-fit: cover;';\n card.appendChild(img);\n }\n }\n \n const cardBody = document.createElement('div');\n cardBody.style.cssText = 'padding: 20px;';\n \n if (title) {\n const titleEl = document.createElement('h3');\n titleEl.textContent = title;\n titleEl.style.cssText = 'margin: 0 0 12px 0; font-size: 20px; font-weight: 600; color: #1a1a1a;';\n cardBody.appendChild(titleEl);\n }\n \n if (body) {\n const bodyEl = document.createElement('p');\n bodyEl.textContent = body;\n bodyEl.style.cssText = 'margin: 0 0 16px 0; font-size: 14px; color: #666; line-height: 1.5;';\n cardBody.appendChild(bodyEl);\n }\n \n if (cta_text && cta_url) {\n const ctaButton = document.createElement('button');\n ctaButton.textContent = cta_text;\n ctaButton.style.cssText = `\n background: #1a73e8;\n color: white;\n border: none;\n padding: 10px 20px;\n border-radius: 6px;\n font-weight: 600;\n cursor: pointer;\n font-size: 14px;\n `;\n \n ctaButton.addEventListener('click', () => {\n this.trackEvent(content.placement_id, content.variant_id, 'click');\n const safeUrl = this.sanitizeUrl(cta_url);\n if (safeUrl) {\n window.location.href = safeUrl;\n }\n });\n \n cardBody.appendChild(ctaButton);\n }\n \n card.appendChild(cardBody);\n container.appendChild(card);\n }\n \n private renderCarousel(container: HTMLElement, content: PlacementContent): void {\n const { items } = content.content;\n \n if (!Array.isArray(items) || items.length === 0) {\n this.log('Carousel items empty or invalid', true);\n return;\n }\n \n const carousel = document.createElement('div');\n carousel.className = 'aegis-placement-carousel';\n carousel.style.cssText = `\n display: flex;\n gap: 16px;\n overflow-x: auto;\n padding: 8px 0;\n scroll-behavior: smooth;\n -webkit-overflow-scrolling: touch;\n `;\n \n for (const item of items) {\n const carouselItem = document.createElement('div');\n carouselItem.style.cssText = `\n flex: 0 0 250px;\n background: white;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n overflow: hidden;\n cursor: pointer;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n `;\n \n if (item.image_url) {\n const img = document.createElement('img');\n const safeUrl = this.sanitizeUrl(item.image_url);\n if (safeUrl) {\n img.src = safeUrl;\n img.alt = item.title || '';\n img.style.cssText = 'width: 100%; height: 150px; object-fit: cover;';\n carouselItem.appendChild(img);\n }\n }\n \n const itemContent = document.createElement('div');\n itemContent.style.cssText = 'padding: 12px;';\n \n if (item.title) {\n const title = document.createElement('div');\n title.textContent = item.title;\n title.style.cssText = 'font-size: 14px; font-weight: 600; margin-bottom: 4px; color: #1a1a1a;';\n itemContent.appendChild(title);\n }\n \n if (item.price) {\n const price = document.createElement('div');\n price.textContent = item.price;\n price.style.cssText = 'font-size: 16px; font-weight: 700; color: #1a73e8;';\n itemContent.appendChild(price);\n }\n \n carouselItem.appendChild(itemContent);\n \n if (item.url) {\n carouselItem.addEventListener('click', () => {\n this.trackEvent(content.placement_id, content.variant_id, 'click', { item_index: items.indexOf(item) });\n const safeUrl = this.sanitizeUrl(item.url);\n if (safeUrl) {\n window.location.href = safeUrl;\n }\n });\n }\n \n carousel.appendChild(carouselItem);\n }\n \n container.appendChild(carousel);\n }\n \n private renderVideo(container: HTMLElement, content: PlacementContent): void {\n const { video_url, poster_url, autoplay, muted } = content.content;\n \n if (!video_url) {\n this.log('Video URL missing', true);\n return;\n }\n \n const safeVideoUrl = this.sanitizeUrl(video_url);\n if (!safeVideoUrl) {\n this.log('Invalid video URL', true);\n return;\n }\n \n const video = document.createElement('video');\n video.src = safeVideoUrl;\n video.controls = true;\n video.autoplay = autoplay || false;\n video.muted = muted || false;\n video.style.cssText = 'width: 100%; border-radius: 8px;';\n \n if (poster_url) {\n const safePosterUrl = this.sanitizeUrl(poster_url);\n if (safePosterUrl) {\n video.poster = safePosterUrl;\n }\n }\n \n video.addEventListener('play', () => {\n this.trackEvent(content.placement_id, content.variant_id, 'click', { action: 'video_play' });\n });\n \n container.appendChild(video);\n }\n \n private renderHTML(container: HTMLElement, content: PlacementContent): void {\n const { html } = content.content;\n \n if (!html) {\n this.log('HTML content missing', true);\n return;\n }\n \n const wrapper = document.createElement('div');\n wrapper.className = 'aegis-placement-html';\n wrapper.innerHTML = this.sanitizeHTML(html);\n \n const links = wrapper.querySelectorAll('a');\n links.forEach((link) => {\n link.addEventListener('click', (e) => {\n this.trackEvent(content.placement_id, content.variant_id, 'click');\n });\n });\n \n container.appendChild(wrapper);\n }\n \n private renderDynamicInjection(content: PlacementContent): void {\n const { html } = content.content;\n const cssSelector = content.css_selector;\n const injectionMode = content.injection_mode || 'replace';\n \n if (!cssSelector) {\n this.log('CSS selector missing for dynamic injection', true);\n return;\n }\n \n if (!html) {\n this.log('HTML content missing for dynamic injection', true);\n return;\n }\n \n let targetElement: HTMLElement | null = null;\n \n try {\n targetElement = document.querySelector(cssSelector);\n } catch (error) {\n this.log(`Invalid CSS selector: ${cssSelector}`, true);\n return;\n }\n \n if (!targetElement) {\n this.log(`Target element not found for selector: ${cssSelector}`, true);\n return;\n }\n \n const wrapper = document.createElement('div');\n wrapper.className = 'aegis-dynamic-injection';\n wrapper.setAttribute('data-placement-id', content.placement_id);\n wrapper.setAttribute('data-variant-id', content.variant_id);\n wrapper.innerHTML = this.sanitizeHTML(html);\n \n const links = wrapper.querySelectorAll('a');\n links.forEach((link) => {\n link.addEventListener('click', () => {\n this.trackEvent(content.placement_id, content.variant_id, 'click');\n });\n });\n \n switch (injectionMode) {\n case 'replace':\n targetElement.innerHTML = '';\n targetElement.appendChild(wrapper);\n this.log(`Replaced content in ${cssSelector}`, false);\n break;\n \n case 'append':\n targetElement.appendChild(wrapper);\n this.log(`Appended content to ${cssSelector}`, false);\n break;\n \n case 'prepend':\n targetElement.insertBefore(wrapper, targetElement.firstChild);\n this.log(`Prepended content to ${cssSelector}`, false);\n break;\n \n default:\n this.log(`Unknown injection mode: ${injectionMode}`, true);\n return;\n }\n \n this.log(`Dynamically injected content for ${content.placement_id} into ${cssSelector} (${injectionMode})`);\n }\n \n private renderFallback(slot: PlacementSlot): void {\n if (!slot.fallbackContent) return;\n \n const container = document.getElementById(slot.containerId);\n if (!container) return;\n \n container.innerHTML = slot.fallbackContent;\n this.log(`Rendered fallback content for: ${slot.placementId}`);\n }\n \n private async trackEvent(\n placementId: string,\n variantId: string,\n eventType: 'impression' | 'click' | 'conversion',\n metadata: Record<string, any> = {}\n ): Promise<void> {\n try {\n const url = `${this.apiHost}/v1/placements/track`;\n \n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-Aegis-Write-Key': this.writeKey,\n 'X-Device-Type': this.getDeviceType(),\n 'X-Platform': 'web'\n };\n \n if (this.userId) headers['X-User-ID'] = this.userId;\n if (this.contactId) headers['X-Contact-ID'] = this.contactId;\n if (this.organizationId) headers['X-Organization-ID'] = this.organizationId;\n \n const body = {\n placement_id: placementId,\n variant_id: variantId,\n event_type: eventType,\n metadata: {\n device_type: this.getDeviceType(),\n platform: 'web',\n ...metadata\n }\n };\n \n fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body)\n }).catch(err => this.log(`Track event failed: ${err}`, true));\n \n this.log(`Tracked ${eventType}: ${placementId}`);\n \n } catch (error) {\n this.log(`Error tracking event: ${error}`, true);\n }\n }\n \n private connectSSE(): void {\n if (this.eventSource) {\n this.disconnectSSE();\n }\n \n if (!this.organizationId) {\n this.log('Cannot connect SSE without organization ID', true);\n return;\n }\n \n const url = new URL('/v1/stream/realtime', this.apiHost);\n \n const headers: Record<string, string> = {\n 'X-Aegis-Write-Key': this.writeKey,\n 'X-Organization-ID': this.organizationId,\n };\n \n if (this.contactId) {\n headers['X-Contact-ID'] = this.contactId;\n }\n \n const queryParams = new URLSearchParams();\n Object.entries(headers).forEach(([key, value]) => {\n queryParams.append(key, value);\n });\n \n this.eventSource = new EventSource(`${url}?${queryParams.toString()}`);\n \n this.eventSource.addEventListener('open', () => {\n this.log('SSE connection established');\n this.reconnectAttempts = 0;\n });\n \n this.eventSource.addEventListener('placement_content_updated', (event: MessageEvent) => {\n try {\n const data = JSON.parse(event.data);\n this.log(`Received placement content update: ${data.placement_id}`);\n this.refreshPlacements();\n } catch (error) {\n this.log(`Error parsing SSE event: ${error}`, true);\n }\n });\n \n this.eventSource.addEventListener('heartbeat', (event: MessageEvent) => {\n this.log('SSE heartbeat received');\n });\n \n this.eventSource.addEventListener('error', (error) => {\n this.log('SSE connection error', true);\n \n if (this.eventSource?.readyState === EventSource.CLOSED) {\n this.attemptReconnect();\n }\n });\n }\n \n private disconnectSSE(): void {\n if (this.eventSource) {\n this.eventSource.close();\n this.eventSource = undefined;\n this.log('SSE connection closed');\n }\n }\n \n private attemptReconnect(): void {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n this.log('Max reconnect attempts reached, giving up', true);\n return;\n }\n \n this.reconnectAttempts++;\n const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);\n \n this.log(`Reconnecting SSE in ${delay}ms (attempt ${this.reconnectAttempts})`);\n \n setTimeout(() => {\n if (this.isInitialized && this.enableSSE && this.organizationId) {\n this.connectSSE();\n }\n }, delay);\n }\n \n private getDeviceType(): string {\n const width = window.innerWidth;\n if (width < 768) return 'mobile_web';\n if (width < 1024) return 'tablet_web';\n return 'desktop_web';\n }\n \n private sanitizeUrl(url: string): string | null {\n try {\n const parsed = new URL(url, window.location.href);\n \n if (parsed.protocol === 'javascript:' || parsed.protocol === 'data:') {\n this.log(`Blocked unsafe URL protocol: ${parsed.protocol}`, true);\n return null;\n }\n \n return parsed.href;\n } catch {\n this.log(`Invalid URL: ${url}`, true);\n return null;\n }\n }\n \n private sanitizeColor(color: string): string {\n const hexPattern = /^#[0-9A-Fa-f]{3,6}$/;\n const rgbPattern = /^rgba?\\(\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*\\d+\\s*(,\\s*[\\d.]+\\s*)?\\)$/;\n const namedColors = ['white', 'black', 'red', 'blue', 'green', 'yellow', 'transparent'];\n \n if (hexPattern.test(color) || rgbPattern.test(color) || namedColors.includes(color.toLowerCase())) {\n return color;\n }\n \n this.log(`Invalid color: ${color}`, true);\n return '#000000';\n }\n \n private sanitizeHTML(html: string): string {\n const tempDiv = document.createElement('div');\n tempDiv.textContent = html;\n return tempDiv.innerHTML;\n }\n \n private log(message: string, isError = false): void {\n if (this.debugMode || isError) {\n console[isError ? 'error' : 'log'](`[AegisPlacements] ${message}`);\n }\n }\n \n destroy(): void {\n this.disconnectSSE();\n this.slots.clear();\n this.placements.clear();\n this.renderedSlots.clear();\n this.isInitialized = false;\n this.log('AegisPlacements destroyed');\n }\n}\n","/**\n * AegisWidgetManager - Web SDK Widget Module\n * \n * Smart Pull architecture for persistent web widgets.\n * \n * Features:\n * - Gamification (spin wheel, scratch card) with server-side prize generation\n * - Chat bubbles (WhatsApp, support)\n * - Social proof toasts (real-time purchase notifications)\n * - Feedback forms (NPS, surveys)\n * \n * Security:\n * - XSS Protection: Uses DOM APIs instead of innerHTML\n * - Server-side prize generation prevents client manipulation\n * - URL validation prevents javascript: protocol injection\n * \n * Architecture:\n * - Fetches widget configs from /v1/widgets/config on page load\n * - Integrates with TriggerEngine for behavioral triggers\n * - Tracks widget events (show, click, dismiss, submit)\n * - Server-side prize generation for gamification\n */\n\nimport { TriggerEngine } from '../triggers/TriggerEngine';\n\nexport interface WidgetConfig {\n widget_id: string;\n widget_type: 'chat_bubble' | 'spin_wheel' | 'scratch_card' | 'toast' | 'feedback_form' | 'exit_intent_popup';\n name: string;\n config: Record<string, any>;\n position?: string;\n priority: number;\n trigger_rules?: {\n type: 'exit_intent' | 'scroll_depth' | 'time_on_page' | 'immediate';\n config?: Record<string, any>;\n };\n}\n\nexport interface GamificationPrize {\n prize_label: string;\n prize_value?: string;\n coupon_code?: string;\n play_id: string;\n}\n\nexport interface AegisWidgetConfig {\n writeKey: string;\n apiHost?: string;\n userId?: string;\n contactId?: string;\n organizationId?: string;\n debugMode?: boolean;\n triggerEngine?: TriggerEngine;\n enablePrefetch?: boolean;\n cssCustomization?: WidgetCSSCustomization;\n onEvent?: (eventType: string, data: any) => void;\n /** Source platform passed as X-Source-Platform header so the API\n * can filter campaigns whose display_rules.sources restricts them\n * to specific integrations (e.g. 'shopify', 'woocommerce'). */\n sourcePlatform?: 'web' | 'shopify' | 'woocommerce' | 'mobile_sdk';\n}\n\nexport interface WidgetCSSCustomization {\n exitIntent?: {\n backgroundColor?: string;\n textColor?: string;\n accentColor?: string;\n borderRadius?: string;\n fontFamily?: string;\n overlayOpacity?: number;\n };\n spinWheel?: {\n backgroundColor?: string;\n textColor?: string;\n accentColor?: string;\n borderRadius?: string;\n fontFamily?: string;\n wheelColors?: string[];\n buttonColor?: string;\n };\n chatBubble?: {\n backgroundColor?: string;\n textColor?: string;\n position?: 'bottom_right' | 'bottom_left' | 'top_right' | 'top_left';\n size?: 'small' | 'medium' | 'large';\n };\n}\n\nexport interface PrefetchWidgetConfig {\n exit_intent?: {\n enabled: boolean;\n type: 'cart_recovery' | 'lead_gen';\n tier?: string;\n title?: string;\n message?: string;\n discount_code?: string;\n discount_percentage?: number;\n cta_text?: string;\n cta_url?: string;\n background_color?: string;\n text_color?: string;\n accent_color?: string;\n show_cart_items?: boolean;\n show_timer?: boolean;\n timer_minutes?: number;\n priority: number;\n mobile_triggers?: {\n scroll_velocity?: boolean;\n scroll_threshold?: number;\n scroll_min_position?: number;\n scroll_cooldown?: number;\n idle_timer?: boolean;\n idle_seconds?: number;\n visibility_change?: boolean;\n back_button?: boolean;\n };\n };\n spin_wheel?: {\n enabled: boolean;\n type: 'lead_gen' | 'cart_recovery';\n title?: string;\n prizes?: any[];\n priority: number;\n };\n}\n\nexport interface CartData {\n cart_id: string;\n cart_total: number;\n cart_currency: string;\n cart_items: Array<{\n product_id: string;\n product_name?: string;\n quantity: number;\n price?: number;\n }>;\n}\n\nexport class AegisWidgetManager {\n private writeKey: string;\n private apiHost: string;\n private userId?: string;\n private contactId?: string;\n private organizationId?: string;\n private debugMode: boolean;\n private triggerEngine?: TriggerEngine;\n private enablePrefetch: boolean;\n private cssCustomization: WidgetCSSCustomization;\n private onEvent?: (eventType: string, data: any) => void;\n private sourcePlatform?: string;\n\n private widgets: WidgetConfig[] = [];\n private renderedWidgets = new Set<string>();\n private isInitialized = false;\n \n private prefetchWidgetConfigs: PrefetchWidgetConfig = {};\n private cartData?: CartData;\n \n constructor(config: AegisWidgetConfig) {\n this.writeKey = config.writeKey;\n this.apiHost = config.apiHost || 'https://api.aegis.ai';\n this.userId = config.userId;\n this.contactId = config.contactId;\n this.organizationId = config.organizationId;\n this.debugMode = config.debugMode || false;\n this.triggerEngine = config.triggerEngine;\n this.enablePrefetch = config.enablePrefetch !== false;\n this.cssCustomization = config.cssCustomization || {};\n this.onEvent = config.onEvent;\n this.sourcePlatform = config.sourcePlatform;\n }\n \n updateCSSCustomization(customization: WidgetCSSCustomization): void {\n this.cssCustomization = { ...this.cssCustomization, ...customization };\n this.log('CSS customization updated');\n }\n \n private emitEvent(eventType: string, data: any): void {\n if (this.onEvent) {\n try {\n this.onEvent(eventType, data);\n } catch (error) {\n this.log(`Error in event callback: ${error}`, true);\n }\n }\n }\n \n async initialize(): Promise<void> {\n if (this.isInitialized) {\n this.log('AegisWidgets already initialized');\n return;\n }\n \n if (this.enablePrefetch && this.contactId) {\n await this.fetchPrefetchConfigs();\n this.preloadWidgetAssets();\n }\n \n await this.fetchWidgets();\n \n this.renderImmediateWidgets();\n \n this.setupTriggerListeners();\n \n this.setupExitIntentWithPrefetch();\n \n this.isInitialized = true;\n this.log('AegisWidgets initialized successfully');\n }\n \n setCartData(cartData: CartData): void {\n this.cartData = cartData;\n this.log(`Cart data updated: ${cartData.cart_items.length} items, total: ${cartData.cart_currency} ${cartData.cart_total}`);\n }\n \n private detectPlatformCart(): CartData | null {\n const shopifyCart = this.normalizeShopifyCart();\n if (shopifyCart) {\n this.log('Detected Shopify cart via browser globals');\n return shopifyCart;\n }\n \n const wooCart = this.normalizeWooCart();\n if (wooCart) {\n this.log('Detected WooCommerce cart via injected data');\n return wooCart;\n }\n \n const magentoCart = this.normalizeMagentoCart();\n if (magentoCart) {\n this.log('Detected Magento cart via localStorage');\n return magentoCart;\n }\n \n if (this.cartData) {\n this.log('Using manually set cart data');\n return this.cartData;\n }\n \n return null;\n }\n \n private normalizeShopifyCart(): CartData | null {\n try {\n if (typeof window === 'undefined') return null;\n \n const win = window as any;\n \n if (win.Shopify?.checkout) {\n const checkout = win.Shopify.checkout;\n return {\n cart_id: checkout.token || `shopify_${Date.now()}`,\n cart_total: parseFloat(checkout.total_price) || 0,\n cart_currency: checkout.currency || 'USD',\n cart_items: (checkout.line_items || []).map((item: any) => ({\n product_id: String(item.product_id || item.id),\n product_name: item.title || item.product_title,\n quantity: item.quantity || 1,\n price: parseFloat(item.price) || 0\n }))\n };\n }\n \n const cartJsonEl = document.getElementById('cart-json');\n if (cartJsonEl?.textContent) {\n const cart = JSON.parse(cartJsonEl.textContent);\n return {\n cart_id: cart.token || `shopify_${Date.now()}`,\n cart_total: (cart.total_price || 0) / 100,\n cart_currency: cart.currency || 'USD',\n cart_items: (cart.items || []).map((item: any) => ({\n product_id: String(item.product_id || item.id),\n product_name: item.product_title || item.title,\n quantity: item.quantity || 1,\n price: (item.price || 0) / 100\n }))\n };\n }\n \n return null;\n } catch (error) {\n this.log(`Error detecting Shopify cart: ${error}`, true);\n return null;\n }\n }\n \n private normalizeWooCart(): CartData | null {\n try {\n if (typeof window === 'undefined') return null;\n \n const win = window as any;\n \n if (win.aegis_cart) {\n const cart = win.aegis_cart;\n return {\n cart_id: cart.cart_id || `woo_${Date.now()}`,\n cart_total: parseFloat(cart.cart_total) || 0,\n cart_currency: cart.cart_currency || 'USD',\n cart_items: (cart.cart_items || []).map((item: any) => ({\n product_id: String(item.product_id),\n product_name: item.product_name,\n quantity: item.quantity || 1,\n price: parseFloat(item.price) || 0\n }))\n };\n }\n \n return null;\n } catch (error) {\n this.log(`Error detecting WooCommerce cart: ${error}`, true);\n return null;\n }\n }\n \n private normalizeMagentoCart(): CartData | null {\n try {\n if (typeof window === 'undefined' || !window.localStorage) return null;\n \n const mageCacheStr = localStorage.getItem('mage-cache-storage');\n if (!mageCacheStr) return null;\n \n const mageCache = JSON.parse(mageCacheStr);\n if (!mageCache?.cart) return null;\n \n const cart = mageCache.cart;\n \n return {\n cart_id: cart.quote_id || cart.id || `magento_${Date.now()}`,\n cart_total: parseFloat(cart.subtotalAmount || cart.subtotal || 0),\n cart_currency: cart.currencyCode || 'USD',\n cart_items: (cart.items || []).map((item: any) => ({\n product_id: String(item.item_id || item.product_id),\n product_name: item.product_name || item.name,\n quantity: item.qty || 1,\n price: parseFloat(item.product_price_value || item.price || 0)\n }))\n };\n } catch (error) {\n this.log(`Error detecting Magento cart: ${error}`, true);\n return null;\n }\n }\n \n private preloadWidgetAssets(): void {\n try {\n const exitIntentConfig = this.prefetchWidgetConfigs.exit_intent;\n if (exitIntentConfig?.enabled) {\n const imageUrl = (exitIntentConfig as any).image_url;\n if (imageUrl) {\n const img = new Image();\n img.src = imageUrl;\n this.log(`Preloading exit intent image: ${imageUrl}`);\n }\n }\n \n const spinWheelConfig = this.prefetchWidgetConfigs.spin_wheel;\n if (spinWheelConfig?.enabled) {\n const imageUrl = (spinWheelConfig as any).image_url;\n if (imageUrl) {\n const img = new Image();\n img.src = imageUrl;\n this.log(`Preloading spin wheel image: ${imageUrl}`);\n }\n }\n } catch (error) {\n this.log(`Error preloading widget assets: ${error}`, true);\n }\n }\n \n private async fetchPrefetchConfigs(): Promise<void> {\n try {\n const startTime = performance.now();\n const url = `${this.apiHost}/v1/widgets/config/prefetch`;\n \n const headers: Record<string, string> = {\n 'X-Aegis-Write-Key': this.writeKey,\n };\n \n if (this.contactId) headers['X-Contact-ID'] = this.contactId;\n if (this.organizationId) headers['X-Organization-ID'] = this.organizationId;\n \n const response = await fetch(url, { headers });\n \n if (!response.ok) {\n throw new Error(`Failed to fetch prefetch configs: ${response.status}`);\n }\n \n this.prefetchWidgetConfigs = await response.json();\n \n const elapsed = performance.now() - startTime;\n this.log(`Fetched prefetch widget configs in ${elapsed.toFixed(2)}ms`);\n \n } catch (error) {\n this.log(`Error fetching prefetch configs: ${error}`, true);\n }\n }\n \n private async fetchWidgets(): Promise<void> {\n try {\n const url = `${this.apiHost}/v1/widgets/config`;\n \n const headers: Record<string, string> = {\n 'X-Aegis-Write-Key': this.writeKey,\n 'X-Device-Platform': 'web',\n 'X-Device-Type': this.getDeviceType()\n };\n\n if (this.userId) headers['X-User-ID'] = this.userId;\n if (this.contactId) headers['X-Contact-ID'] = this.contactId;\n if (this.organizationId) headers['X-Organization-ID'] = this.organizationId;\n if (this.sourcePlatform) headers['X-Source-Platform'] = this.sourcePlatform;\n \n const response = await fetch(url, { headers });\n \n if (!response.ok) {\n throw new Error(`Failed to fetch widgets: ${response.status}`);\n }\n \n this.widgets = await response.json();\n \n this.log(`Fetched ${this.widgets.length} widgets`);\n \n } catch (error) {\n this.log(`Error fetching widgets: ${error}`, true);\n }\n }\n \n private renderImmediateWidgets(): void {\n const immediateWidgets = this.widgets.filter(w => \n !w.trigger_rules || w.trigger_rules.type === 'immediate'\n );\n \n immediateWidgets.forEach(widget => this.renderWidget(widget));\n }\n \n private setupTriggerListeners(): void {\n if (!this.triggerEngine) {\n this.log('TriggerEngine not provided, skipping trigger-based widgets');\n return;\n }\n \n this.widgets.forEach(widget => {\n if (!widget.trigger_rules) return;\n \n const { type, config } = widget.trigger_rules;\n \n switch (type) {\n case 'exit_intent':\n this.triggerEngine!.registerExitIntent();\n this.triggerEngine!.on('exit_intent', () => {\n if (!this.renderedWidgets.has(widget.widget_id)) {\n this.renderWidget(widget);\n }\n });\n break;\n \n case 'scroll_depth':\n const depthPercent = (config as any)?.depth_percent || 50;\n this.triggerEngine!.registerScrollDepth(depthPercent);\n this.triggerEngine!.on(`scroll_depth_${depthPercent}`, () => {\n if (!this.renderedWidgets.has(widget.widget_id)) {\n this.renderWidget(widget);\n }\n });\n break;\n \n case 'time_on_page':\n const seconds = (config as any)?.seconds || 30;\n this.triggerEngine!.registerTimeOnPage(seconds);\n this.triggerEngine!.on(`time_on_page_${seconds}`, () => {\n if (!this.renderedWidgets.has(widget.widget_id)) {\n this.renderWidget(widget);\n }\n });\n break;\n }\n });\n }\n \n private setupExitIntentWithPrefetch(): void {\n if (!this.enablePrefetch || !this.triggerEngine) {\n return;\n }\n \n const spinWheelConfig = this.prefetchWidgetConfigs.spin_wheel;\n const exitIntentConfig = this.prefetchWidgetConfigs.exit_intent;\n \n if (spinWheelConfig && spinWheelConfig.enabled) {\n const isMobile = this.isMobileDevice();\n const mobileConfig = exitIntentConfig?.mobile_triggers || {};\n \n const handleSpinWheelIntent = () => {\n const widgetId = `prefetch_spin_wheel_${Date.now()}`;\n \n if (this.renderedWidgets.has(widgetId)) {\n return;\n }\n \n this.renderedWidgets.add(widgetId);\n \n const detectedCart = this.detectPlatformCart();\n \n if (spinWheelConfig.type === 'cart_recovery' && detectedCart) {\n this.cartData = detectedCart;\n this.renderSpinWheelWidget(widgetId, spinWheelConfig);\n this.sendCartAbandonmentBeacon();\n } else if (spinWheelConfig.type === 'lead_gen') {\n this.renderSpinWheelWidget(widgetId, spinWheelConfig);\n }\n };\n \n if (isMobile) {\n const scrollVelocityEnabled = mobileConfig.scroll_velocity !== false;\n if (scrollVelocityEnabled) {\n this.triggerEngine.registerScrollVelocity({\n threshold: mobileConfig.scroll_threshold || 0.5,\n minScrollPosition: mobileConfig.scroll_min_position || 100,\n cooldown: mobileConfig.scroll_cooldown || 5000\n });\n this.triggerEngine.on('mobile_exit_intent', handleSpinWheelIntent);\n this.log('Registered mobile scroll velocity trigger for spin wheel');\n }\n \n const idleTimerEnabled = mobileConfig.idle_timer !== false;\n if (idleTimerEnabled) {\n const idleSeconds = mobileConfig.idle_seconds || 15;\n this.triggerEngine.registerInactivity(idleSeconds);\n this.triggerEngine.on(`inactivity_${idleSeconds}`, handleSpinWheelIntent);\n this.log(`Registered mobile idle timer trigger for spin wheel: ${idleSeconds}s`);\n }\n \n const visibilityChangeEnabled = mobileConfig.visibility_change !== false;\n if (visibilityChangeEnabled) {\n const detectedCart = this.detectPlatformCart();\n if (detectedCart && detectedCart.cart_items && detectedCart.cart_items.length > 0) {\n this.triggerEngine.registerVisibilityChange();\n this.triggerEngine.on('visibility_hidden', handleSpinWheelIntent);\n this.log('Registered mobile visibility change trigger for spin wheel (cart detected)');\n }\n }\n \n const backButtonEnabled = mobileConfig.back_button === true;\n if (backButtonEnabled) {\n this.triggerEngine.registerBackButton();\n this.triggerEngine.on('back_button', handleSpinWheelIntent);\n this.log('Registered mobile back button trigger for spin wheel');\n }\n \n this.log(`Setup mobile spin wheel: type=${spinWheelConfig.type}, priority=${spinWheelConfig.priority}`);\n } else {\n this.triggerEngine.registerExitIntent();\n this.triggerEngine.on('exit_intent', handleSpinWheelIntent);\n this.log(`Setup desktop spin wheel exit intent: type=${spinWheelConfig.type}, priority=${spinWheelConfig.priority}`);\n }\n \n return;\n }\n \n if (!exitIntentConfig || !exitIntentConfig.enabled) {\n this.log('No exit intent config found in prefetch');\n return;\n }\n \n const isMobile = this.isMobileDevice();\n const mobileConfig = exitIntentConfig.mobile_triggers || {};\n \n const handleExitIntent = () => {\n const widgetId = `prefetch_exit_intent_${Date.now()}`;\n \n if (this.renderedWidgets.has(widgetId)) {\n return;\n }\n \n this.renderedWidgets.add(widgetId);\n \n const detectedCart = this.detectPlatformCart();\n \n if (exitIntentConfig.type === 'cart_recovery' && detectedCart) {\n this.cartData = detectedCart;\n this.renderCartRecoveryPopup(widgetId, exitIntentConfig);\n this.sendCartAbandonmentBeacon();\n } else if (exitIntentConfig.type === 'lead_gen') {\n this.renderLeadGenPopup(widgetId, exitIntentConfig);\n } else {\n this.log('Unknown exit intent type or missing cart data');\n }\n };\n \n if (isMobile) {\n const scrollVelocityEnabled = mobileConfig.scroll_velocity !== false;\n if (scrollVelocityEnabled) {\n this.triggerEngine.registerScrollVelocity({\n threshold: mobileConfig.scroll_threshold || 0.5,\n minScrollPosition: mobileConfig.scroll_min_position || 100,\n cooldown: mobileConfig.scroll_cooldown || 5000\n });\n this.triggerEngine.on('mobile_exit_intent', handleExitIntent);\n this.log('Registered mobile scroll velocity trigger');\n }\n \n const idleTimerEnabled = mobileConfig.idle_timer !== false;\n if (idleTimerEnabled) {\n const idleSeconds = mobileConfig.idle_seconds || 15;\n this.triggerEngine.registerInactivity(idleSeconds);\n this.triggerEngine.on(`inactivity_${idleSeconds}`, handleExitIntent);\n this.log(`Registered mobile idle timer trigger: ${idleSeconds}s`);\n }\n \n const visibilityChangeEnabled = mobileConfig.visibility_change !== false;\n if (visibilityChangeEnabled) {\n const detectedCart = this.detectPlatformCart();\n if (detectedCart && detectedCart.cart_items && detectedCart.cart_items.length > 0) {\n this.triggerEngine.registerVisibilityChange();\n this.triggerEngine.on('visibility_hidden', handleExitIntent);\n this.log('Registered mobile visibility change trigger (cart detected)');\n } else {\n this.log('Skipped visibility change trigger (no cart items)');\n }\n }\n \n const backButtonEnabled = mobileConfig.back_button === true;\n if (backButtonEnabled) {\n this.triggerEngine.registerBackButton();\n this.triggerEngine.on('back_button', handleExitIntent);\n this.log('Registered mobile back button trigger (aggressive mode)');\n }\n \n this.log(`Setup mobile exit intent: type=${exitIntentConfig.type}, priority=${exitIntentConfig.priority}`);\n } else {\n this.triggerEngine.registerExitIntent();\n this.triggerEngine.on('exit_intent', handleExitIntent);\n this.log(`Setup desktop exit intent: type=${exitIntentConfig.type}, priority=${exitIntentConfig.priority}`);\n }\n }\n \n private sendCartAbandonmentBeacon(): void {\n if (!this.cartData) {\n this.log('No cart data available for beacon', true);\n return;\n }\n \n const beaconData = {\n organization_id: this.organizationId || 'default',\n contact_id: this.contactId,\n cart_id: this.cartData.cart_id,\n cart_total: this.cartData.cart_total,\n cart_currency: this.cartData.cart_currency,\n cart_items: this.cartData.cart_items,\n user_email: this.userId,\n abandoned_at: new Date().toISOString(),\n page_url: window.location.href,\n referrer: document.referrer\n };\n \n const beaconUrl = `${this.apiHost}/v1/widgets/beacon/cart-abandoned`;\n \n if (navigator.sendBeacon) {\n const blob = new Blob([JSON.stringify(beaconData)], { type: 'application/json' });\n const sent = navigator.sendBeacon(beaconUrl, blob);\n \n if (sent) {\n this.log('Cart abandonment beacon sent successfully');\n } else {\n this.log('Failed to send cart abandonment beacon', true);\n }\n } else {\n fetch(beaconUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Aegis-Write-Key': this.writeKey\n },\n body: JSON.stringify(beaconData),\n keepalive: true\n }).catch(err => {\n this.log(`Error sending cart abandonment via fetch: ${err}`, true);\n });\n }\n }\n \n private renderWidget(widget: WidgetConfig): void {\n if (this.renderedWidgets.has(widget.widget_id)) {\n return;\n }\n \n this.renderedWidgets.add(widget.widget_id);\n \n switch (widget.widget_type) {\n case 'chat_bubble':\n this.renderChatBubble(widget);\n break;\n case 'spin_wheel':\n this.renderSpinWheel(widget);\n break;\n case 'scratch_card':\n this.renderScratchCard(widget);\n break;\n case 'toast':\n this.renderToast(widget);\n break;\n case 'feedback_form':\n this.renderFeedbackForm(widget);\n break;\n case 'exit_intent_popup':\n this.renderExitIntentPopup(widget);\n break;\n default:\n this.log(`Unknown widget type: ${widget.widget_type}`, true);\n }\n \n this.trackEvent(widget.widget_id, 'show');\n }\n \n private renderChatBubble(widget: WidgetConfig): void {\n const { text, icon_url, link_url, background_color, text_color } = widget.config;\n const position = widget.position || 'bottom_right';\n \n const bubble = document.createElement('div');\n bubble.className = 'aegis-chat-bubble';\n bubble.setAttribute('data-widget-id', widget.widget_id);\n \n const positionStyles: Record<string, string> = {\n bottom_right: 'bottom: 20px; right: 20px;',\n bottom_left: 'bottom: 20px; left: 20px;',\n top_right: 'top: 20px; right: 20px;',\n top_left: 'top: 20px; left: 20px;'\n };\n \n bubble.style.cssText = `\n position: fixed;\n ${positionStyles[position] || positionStyles.bottom_right}\n background: ${this.sanitizeColor(background_color || '#25D366')};\n color: ${this.sanitizeColor(text_color || '#ffffff')};\n padding: 16px 24px;\n border-radius: 50px;\n box-shadow: 0 4px 12px rgba(0,0,0,0.15);\n cursor: pointer;\n z-index: 999999;\n display: flex;\n align-items: center;\n gap: 12px;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n font-weight: 600;\n font-size: 14px;\n animation: aegisBubbleIn 0.3s ease-out;\n `;\n \n if (icon_url) {\n const icon = document.createElement('img');\n const safeUrl = this.sanitizeUrl(icon_url);\n if (safeUrl) {\n icon.src = safeUrl;\n icon.alt = '';\n icon.style.cssText = 'width: 24px; height: 24px;';\n bubble.appendChild(icon);\n }\n }\n \n const textEl = document.createElement('span');\n textEl.textContent = text || 'Chat with us';\n bubble.appendChild(textEl);\n \n bubble.addEventListener('click', () => {\n this.trackEvent(widget.widget_id, 'click');\n const safeUrl = this.sanitizeUrl(link_url);\n if (safeUrl) {\n window.open(safeUrl, '_blank');\n }\n });\n \n this.addAnimationStyles();\n document.body.appendChild(bubble);\n }\n \n private renderSpinWheel(widget: WidgetConfig): void {\n const overlay = document.createElement('div');\n overlay.className = 'aegis-gamification-overlay';\n overlay.setAttribute('data-widget-id', widget.widget_id);\n \n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.7);\n z-index: 1000000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: aegisFadeIn 0.3s ease-out;\n `;\n \n const modal = document.createElement('div');\n modal.className = 'aegis-spin-wheel-modal';\n modal.style.cssText = `\n background: white;\n border-radius: 16px;\n padding: 32px;\n max-width: 500px;\n width: 90%;\n box-shadow: 0 10px 40px rgba(0,0,0,0.3);\n text-align: center;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n animation: aegisScaleIn 0.3s ease-out;\n `;\n \n const title = document.createElement('h2');\n title.textContent = widget.config.title || 'Spin to Win!';\n title.style.cssText = 'margin: 0 0 16px 0; font-size: 24px; font-weight: 700; color: #1a1a1a;';\n modal.appendChild(title);\n \n const description = document.createElement('p');\n description.textContent = widget.config.description || 'Try your luck and win exclusive prizes!';\n description.style.cssText = 'margin: 0 0 24px 0; font-size: 14px; color: #666;';\n modal.appendChild(description);\n \n const wheelPlaceholder = document.createElement('div');\n wheelPlaceholder.style.cssText = `\n width: 300px;\n height: 300px;\n margin: 0 auto 24px;\n background: linear-gradient(45deg, #ff6b6b, #feca57, #48dbfb, #ff6348);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 48px;\n color: white;\n `;\n wheelPlaceholder.textContent = '🎰';\n modal.appendChild(wheelPlaceholder);\n \n const spinButton = document.createElement('button');\n spinButton.textContent = 'SPIN NOW!';\n spinButton.style.cssText = `\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n border: none;\n padding: 16px 48px;\n border-radius: 8px;\n font-weight: 700;\n font-size: 16px;\n cursor: pointer;\n margin-bottom: 16px;\n `;\n \n spinButton.addEventListener('click', async () => {\n spinButton.disabled = true;\n spinButton.textContent = 'SPINNING...';\n \n try {\n const prize = await this.generatePrize(widget.config.config_id);\n \n wheelPlaceholder.style.animation = 'aegisSpin 2s ease-out';\n \n setTimeout(() => {\n this.showPrizeResult(modal, prize);\n }, 2000);\n \n } catch (error) {\n this.log(`Error generating prize: ${error}`, true);\n spinButton.disabled = false;\n spinButton.textContent = 'TRY AGAIN';\n }\n });\n \n modal.appendChild(spinButton);\n \n const closeButton = document.createElement('button');\n closeButton.textContent = '×';\n closeButton.setAttribute('aria-label', 'Close');\n closeButton.style.cssText = `\n position: absolute;\n top: 16px;\n right: 16px;\n background: transparent;\n border: none;\n font-size: 28px;\n cursor: pointer;\n color: #999;\n `;\n \n closeButton.addEventListener('click', () => {\n this.trackEvent(widget.widget_id, 'dismiss');\n document.body.removeChild(overlay);\n this.renderedWidgets.delete(widget.widget_id);\n });\n \n modal.style.position = 'relative';\n modal.appendChild(closeButton);\n \n overlay.appendChild(modal);\n this.addAnimationStyles();\n document.body.appendChild(overlay);\n }\n \n private renderSpinWheelWidget(widgetId: string, config: NonNullable<PrefetchWidgetConfig['spin_wheel']>): void {\n const cart = this.detectPlatformCart();\n \n if (config.type === 'cart_recovery' && !cart) {\n this.log('Spin wheel requires cart, but none detected');\n return;\n }\n \n if (cart) {\n this.cartData = cart;\n }\n \n const customization = this.cssCustomization.spinWheel || {};\n const accentColor = customization.accentColor || (config as any).accent_color || '#FF6B6B';\n const backgroundColor = customization.backgroundColor || (config as any).background_color || '#FFFFFF';\n const textColor = customization.textColor || (config as any).text_color || '#333333';\n const buttonColor = customization.buttonColor || (config as any).button_color || accentColor;\n const wheelColors = customization.wheelColors || ['#FF6B6B', '#4ECDC4', '#FFE66D', '#95E1D3'];\n \n const overlay = document.createElement('div');\n overlay.className = 'aegis-spin-wheel-overlay';\n overlay.setAttribute('data-widget-id', widgetId);\n \n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.7);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 999999;\n animation: aegisFadeIn 0.3s ease;\n `;\n \n const modal = document.createElement('div');\n modal.className = 'aegis-spin-wheel-modal';\n modal.style.cssText = `\n background: ${this.sanitizeColor(backgroundColor)};\n border-radius: 16px;\n padding: 32px;\n max-width: 500px;\n width: 90%;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n position: relative;\n animation: aegisScaleIn 0.4s ease;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n `;\n \n const closeBtn = document.createElement('button');\n closeBtn.innerHTML = '✕';\n closeBtn.className = 'aegis-spin-wheel-close';\n closeBtn.style.cssText = `\n position: absolute;\n top: 16px;\n right: 16px;\n background: none;\n border: none;\n font-size: 24px;\n cursor: pointer;\n color: #999;\n `;\n closeBtn.onclick = () => {\n this.trackEvent(widgetId, 'dismiss', { type: 'spin_wheel' });\n document.body.removeChild(overlay);\n this.renderedWidgets.delete(widgetId);\n };\n modal.appendChild(closeBtn);\n \n const title = document.createElement('h2');\n title.textContent = this.interpolateCartVariables((config as any).title || 'Spin to Win!');\n title.style.cssText = `\n margin: 0 0 16px 0;\n font-size: 28px;\n font-weight: bold;\n text-align: center;\n color: ${this.sanitizeColor(textColor)};\n `;\n modal.appendChild(title);\n \n if (cart) {\n const subtitle = document.createElement('p');\n subtitle.textContent = `Complete your ${cart.cart_currency} ${cart.cart_total.toFixed(2)} order and save!`;\n subtitle.style.cssText = `\n margin: 0 0 24px 0;\n font-size: 16px;\n text-align: center;\n color: #666;\n `;\n modal.appendChild(subtitle);\n }\n \n const wheelContainer = document.createElement('div');\n wheelContainer.className = 'aegis-wheel-container';\n wheelContainer.style.cssText = `\n width: 300px;\n height: 300px;\n margin: 0 auto 24px auto;\n background: conic-gradient(\n from 0deg,\n ${wheelColors[0]} 0deg 90deg,\n ${wheelColors[1]} 90deg 180deg,\n ${wheelColors[2]} 180deg 270deg,\n ${wheelColors[3]} 270deg 360deg\n );\n border-radius: 50%;\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n `;\n \n const form = document.createElement('form');\n form.className = 'aegis-spin-form';\n form.style.cssText = 'display: block;';\n \n const phoneInput = document.createElement('input');\n phoneInput.type = 'tel';\n phoneInput.placeholder = 'Enter your phone number';\n phoneInput.required = true;\n phoneInput.style.cssText = `\n width: 100%;\n padding: 14px;\n border: 2px solid #ddd;\n border-radius: 8px;\n font-size: 16px;\n margin-bottom: 12px;\n box-sizing: border-box;\n `;\n form.appendChild(phoneInput);\n \n const emailInput = document.createElement('input');\n emailInput.type = 'email';\n emailInput.placeholder = 'Enter your email (optional)';\n emailInput.style.cssText = `\n width: 100%;\n padding: 14px;\n border: 2px solid #ddd;\n border-radius: 8px;\n font-size: 16px;\n margin-bottom: 12px;\n box-sizing: border-box;\n `;\n form.appendChild(emailInput);\n \n const nameInput = document.createElement('input');\n nameInput.type = 'text';\n nameInput.placeholder = 'Enter your name (optional)';\n nameInput.style.cssText = `\n width: 100%;\n padding: 14px;\n border: 2px solid #ddd;\n border-radius: 8px;\n font-size: 16px;\n margin-bottom: 12px;\n box-sizing: border-box;\n `;\n form.appendChild(nameInput);\n \n const submitButton = document.createElement('button');\n submitButton.type = 'submit';\n submitButton.textContent = 'Spin the Wheel!';\n submitButton.style.cssText = `\n width: 100%;\n padding: 14px;\n background: ${this.sanitizeColor(buttonColor)};\n color: white;\n border: none;\n border-radius: 8px;\n font-size: 16px;\n font-weight: 700;\n cursor: pointer;\n `;\n form.appendChild(submitButton);\n \n const errorMessage = document.createElement('div');\n errorMessage.className = 'aegis-spin-error';\n errorMessage.style.cssText = `\n color: #d32f2f;\n font-size: 14px;\n margin-top: 12px;\n text-align: center;\n display: none;\n `;\n form.appendChild(errorMessage);\n \n form.addEventListener('submit', async (e) => {\n e.preventDefault();\n \n const phone = phoneInput.value.trim();\n const email = emailInput.value.trim();\n const name = nameInput.value.trim();\n \n if (!this.validatePhone(phone)) {\n errorMessage.textContent = 'Please enter a valid phone number (e.g., +1234567890)';\n errorMessage.style.display = 'block';\n return;\n }\n \n if (email && !this.validateEmail(email)) {\n errorMessage.textContent = 'Please enter a valid email address';\n errorMessage.style.display = 'block';\n return;\n }\n \n errorMessage.style.display = 'none';\n submitButton.disabled = true;\n submitButton.textContent = 'Spinning...';\n \n wheelContainer.style.animation = 'aegisSpin 2s ease-out';\n \n setTimeout(async () => {\n try {\n const prize = await this.submitSpinWheel({\n phone,\n email,\n name,\n cart,\n widgetId\n });\n \n this.showSpinWheelPrize(modal, prize);\n this.trackEvent(widgetId, 'submit', {\n type: 'spin_wheel',\n prize_label: prize.prize_label,\n has_email: !!email\n });\n \n } catch (error) {\n this.log(`Error submitting spin wheel: ${error}`, true);\n errorMessage.textContent = 'Failed to submit. Please try again.';\n errorMessage.style.display = 'block';\n submitButton.disabled = false;\n submitButton.textContent = 'Spin the Wheel!';\n wheelContainer.style.animation = '';\n }\n }, 2000);\n });\n \n modal.appendChild(wheelContainer);\n modal.appendChild(form);\n overlay.appendChild(modal);\n this.addAnimationStyles();\n document.body.appendChild(overlay);\n \n this.trackEvent(widgetId, 'show', { type: 'spin_wheel' });\n }\n \n private validatePhone(phone: string): boolean {\n const e164Regex = /^\\+?[1-9]\\d{1,14}$/;\n return e164Regex.test(phone.replace(/[\\s()-]/g, ''));\n }\n \n private validateEmail(email: string): boolean {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return emailRegex.test(email);\n }\n \n private async submitSpinWheel(data: {\n phone: string;\n email: string;\n name: string;\n cart: CartData | null;\n widgetId: string;\n }): Promise<GamificationPrize> {\n const url = `${this.apiHost}/v1/widgets/spin-wheel/submit`;\n \n const headers: Record<string, string> = {\n 'X-Aegis-Write-Key': this.writeKey,\n 'Content-Type': 'application/json'\n };\n \n if (this.organizationId) headers['X-Organization-ID'] = this.organizationId;\n \n const geoRegion = this.detectGeoRegion();\n const deviceType = this.getDeviceType();\n const utmParams = this.getUTMParams();\n \n const body: any = {\n phone: data.phone.replace(/[\\s()-]/g, ''),\n email: data.email || undefined,\n name: data.name || undefined,\n cart_id: data.cart?.cart_id || `web_${Date.now()}`,\n cart_token: data.cart?.cart_id,\n cart_total: data.cart?.cart_total || 0,\n cart_currency: data.cart?.cart_currency || 'USD',\n cart_items: data.cart?.cart_items || [],\n cart_url: window.location.href,\n platform: 'web',\n geo_region: geoRegion,\n device_type: deviceType,\n session_id: this.getSessionId() || undefined,\n anonymous_id: this.getAnonymousId() || undefined,\n utm_source: utmParams.utm_source,\n utm_medium: utmParams.utm_medium,\n utm_campaign: utmParams.utm_campaign\n };\n \n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body)\n });\n \n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to submit spin wheel: ${response.status} - ${errorText}`);\n }\n \n return await response.json();\n }\n \n private showSpinWheelPrize(modal: HTMLElement, prize: GamificationPrize): void {\n modal.innerHTML = '';\n \n const resultContainer = document.createElement('div');\n resultContainer.style.cssText = 'text-align: center; padding: 40px 20px;';\n \n const emoji = document.createElement('div');\n emoji.textContent = '🎉';\n emoji.style.cssText = 'font-size: 60px; margin-bottom: 20px;';\n resultContainer.appendChild(emoji);\n \n const title = document.createElement('h2');\n title.textContent = 'Congratulations!';\n title.style.cssText = 'margin: 0 0 12px 0; font-size: 28px; font-weight: 700; color: #1a73e8;';\n resultContainer.appendChild(title);\n \n const prizeLabel = document.createElement('p');\n prizeLabel.textContent = prize.prize_label;\n prizeLabel.style.cssText = 'margin: 0 0 20px 0; font-size: 20px; font-weight: 600; color: #333;';\n resultContainer.appendChild(prizeLabel);\n \n if (prize.coupon_code) {\n const couponContainer = document.createElement('div');\n couponContainer.style.cssText = `\n background: #f5f5f5;\n padding: 16px;\n border-radius: 8px;\n margin-bottom: 20px;\n border: 2px dashed #1a73e8;\n `;\n \n const couponLabel = document.createElement('div');\n couponLabel.textContent = 'Your coupon code:';\n couponLabel.style.cssText = 'font-size: 12px; color: #666; margin-bottom: 8px;';\n couponContainer.appendChild(couponLabel);\n \n const couponCode = document.createElement('div');\n couponCode.textContent = prize.coupon_code;\n couponCode.style.cssText = 'font-size: 24px; font-weight: 700; color: #1a73e8; letter-spacing: 2px;';\n couponContainer.appendChild(couponCode);\n \n resultContainer.appendChild(couponContainer);\n }\n \n const message = document.createElement('p');\n message.textContent = 'Check your WhatsApp/SMS for your discount code and cart link!';\n message.style.cssText = 'margin: 0 0 20px 0; font-size: 14px; color: #666;';\n resultContainer.appendChild(message);\n \n const closeButton = document.createElement('button');\n closeButton.textContent = 'Close';\n closeButton.style.cssText = `\n background: #1a73e8;\n color: white;\n border: none;\n padding: 12px 32px;\n border-radius: 8px;\n font-weight: 600;\n font-size: 14px;\n cursor: pointer;\n `;\n \n closeButton.addEventListener('click', () => {\n const overlay = modal.parentElement;\n if (overlay && document.body.contains(overlay)) {\n document.body.removeChild(overlay);\n }\n });\n \n resultContainer.appendChild(closeButton);\n modal.appendChild(resultContainer);\n }\n \n private detectGeoRegion(): string {\n const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n \n if (timezone.includes('America')) return 'north_america';\n if (timezone.includes('Europe')) return 'europe';\n if (timezone.includes('Asia/Kolkata') || timezone.includes('Asia/Calcutta')) return 'india';\n if (timezone.includes('Asia/Singapore') || timezone.includes('Asia/Bangkok') || timezone.includes('Asia/Jakarta')) return 'southeast_asia';\n if (timezone.includes('Asia/Dubai') || timezone.includes('Asia/Riyadh')) return 'middle_east';\n if (timezone.includes('America') && (timezone.includes('Sao_Paulo') || timezone.includes('Buenos_Aires'))) return 'latin_america';\n if (timezone.includes('Australia') || timezone.includes('Pacific/Auckland')) return 'oceania';\n \n return 'north_america';\n }\n \n private getUTMParams(): { utm_source?: string; utm_medium?: string; utm_campaign?: string } {\n const params = new URLSearchParams(window.location.search);\n return {\n utm_source: params.get('utm_source') || undefined,\n utm_medium: params.get('utm_medium') || undefined,\n utm_campaign: params.get('utm_campaign') || undefined\n };\n }\n \n private getSessionId(): string | null {\n return sessionStorage.getItem('aegis_session_id');\n }\n \n private getAnonymousId(): string | null {\n return localStorage.getItem('aegis_anonymous_id');\n }\n \n private renderScratchCard(widget: WidgetConfig): void {\n const overlay = document.createElement('div');\n overlay.className = 'aegis-gamification-overlay';\n overlay.setAttribute('data-widget-id', widget.widget_id);\n \n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.7);\n z-index: 1000000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: aegisFadeIn 0.3s ease-out;\n `;\n \n const modal = document.createElement('div');\n modal.className = 'aegis-scratch-card-modal';\n modal.style.cssText = `\n background: white;\n border-radius: 16px;\n padding: 32px;\n max-width: 500px;\n width: 90%;\n box-shadow: 0 10px 40px rgba(0,0,0,0.3);\n text-align: center;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n animation: aegisScaleIn 0.3s ease-out;\n `;\n \n const title = document.createElement('h2');\n title.textContent = widget.config.title || 'Scratch & Win!';\n title.style.cssText = 'margin: 0 0 16px 0; font-size: 24px; font-weight: 700; color: #1a1a1a;';\n modal.appendChild(title);\n \n const description = document.createElement('p');\n description.textContent = widget.config.description || 'Scratch to reveal your prize!';\n description.style.cssText = 'margin: 0 0 24px 0; font-size: 14px; color: #666;';\n modal.appendChild(description);\n \n const canvas = document.createElement('canvas');\n canvas.width = 300;\n canvas.height = 200;\n canvas.style.cssText = `\n border-radius: 8px;\n cursor: pointer;\n margin: 0 auto 24px;\n display: block;\n box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n `;\n modal.appendChild(canvas);\n \n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.fillStyle = '#c0c0c0';\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n ctx.fillStyle = '#888';\n ctx.font = '20px Arial';\n ctx.textAlign = 'center';\n ctx.fillText('Scratch here!', canvas.width / 2, canvas.height / 2);\n \n let isScratching = false;\n \n const scratch = (x: number, y: number) => {\n ctx.globalCompositeOperation = 'destination-out';\n ctx.beginPath();\n ctx.arc(x, y, 20, 0, Math.PI * 2);\n ctx.fill();\n };\n \n canvas.addEventListener('mousedown', () => { isScratching = true; });\n canvas.addEventListener('mouseup', () => { isScratching = false; });\n canvas.addEventListener('mousemove', (e) => {\n if (isScratching) {\n const rect = canvas.getBoundingClientRect();\n scratch(e.clientX - rect.left, e.clientY - rect.top);\n }\n });\n }\n \n const scratchButton = document.createElement('button');\n scratchButton.textContent = 'REVEAL PRIZE';\n scratchButton.style.cssText = `\n background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);\n color: white;\n border: none;\n padding: 16px 48px;\n border-radius: 8px;\n font-weight: 700;\n font-size: 16px;\n cursor: pointer;\n `;\n \n scratchButton.addEventListener('click', async () => {\n scratchButton.disabled = true;\n scratchButton.textContent = 'REVEALING...';\n \n try {\n const prize = await this.generatePrize(widget.config.config_id);\n this.showPrizeResult(modal, prize);\n } catch (error) {\n this.log(`Error generating prize: ${error}`, true);\n scratchButton.disabled = false;\n scratchButton.textContent = 'TRY AGAIN';\n }\n });\n \n modal.appendChild(scratchButton);\n \n overlay.appendChild(modal);\n this.addAnimationStyles();\n document.body.appendChild(overlay);\n }\n \n private renderToast(widget: WidgetConfig): void {\n const { message, icon, duration } = widget.config;\n const position = widget.position || 'bottom_left';\n \n const toast = document.createElement('div');\n toast.className = 'aegis-toast';\n toast.setAttribute('data-widget-id', widget.widget_id);\n \n const positionStyles: Record<string, string> = {\n bottom_left: 'bottom: 20px; left: 20px;',\n bottom_right: 'bottom: 20px; right: 20px;',\n top_left: 'top: 20px; left: 20px;',\n top_right: 'top: 20px; right: 20px;'\n };\n \n toast.style.cssText = `\n position: fixed;\n ${positionStyles[position] || positionStyles.bottom_left}\n background: white;\n padding: 16px 20px;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0,0,0,0.15);\n z-index: 999998;\n display: flex;\n align-items: center;\n gap: 12px;\n max-width: 350px;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n animation: aegisToastIn 0.3s ease-out;\n `;\n \n if (icon) {\n const iconEl = document.createElement('div');\n iconEl.textContent = icon;\n iconEl.style.cssText = 'font-size: 20px;';\n toast.appendChild(iconEl);\n }\n \n const messageEl = document.createElement('div');\n messageEl.textContent = message || 'Someone just made a purchase!';\n messageEl.style.cssText = 'flex: 1; font-size: 13px; color: #333;';\n toast.appendChild(messageEl);\n \n this.addAnimationStyles();\n document.body.appendChild(toast);\n \n setTimeout(() => {\n toast.style.animation = 'aegisToastOut 0.3s ease-out';\n setTimeout(() => {\n if (document.body.contains(toast)) {\n document.body.removeChild(toast);\n }\n this.renderedWidgets.delete(widget.widget_id);\n }, 300);\n }, duration || 5000);\n }\n \n private renderFeedbackForm(widget: WidgetConfig): void {\n const overlay = document.createElement('div');\n overlay.className = 'aegis-feedback-overlay';\n overlay.setAttribute('data-widget-id', widget.widget_id);\n \n overlay.style.cssText = `\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n width: 400px;\n background: white;\n box-shadow: -4px 0 20px rgba(0,0,0,0.15);\n z-index: 1000000;\n padding: 32px;\n overflow-y: auto;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n animation: aegisSlideInRight 0.3s ease-out;\n `;\n \n const title = document.createElement('h2');\n title.textContent = widget.config.title || 'We value your feedback!';\n title.style.cssText = 'margin: 0 0 8px 0; font-size: 20px; font-weight: 600; color: #1a1a1a;';\n overlay.appendChild(title);\n \n const description = document.createElement('p');\n description.textContent = widget.config.description || 'Help us improve your experience.';\n description.style.cssText = 'margin: 0 0 24px 0; font-size: 14px; color: #666;';\n overlay.appendChild(description);\n \n const form = document.createElement('form');\n \n const label = document.createElement('label');\n label.textContent = 'How likely are you to recommend us? (0-10)';\n label.style.cssText = 'display: block; font-size: 14px; font-weight: 600; margin-bottom: 8px; color: #333;';\n form.appendChild(label);\n \n const input = document.createElement('input');\n input.type = 'number';\n input.min = '0';\n input.max = '10';\n input.style.cssText = `\n width: 100%;\n padding: 12px;\n border: 1px solid #ddd;\n border-radius: 6px;\n font-size: 14px;\n margin-bottom: 16px;\n `;\n form.appendChild(input);\n \n const textareaLabel = document.createElement('label');\n textareaLabel.textContent = 'Tell us more (optional)';\n textareaLabel.style.cssText = 'display: block; font-size: 14px; font-weight: 600; margin-bottom: 8px; color: #333;';\n form.appendChild(textareaLabel);\n \n const textarea = document.createElement('textarea');\n textarea.rows = 4;\n textarea.style.cssText = `\n width: 100%;\n padding: 12px;\n border: 1px solid #ddd;\n border-radius: 6px;\n font-size: 14px;\n resize: vertical;\n margin-bottom: 16px;\n font-family: inherit;\n `;\n form.appendChild(textarea);\n \n const submitButton = document.createElement('button');\n submitButton.type = 'submit';\n submitButton.textContent = 'Submit Feedback';\n submitButton.style.cssText = `\n width: 100%;\n background: #1a73e8;\n color: white;\n border: none;\n padding: 12px;\n border-radius: 6px;\n font-weight: 600;\n font-size: 14px;\n cursor: pointer;\n `;\n form.appendChild(submitButton);\n \n form.addEventListener('submit', async (e) => {\n e.preventDefault();\n \n submitButton.disabled = true;\n submitButton.textContent = 'Submitting...';\n \n try {\n await this.submitFeedback(widget.widget_id, {\n score: parseInt(input.value),\n comment: textarea.value\n });\n \n overlay.innerHTML = '<div style=\"text-align: center; padding: 60px 20px;\"><h3 style=\"margin: 0 0 12px 0; color: #1a73e8;\">Thank you!</h3><p style=\"margin: 0; color: #666;\">Your feedback helps us improve.</p></div>';\n \n setTimeout(() => {\n document.body.removeChild(overlay);\n }, 2000);\n \n } catch (error) {\n this.log(`Error submitting feedback: ${error}`, true);\n submitButton.disabled = false;\n submitButton.textContent = 'Submit Feedback';\n }\n });\n \n overlay.appendChild(form);\n \n const closeButton = document.createElement('button');\n closeButton.textContent = '×';\n closeButton.setAttribute('aria-label', 'Close');\n closeButton.style.cssText = `\n position: absolute;\n top: 16px;\n right: 16px;\n background: transparent;\n border: none;\n font-size: 28px;\n cursor: pointer;\n color: #999;\n `;\n \n closeButton.addEventListener('click', () => {\n this.trackEvent(widget.widget_id, 'dismiss');\n document.body.removeChild(overlay);\n this.renderedWidgets.delete(widget.widget_id);\n });\n \n overlay.appendChild(closeButton);\n \n this.addAnimationStyles();\n document.body.appendChild(overlay);\n }\n \n private renderExitIntentPopup(widget: WidgetConfig): void {\n const { title, description, cta_text, cta_url, image_url } = widget.config;\n \n const overlay = document.createElement('div');\n overlay.className = 'aegis-exit-popup-overlay';\n overlay.setAttribute('data-widget-id', widget.widget_id);\n \n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.7);\n z-index: 1000000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: aegisFadeIn 0.3s ease-out;\n `;\n \n const modal = document.createElement('div');\n modal.className = 'aegis-exit-popup-modal';\n modal.style.cssText = `\n background: white;\n border-radius: 16px;\n max-width: 600px;\n width: 90%;\n overflow: hidden;\n box-shadow: 0 10px 40px rgba(0,0,0,0.3);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n animation: aegisScaleIn 0.3s ease-out;\n `;\n \n if (image_url) {\n const img = document.createElement('img');\n const safeUrl = this.sanitizeUrl(image_url);\n if (safeUrl) {\n img.src = safeUrl;\n img.alt = '';\n img.style.cssText = 'width: 100%; height: 250px; object-fit: cover;';\n modal.appendChild(img);\n }\n }\n \n const content = document.createElement('div');\n content.style.cssText = 'padding: 32px;';\n \n const titleEl = document.createElement('h2');\n titleEl.textContent = title || 'Wait! Don\\'t leave yet!';\n titleEl.style.cssText = 'margin: 0 0 16px 0; font-size: 28px; font-weight: 700; color: #1a1a1a;';\n content.appendChild(titleEl);\n \n const descEl = document.createElement('p');\n descEl.textContent = description || 'Get 10% off your first order!';\n descEl.style.cssText = 'margin: 0 0 24px 0; font-size: 16px; color: #666; line-height: 1.5;';\n content.appendChild(descEl);\n \n if (cta_text && cta_url) {\n const ctaButton = document.createElement('button');\n ctaButton.textContent = cta_text;\n ctaButton.style.cssText = `\n background: #1a73e8;\n color: white;\n border: none;\n padding: 16px 32px;\n border-radius: 8px;\n font-weight: 600;\n font-size: 16px;\n cursor: pointer;\n width: 100%;\n `;\n \n ctaButton.addEventListener('click', () => {\n this.trackEvent(widget.widget_id, 'click');\n const safeUrl = this.sanitizeUrl(cta_url);\n if (safeUrl) {\n window.location.href = safeUrl;\n }\n });\n \n content.appendChild(ctaButton);\n }\n \n modal.appendChild(content);\n \n const closeButton = document.createElement('button');\n closeButton.textContent = '×';\n closeButton.setAttribute('aria-label', 'Close');\n closeButton.style.cssText = `\n position: absolute;\n top: 16px;\n right: 16px;\n background: white;\n border: none;\n font-size: 28px;\n cursor: pointer;\n color: #666;\n width: 40px;\n height: 40px;\n border-radius: 50%;\n box-shadow: 0 2px 8px rgba(0,0,0,0.2);\n `;\n \n closeButton.addEventListener('click', () => {\n this.trackEvent(widget.widget_id, 'dismiss');\n document.body.removeChild(overlay);\n this.renderedWidgets.delete(widget.widget_id);\n });\n \n modal.style.position = 'relative';\n modal.appendChild(closeButton);\n \n overlay.appendChild(modal);\n this.addAnimationStyles();\n document.body.appendChild(overlay);\n }\n \n private async generatePrize(configId: string): Promise<GamificationPrize> {\n const url = `${this.apiHost}/v1/widgets/gamification/generate-prize`;\n \n const headers: Record<string, string> = {\n 'X-Aegis-Write-Key': this.writeKey,\n 'Content-Type': 'application/json'\n };\n \n if (this.userId) headers['X-User-ID'] = this.userId;\n if (this.contactId) headers['X-Contact-ID'] = this.contactId;\n if (this.organizationId) headers['X-Organization-ID'] = this.organizationId;\n \n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify({ config_id: configId })\n });\n \n if (!response.ok) {\n throw new Error(`Failed to generate prize: ${response.status}`);\n }\n \n return await response.json();\n }\n \n private showPrizeResult(modal: HTMLElement, prize: GamificationPrize): void {\n modal.innerHTML = '';\n \n const resultContainer = document.createElement('div');\n resultContainer.style.cssText = 'text-align: center; padding: 40px 20px;';\n \n const emoji = document.createElement('div');\n emoji.textContent = '🎉';\n emoji.style.cssText = 'font-size: 60px; margin-bottom: 20px;';\n resultContainer.appendChild(emoji);\n \n const title = document.createElement('h2');\n title.textContent = 'Congratulations!';\n title.style.cssText = 'margin: 0 0 12px 0; font-size: 28px; font-weight: 700; color: #1a73e8;';\n resultContainer.appendChild(title);\n \n const prizeLabel = document.createElement('p');\n prizeLabel.textContent = prize.prize_label;\n prizeLabel.style.cssText = 'margin: 0 0 20px 0; font-size: 20px; font-weight: 600; color: #333;';\n resultContainer.appendChild(prizeLabel);\n \n if (prize.coupon_code) {\n const couponContainer = document.createElement('div');\n couponContainer.style.cssText = `\n background: #f5f5f5;\n padding: 16px;\n border-radius: 8px;\n margin-bottom: 20px;\n border: 2px dashed #1a73e8;\n `;\n \n const couponLabel = document.createElement('div');\n couponLabel.textContent = 'Your coupon code:';\n couponLabel.style.cssText = 'font-size: 12px; color: #666; margin-bottom: 8px;';\n couponContainer.appendChild(couponLabel);\n \n const couponCode = document.createElement('div');\n couponCode.textContent = prize.coupon_code;\n couponCode.style.cssText = 'font-size: 24px; font-weight: 700; color: #1a73e8; letter-spacing: 2px;';\n couponContainer.appendChild(couponCode);\n \n resultContainer.appendChild(couponContainer);\n }\n \n const closeButton = document.createElement('button');\n closeButton.textContent = 'Close';\n closeButton.style.cssText = `\n background: #1a73e8;\n color: white;\n border: none;\n padding: 12px 32px;\n border-radius: 8px;\n font-weight: 600;\n font-size: 14px;\n cursor: pointer;\n `;\n \n closeButton.addEventListener('click', () => {\n const overlay = modal.parentElement;\n if (overlay && document.body.contains(overlay)) {\n document.body.removeChild(overlay);\n }\n });\n \n resultContainer.appendChild(closeButton);\n modal.appendChild(resultContainer);\n }\n \n private async submitFeedback(widgetId: string, data: Record<string, any>): Promise<void> {\n const url = `${this.apiHost}/v1/widgets/track-event`;\n \n const headers: Record<string, string> = {\n 'X-Aegis-Write-Key': this.writeKey,\n 'Content-Type': 'application/json'\n };\n \n if (this.userId) headers['X-User-ID'] = this.userId;\n if (this.contactId) headers['X-Contact-ID'] = this.contactId;\n if (this.organizationId) headers['X-Organization-ID'] = this.organizationId;\n \n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n widget_id: widgetId,\n event_type: 'submit',\n event_data: data\n })\n });\n \n if (!response.ok) {\n throw new Error(`Failed to submit feedback: ${response.status}`);\n }\n }\n \n private async trackEvent(widgetId: string, eventType: string, metadata?: Record<string, any>): Promise<void> {\n try {\n const url = `${this.apiHost}/v1/widgets/track-event`;\n \n const headers: Record<string, string> = {\n 'X-Aegis-Write-Key': this.writeKey,\n 'Content-Type': 'application/json'\n };\n \n if (this.userId) headers['X-User-ID'] = this.userId;\n if (this.contactId) headers['X-Contact-ID'] = this.contactId;\n if (this.organizationId) headers['X-Organization-ID'] = this.organizationId;\n \n await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n widget_id: widgetId,\n event_type: eventType,\n event_data: metadata || {}\n })\n });\n \n } catch (error) {\n this.log(`Error tracking widget event: ${error}`, true);\n }\n }\n \n private sanitizeUrl(url?: string): string | null {\n if (!url) return null;\n \n try {\n const parsed = new URL(url, window.location.href);\n if (parsed.protocol === 'javascript:' || parsed.protocol === 'data:') {\n this.log(`Blocked dangerous URL: ${url}`, true);\n return null;\n }\n return parsed.href;\n } catch {\n this.log(`Invalid URL: ${url}`, true);\n return null;\n }\n }\n \n private sanitizeColor(color: string): string {\n if (/^#[0-9A-F]{3,8}$/i.test(color)) {\n return color;\n }\n \n if (/^rgb\\(\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*\\d+\\s*\\)$/i.test(color)) {\n return color;\n }\n \n if (/^rgba\\(\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*[\\d.]+\\s*\\)$/i.test(color)) {\n return color;\n }\n \n return '#1a73e8';\n }\n \n private getDeviceType(): string {\n const ua = navigator.userAgent;\n if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(ua)) {\n return 'tablet';\n }\n if (/Mobile|Android|iP(hone|od)|IEMobile|BlackBerry|Kindle|Silk-Accelerated|(hpw|web)OS|Opera M(obi|ini)/.test(ua)) {\n return 'mobile';\n }\n return 'desktop';\n }\n \n private isMobileDevice(): boolean {\n const deviceType = this.getDeviceType();\n return deviceType === 'mobile' || deviceType === 'tablet';\n }\n \n private addAnimationStyles(): void {\n if (document.getElementById('aegis-widget-animations')) {\n return;\n }\n \n const style = document.createElement('style');\n style.id = 'aegis-widget-animations';\n style.textContent = `\n @keyframes aegisFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n \n @keyframes aegisScaleIn {\n from { transform: scale(0.8); opacity: 0; }\n to { transform: scale(1); opacity: 1; }\n }\n \n @keyframes aegisBubbleIn {\n from { transform: translateY(20px); opacity: 0; }\n to { transform: translateY(0); opacity: 1; }\n }\n \n @keyframes aegisToastIn {\n from { transform: translateX(-100%); opacity: 0; }\n to { transform: translateX(0); opacity: 1; }\n }\n \n @keyframes aegisToastOut {\n from { transform: translateX(0); opacity: 1; }\n to { transform: translateX(-100%); opacity: 0; }\n }\n \n @keyframes aegisSlideInRight {\n from { transform: translateX(100%); }\n to { transform: translateX(0); }\n }\n \n @keyframes aegisSpin {\n from { transform: rotate(0deg); }\n to { transform: rotate(1440deg); }\n }\n `;\n document.head.appendChild(style);\n }\n \n private renderCartRecoveryPopup(widgetId: string, config: NonNullable<PrefetchWidgetConfig['exit_intent']>): void {\n const overlay = document.createElement('div');\n overlay.className = 'aegis-exit-popup-overlay';\n overlay.setAttribute('data-widget-id', widgetId);\n \n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.7);\n z-index: 1000000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: aegisFadeIn 0.3s ease-out;\n `;\n \n const modal = document.createElement('div');\n modal.className = 'aegis-cart-recovery-modal';\n modal.style.cssText = `\n background: ${this.sanitizeColor(config.background_color || '#FFFFFF')};\n color: ${this.sanitizeColor(config.text_color || '#333333')};\n border-radius: 16px;\n max-width: 600px;\n width: 90%;\n padding: 40px;\n box-shadow: 0 10px 40px rgba(0,0,0,0.3);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n animation: aegisScaleIn 0.3s ease-out;\n position: relative;\n `;\n \n const title = document.createElement('h2');\n const titleText = this.interpolateCartVariables(config.title || 'Complete Your Order');\n title.textContent = titleText;\n title.style.cssText = `margin: 0 0 16px 0; font-size: 28px; font-weight: 700; color: ${this.sanitizeColor(config.accent_color || '#FF6B00')};`;\n modal.appendChild(title);\n \n const message = document.createElement('p');\n const messageText = this.interpolateCartVariables(config.message || 'Your cart is waiting for you!');\n message.textContent = messageText;\n message.style.cssText = 'margin: 0 0 24px 0; font-size: 16px; line-height: 1.5;';\n modal.appendChild(message);\n \n if (config.show_cart_items && this.cartData) {\n const cartItems = document.createElement('div');\n cartItems.style.cssText = 'margin: 0 0 24px 0; padding: 16px; background: rgba(0,0,0,0.05); border-radius: 8px;';\n \n const cartTitle = document.createElement('div');\n cartTitle.textContent = `${this.cartData.cart_items.length} items in your cart`;\n cartTitle.style.cssText = 'font-weight: 600; margin-bottom: 12px;';\n cartItems.appendChild(cartTitle);\n \n this.cartData.cart_items.slice(0, 3).forEach(item => {\n const itemDiv = document.createElement('div');\n itemDiv.textContent = `${item.quantity}× ${item.product_name || item.product_id}`;\n itemDiv.style.cssText = 'font-size: 14px; margin-bottom: 4px;';\n cartItems.appendChild(itemDiv);\n });\n \n modal.appendChild(cartItems);\n }\n \n if (config.discount_code) {\n const discountBox = document.createElement('div');\n discountBox.style.cssText = `\n margin: 0 0 24px 0;\n padding: 16px;\n background: ${this.sanitizeColor(config.accent_color || '#FF6B00')};\n color: white;\n border-radius: 8px;\n text-align: center;\n font-weight: 700;\n font-size: 18px;\n `;\n discountBox.textContent = `Use code: ${config.discount_code} for ${config.discount_percentage || 10}% off!`;\n modal.appendChild(discountBox);\n }\n \n if (config.show_timer && config.timer_minutes) {\n const timer = document.createElement('div');\n timer.style.cssText = 'margin: 0 0 24px 0; text-align: center; font-size: 14px; color: #999;';\n timer.textContent = `⏰ Offer expires in ${config.timer_minutes} minutes`;\n modal.appendChild(timer);\n }\n \n const ctaButton = document.createElement('button');\n ctaButton.textContent = config.cta_text || 'Complete Checkout';\n ctaButton.style.cssText = `\n background: ${this.sanitizeColor(config.accent_color || '#FF6B00')};\n color: white;\n border: none;\n padding: 16px 32px;\n border-radius: 8px;\n font-weight: 700;\n font-size: 16px;\n cursor: pointer;\n width: 100%;\n `;\n \n ctaButton.addEventListener('click', () => {\n this.trackEvent(widgetId, 'click', { type: 'cart_recovery' });\n const checkoutUrl = this.sanitizeUrl(config.cta_url || '/checkout');\n if (checkoutUrl) {\n window.location.href = checkoutUrl;\n }\n });\n \n modal.appendChild(ctaButton);\n \n const closeButton = document.createElement('button');\n closeButton.textContent = '×';\n closeButton.setAttribute('aria-label', 'Close');\n closeButton.style.cssText = `\n position: absolute;\n top: 16px;\n right: 16px;\n background: transparent;\n border: none;\n font-size: 28px;\n cursor: pointer;\n color: #999;\n `;\n \n closeButton.addEventListener('click', () => {\n this.trackEvent(widgetId, 'dismiss', { type: 'cart_recovery' });\n document.body.removeChild(overlay);\n this.renderedWidgets.delete(widgetId);\n });\n \n modal.appendChild(closeButton);\n overlay.appendChild(modal);\n this.addAnimationStyles();\n document.body.appendChild(overlay);\n \n this.trackEvent(widgetId, 'show', { type: 'cart_recovery', tier: config.tier });\n }\n \n private renderLeadGenPopup(widgetId: string, config: NonNullable<PrefetchWidgetConfig['exit_intent']>): void {\n const overlay = document.createElement('div');\n overlay.className = 'aegis-exit-popup-overlay';\n overlay.setAttribute('data-widget-id', widgetId);\n \n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.7);\n z-index: 1000000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: aegisFadeIn 0.3s ease-out;\n `;\n \n const modal = document.createElement('div');\n modal.className = 'aegis-leadgen-modal';\n modal.style.cssText = `\n background: white;\n border-radius: 16px;\n max-width: 500px;\n width: 90%;\n padding: 40px;\n box-shadow: 0 10px 40px rgba(0,0,0,0.3);\n text-align: center;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n animation: aegisScaleIn 0.3s ease-out;\n position: relative;\n `;\n \n const title = document.createElement('h2');\n title.textContent = config.title || 'Get 10% Off Your First Order!';\n title.style.cssText = 'margin: 0 0 16px 0; font-size: 28px; font-weight: 700; color: #1a1a1a;';\n modal.appendChild(title);\n \n const message = document.createElement('p');\n message.textContent = config.message || 'Subscribe to our newsletter and get an exclusive discount code.';\n message.style.cssText = 'margin: 0 0 24px 0; font-size: 16px; color: #666;';\n modal.appendChild(message);\n \n const form = document.createElement('form');\n \n const emailInput = document.createElement('input');\n emailInput.type = 'email';\n emailInput.placeholder = 'Enter your email';\n emailInput.required = true;\n emailInput.style.cssText = `\n width: 100%;\n padding: 14px;\n border: 2px solid #ddd;\n border-radius: 8px;\n font-size: 16px;\n margin-bottom: 16px;\n box-sizing: border-box;\n `;\n form.appendChild(emailInput);\n \n const submitButton = document.createElement('button');\n submitButton.type = 'submit';\n submitButton.textContent = 'Get My Discount';\n submitButton.style.cssText = `\n width: 100%;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n border: none;\n padding: 16px 32px;\n border-radius: 8px;\n font-weight: 700;\n font-size: 16px;\n cursor: pointer;\n `;\n form.appendChild(submitButton);\n \n form.addEventListener('submit', async (e) => {\n e.preventDefault();\n \n submitButton.disabled = true;\n submitButton.textContent = 'Submitting...';\n \n try {\n await this.trackEvent(widgetId, 'submit', { \n type: 'lead_gen',\n email: emailInput.value \n });\n \n modal.innerHTML = `\n <div style=\"text-align: center; padding: 20px;\">\n <div style=\"font-size: 48px; margin-bottom: 16px;\">✅</div>\n <h3 style=\"margin: 0 0 12px 0; color: #1a73e8;\">Thank You!</h3>\n <p style=\"margin: 0; color: #666;\">Check your email for your discount code!</p>\n </div>\n `;\n \n setTimeout(() => {\n document.body.removeChild(overlay);\n }, 2500);\n \n } catch (error) {\n this.log(`Error submitting lead gen form: ${error}`, true);\n submitButton.disabled = false;\n submitButton.textContent = 'Get My Discount';\n }\n });\n \n modal.appendChild(form);\n \n const closeButton = document.createElement('button');\n closeButton.textContent = '×';\n closeButton.setAttribute('aria-label', 'Close');\n closeButton.style.cssText = `\n position: absolute;\n top: 16px;\n right: 16px;\n background: transparent;\n border: none;\n font-size: 28px;\n cursor: pointer;\n color: #999;\n `;\n \n closeButton.addEventListener('click', () => {\n this.trackEvent(widgetId, 'dismiss', { type: 'lead_gen' });\n document.body.removeChild(overlay);\n this.renderedWidgets.delete(widgetId);\n });\n \n modal.appendChild(closeButton);\n overlay.appendChild(modal);\n this.addAnimationStyles();\n document.body.appendChild(overlay);\n \n this.trackEvent(widgetId, 'show', { type: 'lead_gen' });\n }\n \n private interpolateCartVariables(template: string): string {\n if (!this.cartData) return template;\n \n return template\n .replace(/\\{\\{cart_total\\}\\}/g, `${this.cartData.cart_currency} ${this.cartData.cart_total.toFixed(2)}`)\n .replace(/\\{\\{cart_currency\\}\\}/g, this.cartData.cart_currency)\n .replace(/\\{\\{cart_items_count\\}\\}/g, this.cartData.cart_items.length.toString());\n }\n \n private log(message: string, isError: boolean = false): void {\n if (this.debugMode || isError) {\n const method = isError ? 'error' : 'log';\n console[method](`[AegisWidgets] ${message}`);\n }\n }\n}\n","/**\n * TriggerEngine - Client-Side Trigger Evaluation\n * \n * Evaluates behavioral triggers that require real-time client state:\n * - Scroll depth (e.g., user scrolled >= 50%)\n * - Time on page (e.g., >= 30 seconds on current page)\n * - Exit intent (mouse leaving viewport toward browser controls)\n * - Inactivity (no user interaction for X seconds)\n * - Scroll velocity (mobile exit intent - fast upward scroll)\n * - Visibility change (tab/app switching)\n * - Back button (history navigation)\n * \n * Architecture:\n * - Server evaluates historical triggers (event counts, segments)\n * - Client evaluates behavioral triggers (scroll, time, exit intent)\n * - Zero latency - no server round trip needed\n * \n * Usage:\n * const trigger = new TriggerEngine();\n * trigger.on('scroll_depth_50', (data) => {\n * console.log('User scrolled to 50%', data);\n * });\n * trigger.start();\n */\n\nexport interface TriggerRule {\n type: 'scroll_depth' | 'time_on_page' | 'exit_intent' | 'inactivity' | 'scroll_velocity' | 'visibility_change' | 'back_button';\n config: ScrollDepthConfig | TimeOnPageConfig | ExitIntentConfig | InactivityConfig | ScrollVelocityConfig | VisibilityChangeConfig | BackButtonConfig;\n}\n\nexport interface ScrollDepthConfig {\n depth_percent: number;\n}\n\nexport interface TimeOnPageConfig {\n seconds: number;\n}\n\nexport interface ExitIntentConfig {\n enabled: boolean;\n}\n\nexport interface InactivityConfig {\n idle_seconds: number;\n}\n\nexport interface ScrollVelocityConfig {\n threshold: number;\n minScrollPosition: number;\n cooldown: number;\n}\n\nexport interface VisibilityChangeConfig {\n enabled: boolean;\n}\n\nexport interface BackButtonConfig {\n enabled: boolean;\n}\n\nexport interface TriggerEvent {\n type: string;\n data: Record<string, any>;\n timestamp: number;\n}\n\ntype TriggerCallback = (event: TriggerEvent) => void;\n\nexport class TriggerEngine {\n private listeners: Map<string, Set<TriggerCallback>> = new Map();\n private isStarted = false;\n \n private scrollDepthTargets = new Set<number>();\n private scrollDepthReached = new Set<number>();\n \n private timeOnPageTargets = new Map<number, number>();\n private pageLoadTime?: number;\n \n private exitIntentEnabled = false;\n private exitIntentFired = false;\n \n private inactivityTargets = new Map<number, number>();\n private lastActivityTime = Date.now();\n private inactivityCheckInterval?: number;\n \n private scrollVelocityEnabled = false;\n private scrollVelocityFired = false;\n private scrollVelocityConfig: ScrollVelocityConfig = {\n threshold: 0.5,\n minScrollPosition: 100,\n cooldown: 5000\n };\n private lastScrollY = 0;\n private lastScrollTime = Date.now();\n private scrollVelocityCooldownTimer?: number;\n \n private visibilityChangeEnabled = false;\n \n private backButtonEnabled = false;\n private backButtonFired = false;\n \n constructor() {}\n \n on(eventType: string, callback: TriggerCallback): void {\n if (!this.listeners.has(eventType)) {\n this.listeners.set(eventType, new Set());\n }\n this.listeners.get(eventType)!.add(callback);\n }\n \n off(eventType: string, callback: TriggerCallback): void {\n const callbacks = this.listeners.get(eventType);\n if (callbacks) {\n callbacks.delete(callback);\n }\n }\n \n registerScrollDepth(depthPercent: number): void {\n this.scrollDepthTargets.add(depthPercent);\n }\n \n registerTimeOnPage(seconds: number): void {\n if (!this.timeOnPageTargets.has(seconds)) {\n const timerId = window.setTimeout(() => {\n this.emit(`time_on_page_${seconds}`, {\n seconds,\n page_url: window.location.href\n });\n this.timeOnPageTargets.delete(seconds);\n }, seconds * 1000);\n \n this.timeOnPageTargets.set(seconds, timerId);\n }\n }\n \n registerExitIntent(): void {\n this.exitIntentEnabled = true;\n }\n \n registerInactivity(idleSeconds: number): void {\n if (!this.inactivityTargets.has(idleSeconds)) {\n const timerId = window.setTimeout(() => {\n const idleTime = (Date.now() - this.lastActivityTime) / 1000;\n \n if (idleTime >= idleSeconds) {\n this.emit(`inactivity_${idleSeconds}`, {\n idle_seconds: idleSeconds,\n actual_idle_time: idleTime\n });\n }\n \n this.inactivityTargets.delete(idleSeconds);\n }, idleSeconds * 1000);\n \n this.inactivityTargets.set(idleSeconds, timerId);\n }\n }\n \n registerScrollVelocity(config?: Partial<ScrollVelocityConfig>): void {\n this.scrollVelocityEnabled = true;\n \n if (config) {\n this.scrollVelocityConfig = {\n threshold: config.threshold ?? this.scrollVelocityConfig.threshold,\n minScrollPosition: config.minScrollPosition ?? this.scrollVelocityConfig.minScrollPosition,\n cooldown: config.cooldown ?? this.scrollVelocityConfig.cooldown\n };\n }\n }\n \n registerVisibilityChange(): void {\n this.visibilityChangeEnabled = true;\n }\n \n registerBackButton(): void {\n this.backButtonEnabled = true;\n }\n \n start(): void {\n if (this.isStarted) {\n return;\n }\n \n this.pageLoadTime = Date.now();\n this.lastActivityTime = Date.now();\n this.lastScrollY = window.scrollY || 0;\n this.lastScrollTime = Date.now();\n \n if (this.scrollDepthTargets.size > 0) {\n this.attachScrollListener();\n }\n \n if (this.exitIntentEnabled) {\n this.attachExitIntentListener();\n }\n \n if (this.scrollVelocityEnabled) {\n this.attachScrollVelocityListener();\n }\n \n if (this.visibilityChangeEnabled) {\n this.attachVisibilityChangeListener();\n }\n \n if (this.backButtonEnabled) {\n this.attachBackButtonListener();\n }\n \n this.attachActivityListeners();\n \n this.startInactivityCheck();\n \n this.isStarted = true;\n }\n \n stop(): void {\n if (!this.isStarted) {\n return;\n }\n \n this.removeScrollListener();\n this.removeExitIntentListener();\n this.removeScrollVelocityListener();\n this.removeVisibilityChangeListener();\n this.removeBackButtonListener();\n this.removeActivityListeners();\n \n this.timeOnPageTargets.forEach(timerId => clearTimeout(timerId));\n this.timeOnPageTargets.clear();\n \n this.inactivityTargets.forEach(timerId => clearTimeout(timerId));\n this.inactivityTargets.clear();\n \n if (this.inactivityCheckInterval) {\n clearInterval(this.inactivityCheckInterval);\n this.inactivityCheckInterval = undefined;\n }\n \n if (this.scrollVelocityCooldownTimer) {\n clearTimeout(this.scrollVelocityCooldownTimer);\n this.scrollVelocityCooldownTimer = undefined;\n }\n \n this.isStarted = false;\n }\n \n reset(): void {\n this.scrollDepthReached.clear();\n this.exitIntentFired = false;\n this.scrollVelocityFired = false;\n this.backButtonFired = false;\n this.pageLoadTime = Date.now();\n this.lastActivityTime = Date.now();\n this.lastScrollY = window.scrollY || 0;\n this.lastScrollTime = Date.now();\n \n if (this.scrollVelocityCooldownTimer) {\n clearTimeout(this.scrollVelocityCooldownTimer);\n this.scrollVelocityCooldownTimer = undefined;\n }\n }\n \n private attachScrollListener(): void {\n window.addEventListener('scroll', this.handleScroll, { passive: true });\n this.handleScroll();\n }\n \n private removeScrollListener(): void {\n window.removeEventListener('scroll', this.handleScroll);\n }\n \n private handleScroll = (): void => {\n const scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n const scrollHeight = document.documentElement.scrollHeight - window.innerHeight;\n const scrollPercent = scrollHeight > 0 ? (scrollTop / scrollHeight) * 100 : 0;\n \n for (const targetDepth of this.scrollDepthTargets) {\n if (scrollPercent >= targetDepth && !this.scrollDepthReached.has(targetDepth)) {\n this.scrollDepthReached.add(targetDepth);\n \n this.emit(`scroll_depth_${targetDepth}`, {\n depth_percent: targetDepth,\n actual_percent: scrollPercent,\n scroll_top: scrollTop,\n scroll_height: scrollHeight\n });\n }\n }\n };\n \n private attachExitIntentListener(): void {\n document.addEventListener('mouseleave', this.handleExitIntent);\n }\n \n private removeExitIntentListener(): void {\n document.removeEventListener('mouseleave', this.handleExitIntent);\n }\n \n private handleExitIntent = (event: MouseEvent): void => {\n if (this.exitIntentFired) {\n return;\n }\n \n if (event.clientY < 10) {\n this.exitIntentFired = true;\n \n this.emit('exit_intent', {\n client_y: event.clientY,\n page_url: window.location.href,\n time_on_page: this.pageLoadTime ? (Date.now() - this.pageLoadTime) / 1000 : 0\n });\n }\n };\n \n private attachScrollVelocityListener(): void {\n window.addEventListener('scroll', this.handleScrollVelocity, { passive: true });\n }\n \n private removeScrollVelocityListener(): void {\n window.removeEventListener('scroll', this.handleScrollVelocity);\n }\n \n private handleScrollVelocity = (): void => {\n if (this.scrollVelocityFired) {\n return;\n }\n \n const currentY = window.scrollY || document.documentElement.scrollTop;\n const currentTime = Date.now();\n const timeDiff = currentTime - this.lastScrollTime;\n \n if (timeDiff > 100) {\n const distance = this.lastScrollY - currentY;\n const velocity = Math.abs(distance / timeDiff);\n \n if (\n distance > 0 &&\n velocity > this.scrollVelocityConfig.threshold &&\n currentY > this.scrollVelocityConfig.minScrollPosition\n ) {\n this.scrollVelocityFired = true;\n \n this.emit('mobile_exit_intent', {\n scroll_velocity: velocity,\n scroll_distance: distance,\n current_position: currentY,\n page_url: window.location.href,\n time_on_page: this.pageLoadTime ? (Date.now() - this.pageLoadTime) / 1000 : 0\n });\n \n this.scrollVelocityCooldownTimer = window.setTimeout(() => {\n this.scrollVelocityFired = false;\n }, this.scrollVelocityConfig.cooldown);\n }\n \n this.lastScrollY = currentY;\n this.lastScrollTime = currentTime;\n }\n };\n \n private attachVisibilityChangeListener(): void {\n document.addEventListener('visibilitychange', this.handleVisibilityChange);\n }\n \n private removeVisibilityChangeListener(): void {\n document.removeEventListener('visibilitychange', this.handleVisibilityChange);\n }\n \n private handleVisibilityChange = (): void => {\n if (document.hidden) {\n this.emit('visibility_hidden', {\n page_url: window.location.href,\n time_on_page: this.pageLoadTime ? (Date.now() - this.pageLoadTime) / 1000 : 0\n });\n } else {\n this.emit('visibility_visible', {\n page_url: window.location.href\n });\n }\n };\n \n private attachBackButtonListener(): void {\n if (typeof window !== 'undefined' && window.history) {\n window.history.pushState(null, '', window.location.href);\n window.addEventListener('popstate', this.handleBackButton);\n }\n }\n \n private removeBackButtonListener(): void {\n window.removeEventListener('popstate', this.handleBackButton);\n }\n \n private handleBackButton = (): void => {\n if (this.backButtonFired) {\n return;\n }\n \n this.backButtonFired = true;\n \n window.history.pushState(null, '', window.location.href);\n \n this.emit('back_button', {\n page_url: window.location.href,\n time_on_page: this.pageLoadTime ? (Date.now() - this.pageLoadTime) / 1000 : 0\n });\n };\n \n private attachActivityListeners(): void {\n const events = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart', 'click'];\n events.forEach(event => {\n document.addEventListener(event, this.handleActivity, { passive: true });\n });\n }\n \n private removeActivityListeners(): void {\n const events = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart', 'click'];\n events.forEach(event => {\n document.removeEventListener(event, this.handleActivity);\n });\n }\n \n private handleActivity = (): void => {\n this.lastActivityTime = Date.now();\n };\n \n private startInactivityCheck(): void {\n this.inactivityCheckInterval = window.setInterval(() => {\n const idleTime = (Date.now() - this.lastActivityTime) / 1000;\n \n for (const [idleSeconds] of this.inactivityTargets) {\n if (idleTime >= idleSeconds) {\n this.emit(`inactivity_${idleSeconds}`, {\n idle_seconds: idleSeconds,\n actual_idle_time: idleTime\n });\n \n const timerId = this.inactivityTargets.get(idleSeconds);\n if (timerId) {\n clearTimeout(timerId);\n this.inactivityTargets.delete(idleSeconds);\n }\n }\n }\n }, 1000);\n }\n \n private emit(eventType: string, data: Record<string, any>): void {\n const event: TriggerEvent = {\n type: eventType,\n data,\n timestamp: Date.now()\n };\n \n const callbacks = this.listeners.get(eventType);\n if (callbacks) {\n callbacks.forEach(callback => {\n try {\n callback(event);\n } catch (error) {\n console.error(`Error in trigger callback for ${eventType}:`, error);\n }\n });\n }\n \n const wildcardCallbacks = this.listeners.get('*');\n if (wildcardCallbacks) {\n wildcardCallbacks.forEach(callback => {\n try {\n callback(event);\n } catch (error) {\n console.error(`Error in wildcard trigger callback:`, error);\n }\n });\n }\n }\n}\n"],"names":["DEFAULT_CONFIG","workspace_id","batch_size","batch_interval","capture_utm","capture_referrer","auto_page_view","session_timeout","debug","respect_dnt","cross_domain_tracking","secure_cookie","enable_offline_mode","max_offline_events","retry_failed_requests","max_retries","retry_backoff_multiplier","request_timeout","auto_region_detection","wait_for_consent","enable_consent_mode","integrate_onetrust","integrate_cookiebot","integrate_google_consent_mode","default_consent","analytics","marketing","functional","initialized","api_host","cell_endpoints","preferred_region","cookie_domain","plugins","active_cell","generateUUID","crypto","randomUUID","replace","c","r","Math","random","toString","generateMessageId","Date","now","slice","logger","constructor","this","enabled","prefix","enable","disable","isEnabled","message","args","info","console","warn","error","Identity","storage","userId","traits","anonymousId","getOrCreateAnonymousId","loadUserIdentity","id","get","set","storedUserId","storedTraits","JSON","parse","getAnonymousId","setUserId","setTraits","getUserId","stringify","getTraits","reset","remove","alias","newUserId","previousId","getState","SessionManager","sessionTimeoutMinutes","eventCount","checkInterval","activityThrottle","lastActivityUpdate","adClickIDs","sessionTimeout","lastActivityTime","sessionStartTime","session","loadSession","sessionId","startTime","landingPage","createNewSession","startActivityTracking","startExpiryCheck","sessionData","newSessionId","persistSession","activityHandler","onActivity","forEach","event","window","addEventListener","passive","document","visibilityState","setInterval","checkSessionExpiry","getSessionId","incrementEventCount","getSessionDuration","getEventCount","setAdClickIDs","Object","keys","length","getAdClickIDs","getLandingPage","destroy","clearInterval","EventQueue","config","transport","buffer","flushInterval","isFlushing","offlineQueue","isOnline","navigator","onLine","enableOfflineMode","loadOfflineQueue","setupOnlineListener","startFlushTimer","setupUnloadHandlers","offlineData","events","Array","isArray","maxOfflineEvents","flushOfflineQueue","saveOfflineQueue","data","flush","send","success","push","type","batchSize","addToOfflineQueue","shift","result","unshift","batchInterval","flushBeforeUnload","persistBufferToOfflineQueue","getQueueSize","getOfflineQueueSize","clear","Transport","activeCell","healthCheckInterval","regionLatencyMap","Map","cellEndpoints","initializeCellularArchitecture","cachedCell","loadCachedCell","isCellHealthy","selectOptimalCell","startHealthChecks","cached","saveCachedCell","cell","healthy","some","region","url","preferredRegion","preferredCell","find","autoRegionDetection","detectOptimalRegion","selectCellByPriority","healthyCells","filter","latencyPromises","map","async","latency","measureLatency","results","Promise","all","sort","a","b","optimalCell","performance","controller","AbortController","timeoutId","setTimeout","abort","response","fetch","method","signal","clearTimeout","ok","Infinity","sortedCells","priority","performHealthChecks","healthPromises","isHealthy","checkCellHealth","endpoint","getActiveEndpoint","payload","buildPayload","sendBeacon","sendViaBeacon","resolve","sendViaFetch","apiHost","Error","batch","sentAt","toISOString","writeKey","context","blob","Blob","attempt","requestTimeout","headers","Authorization","body","keepalive","json","errorText","text","status","statusText","shouldRetry","retryRequest","statusCode","retryFailedRequests","maxRetries","delay","pow","retryBackoffMultiplier","getActiveCell","getRegionLatencies","STORAGE_PREFIX","Storage","options","useLocalStorage","isLocalStorageAvailable","test","localStorage","setItem","removeItem","key","value","expiryDays","fullKey","item","expiry","setCookie","itemStr","getItem","getCookie","deleteCookie","startsWith","cookie","split","trim","name","days","date","setTime","getTime","cookieStr","toUTCString","secureCookie","location","protocol","cookieDomain","crossDomain","domain","getRootDomain","nameEQ","ca","i","charAt","substring","indexOf","hostname","parts","join","buildContext","utm","searchParams","URL","URLSearchParams","search","parseUTMParameters","device","ua","userAgent","detectDevice","os","version","match","detectOS","browser","detectBrowser","network","connection","mozConnection","webkitConnection","effectiveType","downlink","rtt","detectNetworkInfo","library","page","path","pathname","referrer","title","href","hash","locale","language","timezone","Intl","DateTimeFormat","resolvedOptions","timeZone","screen","width","height","density","devicePixelRatio","viewport","innerWidth","innerHeight","campaign","PluginRegistry","register","plugin","has","unregister","pluginName","delete","getAll","from","values","executeHook","hookName","hook","apply","String","onError","onErrorError","executeHookChain","initialValue","additionalArgs","executeHookParallel","promises","promise","ConsentManager","listeners","defaultConsent","waitForConsent","consentStorageKey","preferences","loadPreferences","stored","parsed","mergeWithDefaults","getDefaultPreferences","necessary","savePreferences","setConsent","updated","notifyListeners","grantAll","denyAll","hasConsent","category","getPreferences","getStatus","isAnalyticsEnabled","isMarketingEnabled","onChange","callback","index","splice","listener","integrateOneTrust","OneTrust","syncWithOneTrust","activeGroups","OnetrustActiveGroups","includes","OptanonWrapper","originalWrapper","integrateCookiebot","cookiebot","Cookiebot","syncWithCookiebot","consent","statistics","integrateGoogleConsentMode","gtag","updateGoogleConsent","ad_storage","analytics_storage","ad_user_data","ad_personalization","functionality_storage","personalization_storage","security_storage","Aegis","queue","initPromise","init","_init","_a","shouldRespectDNT","toLowerCase","pattern","isBot","buildConfig","identity","captureAdClickIDsOnInit","write_key","initializePlugins","dnt","doNotTrack","msDoNotTrack","parseAdClickIDs","hasAdClickIDs","use","catch","track","eventName","properties","assertInitialized","messageId","timestamp","captureEvent","identify","group","groupId","transformedEvent","setCell","cellEndpoint","existingCell","assign","getCellInfo","latencies","grantConsent","denyConsent","getConsentPreferences","onConsentChange","globalName","existingQueue","instance","loadOptions","_loadOptions","AegisInAppManager","campaigns","displayedCampaigns","Set","isInitialized","reconnectAttempts","maxReconnectAttempts","contactId","organizationId","debugMode","enableSSE","initialize","log","refreshCampaigns","connectSSE","updateUserId","updateContactId","disconnectSSE","eventSource","queryParams","entries","append","EventSource","campaign_id","readyState","CLOSED","attemptReconnect","close","min","device_type","detectDeviceType","page_url","isNewUser","abAssignments","getABAssignments","btoa","processABAssignments","tryDisplayNextCampaign","assigned_variant_id","getVariantId","campaignId","displayCampaign","add","interactiveSubTypes","sub_type","renderInteractive","trackEvent","renderModal","renderBanner","renderFullScreen","renderHalfInterstitial","renderAlert","renderPIP","renderTooltip","ic","interactive_config","bg","sanitizeColor","background_color","text_color","renderNPSSurvey","renderCountdownOffer","renderStarRating","renderQuickPoll","renderQuiz","dispatchEvent","CustomEvent","detail","overlay","createOverlay","modal","createElement","style","cssText","question","textContent","nps_question","appendChild","scale","btn","labels","notLikely","veryLikely","addCloseButton","addAnimationStyles","label","countdown_label","digits","digitStyle","val","el","targetStr","countdown_target","target","update","diff","max","h","floor","padStart","m","s","spans","querySelectorAll","requestAnimationFrame","desc","button_text","createCTAButton","stars","maxStars","rating_scale","star","transform","poll_options","optionsList","opt","optBtn","questions","currentQ","renderQuestion","childNodes","removeChild","lastChild","thank_you_message","q","progress","questionText","optionsDiv","className","action_url","safeUrl","sanitizeUrl","open","container","removeModal","banner","setAttribute","contentContainer","image_url","img","src","alt","textContainer","actionsContainer","ctaButton","removeBanner","closeButton","content","actions","position","alert","buttonContainer","cancelButton","pip","video_url","video","controls","autoplay","muted","animation","parentNode","cursor","e","anchorSelector","tooltip_anchor_selector","preferredPosition","tooltip_position","anchor","querySelector","textColor","tooltip","arrow","closeBtn","dismiss","stopPropagation","cta","anchorRect","getBoundingClientRect","tooltipRect","scrollX","scrollY","top","left","arrowTop","arrowLeft","arrowBottom","arrowRight","right","bottom","outsideClickHandler","contains","removeEventListener","getElementById","head","parsedUrl","origin","color","eventType","externalEventId","ingressEvent","tenant_id","source","external_event_id","event_type","user_id","contact_id","platform","variant_id","trace_id","metadata","level","styles","clearABState","AegisPlacementManager","placements","slots","renderedSlots","refreshPlacements","placementId","slot","existingContent","renderSlot","fallbackContent","renderFallback","placementIds","getDeviceType","placement","placement_id","renderAllSlots","size","content_type","renderDynamicInjection","containerId","innerHTML","renderCard","renderCarousel","renderVideo","renderHTML","onRender","cta_text","cta_url","titleEl","bodyEl","card","cardBody","items","carousel","carouselItem","itemContent","price","item_index","poster_url","safeVideoUrl","safePosterUrl","poster","action","html","wrapper","sanitizeHTML","link","cssSelector","css_selector","injectionMode","injection_mode","targetElement","insertBefore","firstChild","variantId","err","tempDiv","isError","AegisWidgetManager","widgets","renderedWidgets","prefetchWidgetConfigs","triggerEngine","enablePrefetch","cssCustomization","onEvent","sourcePlatform","updateCSSCustomization","customization","emitEvent","fetchPrefetchConfigs","preloadWidgetAssets","fetchWidgets","renderImmediateWidgets","setupTriggerListeners","setupExitIntentWithPrefetch","setCartData","cartData","cart_items","cart_currency","cart_total","detectPlatformCart","shopifyCart","normalizeShopifyCart","wooCart","normalizeWooCart","magentoCart","normalizeMagentoCart","win","Shopify","checkout","cart_id","token","parseFloat","total_price","currency","line_items","product_id","product_name","product_title","quantity","cartJsonEl","cart","aegis_cart","mageCacheStr","mageCache","quote_id","subtotalAmount","subtotal","currencyCode","item_id","qty","product_price_value","exitIntentConfig","exit_intent","imageUrl","Image","spinWheelConfig","spin_wheel","elapsed","toFixed","w","trigger_rules","widget","renderWidget","registerExitIntent","on","widget_id","depthPercent","depth_percent","registerScrollDepth","seconds","registerTimeOnPage","isMobile","isMobileDevice","mobileConfig","mobile_triggers","handleSpinWheelIntent","widgetId","detectedCart","renderSpinWheelWidget","sendCartAbandonmentBeacon","scroll_velocity","registerScrollVelocity","threshold","scroll_threshold","minScrollPosition","scroll_min_position","cooldown","scroll_cooldown","idle_timer","idleSeconds","idle_seconds","registerInactivity","visibility_change","registerVisibilityChange","back_button","registerBackButton","handleExitIntent","renderCartRecoveryPopup","renderLeadGenPopup","beaconData","organization_id","user_email","abandoned_at","beaconUrl","widget_type","renderChatBubble","renderSpinWheel","renderScratchCard","renderToast","renderFeedbackForm","renderExitIntentPopup","icon_url","link_url","bubble","positionStyles","bottom_right","bottom_left","top_right","top_left","icon","textEl","description","wheelPlaceholder","spinButton","disabled","prize","generatePrize","config_id","showPrizeResult","spinWheel","accentColor","accent_color","backgroundColor","buttonColor","button_color","wheelColors","onclick","interpolateCartVariables","subtitle","wheelContainer","form","phoneInput","placeholder","required","emailInput","nameInput","submitButton","errorMessage","preventDefault","phone","email","validatePhone","validateEmail","display","submitSpinWheel","showSpinWheelPrize","prize_label","has_email","geoRegion","detectGeoRegion","deviceType","utmParams","getUTMParams","cart_token","_b","_c","_d","_e","cart_url","geo_region","session_id","anonymous_id","utm_source","utm_medium","utm_campaign","resultContainer","emoji","prizeLabel","coupon_code","couponContainer","couponLabel","couponCode","parentElement","params","sessionStorage","canvas","ctx","getContext","fillStyle","fillRect","font","textAlign","fillText","isScratching","scratch","x","y","globalCompositeOperation","beginPath","arc","PI","fill","rect","clientX","clientY","scratchButton","duration","toast","iconEl","messageEl","input","textareaLabel","textarea","rows","submitFeedback","score","parseInt","comment","descEl","configId","event_data","titleText","messageText","show_cart_items","cartItems","cartTitle","itemDiv","discount_code","discountBox","discount_percentage","show_timer","timer_minutes","timer","checkoutUrl","tier","template","TriggerEngine","isStarted","scrollDepthTargets","scrollDepthReached","timeOnPageTargets","exitIntentEnabled","exitIntentFired","inactivityTargets","scrollVelocityEnabled","scrollVelocityFired","scrollVelocityConfig","lastScrollY","lastScrollTime","visibilityChangeEnabled","backButtonEnabled","backButtonFired","handleScroll","scrollTop","pageYOffset","documentElement","scrollHeight","scrollPercent","targetDepth","emit","actual_percent","scroll_top","scroll_height","client_y","time_on_page","pageLoadTime","handleScrollVelocity","currentY","currentTime","timeDiff","distance","velocity","abs","scroll_distance","current_position","scrollVelocityCooldownTimer","handleVisibilityChange","hidden","handleBackButton","history","pushState","handleActivity","off","callbacks","timerId","idleTime","actual_idle_time","start","attachScrollListener","attachExitIntentListener","attachScrollVelocityListener","attachVisibilityChangeListener","attachBackButtonListener","attachActivityListeners","startInactivityCheck","stop","removeScrollListener","removeExitIntentListener","removeScrollVelocityListener","removeVisibilityChangeListener","removeBackButtonListener","removeActivityListeners","inactivityCheckInterval","wildcardCallbacks"],"mappings":"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"}