@active-reach/web-sdk 1.7.3 → 1.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aegis-sw.js +1 -1
- package/dist/aegis.min.js +1 -1
- package/dist/aegis.min.js.map +1 -1
- package/dist/inapp/AegisInAppManager.d.ts +19 -0
- package/dist/inapp/AegisInAppManager.d.ts.map +1 -1
- package/dist/index.js +38 -5
- package/dist/index.js.map +1 -1
- package/dist/push/AegisWebPush.d.ts +1 -0
- package/dist/push/AegisWebPush.d.ts.map +1 -1
- package/dist/push/AegisWebPush.js +33 -0
- package/dist/push/AegisWebPush.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/utils/debounce.ts","../src/inapp/renderers/carousel-cards.ts","../src/inapp/renderers/sticky-bar.ts","../src/inapp/renderers/progress-bar.ts","../src/inapp/renderers/coachmark-tour.ts","../src/inapp/renderers/product-recommendation.ts","../src/inapp/AegisInAppManager.ts","../src/inapp/renderPreview.ts","../src/placements/AegisPlacementManager.ts","../src/triggers/TriggerEngine.ts","../src/core/sdk-config-poller.ts","../src/core/prefetch-bundle-client.ts","../src/inbox/AegisInbox.ts","../src/widgets/AegisWidgetManager.ts","../src/runtime/AegisMessageRuntime.ts","../src/core/bootstrap.ts","../src/index.ts"],"sourcesContent":["export function debounce<T extends (...args: any[]) => any>(\n func: T,\n wait: number\n): (...args: Parameters<T>) => void {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n return function debounced(...args: Parameters<T>): void {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n\n timeoutId = setTimeout(() => {\n func(...args);\n timeoutId = null;\n }, wait);\n };\n}\n\nexport function throttle<T extends (...args: any[]) => any>(\n func: T,\n limit: number\n): (...args: Parameters<T>) => void {\n let inThrottle = false;\n\n return function throttled(...args: Parameters<T>): void {\n if (!inThrottle) {\n func(...args);\n inThrottle = true;\n setTimeout(() => {\n inThrottle = false;\n }, limit);\n }\n };\n}\n","/**\n * CarouselCards renderer — a swipeable / autoplaying sequence of product\n * cards. Used for post-purchase upsells, cross-sell, and \"recently viewed\"\n * surfaces. The entire card list is pre-bundled — no network call on\n * trigger; slide advance is pure client state.\n *\n * Data shape (interactive_config, populated at campaign create time and\n * validated server-side):\n * cards: Array<{ image_url?, title, body?, cta_text?, cta_url? }>\n * autoplay_ms?: number // 0 = manual advance only\n * loop?: boolean // wrap to card 0 on last-next\n */\n\nimport type { RenderContext } from './types';\n\ntype Card = {\n image_url?: string;\n title?: string;\n body?: string;\n cta_text?: string;\n cta_url?: string;\n};\n\nconst MAX_CARDS_RENDERED = 10;\n\nexport function renderCarouselCards(ctx: RenderContext): void {\n const { campaign, trackEvent, sanitizeUrl, sanitizeColor, log, addAnimationStyles } = ctx;\n const ic = (campaign.interactive_config || {}) as Record<string, unknown>;\n const rawCards = Array.isArray(ic.cards) ? (ic.cards as Card[]) : [];\n const cards = rawCards.slice(0, MAX_CARDS_RENDERED);\n\n if (cards.length === 0) {\n log('carousel_cards rendered with zero cards — skipping', 'warn');\n return;\n }\n\n const autoplay = Number(ic.autoplay_ms) || 0;\n const loop = ic.loop !== false; // default true\n\n addAnimationStyles();\n\n const bg = sanitizeColor((campaign.background_color as string) || '#ffffff');\n const fg = sanitizeColor((campaign.text_color as string) || '#0f172a');\n\n const overlay = document.createElement('div');\n overlay.className = 'aegis-in-app-carousel-overlay';\n overlay.setAttribute('data-campaign-id', campaign.id);\n overlay.style.cssText = `\n position: fixed; left: 0; right: 0; bottom: 0;\n z-index: 99999; padding: 12px 12px 20px;\n background: rgba(0,0,0,0.12); backdrop-filter: blur(8px);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n animation: aegisSlideInFromBottom 0.3s ease-out;\n `;\n\n const card = document.createElement('div');\n card.style.cssText = `\n background: ${bg}; color: ${fg}; border-radius: 16px;\n box-shadow: 0 8px 20px rgba(0,0,0,0.08); padding: 16px;\n max-width: 520px; margin: 0 auto; position: relative;\n `;\n\n const header = document.createElement('div');\n header.style.cssText = 'display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; margin-bottom: 12px;';\n\n const headerText = document.createElement('div');\n const title = document.createElement('div');\n title.textContent = campaign.title;\n title.style.cssText = 'font-weight: 700; font-size: 15px; margin-bottom: 2px;';\n const body = document.createElement('div');\n body.textContent = campaign.body;\n body.style.cssText = 'font-size: 13px; opacity: 0.75;';\n headerText.appendChild(title);\n headerText.appendChild(body);\n header.appendChild(headerText);\n\n const closeBtn = document.createElement('button');\n closeBtn.textContent = '✕';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.style.cssText = `\n background: transparent; border: none; color: inherit;\n font-size: 16px; cursor: pointer; opacity: 0.6; padding: 2px 6px;\n `;\n closeBtn.addEventListener('click', () => {\n trackEvent(campaign.id, 'dismissed');\n overlay.remove();\n });\n header.appendChild(closeBtn);\n card.appendChild(header);\n\n const track = document.createElement('div');\n track.style.cssText = `\n display: flex; gap: 10px; overflow-x: auto; scroll-snap-type: x mandatory;\n scrollbar-width: none; -ms-overflow-style: none; padding-bottom: 4px;\n `;\n (track.style as unknown as { msOverflowStyle?: string }).msOverflowStyle = 'none';\n track.addEventListener('wheel', (e) => {\n if (Math.abs(e.deltaX) < Math.abs(e.deltaY)) return;\n track.scrollLeft += e.deltaX;\n });\n\n cards.forEach((c, i) => {\n const tile = document.createElement('div');\n tile.setAttribute('data-card-index', String(i));\n tile.style.cssText = `\n flex: 0 0 auto; width: 140px; scroll-snap-align: start;\n background: ${fg}0a; border-radius: 12px; padding: 10px;\n display: flex; flex-direction: column; gap: 6px;\n cursor: ${c.cta_url ? 'pointer' : 'default'};\n `;\n if (c.image_url) {\n const img = document.createElement('img');\n const safe = sanitizeUrl(c.image_url);\n if (safe) {\n img.src = safe;\n img.alt = '';\n img.loading = 'lazy';\n img.style.cssText = 'width: 100%; height: 96px; border-radius: 8px; object-fit: cover;';\n tile.appendChild(img);\n }\n }\n if (c.title) {\n const t = document.createElement('div');\n t.textContent = c.title;\n t.style.cssText = 'font-weight: 600; font-size: 13px; line-height: 1.3;';\n tile.appendChild(t);\n }\n if (c.body) {\n const b = document.createElement('div');\n b.textContent = c.body;\n b.style.cssText = 'font-size: 11.5px; opacity: 0.72; line-height: 1.3;';\n tile.appendChild(b);\n }\n if (c.cta_text && c.cta_url) {\n const cta = document.createElement('button');\n cta.textContent = c.cta_text;\n cta.style.cssText = `\n margin-top: auto; background: ${fg}; color: ${bg};\n border: none; padding: 6px 10px; border-radius: 999px;\n font-size: 12px; font-weight: 600; cursor: pointer;\n `;\n const goto = (e: Event) => {\n e.stopPropagation();\n trackEvent(campaign.id, 'clicked');\n const safe = sanitizeUrl(c.cta_url!);\n if (safe) window.location.href = safe;\n };\n cta.addEventListener('click', goto);\n tile.appendChild(cta);\n tile.addEventListener('click', goto);\n }\n track.appendChild(tile);\n });\n card.appendChild(track);\n\n // Dots + autoplay\n const dots = document.createElement('div');\n dots.style.cssText = 'display: flex; justify-content: center; gap: 6px; margin-top: 10px;';\n const dotEls: HTMLSpanElement[] = [];\n cards.forEach(() => {\n const dot = document.createElement('span');\n dot.style.cssText = `\n width: 6px; height: 6px; border-radius: 999px; background: ${fg};\n opacity: 0.25; transition: opacity 0.2s;\n `;\n dotEls.push(dot);\n dots.appendChild(dot);\n });\n card.appendChild(dots);\n\n const setActive = (idx: number) => {\n dotEls.forEach((d, i) => (d.style.opacity = i === idx ? '0.9' : '0.25'));\n };\n setActive(0);\n\n let activeIdx = 0;\n const tiles = track.querySelectorAll<HTMLDivElement>('[data-card-index]');\n const goto = (idx: number) => {\n activeIdx = ((idx % cards.length) + cards.length) % cards.length;\n const el = tiles[activeIdx];\n if (el) {\n el.scrollIntoView({ behavior: 'smooth', inline: 'start', block: 'nearest' });\n setActive(activeIdx);\n }\n };\n\n let autoplayTimer: ReturnType<typeof setInterval> | null = null;\n if (autoplay > 0 && cards.length > 1) {\n autoplayTimer = setInterval(() => {\n const next = activeIdx + 1;\n if (next >= cards.length && !loop) {\n if (autoplayTimer) clearInterval(autoplayTimer);\n return;\n }\n goto(next);\n }, autoplay);\n }\n\n overlay.addEventListener('remove', () => {\n if (autoplayTimer) clearInterval(autoplayTimer);\n });\n\n // Observe scroll to keep dots in sync when the user swipes.\n track.addEventListener('scroll', () => {\n const approx = Math.round(track.scrollLeft / 150);\n if (approx !== activeIdx && approx >= 0 && approx < cards.length) {\n activeIdx = approx;\n setActive(activeIdx);\n }\n });\n\n overlay.appendChild(card);\n document.body.appendChild(overlay);\n}\n","/**\n * StickyBar renderer — a pinned notification strip at the top or bottom\n * of the viewport. Used for free-shipping hints, flash-sale banners,\n * cart-reminder strips. Dismissible, optionally auto-hiding.\n *\n * interactive_config:\n * sticky_position: 'top' | 'bottom' (required)\n * sticky_bg_color?: string\n * sticky_dismissible?: boolean default true\n * sticky_auto_hide_ms?: number 0 = never\n */\n\nimport type { RenderContext } from './types';\n\n// Persist per-campaign dismissal across reloads so we don't re-show a\n// bar the user already closed. Scoped per campaign ID; storage key\n// survives navigation but is cleared when the user explicitly clears site data.\nconst DISMISS_STORAGE_PREFIX = 'aegis_sticky_dismissed:';\n\nexport function renderStickyBar(ctx: RenderContext): void {\n const { campaign, trackEvent, sanitizeUrl, sanitizeColor, log, addAnimationStyles } = ctx;\n const ic = (campaign.interactive_config || {}) as Record<string, unknown>;\n\n const position = ic.sticky_position === 'top' ? 'top' : 'bottom';\n const dismissible = ic.sticky_dismissible !== false;\n const autoHide = Number(ic.sticky_auto_hide_ms) || 0;\n\n // Already dismissed this session? Skip silently — the prefetch bundle\n // keeps re-offering it, but the user's explicit close stands until TTL.\n try {\n if (\n typeof localStorage !== 'undefined' &&\n localStorage.getItem(DISMISS_STORAGE_PREFIX + campaign.id)\n ) {\n log(`sticky_bar ${campaign.id} suppressed — user dismissed earlier`);\n return;\n }\n } catch {\n // localStorage blocked — fall through and render\n }\n\n addAnimationStyles();\n\n const bg = sanitizeColor(\n (ic.sticky_bg_color as string) || (campaign.background_color as string) || '#4169e1',\n );\n const fg = sanitizeColor((campaign.text_color as string) || '#ffffff');\n\n const bar = document.createElement('div');\n bar.className = 'aegis-in-app-sticky-bar';\n bar.setAttribute('data-campaign-id', campaign.id);\n\n const positionCss =\n position === 'top'\n ? 'top: 0; left: 0; right: 0; animation: aegisSlideDown 0.3s ease-out;'\n : 'bottom: 0; left: 0; right: 0; animation: aegisSlideInFromBottom 0.3s ease-out;';\n\n bar.style.cssText = `\n position: fixed; ${positionCss}\n background: ${bg}; color: ${fg};\n padding: 10px 14px; z-index: 999998;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n display: flex; align-items: center; gap: 12px; justify-content: center;\n box-shadow: 0 ${position === 'top' ? '2px' : '-2px'} 8px rgba(0,0,0,0.08);\n `;\n\n const label = document.createElement('div');\n label.style.cssText = 'flex: 0 1 auto; font-size: 13px; font-weight: 500; text-align: center;';\n const strong = document.createElement('strong');\n strong.textContent = campaign.title;\n strong.style.cssText = 'margin-right: 6px; font-weight: 700;';\n label.appendChild(strong);\n label.appendChild(document.createTextNode(campaign.body));\n bar.appendChild(label);\n\n if (campaign.action_url && campaign.button_text) {\n const cta = document.createElement('button');\n cta.textContent = campaign.button_text;\n cta.style.cssText = `\n background: ${fg}; color: ${bg};\n border: none; padding: 6px 14px; border-radius: 999px;\n font-size: 12px; font-weight: 700; cursor: pointer; white-space: nowrap;\n `;\n cta.addEventListener('click', () => {\n trackEvent(campaign.id, 'clicked');\n const safe = sanitizeUrl(campaign.action_url!);\n if (safe) window.location.href = safe;\n });\n bar.appendChild(cta);\n }\n\n let autoHideTimer: ReturnType<typeof setTimeout> | null = null;\n const remove = (persist: boolean) => {\n if (autoHideTimer) clearTimeout(autoHideTimer);\n if (persist) {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem(DISMISS_STORAGE_PREFIX + campaign.id, '1');\n }\n } catch {\n // swallow — localStorage may be disabled\n }\n }\n bar.remove();\n };\n\n if (dismissible) {\n const close = document.createElement('button');\n close.textContent = '✕';\n close.setAttribute('aria-label', 'Dismiss');\n close.style.cssText = `\n background: transparent; border: none; color: inherit;\n font-size: 16px; cursor: pointer; padding: 0 4px; opacity: 0.75;\n `;\n close.addEventListener('click', () => {\n trackEvent(campaign.id, 'dismissed');\n remove(true);\n });\n bar.appendChild(close);\n }\n\n if (autoHide > 0) {\n autoHideTimer = setTimeout(() => remove(false), autoHide);\n }\n\n document.body.appendChild(bar);\n}\n","/**\n * ProgressBar renderer — a persistent bar that shows the user's progress\n * toward a reward threshold (free shipping, loyalty tier, referral bonus).\n *\n * Two sources of the current value:\n * 'client' — cheap: read from window.Shopify / WooCommerce / Magento\n * cart globals. Untrusted; fine for visual-only hints.\n * 'sse' — trusted: cell-plane pushes current_value via SSE to the\n * already-shipped realtime server. For cart-gated rewards\n * (must agree with server-side checkout guard), prefer SSE.\n *\n * For Phase 1 we implement CLIENT mode end-to-end. SSE mode reads\n * `window.__aegisProgressSSE[campaign.id]` if populated by a parent app\n * — higher-level integration (the SSE bridge) can push values there.\n *\n * interactive_config:\n * progress_goal_type: 'cart_total' | 'items_in_cart' | 'loyalty_points' | 'referrals'\n * progress_threshold: number\n * progress_reward_text?: string\n * progress_source?: 'client' | 'sse' default 'client'\n */\n\nimport type { RenderContext } from './types';\n\ntype GoalType = 'cart_total' | 'items_in_cart' | 'loyalty_points' | 'referrals';\n\nexport function renderProgressBar(ctx: RenderContext): void {\n const { campaign, trackEvent, sanitizeColor, log, addAnimationStyles } = ctx;\n const ic = (campaign.interactive_config || {}) as Record<string, unknown>;\n\n const goalType = (ic.progress_goal_type as GoalType) || 'cart_total';\n const threshold = Number(ic.progress_threshold);\n if (!(threshold > 0)) {\n log('progress_bar requires a positive progress_threshold — skipping', 'warn');\n return;\n }\n const rewardText =\n (ic.progress_reward_text as string) || (campaign.body as string) || 'Unlocked!';\n const source = ic.progress_source === 'sse' ? 'sse' : 'client';\n\n addAnimationStyles();\n\n const bg = sanitizeColor((campaign.background_color as string) || '#f8fafc');\n const fill = sanitizeColor((campaign.text_color as string) || '#4169e1');\n const fg = '#0f172a';\n\n const bar = document.createElement('div');\n bar.className = 'aegis-in-app-progress-bar';\n bar.setAttribute('data-campaign-id', campaign.id);\n bar.style.cssText = `\n position: fixed; left: 12px; right: 12px; bottom: 12px;\n max-width: 540px; margin: 0 auto;\n background: ${bg}; color: ${fg}; border-radius: 12px;\n padding: 10px 14px; z-index: 999997;\n box-shadow: 0 8px 20px rgba(0,0,0,0.08);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n animation: aegisSlideInFromBottom 0.3s ease-out;\n `;\n\n const label = document.createElement('div');\n label.style.cssText = 'display: flex; justify-content: space-between; font-size: 13px; font-weight: 600; margin-bottom: 6px;';\n\n const leading = document.createElement('span');\n leading.textContent = campaign.title;\n label.appendChild(leading);\n\n const numeric = document.createElement('span');\n numeric.style.cssText = 'opacity: 0.7; font-weight: 500;';\n label.appendChild(numeric);\n bar.appendChild(label);\n\n const shell = document.createElement('div');\n shell.style.cssText = `\n height: 8px; border-radius: 999px; background: ${fill}22;\n overflow: hidden;\n `;\n const fillEl = document.createElement('div');\n fillEl.style.cssText = `\n height: 100%; border-radius: 999px; background: ${fill};\n width: 0%; transition: width 0.4s cubic-bezier(.4,0,.2,1);\n `;\n shell.appendChild(fillEl);\n bar.appendChild(shell);\n\n const footnote = document.createElement('div');\n footnote.style.cssText = 'font-size: 11.5px; opacity: 0.65; margin-top: 6px;';\n bar.appendChild(footnote);\n\n const readCurrentValue = (): number => {\n if (source === 'sse') {\n const hook = (window as unknown as {\n __aegisProgressSSE?: Record<string, number>;\n }).__aegisProgressSSE;\n return (hook && typeof hook[campaign.id] === 'number' ? hook[campaign.id] : 0) as number;\n }\n // client mode — read the platform cart globals the widget manager\n // already normalises (Shopify/Woo/Magento). We peek at the same\n // locations without pulling in AegisWidgetManager's 2k-line module.\n try {\n if (goalType === 'cart_total' || goalType === 'items_in_cart') {\n const win = window as unknown as {\n Shopify?: { checkout?: { total_price?: string | number } };\n aegis_cart?: { cart_total?: number; cart_items?: unknown[] };\n localStorage?: Storage;\n };\n if (win.Shopify?.checkout) {\n const v = parseFloat(String(win.Shopify.checkout.total_price || 0));\n return goalType === 'cart_total' ? v : 0;\n }\n if (win.aegis_cart) {\n if (goalType === 'items_in_cart') {\n return Array.isArray(win.aegis_cart.cart_items) ? win.aegis_cart.cart_items.length : 0;\n }\n return Number(win.aegis_cart.cart_total || 0);\n }\n // Magento cache fallback\n try {\n const cacheStr = window.localStorage?.getItem('mage-cache-storage');\n if (cacheStr) {\n const cache = JSON.parse(cacheStr) as { cart?: { subtotalAmount?: number; items?: unknown[] } };\n const cart = cache.cart;\n if (cart) {\n return goalType === 'cart_total'\n ? Number(cart.subtotalAmount || 0)\n : Array.isArray(cart.items)\n ? cart.items.length\n : 0;\n }\n }\n } catch {\n /* noop */\n }\n }\n // loyalty_points / referrals are expected to flow via SSE/push; in\n // client mode we cannot trust a local counter.\n return 0;\n } catch {\n return 0;\n }\n };\n\n let lastFiredUnlock = false;\n const update = () => {\n const cur = readCurrentValue();\n const pct = Math.max(0, Math.min(100, (cur / threshold) * 100));\n fillEl.style.width = `${pct}%`;\n numeric.textContent = `${cur.toFixed(0)} / ${threshold.toFixed(0)}`;\n if (pct >= 100) {\n footnote.textContent = rewardText;\n if (!lastFiredUnlock) {\n lastFiredUnlock = true;\n trackEvent(campaign.id, 'clicked'); // \"unlocked\" recorded as click\n }\n } else {\n const remaining = Math.max(0, threshold - cur);\n footnote.textContent = `Add ${remaining.toFixed(0)} more to unlock: ${rewardText}`;\n }\n };\n\n update();\n\n // Client-mode cart state changes fire events on the storefront globals\n // (Shopify emits `cart:updated`, Woo emits its own). Poll fallback at\n // 1s — negligible overhead because every tick is synchronous.\n const pollTimer = setInterval(update, 1000);\n const cleanup = () => clearInterval(pollTimer);\n window.addEventListener('beforeunload', cleanup, { once: true });\n bar.addEventListener('remove', cleanup);\n\n document.body.appendChild(bar);\n}\n","/**\n * CoachmarkTour renderer — a guided, multi-step walkthrough anchored to\n * DOM elements via CSS selectors. One tooltip appears at a time with\n * next/back navigation; completion + skip are persisted per contact via\n * localStorage under the `resume_key`, so an abandoned tour resumes on\n * the next visit instead of restarting or re-bothering the user.\n *\n * interactive_config:\n * steps: Array<{\n * anchor_web?: string, // CSS selector for THIS platform\n * anchor_android?: string, // ignored on web\n * anchor_ios?: string, // ignored on web\n * title: string,\n * body: string,\n * placement?: 'top' | 'bottom' | 'left' | 'right',\n * cta_text?: string,\n * }>\n * resume_key: string,\n * allow_skip?: boolean,\n * show_progress_dots?: boolean,\n */\n\nimport type { RenderContext } from './types';\n\ntype Step = {\n anchor_web?: string;\n anchor_android?: string;\n anchor_ios?: string;\n title: string;\n body: string;\n placement?: 'top' | 'bottom' | 'left' | 'right';\n cta_text?: string;\n};\n\nconst RESUME_PREFIX = 'aegis_coachmark_progress:';\n\nfunction readResumeIdx(resumeKey: string): number {\n try {\n if (typeof localStorage === 'undefined') return 0;\n const raw = localStorage.getItem(RESUME_PREFIX + resumeKey);\n const n = raw ? parseInt(raw, 10) : 0;\n return Number.isFinite(n) && n >= 0 ? n : 0;\n } catch {\n return 0;\n }\n}\n\nfunction writeResumeIdx(resumeKey: string, idx: number): void {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem(RESUME_PREFIX + resumeKey, String(idx));\n }\n } catch {\n /* noop */\n }\n}\n\nfunction clearResume(resumeKey: string): void {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.removeItem(RESUME_PREFIX + resumeKey);\n }\n } catch {\n /* noop */\n }\n}\n\nexport function renderCoachmarkTour(ctx: RenderContext): void {\n const { campaign, trackEvent, sanitizeColor, log, addAnimationStyles } = ctx;\n const ic = (campaign.interactive_config || {}) as Record<string, unknown>;\n\n const resumeKey = ic.resume_key as string | undefined;\n if (!resumeKey) {\n log('coachmark_tour requires interactive_config.resume_key — skipping', 'warn');\n return;\n }\n\n const steps = Array.isArray(ic.steps) ? (ic.steps as Step[]) : [];\n if (steps.length === 0) {\n log('coachmark_tour has no steps — skipping', 'warn');\n return;\n }\n\n const allowSkip = ic.allow_skip !== false;\n const showDots = ic.show_progress_dots !== false;\n\n addAnimationStyles();\n\n const bg = sanitizeColor((campaign.background_color as string) || '#0f172a');\n const fg = sanitizeColor((campaign.text_color as string) || '#ffffff');\n\n // Resume or start at 0.\n let current = readResumeIdx(resumeKey);\n if (current >= steps.length) {\n log(`coachmark_tour ${resumeKey} already complete — not re-showing`);\n return;\n }\n\n // Track the single overall impression once per mount.\n trackEvent(campaign.id, 'impression');\n\n let pointerEl: HTMLElement | null = null;\n let tipEl: HTMLElement | null = null;\n let highlightEl: HTMLElement | null = null;\n\n const cleanupOne = () => {\n pointerEl?.remove();\n tipEl?.remove();\n highlightEl?.remove();\n pointerEl = null;\n tipEl = null;\n highlightEl = null;\n };\n\n const finish = (opts: { skipped: boolean }) => {\n cleanupOne();\n if (opts.skipped) {\n trackEvent(campaign.id, 'dismissed');\n } else {\n trackEvent(campaign.id, 'clicked'); // completion\n }\n // Mark tour as complete so we never restart it for this contact.\n writeResumeIdx(resumeKey, steps.length);\n };\n\n const showStep = (idx: number) => {\n cleanupOne();\n const step = steps[idx];\n if (!step) {\n finish({ skipped: false });\n return;\n }\n writeResumeIdx(resumeKey, idx);\n\n const selector = step.anchor_web;\n let anchor: Element | null = null;\n if (selector) {\n try {\n anchor = document.querySelector(selector);\n } catch {\n anchor = null;\n }\n }\n if (!anchor) {\n log(`coachmark step ${idx} — selector '${selector}' not found; advancing`, 'warn');\n showStep(idx + 1);\n return;\n }\n\n const rect = anchor.getBoundingClientRect();\n // Slight highlight around the anchor so the user's eye snaps to it.\n highlightEl = document.createElement('div');\n highlightEl.style.cssText = `\n position: fixed;\n top: ${rect.top - 6}px; left: ${rect.left - 6}px;\n width: ${rect.width + 12}px; height: ${rect.height + 12}px;\n border-radius: 10px; z-index: 999998;\n box-shadow: 0 0 0 2px ${fg}, 0 0 0 9999px rgba(0,0,0,0.4);\n pointer-events: none;\n transition: all 0.2s ease;\n `;\n document.body.appendChild(highlightEl);\n\n const placement = step.placement || 'bottom';\n tipEl = document.createElement('div');\n tipEl.setAttribute('data-campaign-id', campaign.id);\n tipEl.style.cssText = `\n position: fixed; z-index: 999999;\n background: ${bg}; color: ${fg};\n padding: 12px 14px; border-radius: 12px;\n max-width: 260px;\n box-shadow: 0 8px 24px rgba(0,0,0,0.25);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n animation: aegisFadeIn 0.2s ease;\n `;\n\n const titleEl = document.createElement('div');\n titleEl.textContent = step.title;\n titleEl.style.cssText = 'font-weight: 700; font-size: 13px; margin-bottom: 4px;';\n tipEl.appendChild(titleEl);\n\n const bodyEl = document.createElement('div');\n bodyEl.textContent = step.body;\n bodyEl.style.cssText = 'font-size: 12.5px; line-height: 1.4; opacity: 0.9;';\n tipEl.appendChild(bodyEl);\n\n const controls = document.createElement('div');\n controls.style.cssText = 'display: flex; align-items: center; justify-content: space-between; margin-top: 10px; gap: 8px;';\n\n // Dots\n if (showDots) {\n const dots = document.createElement('div');\n dots.style.cssText = 'display: flex; gap: 4px;';\n steps.forEach((_, i) => {\n const d = document.createElement('span');\n d.style.cssText = `\n width: 5px; height: 5px; border-radius: 999px;\n background: ${fg}; opacity: ${i === idx ? '0.95' : '0.3'};\n `;\n dots.appendChild(d);\n });\n controls.appendChild(dots);\n } else {\n controls.appendChild(document.createElement('span'));\n }\n\n const buttons = document.createElement('div');\n buttons.style.cssText = 'display: flex; gap: 6px;';\n\n if (allowSkip && idx < steps.length - 1) {\n const skip = document.createElement('button');\n skip.textContent = 'Skip';\n skip.style.cssText = `\n background: transparent; color: inherit; opacity: 0.7;\n border: none; font-size: 12px; cursor: pointer; padding: 6px 8px;\n `;\n skip.addEventListener('click', () => finish({ skipped: true }));\n buttons.appendChild(skip);\n }\n\n const next = document.createElement('button');\n const isLast = idx === steps.length - 1;\n next.textContent = step.cta_text || (isLast ? 'Done' : 'Next');\n next.style.cssText = `\n background: ${fg}; color: ${bg};\n border: none; padding: 6px 12px; border-radius: 999px;\n font-size: 12px; font-weight: 700; cursor: pointer;\n `;\n next.addEventListener('click', () => {\n if (isLast) {\n finish({ skipped: false });\n } else {\n showStep(idx + 1);\n }\n });\n buttons.appendChild(next);\n\n controls.appendChild(buttons);\n tipEl.appendChild(controls);\n document.body.appendChild(tipEl);\n\n // Position after insertion so we know the tip's own dimensions.\n const tipRect = tipEl.getBoundingClientRect();\n const margin = 12;\n let top = rect.bottom + margin;\n let left = rect.left;\n if (placement === 'top') {\n top = rect.top - tipRect.height - margin;\n } else if (placement === 'left') {\n top = rect.top;\n left = rect.left - tipRect.width - margin;\n } else if (placement === 'right') {\n top = rect.top;\n left = rect.right + margin;\n }\n // Clamp to viewport.\n top = Math.max(8, Math.min(window.innerHeight - tipRect.height - 8, top));\n left = Math.max(8, Math.min(window.innerWidth - tipRect.width - 8, left));\n tipEl.style.top = `${top}px`;\n tipEl.style.left = `${left}px`;\n };\n\n showStep(current);\n\n // If the host page unloads mid-tour, leave the current index persisted so\n // the next session resumes from there. Nothing else to do — writeResumeIdx\n // was called in showStep.\n // Expose a cancel hook so app code can reset the tour from Dev Tools etc.\n (window as unknown as { aegisResetTour?: (key: string) => void }).aegisResetTour = (key: string) => clearResume(key);\n}\n","/**\n * ProductRecommendation renderer — personalized product grid/row rendered\n * from `interactive_config.cards[]` that the cell-plane populated at\n * bundle-assembly time. The SDK never calls a product-API at render\n * time — the preload contract is that the recommended products are\n * already in the bundle.\n *\n * The layout is narrower than the generic carousel because product recs\n * should feel like a first-class product grid, not a marketing slider.\n * Three layouts: grid (2-col / 3-col responsive), row (horizontal-scroll),\n * carousel (same as carousel_cards but different framing copy).\n *\n * interactive_config:\n * rec_source?: 'viewed' | 'abandoned' | 'cross_sell' | 'trending' | 'personalized'\n * (metadata only — the actual product list is in `cards[]`)\n * rec_count?: number (display hint; rendering is driven by cards.length)\n * rec_layout?: 'grid' | 'row' | 'carousel' default 'grid'\n * rec_cta_text?: string default 'Shop now'\n * cards: Array<{ image_url?, title?, body?, cta_url?, metadata? }>\n */\n\nimport type { RenderContext } from './types';\n\ntype Card = {\n image_url?: string;\n title?: string;\n body?: string;\n cta_text?: string;\n cta_url?: string;\n metadata?: Record<string, unknown>;\n};\n\nconst MAX_PRODUCTS = 24;\n\nexport function renderProductRecommendation(ctx: RenderContext): void {\n const { campaign, trackEvent, sanitizeUrl, sanitizeColor, log, addAnimationStyles } = ctx;\n const ic = (campaign.interactive_config || {}) as Record<string, unknown>;\n\n const rawCards = Array.isArray(ic.cards) ? (ic.cards as Card[]) : [];\n const cards = rawCards.slice(0, MAX_PRODUCTS);\n if (cards.length === 0) {\n log('product_recommendation rendered with zero products — skipping', 'warn');\n return;\n }\n\n const layout = (ic.rec_layout as string) || 'grid';\n const ctaDefault = (ic.rec_cta_text as string) || 'Shop now';\n\n addAnimationStyles();\n\n const bg = sanitizeColor((campaign.background_color as string) || '#ffffff');\n const fg = sanitizeColor((campaign.text_color as string) || '#0f172a');\n const accent = sanitizeColor('#4169e1');\n\n const overlay = document.createElement('div');\n overlay.className = 'aegis-in-app-product-rec';\n overlay.setAttribute('data-campaign-id', campaign.id);\n overlay.style.cssText = `\n position: fixed; inset: 0;\n background: rgba(15,23,42,0.55); backdrop-filter: blur(4px);\n display: flex; align-items: flex-end; justify-content: center;\n z-index: 99999; animation: aegisFadeIn 0.25s ease;\n `;\n\n const sheet = document.createElement('div');\n sheet.style.cssText = `\n background: ${bg}; color: ${fg};\n max-width: 560px; width: 100%; max-height: 80vh; overflow-y: auto;\n border-radius: 20px 20px 0 0;\n padding: 18px 16px 22px;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n animation: aegisSlideInFromBottom 0.3s ease-out;\n box-shadow: 0 -12px 30px rgba(0,0,0,0.12);\n `;\n\n // Drag handle (decorative, for mobile context)\n const handle = document.createElement('div');\n handle.style.cssText = `\n width: 36px; height: 4px; border-radius: 999px; background: ${fg}1f;\n margin: 0 auto 12px;\n `;\n sheet.appendChild(handle);\n\n const header = document.createElement('div');\n header.style.cssText = 'display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;';\n\n const headerText = document.createElement('div');\n const title = document.createElement('div');\n title.textContent = campaign.title;\n title.style.cssText = 'font-weight: 700; font-size: 16px; margin-bottom: 2px;';\n const body = document.createElement('div');\n body.textContent = campaign.body;\n body.style.cssText = 'font-size: 13px; opacity: 0.7; line-height: 1.4;';\n headerText.appendChild(title);\n headerText.appendChild(body);\n header.appendChild(headerText);\n\n const close = document.createElement('button');\n close.textContent = '✕';\n close.setAttribute('aria-label', 'Close');\n close.style.cssText = `\n background: transparent; border: none; color: inherit;\n font-size: 18px; cursor: pointer; padding: 4px 8px; opacity: 0.7;\n `;\n close.addEventListener('click', () => {\n trackEvent(campaign.id, 'dismissed');\n overlay.remove();\n });\n header.appendChild(close);\n sheet.appendChild(header);\n\n const grid = document.createElement('div');\n if (layout === 'row' || layout === 'carousel') {\n grid.style.cssText = `\n display: flex; gap: 10px; overflow-x: auto;\n scroll-snap-type: x mandatory; padding: 14px 0 4px;\n `;\n } else {\n grid.style.cssText = `\n display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;\n padding-top: 14px;\n `;\n }\n\n cards.forEach((c) => {\n const tile = document.createElement('div');\n const isRow = layout === 'row' || layout === 'carousel';\n tile.style.cssText = `\n background: ${fg}08; border-radius: 12px;\n padding: 10px; display: flex; flex-direction: column; gap: 6px;\n cursor: ${c.cta_url ? 'pointer' : 'default'};\n ${isRow ? 'flex: 0 0 150px; scroll-snap-align: start;' : ''}\n transition: transform 0.15s ease;\n `;\n\n if (c.image_url) {\n const img = document.createElement('img');\n const safe = sanitizeUrl(c.image_url);\n if (safe) {\n img.src = safe;\n img.alt = '';\n img.loading = 'lazy';\n img.style.cssText = 'width: 100%; aspect-ratio: 1 / 1; border-radius: 8px; object-fit: cover;';\n tile.appendChild(img);\n }\n }\n\n if (c.title) {\n const t = document.createElement('div');\n t.textContent = c.title;\n t.style.cssText = 'font-weight: 600; font-size: 13px; line-height: 1.3;';\n tile.appendChild(t);\n }\n\n // Price lives in metadata.price per the dashboard schema; we show it\n // prominently if present.\n const price = c.metadata && typeof c.metadata === 'object' ? (c.metadata as Record<string, unknown>).price : undefined;\n if (price !== undefined) {\n const p = document.createElement('div');\n p.textContent = String(price);\n p.style.cssText = `color: ${accent}; font-weight: 700; font-size: 13px;`;\n tile.appendChild(p);\n } else if (c.body) {\n const b = document.createElement('div');\n b.textContent = c.body;\n b.style.cssText = 'font-size: 11.5px; opacity: 0.72; line-height: 1.3;';\n tile.appendChild(b);\n }\n\n const cta = document.createElement('button');\n cta.textContent = c.cta_text || ctaDefault;\n cta.style.cssText = `\n margin-top: auto;\n background: ${accent}; color: #fff;\n border: none; padding: 7px 10px; border-radius: 999px;\n font-size: 12px; font-weight: 600; cursor: pointer;\n `;\n const go = (e: Event) => {\n e.stopPropagation();\n trackEvent(campaign.id, 'clicked');\n if (c.cta_url) {\n const safe = sanitizeUrl(c.cta_url);\n if (safe) window.location.href = safe;\n }\n };\n cta.addEventListener('click', go);\n tile.appendChild(cta);\n if (c.cta_url) tile.addEventListener('click', go);\n\n grid.appendChild(tile);\n });\n\n sheet.appendChild(grid);\n overlay.appendChild(sheet);\n\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) {\n trackEvent(campaign.id, 'dismissed');\n overlay.remove();\n }\n });\n\n document.body.appendChild(overlay);\n}\n","/**\n * AegisInAppManager - Web SDK In-App Messaging Module\n *\n * HTTP polling 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 (RFC 2026-04-16):\n * - Polls /v1/in-app/active on initialize + on identity change\n * - Caches campaigns locally in memory\n * - Evaluates trigger rules client-side\n * - Tracks events (impression, click, dismiss) asynchronously\n *\n * NOTE: Persistent SSE for downstream delivery is disabled by default\n * (enableSSE=false). Tenant dashboards that need realtime (inbox, chat,\n * live page) open SSE directly via Next.js API routes — not via this SDK.\n * End-user storefronts use polling + Web Push for background delivery.\n */\n\nimport type { RenderContext } from './renderers';\nimport {\n renderCarouselCards,\n renderCoachmarkTour,\n renderProductRecommendation,\n renderProgressBar,\n renderStickyBar,\n} from './renderers';\nimport { Storage } from '../utils/storage';\n\n// Read the SDK's persisted anonymous_id from localStorage/cookie if available.\n// Returns undefined when called server-side (no document/window) or when no\n// id has been minted yet — caller falls through to leaving userId unset.\nfunction readAnonIdFromStorage(): string | undefined {\n if (typeof document === 'undefined') return undefined;\n try {\n const storage = new Storage();\n return storage.get('anon_id') ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nexport interface InAppCampaign {\n id: string;\n type:\n | 'modal'\n | 'banner'\n | 'tooltip'\n | 'full_screen'\n | 'half_interstitial'\n | 'alert'\n | 'pip'\n // Preload-first display types (2026-04-22 §5.4 of the expansion plan)\n | 'carousel_cards'\n | 'sticky_bar'\n | 'progress_bar'\n | 'coachmark_tour'\n | 'product_recommendation';\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 // Conversion-aware suppression — added by Micro-Intent Engine P0a (2026-04-30).\n // Mirrors cell-plane FrequencyCap. When the host app calls\n // `notifyConversion(goalName)`, every armed campaign whose\n // `suppress_after_conversion_seconds` is set gets silenced for that\n // many seconds (session-scoped via sessionStorage). Prevents the\n // \"showing 10% off to a buyer who just paid full price\" failure mode.\n suppress_after_conversion_seconds?: number;\n suppress_after_dismiss_seconds?: number;\n scope?: 'session' | 'user' | 'user_sku';\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 // Resolved by POST /v1/sdk/bootstrap — required in production. Campaigns\n // with a non-empty `target_properties` list are filtered against this on\n // the server, so passing the wrong id (or omitting it) narrows visible\n // campaigns to the property-agnostic ones only.\n propertyId?: string;\n debugMode?: boolean;\n enableSSE?: boolean;\n /**\n * Callback invoked when the manager receives an in-app campaign with\n * a gamification sub_type (spin_wheel / scratch_card). The facade\n * (AegisMessageRuntime) wires this to the widget-renderer path so\n * interactive campaigns render correctly. When this is undefined,\n * gamification campaigns are logged and skipped.\n */\n onInteractiveCampaign?: (campaign: InAppCampaign) => void;\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 propertyId?: string;\n private debugMode: boolean;\n private enableSSE: boolean;\n private onInteractiveCampaign?: (campaign: InAppCampaign) => void;\n\n private campaigns: InAppCampaign[] = [];\n private displayedCampaigns = new Set<string>();\n // Conversion-aware suppression — campaign_id -> epoch_ms when suppression expires.\n // Populated by `notifyConversion()` and rehydrated from sessionStorage in\n // `refreshCampaigns()` so a navigation between pages preserves silence.\n private suppressedUntil = new Map<string, number>();\n private eventSource?: EventSource;\n private isInitialized = false;\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n // sessionStorage key prefix — one entry per goal so we can introspect what\n // converted and when. Format: { ts: epoch_ms }.\n private static readonly CONVERSION_STORAGE_PREFIX = 'aegis_conv_';\n \n constructor(config: AegisInAppConfig) {\n this.writeKey = config.writeKey;\n this.apiHost = config.apiHost || 'https://api.aegis.ai';\n // Fall back to the SDK's persisted anonymous_id (set on first /v1/sdk/bootstrap\n // and reused across the main analytics SDK) so anonymous storefront users\n // get journey-driven in-app messages keyed to the same identity used in\n // /v1/batch payloads. Without this, polling defaults to \"anonymous\" on the\n // server and bucket-misses every per-contact priority queue.\n this.userId = config.userId ?? readAnonIdFromStorage();\n this.contactId = config.contactId;\n this.organizationId = config.organizationId;\n this.propertyId = config.propertyId;\n this.debugMode = config.debugMode || false;\n // SSE is disabled by default. Kept as opt-in capability for future tenant\n // dashboards that embed the Aegis SDK and need realtime updates. End-user\n // storefronts must NOT enable this — persistent-per-tab SSE doesn't scale.\n this.enableSSE = config.enableSSE === true;\n this.onInteractiveCampaign = config.onInteractiveCampaign;\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 /**\n * Conversion-aware suppression. Call this when the host app observes a\n * goal event (purchase, order_placed, checkout_completed, or any custom\n * goal the workspace has configured per-campaign).\n *\n * For every armed campaign whose `frequency.suppress_after_conversion_seconds`\n * is set, this:\n * 1. Persists the conversion in sessionStorage (so subsequent page\n * loads in the same tab retain silence).\n * 2. Computes an expiry epoch_ms and stores it in `suppressedUntil`.\n * 3. The two campaign-evaluation paths (`tryDisplayNextCampaign`\n * and `onClientEvent`) skip campaigns whose `suppressedUntil`\n * has not yet passed.\n *\n * Scope: only `session` is implemented in P0a. `user` and `user_sku`\n * scopes degrade to session-only with a debug log; the schema accepts\n * them so future expansion is non-breaking.\n *\n * Safe to call repeatedly for the same goal — each call refreshes the\n * sessionStorage timestamp and re-applies suppression to any campaigns\n * loaded since the last call.\n */\n notifyConversion(goalName: string): void {\n if (!goalName) {\n this.log('notifyConversion called with empty goalName; ignored', 'warn');\n return;\n }\n const ts = Date.now();\n if (typeof sessionStorage !== 'undefined') {\n try {\n sessionStorage.setItem(\n `${AegisInAppManager.CONVERSION_STORAGE_PREFIX}${goalName}`,\n JSON.stringify({ ts }),\n );\n } catch {\n // sessionStorage may be disabled (Safari private mode, blocked\n // third-party context). Suppression still applies for the\n // current page lifetime via the in-memory map.\n }\n }\n this.applySuppressionFromCampaigns(ts);\n this.log(`notifyConversion: ${goalName} — suppressing ${this.suppressedUntil.size} armed campaigns`);\n }\n\n /**\n * Compute and store `suppressedUntil` entries for every armed campaign\n * whose `frequency.suppress_after_conversion_seconds` is set. Called by\n * `notifyConversion()` and `refreshCampaigns()` (the latter rehydrates\n * suppression for newly-loaded campaigns when a prior conversion event\n * exists in sessionStorage).\n *\n * `convertedAt` is the epoch_ms of the conversion; pass `Date.now()`\n * when called from `notifyConversion`, or the `ts` recovered from\n * sessionStorage when rehydrating.\n */\n private applySuppressionFromCampaigns(convertedAt: number): void {\n for (const c of this.campaigns) {\n const seconds = c.frequency?.suppress_after_conversion_seconds;\n if (typeof seconds !== 'number' || seconds <= 0) continue;\n const scope = c.frequency?.scope ?? 'session';\n if (scope !== 'session') {\n // P0a only implements session scope. Schema accepts user / user_sku\n // so future work doesn't break wire compatibility, but for now we\n // degrade to session and log.\n this.log(\n `applySuppressionFromCampaigns: scope=${scope} not implemented; degrading to session for campaign ${c.id}`,\n 'warn',\n );\n }\n const expiresAt = convertedAt + seconds * 1000;\n // Take the max so a later/longer suppression wins over an earlier one.\n const existing = this.suppressedUntil.get(c.id);\n if (existing === undefined || existing < expiresAt) {\n this.suppressedUntil.set(c.id, expiresAt);\n }\n }\n }\n\n /**\n * Recover any prior conversion timestamps from sessionStorage and apply\n * suppression to currently-loaded campaigns. Called from\n * `refreshCampaigns()` after `this.campaigns` is populated. This is the\n * mechanism that prevents a converted buyer from seeing a discount popup\n * on the next page load within the same session.\n */\n private rehydrateSuppressionFromStorage(): void {\n if (typeof sessionStorage === 'undefined') return;\n let earliestTs: number | null = null;\n try {\n for (let i = 0; i < sessionStorage.length; i++) {\n const key = sessionStorage.key(i);\n if (!key || !key.startsWith(AegisInAppManager.CONVERSION_STORAGE_PREFIX)) continue;\n const raw = sessionStorage.getItem(key);\n if (!raw) continue;\n const parsed = JSON.parse(raw) as { ts?: number };\n if (typeof parsed.ts === 'number') {\n earliestTs = earliestTs === null ? parsed.ts : Math.min(earliestTs, parsed.ts);\n }\n }\n } catch {\n // Malformed entries are silently skipped — suppression simply\n // doesn't apply for them.\n return;\n }\n if (earliestTs !== null) {\n this.applySuppressionFromCampaigns(earliestTs);\n }\n }\n\n /**\n * Returns true if the campaign is currently suppressed (Date.now() is\n * before the stored expiry). Used by both display paths.\n */\n private isSuppressed(campaignId: string): boolean {\n const expiresAt = this.suppressedUntil.get(campaignId);\n if (expiresAt === undefined) return false;\n if (Date.now() >= expiresAt) {\n this.suppressedUntil.delete(campaignId);\n return false;\n }\n return true;\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 if (this.propertyId) {\n headers['X-Property-Id'] = this.propertyId;\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 credentials: 'include',\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch campaigns: ${response.status}`);\n }\n\n const payload = await response.json();\n // Server returns an array; defensively handle error bodies (HTML\n // from misconfigured gateways, {} from maintenance endpoints, etc.)\n // so a bad response doesn't turn `updateContactId` into a thrower.\n this.campaigns = Array.isArray(payload) ? payload : [];\n\n // Process A/B assignments from server response (Critical Fix C)\n this.processABAssignments(this.campaigns);\n\n // Rehydrate conversion suppression from sessionStorage so a buyer\n // who converted on a prior page load in the same tab does not see\n // a discount popup on this load. Must run after this.campaigns is\n // populated and BEFORE tryDisplayNextCampaign so the first display\n // attempt honors suppression.\n this.rehydrateSuppressionFromStorage();\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 // Only auto-display campaigns that DO NOT have a client_trigger.\n // Trigger-gated campaigns wait for the host app to call\n // `onClientEvent()` or for TriggerEngine to fire the matching\n // behavioural event. This preserves the preload-first contract —\n // the campaign is armed but the render is gated.\n // Conversion-aware suppression: campaigns silenced by a prior\n // notifyConversion() call (or rehydrated from sessionStorage) are\n // skipped until their suppression window expires.\n const campaign = this.campaigns.find((c) =>\n !this.displayedCampaigns.has(c.id) && !c.client_trigger && !this.isSuppressed(c.id),\n );\n\n if (campaign) {\n this.displayCampaign(campaign);\n }\n }\n\n /**\n * Evaluate the currently armed campaigns against a client-side event\n * and render any that match their `client_trigger`.\n *\n * Called by the host app (e.g., the EcommerceTracker on product_viewed),\n * or by future TriggerEngine bridges. Safe to call repeatedly for the\n * same event — dedup happens via `displayedCampaigns`.\n *\n * Supported trigger types (align with the cell-plane server-side\n * `display_rules.trigger_type`):\n * - `custom_event` : fire when eventName matches config.event\n * - `product_match` : fire on `product_viewed` when eventData.product_id\n * matches config.product_id (string or string[])\n * - `delay` : client-side setTimeout — evaluated at armeng\n * time (kicked off from `displayCampaign`), not here.\n */\n onClientEvent(eventName: string, eventData: Record<string, unknown> = {}): void {\n for (const c of this.campaigns) {\n if (this.displayedCampaigns.has(c.id)) continue;\n if (!c.client_trigger) continue;\n // Conversion-aware suppression: trigger-gated campaigns silenced by\n // a prior notifyConversion() call are skipped until expiry.\n if (this.isSuppressed(c.id)) continue;\n if (this.matchesClientTrigger(c.client_trigger, eventName, eventData)) {\n this.displayCampaign(c);\n }\n }\n }\n\n private matchesClientTrigger(\n trigger: { type: string; config?: Record<string, unknown> },\n eventName: string,\n eventData: Record<string, unknown>,\n ): boolean {\n const cfg = trigger.config || {};\n switch (trigger.type) {\n case 'custom_event':\n return typeof cfg.event === 'string' && cfg.event === eventName;\n case 'product_match': {\n if (eventName !== 'product_viewed' && eventName !== 'product_view') {\n return false;\n }\n const wantedRaw = cfg.product_id;\n const wanted: string[] = Array.isArray(wantedRaw)\n ? (wantedRaw as string[])\n : typeof wantedRaw === 'string'\n ? [wantedRaw]\n : [];\n if (wanted.length === 0) return false;\n const actual = String(\n eventData.product_id ??\n eventData.productId ??\n (eventData.product as Record<string, unknown> | undefined)?.id ??\n '',\n );\n return wanted.includes(actual);\n }\n default:\n // Unknown or server-evaluated — do not auto-fire from the client.\n return false;\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 // Preload-first display types (2026-04-22). These renderers own their\n // own impression tracking so we don't double-count alongside the\n // trailing `this.trackEvent(... 'impression')` below — return early.\n case 'carousel_cards':\n renderCarouselCards(this.buildRenderContext(campaign));\n this.trackEvent(campaign.id, 'impression');\n return;\n case 'sticky_bar':\n renderStickyBar(this.buildRenderContext(campaign));\n this.trackEvent(campaign.id, 'impression');\n return;\n case 'progress_bar':\n renderProgressBar(this.buildRenderContext(campaign));\n this.trackEvent(campaign.id, 'impression');\n return;\n case 'coachmark_tour':\n // coachmark_tour fires its own impression/dismiss/click events\n // from within its state machine — don't double-report here.\n renderCoachmarkTour(this.buildRenderContext(campaign));\n return;\n case 'product_recommendation':\n renderProductRecommendation(this.buildRenderContext(campaign));\n this.trackEvent(campaign.id, 'impression');\n return;\n }\n\n this.trackEvent(campaign.id, 'impression');\n }\n\n /**\n * Build the shared context passed into the preload-first renderers.\n * Matches the interface in `./renderers/types.ts`. Kept as a private\n * method (rather than inlined at each call-site) so future renderer\n * additions stay consistent and easy to audit.\n */\n private buildRenderContext(campaign: InAppCampaign): RenderContext {\n return {\n campaign,\n trackEvent: (id, evt) => {\n void this.trackEvent(id, evt);\n },\n sanitizeUrl: (url: string) => this.sanitizeUrl(url),\n sanitizeColor: (color: string) => this.sanitizeColor(color),\n log: (msg: string, level?: 'log' | 'warn' | 'error') => this.log(msg, level),\n addAnimationStyles: () => this.addAnimationStyles(),\n };\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 if (this.onInteractiveCampaign) {\n this.onInteractiveCampaign(campaign);\n } else {\n this.log(\n `${campaign.sub_type} campaign received but no onInteractiveCampaign handler wired — install via AegisMessageRuntime`,\n 'warn',\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 /* Bottom-anchored slide IN (opposite of aegisSlideUp which slides OUT).\n Used by the preload-first renderers: sticky_bar (bottom),\n progress_bar, carousel_cards, product_recommendation. */\n @keyframes aegisSlideInFromBottom {\n from { transform: translateY(100%); opacity: 0; }\n to { transform: translateY(0); 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 // Use the public SDK scheme (/v1/in_app/events) — the gateway has an\n // explicit handler that auths via X-Aegis-Write-Key and forwards to\n // event-switchboard. Direct POST to /api/v1/events bypasses the SDK\n // auth model and hits the JWT preHandler → 401.\n // See docs/architecture/API_ROUTING.md §5.\n const url = `${this.apiHost}/v1/in_app/events`;\n const externalEventId = `inapp_${campaignId}_${eventType}_${Date.now()}`;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-Aegis-Write-Key': this.writeKey,\n };\n if (this.organizationId) headers['X-Organization-ID'] = this.organizationId;\n if (this.userId) headers['X-User-ID'] = this.userId;\n if (this.contactId) headers['X-Contact-ID'] = this.contactId;\n\n const body = {\n campaign_id: campaignId,\n event_type: eventType,\n user_id: this.userId,\n contact_id: this.contactId,\n anonymous_id: this.userId,\n platform: 'web',\n metadata: {\n property_id: this.propertyId,\n variant_id: this.getVariantId(campaignId) ?? undefined,\n },\n idempotency_key: externalEventId,\n };\n\n fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n credentials: 'include',\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 if (typeof document !== 'undefined') {\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\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 * renderPreview — Static Preview Renderer for Dashboard iframe (Critical Fix A)\n *\n * Used exclusively by the sandboxed iframe preview route\n * (`/api/preview/in-app/route.tsx`). Renders a single campaign into the\n * current document body using the same rendering logic as the production SDK.\n *\n * Data flow:\n * editor-sidebar.tsx → onChange → formState → postMessage({type:'preview_update', config})\n * → iframe receives message → calls renderPreview(config)\n *\n * This ensures 100% fidelity between the dashboard editor preview and\n * production rendering — both use the same SDK code.\n */\n\nimport type { InAppCampaign } from './AegisInAppManager';\nimport { AegisInAppManager } from './AegisInAppManager';\n\n/**\n * Renders a single in-app campaign into the current document for preview.\n *\n * Creates a temporary AegisInAppManager with preview-only config (no tracking,\n * no SSE, no network requests). Calls the same rendering pipeline as production.\n */\nexport function renderPreview(config: InAppCampaign & { interactive_config?: Record<string, unknown> }): void {\n // Clear previous preview\n document.querySelectorAll(\n '[class^=\"aegis-in-app-\"]'\n ).forEach((el) => {\n if (el.parentNode) {\n el.parentNode.removeChild(el);\n }\n });\n\n if (!config) return;\n\n // Create a lightweight preview-only manager\n const manager = new AegisInAppManager({\n writeKey: 'preview-mode',\n apiHost: '',\n debugMode: false,\n enableSSE: false,\n });\n\n // Override trackEvent to be a no-op in preview mode\n // Access private via any cast — preview only, not production code\n const m = manager as unknown as {\n displayCampaign: (campaign: InAppCampaign) => void;\n trackEvent: (campaignId: string, eventType: string) => Promise<void>;\n addAnimationStyles: () => void;\n };\n\n // No-op tracking for preview\n m.trackEvent = async () => {};\n\n // Ensure animation styles are injected\n m.addAnimationStyles();\n\n // Render the campaign\n m.displayCampaign(config);\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 DOMPurify (when available) with allowlisted tags/attrs; safe text-only fallback\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 // Use DOMPurify if available (recommended for production)\n const purify = (window as unknown as Record<string, unknown>).DOMPurify as\n | { sanitize: (dirty: string, cfg?: Record<string, unknown>) => string }\n | undefined;\n\n if (purify?.sanitize) {\n return purify.sanitize(html, {\n ALLOWED_TAGS: [\n 'a', 'b', 'br', 'div', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'i', 'img', 'li', 'ol', 'p', 'span', 'strong', 'u', 'ul', 'table',\n 'thead', 'tbody', 'tr', 'th', 'td', 'blockquote', 'hr', 'figure',\n 'figcaption', 'picture', 'source', 'video', 'section', 'article',\n ],\n ALLOWED_ATTR: [\n 'href', 'target', 'rel', 'src', 'alt', 'width', 'height', 'class',\n 'id', 'style', 'title', 'loading', 'srcset', 'sizes', 'type',\n 'media', 'controls', 'poster',\n ],\n ALLOW_DATA_ATTR: false,\n });\n }\n\n // Built-in fallback: strip all tags via DOM parsing, then re-allow safe subset\n this.log(\n 'DOMPurify not found — falling back to built-in sanitizer. ' +\n 'For full HTML placement support, add <script src=\"https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.2.4/purify.min.js\"></script>',\n false\n );\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 * 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","/**\n * SDK Config Poller\n *\n * Fetches non-sensitive SDK configuration from GET /v1/sdk/config\n * with ETag/If-None-Match support for 304 responses.\n *\n * Polls every 5 minutes by default. Config changes are applied\n * to push/in-app managers without re-initialization.\n */\n\nimport { logger } from '../utils/logger';\n\nexport interface SdkConfig {\n version: string;\n push: {\n enabled: boolean;\n vapid_public_key: string | null;\n platforms: string[];\n };\n in_app: {\n enabled: boolean;\n };\n consent: {\n channels_requiring_opt_in: string[];\n };\n}\n\nexport interface SdkConfigPollerOptions {\n apiHost: string;\n writeKey: string;\n organizationId?: string;\n pollIntervalMs?: number;\n}\n\nexport type ConfigChangeCallback = (config: SdkConfig) => void;\n\nexport class SdkConfigPoller {\n private options: Required<Omit<SdkConfigPollerOptions, 'organizationId'>> & { organizationId?: string };\n private currentETag: string | null = null;\n private currentConfig: SdkConfig | null = null;\n private pollTimer: ReturnType<typeof setInterval> | null = null;\n private listeners: ConfigChangeCallback[] = [];\n\n constructor(options: SdkConfigPollerOptions) {\n this.options = {\n pollIntervalMs: 300_000, // 5 minutes\n ...options,\n };\n }\n\n /**\n * Fetch config once (on init) and start polling.\n */\n async start(): Promise<SdkConfig | null> {\n const config = await this.fetchConfig();\n\n this.pollTimer = setInterval(() => {\n this.fetchConfig().catch((err) => {\n logger.warn('SDK config poll failed:', err);\n });\n }, this.options.pollIntervalMs);\n\n return config;\n }\n\n /**\n * Stop polling.\n */\n stop(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n }\n\n /**\n * Register a callback for config changes.\n */\n onChange(callback: ConfigChangeCallback): () => void {\n this.listeners.push(callback);\n return () => {\n const idx = this.listeners.indexOf(callback);\n if (idx >= 0) this.listeners.splice(idx, 1);\n };\n }\n\n /**\n * Get current cached config.\n */\n getConfig(): SdkConfig | null {\n return this.currentConfig;\n }\n\n /**\n * Fetch config with ETag/304 support.\n */\n private async fetchConfig(): Promise<SdkConfig | null> {\n try {\n const headers: Record<string, string> = {\n 'X-Aegis-Write-Key': this.options.writeKey,\n 'Accept': 'application/json',\n };\n\n if (this.options.organizationId) {\n headers['X-Organization-ID'] = this.options.organizationId;\n }\n\n if (this.currentETag) {\n headers['If-None-Match'] = this.currentETag;\n }\n\n const response = await fetch(`${this.options.apiHost}/v1/sdk/config`, {\n method: 'GET',\n headers,\n });\n\n // 304 Not Modified — config unchanged\n if (response.status === 304) {\n return this.currentConfig;\n }\n\n if (!response.ok) {\n logger.warn(`SDK config fetch failed: HTTP ${response.status}`);\n return this.currentConfig;\n }\n\n const config: SdkConfig = await response.json();\n const newETag = response.headers.get('ETag');\n\n if (newETag) {\n this.currentETag = newETag;\n }\n\n // Detect changes\n const changed = !this.currentConfig ||\n JSON.stringify(this.currentConfig) !== JSON.stringify(config);\n\n this.currentConfig = config;\n\n if (changed) {\n for (const listener of this.listeners) {\n try {\n listener(config);\n } catch (err) {\n logger.warn('SDK config change listener error:', err);\n }\n }\n }\n\n return config;\n } catch (err) {\n logger.warn('SDK config fetch error:', err);\n return this.currentConfig;\n }\n }\n}\n","/**\n * PrefetchBundleClient — unified init-time resolver for in-app state.\n *\n * Fetches /v1/sdk/prefetch-bundle at SDK init and on a 5-minute ETag\n * refresh cadence. The bundle payload carries:\n * • `campaigns[]` — eligible, property-scoped, A/B-assigned campaigns\n * armed for this contact. EVERY in-app type is in\n * here (modal, banner, spin_wheel, carousel_cards,\n * sticky_bar, progress_bar, coachmark_tour, etc.).\n * • `inbox` — first page + unread count for the notification\n * drawer; lets AegisInbox hydrate without a second\n * round-trip.\n * • `etag` — content-hashed, stable when state is unchanged;\n * 304 responses cost ~50ms and consume no body.\n * • `invalidation_topic` — SSE channel name the cell-plane publishes\n * to when a playbook arms a campaign mid-session.\n * The SDK does NOT open SSE on that topic today —\n * we rely on the 5-minute poll + an explicit\n * `refresh()` hook that app code (AegisInAppManager,\n * AegisInbox) call on relevant user actions.\n *\n * This is the cornerstone of the preload-first contract from\n * docs/architecture/IN_APP_MESSAGES_EXPANSION_PLAN.md §1. The render\n * path must NEVER hit the network at trigger time — the bundle is\n * populated at init, and everything renders from memory.\n */\n\nimport { logger } from '../utils/logger';\n\nexport interface PrefetchBundleCampaign {\n id: string;\n type: string;\n sub_type?: string;\n title: string;\n body: string;\n image_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 | null;\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 inbox_enabled?: boolean;\n}\n\nexport interface PrefetchBundleInboxEntry {\n id: string;\n source: string;\n campaign_id: string | null;\n title: string;\n body: string;\n media_url: string | null;\n cta_url: string | null;\n metadata: Record<string, unknown> | null;\n read: boolean;\n read_at: string | null;\n created_at: string | null;\n expires_at: string | null;\n}\n\nexport interface PrefetchBundleInbox {\n unread_count: number;\n page: PrefetchBundleInboxEntry[];\n cursor: string | null;\n}\n\nexport interface PrefetchBundle {\n etag: string;\n generated_at: string;\n ttl_seconds: number;\n invalidation_topic: string;\n campaigns: PrefetchBundleCampaign[];\n inbox: PrefetchBundleInbox;\n}\n\nexport interface PrefetchBundleContext {\n device_type?: string;\n page_url?: string;\n geo?: string;\n is_new_user?: boolean;\n}\n\nexport interface PrefetchBundleClientOptions {\n apiHost: string;\n writeKey: string;\n organizationId?: string;\n contactId?: string;\n userId?: string;\n propertyId?: string;\n /** Cached AB assignments from localStorage, base64-json. */\n abAssignments?: Record<string, string>;\n /** Polling cadence; defaults to the bundle's own `ttl_seconds` (300s). */\n pollIntervalMs?: number;\n /** Factory for client context — re-evaluated on each fetch so device/page\n * state stays fresh without forcing callers to re-instantiate the client. */\n contextProvider?: () => PrefetchBundleContext;\n}\n\nexport type PrefetchBundleListener = (bundle: PrefetchBundle) => void;\n\nconst DEFAULT_POLL_MS = 300_000; // 5 minutes — aligns with cell-plane TTL\n\nexport class PrefetchBundleClient {\n private apiHost: string;\n private writeKey: string;\n private organizationId?: string;\n private contactId?: string;\n private userId?: string;\n private propertyId?: string;\n private abAssignments: Record<string, string>;\n private pollIntervalMs: number;\n private contextProvider: () => PrefetchBundleContext;\n\n private currentETag: string | null = null;\n private currentBundle: PrefetchBundle | null = null;\n private pollTimer: ReturnType<typeof setInterval> | null = null;\n private listeners: PrefetchBundleListener[] = [];\n private inflightRefetch: Promise<PrefetchBundle | null> | null = null;\n\n constructor(options: PrefetchBundleClientOptions) {\n this.apiHost = options.apiHost;\n this.writeKey = options.writeKey;\n this.organizationId = options.organizationId;\n this.contactId = options.contactId;\n this.userId = options.userId;\n this.propertyId = options.propertyId;\n this.abAssignments = options.abAssignments ?? {};\n this.pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_MS;\n this.contextProvider = options.contextProvider ?? (() => ({}));\n }\n\n /**\n * Initial fetch + start the background ETag poll. Resolves to the bundle\n * (or `null` if the first fetch failed — callers should fall back to an\n * empty campaign list, not abort SDK init).\n */\n async start(): Promise<PrefetchBundle | null> {\n const bundle = await this.fetch();\n this.pollTimer = setInterval(() => {\n this.fetch().catch((err) => logger.warn('prefetch-bundle poll failed:', err));\n }, this.pollIntervalMs);\n return bundle;\n }\n\n stop(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n }\n\n getBundle(): PrefetchBundle | null {\n return this.currentBundle;\n }\n\n getCampaigns(): PrefetchBundleCampaign[] {\n return this.currentBundle?.campaigns ?? [];\n }\n\n getInbox(): PrefetchBundleInbox {\n return this.currentBundle?.inbox ?? { unread_count: 0, page: [], cursor: null };\n }\n\n /** Force a refresh (dedupes concurrent calls). Exposed so inbox mutations\n * and campaign-activation SSE messages can trigger a refetch on demand. */\n async refresh(): Promise<PrefetchBundle | null> {\n if (this.inflightRefetch) return this.inflightRefetch;\n this.inflightRefetch = this.fetch();\n try {\n return await this.inflightRefetch;\n } finally {\n this.inflightRefetch = null;\n }\n }\n\n /** Subscribe to bundle changes (emits on first fetch + on any content\n * change — ETag 304 does NOT fire the listener). Returns an unsubscribe. */\n onChange(listener: PrefetchBundleListener): () => void {\n this.listeners.push(listener);\n return () => {\n const idx = this.listeners.indexOf(listener);\n if (idx >= 0) this.listeners.splice(idx, 1);\n };\n }\n\n /**\n * Update the identity tuple — called by AegisInAppManager when the host\n * app resolves a contactId post-init (e.g., after login). Triggers an\n * immediate refresh since the eligible campaigns + inbox will differ.\n */\n updateIdentity(partial: {\n contactId?: string;\n userId?: string;\n organizationId?: string;\n propertyId?: string;\n }): void {\n let changed = false;\n if (partial.contactId !== undefined && partial.contactId !== this.contactId) {\n this.contactId = partial.contactId;\n changed = true;\n }\n if (partial.userId !== undefined && partial.userId !== this.userId) {\n this.userId = partial.userId;\n changed = true;\n }\n if (\n partial.organizationId !== undefined &&\n partial.organizationId !== this.organizationId\n ) {\n this.organizationId = partial.organizationId;\n changed = true;\n }\n if (partial.propertyId !== undefined && partial.propertyId !== this.propertyId) {\n this.propertyId = partial.propertyId;\n changed = true;\n }\n if (changed) {\n // Identity change invalidates ETag — drop the cached tag so the next\n // fetch gets a fresh payload instead of a 304 bound to the old identity.\n this.currentETag = null;\n this.refresh().catch((err) =>\n logger.warn('prefetch-bundle identity-refresh failed:', err),\n );\n }\n }\n\n /** Update cached AB assignments. Called by downstream renderers after\n * they display a variant. Persisted to localStorage by higher layers. */\n setAbAssignments(assignments: Record<string, string>): void {\n this.abAssignments = { ...assignments };\n }\n\n /**\n * Wire an already-open realtime subscriber (from `aegis.realtime.subscribe`\n * or a caller-provided EventSource) so the prefetch bundle refreshes\n * instantly when the cell-plane signals `bundle.invalidate` — covering\n * the window between an event (cart abandon, inbox write) and the\n * 5-min ETag poll.\n *\n * `subscriber.onMessage(handler)` must fire with parsed message bodies\n * from the contact's SSE stream. The handler filters for\n * `type === 'bundle.invalidate'` and calls `refresh()`. Returns an\n * unsubscribe function.\n *\n * Degrades gracefully: if the subscriber is missing or throws, the\n * 5-min poll still keeps state converging.\n */\n subscribeInvalidations(subscriber: {\n onMessage: (handler: (msg: { type?: string; [k: string]: unknown }) => void) => () => void;\n }): () => void {\n try {\n const unsub = subscriber.onMessage((msg) => {\n if (msg && msg.type === 'bundle.invalidate') {\n this.refresh().catch((err) =>\n logger.warn('prefetch-bundle invalidate-refresh failed:', err),\n );\n }\n });\n return unsub;\n } catch (err) {\n logger.warn('prefetch-bundle subscribeInvalidations failed — relying on poll:', err);\n return () => {};\n }\n }\n\n // ── internals ──────────────────────────────────────────────────────────\n\n private async fetch(): Promise<PrefetchBundle | null> {\n const ctx = this.contextProvider();\n const qs = new URLSearchParams();\n if (ctx.device_type) qs.set('device_type', ctx.device_type);\n if (ctx.page_url) qs.set('page_url', ctx.page_url);\n if (ctx.geo) qs.set('geo', ctx.geo);\n qs.set('is_new_user', ctx.is_new_user ? 'true' : 'false');\n\n const url = `${this.apiHost}/v1/sdk/prefetch-bundle?${qs.toString()}`;\n\n const headers: Record<string, string> = {\n 'X-Aegis-Write-Key': this.writeKey,\n Accept: 'application/json',\n };\n if (this.organizationId) headers['X-Organization-ID'] = this.organizationId;\n if (this.contactId) headers['X-Contact-ID'] = this.contactId;\n if (this.userId) headers['X-User-ID'] = this.userId;\n if (this.propertyId) headers['X-Property-Id'] = this.propertyId;\n if (this.currentETag) headers['If-None-Match'] = this.currentETag;\n if (Object.keys(this.abAssignments).length > 0) {\n try {\n headers['X-AB-Assignments'] = btoa(JSON.stringify(this.abAssignments));\n } catch {\n // base64 on non-ASCII campaign IDs — skip rather than 400 the request\n }\n }\n\n let response: Response;\n try {\n response = await fetch(url, { method: 'GET', headers });\n } catch (err) {\n logger.warn('prefetch-bundle fetch network error:', err);\n return this.currentBundle;\n }\n\n // 304 — same bundle; listeners are intentionally NOT fired.\n if (response.status === 304) {\n return this.currentBundle;\n }\n\n if (!response.ok) {\n logger.warn(`prefetch-bundle fetch failed: HTTP ${response.status}`);\n return this.currentBundle;\n }\n\n const etag = response.headers.get('ETag');\n let bundle: PrefetchBundle;\n try {\n bundle = (await response.json()) as PrefetchBundle;\n } catch (err) {\n logger.warn('prefetch-bundle invalid JSON:', err);\n return this.currentBundle;\n }\n\n if (etag) this.currentETag = etag;\n this.currentBundle = bundle;\n\n for (const l of this.listeners) {\n try {\n l(bundle);\n } catch (err) {\n logger.warn('prefetch-bundle listener threw:', err);\n }\n }\n\n return bundle;\n }\n}\n","/**\n * AegisInbox — client-side App Inbox (Message Center).\n *\n * Backs the notification drawer on actii.me WebView and every tenant\n * storefront that embeds the Web SDK. Operates against cell-plane's\n * /v1/in-app/inbox family of endpoints (list, unread-count, read,\n * dismiss, read-all).\n *\n * Design choices:\n * • Hydrate from the prefetch bundle at init — no extra HTTP on first\n * paint. PrefetchBundleClient seeds us; we then own the live copy.\n * • Mutations are optimistic + beacon-backed. Read / dismiss writes to\n * local state immediately, then POSTs with `keepalive: true` so an\n * in-flight dismiss survives page unload.\n * • Badge polling uses the tiny `/unread-count` endpoint on a 60-second\n * cadence — matches the `inbox_poll_interval_ms` from sdk_config's\n * TransportConfig.hybrid mode.\n * • No external dependencies; IndexedDB is optional (we gracefully fall\n * back to in-memory when unavailable, e.g., in private browsing).\n */\n\nimport type { PrefetchBundleClient } from '../core/prefetch-bundle-client';\nimport { logger } from '../utils/logger';\n\nexport interface AegisInboxEntry {\n id: string;\n source: string;\n campaign_id: string | null;\n title: string;\n body: string;\n media_url: string | null;\n cta_url: string | null;\n metadata: Record<string, unknown> | null;\n read: boolean;\n read_at: string | null;\n dismissed_at?: string | null;\n created_at: string | null;\n expires_at: string | null;\n}\n\nexport interface AegisInboxConfig {\n apiHost: string;\n writeKey: string;\n organizationId?: string;\n contactId?: string;\n propertyId?: string;\n bundleClient?: PrefetchBundleClient;\n unreadPollIntervalMs?: number;\n}\n\nexport type InboxListener = (state: { entries: AegisInboxEntry[]; unreadCount: number }) => void;\n\nconst DEFAULT_UNREAD_POLL = 60_000;\n\n/** IndexedDB schema version + constants. Offline cache is a nice-to-have,\n * so we never break the app if IDB operations fail. */\nconst IDB_NAME = 'aegis-inbox';\nconst IDB_STORE = 'messages';\nconst IDB_VERSION = 1;\n\nexport class AegisInbox {\n private apiHost: string;\n private writeKey: string;\n private organizationId?: string;\n private contactId?: string;\n private propertyId?: string;\n private bundleClient?: PrefetchBundleClient;\n private unreadPollIntervalMs: number;\n\n private entries: AegisInboxEntry[] = [];\n private unreadCount = 0;\n private cursor: string | null = null;\n private listeners: InboxListener[] = [];\n private pollTimer: ReturnType<typeof setInterval> | null = null;\n private bundleUnsub: (() => void) | null = null;\n\n constructor(config: AegisInboxConfig) {\n this.apiHost = config.apiHost;\n this.writeKey = config.writeKey;\n this.organizationId = config.organizationId;\n this.contactId = config.contactId;\n this.propertyId = config.propertyId;\n this.bundleClient = config.bundleClient;\n this.unreadPollIntervalMs = config.unreadPollIntervalMs ?? DEFAULT_UNREAD_POLL;\n }\n\n /** Hydrate from bundle (if available), restore the IDB cache (if any),\n * then start the background unread-count poll. */\n async initialize(): Promise<void> {\n // Inbox is contact-scoped — if the host app hasn't resolved a contact\n // yet, stay dormant. The host will call setIdentity() later.\n if (!this.contactId || !this.propertyId) {\n logger.warn('AegisInbox: no contact/property yet — staying dormant');\n return;\n }\n\n // Try IDB cache for instant paint on cold start.\n const cached = await this.readCache();\n if (cached.length > 0) {\n this.entries = cached;\n this.recomputeUnread();\n this.emit();\n }\n\n // Hydrate from prefetch bundle if we have one — this is the preload\n // path, no additional network round-trip.\n if (this.bundleClient) {\n const inbox = this.bundleClient.getInbox();\n this.seedFromBundle(inbox.page, inbox.unread_count);\n // Keep following bundle changes — when the bundle-poller refreshes,\n // the inbox slice refreshes too.\n this.bundleUnsub = this.bundleClient.onChange((bundle) => {\n this.seedFromBundle(bundle.inbox.page, bundle.inbox.unread_count);\n });\n } else {\n // No bundle client — do one list call to prime.\n await this.refreshList();\n }\n\n this.pollTimer = setInterval(() => {\n this.refreshUnreadCount().catch((err) =>\n logger.warn('inbox unread-count poll failed:', err),\n );\n }, this.unreadPollIntervalMs);\n }\n\n stop(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n if (this.bundleUnsub) {\n this.bundleUnsub();\n this.bundleUnsub = null;\n }\n }\n\n /** Update identity after login / property switch. Clears the local\n * inbox since it's intrinsically contact+property scoped. */\n setIdentity(partial: { contactId?: string; propertyId?: string; organizationId?: string }): void {\n let changed = false;\n if (partial.contactId !== undefined && partial.contactId !== this.contactId) {\n this.contactId = partial.contactId;\n changed = true;\n }\n if (partial.propertyId !== undefined && partial.propertyId !== this.propertyId) {\n this.propertyId = partial.propertyId;\n changed = true;\n }\n if (partial.organizationId !== undefined && partial.organizationId !== this.organizationId) {\n this.organizationId = partial.organizationId;\n changed = true;\n }\n if (changed) {\n this.entries = [];\n this.unreadCount = 0;\n this.cursor = null;\n this.emit();\n void this.clearCache();\n void this.refreshList();\n }\n }\n\n // ── Read-side API ────────────────────────────────────────────────────\n\n getEntries(): AegisInboxEntry[] {\n return this.entries;\n }\n\n getUnreadCount(): number {\n return this.unreadCount;\n }\n\n /** Pagination cursor (ISO-8601 timestamp of the oldest entry currently\n * held). Pass it back via `loadMore()` to fetch older history. */\n getCursor(): string | null {\n return this.cursor;\n }\n\n /** Append one more page of older entries using the current cursor. */\n async loadMore(): Promise<void> {\n if (!this.contactId || !this.propertyId || !this.cursor) return;\n try {\n const url = `${this.apiHost}/v1/in-app/inbox?limit=20&cursor=${encodeURIComponent(this.cursor)}`;\n const resp = await fetch(url, { headers: this.headers() });\n if (!resp.ok) return;\n const body = (await resp.json()) as {\n entries: AegisInboxEntry[];\n unread_count: number;\n cursor: string | null;\n };\n const byId = new Set(this.entries.map((e) => e.id));\n for (const e of body.entries) {\n if (!byId.has(e.id)) this.entries.push(e);\n }\n this.cursor = body.cursor;\n void this.writeCache();\n this.emit();\n } catch (err) {\n logger.warn('inbox loadMore failed:', err);\n }\n }\n\n onChange(l: InboxListener): () => void {\n this.listeners.push(l);\n return () => {\n const i = this.listeners.indexOf(l);\n if (i >= 0) this.listeners.splice(i, 1);\n };\n }\n\n async refreshList(): Promise<void> {\n if (!this.contactId || !this.propertyId) return;\n try {\n const resp = await fetch(\n `${this.apiHost}/v1/in-app/inbox?limit=20`,\n { headers: this.headers() },\n );\n if (!resp.ok) {\n logger.warn(`inbox list fetch failed: HTTP ${resp.status}`);\n return;\n }\n const body = (await resp.json()) as {\n entries: AegisInboxEntry[];\n unread_count: number;\n cursor: string | null;\n };\n this.entries = body.entries;\n this.unreadCount = body.unread_count;\n this.cursor = body.cursor;\n void this.writeCache();\n this.emit();\n } catch (err) {\n logger.warn('inbox list fetch error:', err);\n }\n }\n\n async refreshUnreadCount(): Promise<void> {\n if (!this.contactId || !this.propertyId) return;\n try {\n const resp = await fetch(\n `${this.apiHost}/v1/in-app/inbox/unread-count`,\n { headers: this.headers() },\n );\n if (!resp.ok) return;\n const body = (await resp.json()) as { unread_count: number };\n if (body.unread_count !== this.unreadCount) {\n this.unreadCount = body.unread_count;\n this.emit();\n // New messages detected — do a list refresh to get them.\n if (this.unreadCount > 0) {\n void this.refreshList();\n }\n }\n } catch {\n /* swallow — transient network */\n }\n }\n\n // ── Mutations (optimistic + beacon) ──────────────────────────────────\n\n async markRead(messageId: string): Promise<void> {\n const entry = this.entries.find((e) => e.id === messageId);\n if (!entry || entry.read) return;\n entry.read = true;\n entry.read_at = new Date().toISOString();\n this.recomputeUnread();\n void this.writeCache();\n this.emit();\n await this.postBeacon(`/v1/in-app/inbox/${messageId}/read`);\n }\n\n async dismiss(messageId: string): Promise<void> {\n const idx = this.entries.findIndex((e) => e.id === messageId);\n if (idx < 0) return;\n const [entry] = this.entries.splice(idx, 1);\n if (entry && !entry.read) {\n this.recomputeUnread();\n }\n void this.writeCache();\n this.emit();\n await this.postBeacon(`/v1/in-app/inbox/${messageId}/dismiss`);\n }\n\n async markAllRead(): Promise<void> {\n const now = new Date().toISOString();\n for (const e of this.entries) {\n if (!e.read) {\n e.read = true;\n e.read_at = now;\n }\n }\n this.unreadCount = 0;\n void this.writeCache();\n this.emit();\n await this.postBeacon('/v1/in-app/inbox/read-all');\n }\n\n // ── Internals ────────────────────────────────────────────────────────\n\n private seedFromBundle(page: AegisInboxEntry[], unreadCount: number): void {\n // Merge rather than overwrite — an entry we already marked read\n // locally should stay read even if the bundle is slightly stale.\n const byId = new Map(this.entries.map((e) => [e.id, e] as const));\n const merged = page.map((incoming) => {\n const existing = byId.get(incoming.id);\n if (existing && existing.read && !incoming.read) {\n return { ...incoming, read: true, read_at: existing.read_at };\n }\n return incoming;\n });\n // Preserve any locally-cached entries that aren't in this bundle page\n // (e.g., older history not included in the first slice).\n for (const [id, e] of byId) {\n if (!merged.find((m) => m.id === id)) merged.push(e);\n }\n merged.sort((a, b) => (b.created_at || '').localeCompare(a.created_at || ''));\n this.entries = merged;\n this.unreadCount = unreadCount;\n void this.writeCache();\n this.emit();\n }\n\n private recomputeUnread(): void {\n this.unreadCount = this.entries.filter((e) => !e.read).length;\n }\n\n private emit(): void {\n const snapshot = { entries: [...this.entries], unreadCount: this.unreadCount };\n for (const l of this.listeners) {\n try {\n l(snapshot);\n } catch (err) {\n logger.warn('inbox listener threw:', err);\n }\n }\n }\n\n private headers(): Record<string, string> {\n const h: Record<string, string> = {\n 'X-Aegis-Write-Key': this.writeKey,\n Accept: 'application/json',\n };\n if (this.organizationId) h['X-Organization-ID'] = this.organizationId;\n if (this.contactId) h['X-Contact-ID'] = this.contactId;\n if (this.propertyId) h['X-Property-Id'] = this.propertyId;\n return h;\n }\n\n /** Best-effort beacon-style POST. Uses `keepalive: true` so it survives\n * a navigation away from the current page (e.g., user taps the CTA\n * which takes them to another URL right after dismiss). */\n private async postBeacon(path: string): Promise<void> {\n if (!this.contactId || !this.propertyId) return;\n try {\n await fetch(`${this.apiHost}${path}`, {\n method: 'POST',\n headers: this.headers(),\n keepalive: true,\n });\n } catch (err) {\n // The mutation is already applied locally; failed delivery will be\n // reconciled on the next refreshList().\n logger.warn(`inbox mutation POST ${path} failed:`, err);\n }\n }\n\n // ── IndexedDB cache (non-critical) ───────────────────────────────────\n\n private async openDb(): Promise<IDBDatabase | null> {\n if (typeof indexedDB === 'undefined') return null;\n return new Promise((resolve) => {\n try {\n const req = indexedDB.open(IDB_NAME, IDB_VERSION);\n req.onerror = () => resolve(null);\n req.onupgradeneeded = () => {\n const db = req.result;\n if (!db.objectStoreNames.contains(IDB_STORE)) {\n db.createObjectStore(IDB_STORE);\n }\n };\n req.onsuccess = () => resolve(req.result);\n } catch {\n resolve(null);\n }\n });\n }\n\n private cacheKey(): string | null {\n if (!this.contactId || !this.propertyId) return null;\n return `${this.organizationId || 'default'}:${this.propertyId}:${this.contactId}`;\n }\n\n private async writeCache(): Promise<void> {\n const key = this.cacheKey();\n if (!key) return;\n const db = await this.openDb();\n if (!db) return;\n try {\n const tx = db.transaction(IDB_STORE, 'readwrite');\n tx.objectStore(IDB_STORE).put(this.entries, key);\n await new Promise<void>((res, rej) => {\n tx.oncomplete = () => res();\n tx.onerror = () => rej(tx.error);\n });\n } catch {\n /* noop */\n } finally {\n db.close();\n }\n }\n\n private async readCache(): Promise<AegisInboxEntry[]> {\n const key = this.cacheKey();\n if (!key) return [];\n const db = await this.openDb();\n if (!db) return [];\n try {\n const tx = db.transaction(IDB_STORE, 'readonly');\n const req = tx.objectStore(IDB_STORE).get(key);\n return await new Promise<AegisInboxEntry[]>((res) => {\n req.onsuccess = () => res((req.result as AegisInboxEntry[]) || []);\n req.onerror = () => res([]);\n });\n } catch {\n return [];\n } finally {\n db.close();\n }\n }\n\n private async clearCache(): Promise<void> {\n const key = this.cacheKey();\n if (!key) return;\n const db = await this.openDb();\n if (!db) return;\n try {\n const tx = db.transaction(IDB_STORE, 'readwrite');\n tx.objectStore(IDB_STORE).delete(key);\n await new Promise<void>((res) => {\n tx.oncomplete = () => res();\n tx.onerror = () => res();\n });\n } catch {\n /* noop */\n } finally {\n db.close();\n }\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';\nimport { Storage } from '../utils/storage';\n\n// Read the SDK's persisted anonymous_id from localStorage/cookie if available.\n// Returns undefined when called server-side or when no id has been minted yet.\n// See AegisInAppManager for the same pattern + canonical contract in\n// docs/architecture/API_ROUTING.md §3.\nfunction readAnonIdFromStorage(): string | undefined {\n if (typeof document === 'undefined') return undefined;\n try {\n const storage = new Storage();\n return storage.get('anon_id') ?? undefined;\n } catch {\n return undefined;\n }\n}\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 /** If true, WidgetManager takes ownership of the TriggerEngine and\n * will call `triggerEngine.stop()` on destroy(). Leave false when\n * the caller shares the engine across managers (e.g. the facade). */\n ownsTriggerEngine?: boolean;\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 private isDestroyed = false;\n private ownsTriggerEngine: boolean;\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 // Fall back to the SDK's persisted anonymous_id when callers don't pass\n // userId explicitly. Without this, /v1/widgets/config requests omit\n // X-User-ID and the cell-plane buckets the call into \"anonymous\", which\n // misses any user-targeted widget configs. Mirror in AegisInAppManager.\n this.userId = config.userId ?? readAnonIdFromStorage();\n this.contactId = config.contactId;\n this.organizationId = config.organizationId;\n this.debugMode = config.debugMode || false;\n this.triggerEngine = config.triggerEngine;\n this.ownsTriggerEngine = config.ownsTriggerEngine === true;\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 /**\n * Swap the identity that outgoing widget requests are attributed to.\n * Safe to call at any time; if prefetch is enabled and the manager\n * has already initialised, this will re-fetch the per-contact widget\n * configs so subsequent renders target the new identity. Does NOT\n * re-render already-visible widgets — a full teardown requires destroy().\n */\n async updateContactId(contactId: string | undefined): Promise<void> {\n if (this.contactId === contactId) return;\n this.contactId = contactId;\n this.log(`Contact ID updated → ${contactId ?? '(cleared)'}`);\n if (this.isInitialized && !this.isDestroyed && this.enablePrefetch && contactId) {\n await this.fetchPrefetchConfigs();\n this.preloadWidgetAssets();\n }\n }\n\n /**\n * Render an in-app campaign whose sub_type routes it to the\n * gamification-widget code path (spin_wheel / scratch_card).\n * InAppCampaign is adapted to the minimal WidgetConfig shape that\n * the internal renderers already understand — no rewrite needed.\n *\n * AegisMessageRuntime wires this method as AegisInAppManager's\n * `onInteractiveCampaign` callback so impressions from the inbox\n * prefetch bundle actually land on screen.\n */\n renderInteractiveCampaign(campaign: {\n id: string;\n title: string;\n sub_type?: string;\n priority?: number;\n interactive_config?: Record<string, unknown>;\n }): void {\n if (this.isDestroyed) return;\n if (typeof document === 'undefined') return;\n const subType = campaign.sub_type;\n if (subType !== 'spin_wheel' && subType !== 'scratch_card') {\n this.log(`renderInteractiveCampaign: unsupported sub_type \"${subType}\"`, true);\n return;\n }\n const widget: WidgetConfig = {\n widget_id: campaign.id,\n widget_type: subType,\n name: campaign.title,\n config: (campaign.interactive_config ?? {}) as Record<string, any>,\n priority: campaign.priority ?? 0,\n };\n if (this.renderedWidgets.has(widget.widget_id)) return;\n this.renderedWidgets.add(widget.widget_id);\n if (subType === 'spin_wheel') {\n this.renderSpinWheel(widget);\n } else {\n this.renderScratchCard(widget);\n }\n }\n\n /**\n * Tear down everything the manager installed: trigger listeners (if\n * we own the TriggerEngine), injected style sheets, and any rendered\n * widget roots. Further render attempts from in-flight triggers are\n * short-circuited by the `isDestroyed` flag.\n */\n destroy(): void {\n if (this.isDestroyed) return;\n this.isDestroyed = true;\n\n if (this.triggerEngine && this.ownsTriggerEngine) {\n this.triggerEngine.stop();\n }\n\n if (typeof document !== 'undefined') {\n const animationStyle = document.getElementById('aegis-widget-animations');\n animationStyle?.remove();\n document.querySelectorAll('[data-aegis-widget-root]').forEach((node) => {\n node.remove();\n });\n }\n\n this.renderedWidgets.clear();\n this.widgets = [];\n this.isInitialized = false;\n this.log('AegisWidgets destroyed');\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, credentials: 'include' });\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, credentials: 'include' });\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 credentials: 'include',\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.isDestroyed) return;\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 bubble.setAttribute('data-aegis-widget-root', '');\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 // Draw an SVG wheel that honours the tenant's configured segments.\n // Each segment's `color` + `label` is painted as a pie slice; falls\n // back to a 4-color placeholder if no segments are provided.\n const segments: Array<{ label: string; color?: string }> = Array.isArray(\n (widget.config as any).segments,\n )\n ? (widget.config as any).segments\n : [\n { label: 'Prize 1', color: '#ff6b6b' },\n { label: 'Prize 2', color: '#feca57' },\n { label: 'Prize 3', color: '#48dbfb' },\n { label: 'Prize 4', color: '#ff6348' },\n ];\n\n const SVG_NS = 'http://www.w3.org/2000/svg';\n const wheel = document.createElementNS(SVG_NS, 'svg');\n wheel.setAttribute('viewBox', '-160 -160 320 320');\n wheel.setAttribute('width', '300');\n wheel.setAttribute('height', '300');\n wheel.style.cssText = 'margin: 0 auto 24px; display: block;';\n\n const n = segments.length;\n const anglePer = (2 * Math.PI) / n;\n const radius = 140;\n for (let i = 0; i < n; i++) {\n const start = i * anglePer - Math.PI / 2;\n const end = start + anglePer;\n const x1 = Math.cos(start) * radius;\n const y1 = Math.sin(start) * radius;\n const x2 = Math.cos(end) * radius;\n const y2 = Math.sin(end) * radius;\n const largeArc = anglePer > Math.PI ? 1 : 0;\n const path = document.createElementNS(SVG_NS, 'path');\n path.setAttribute(\n 'd',\n `M 0 0 L ${x1.toFixed(2)} ${y1.toFixed(2)} A ${radius} ${radius} 0 ${largeArc} 1 ${x2.toFixed(2)} ${y2.toFixed(2)} Z`,\n );\n path.setAttribute('fill', this.sanitizeColor(segments[i].color || '#cccccc'));\n path.setAttribute('stroke', '#ffffff');\n path.setAttribute('stroke-width', '2');\n wheel.appendChild(path);\n\n const labelAngle = start + anglePer / 2;\n const lx = Math.cos(labelAngle) * radius * 0.65;\n const ly = Math.sin(labelAngle) * radius * 0.65;\n const text = document.createElementNS(SVG_NS, 'text');\n text.setAttribute('x', lx.toFixed(2));\n text.setAttribute('y', ly.toFixed(2));\n text.setAttribute('fill', '#ffffff');\n text.setAttribute('font-size', '13');\n text.setAttribute('font-weight', '600');\n text.setAttribute('text-anchor', 'middle');\n text.setAttribute('dominant-baseline', 'middle');\n text.textContent = segments[i].label || `#${i + 1}`;\n wheel.appendChild(text);\n }\n modal.appendChild(wheel);\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 wheel.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 overlay.setAttribute('data-aegis-widget-root', '');\n document.body.appendChild(overlay);\n }\n \n private renderSpinWheelWidget(widgetId: string, config: NonNullable<PrefetchWidgetConfig['spin_wheel']>): void {\n if (this.isDestroyed) return;\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 overlay.setAttribute('data-aegis-widget-root', '');\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 credentials: 'include',\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 overlay.setAttribute('data-aegis-widget-root', '');\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 toast.setAttribute('data-aegis-widget-root', '');\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 overlay.setAttribute('data-aegis-widget-root', '');\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 overlay.setAttribute('data-aegis-widget-root', '');\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 credentials: 'include',\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 credentials: 'include',\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 credentials: 'include',\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 if (this.isDestroyed) return;\n const overlay = document.createElement('div');\n overlay.className = 'aegis-exit-popup-overlay';\n overlay.setAttribute('data-widget-id', widgetId);\n overlay.setAttribute('data-aegis-widget-root', '');\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 overlay.setAttribute('data-aegis-widget-root', '');\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 if (this.isDestroyed) return;\n const overlay = document.createElement('div');\n overlay.className = 'aegis-exit-popup-overlay';\n overlay.setAttribute('data-widget-id', widgetId);\n overlay.setAttribute('data-aegis-widget-root', '');\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 overlay.setAttribute('data-aegis-widget-root', '');\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 * AegisMessageRuntime — unified facade for in-app messaging.\n *\n * The sole public entry point for all 20 in-app types (announce +\n * collect + assist buckets) plus the legacy gamification surface\n * (chat_bubble / toast / exit_intent_popup configured via\n * /v1/widgets/config). Under the hood it composes an\n * `AegisInAppManager` + `AegisWidgetManager`; callers never touch them\n * directly.\n *\n * Public API:\n * new AegisMessageRuntime({ writeKey, apiHost, ... })\n * await runtime.initialize()\n * await runtime.updateContactId(id)\n * runtime.onClientEvent(eventName, data)\n * runtime.destroy()\n *\n * Internal wiring: spin_wheel + scratch_card campaigns land in the\n * inbox prefetch bundle but need DOM renderers that live in\n * WidgetManager. The facade passes an `onInteractiveCampaign` callback\n * into the InAppManager constructor; the callback forwards to\n * `widgets.renderInteractiveCampaign(campaign)` — no CustomEvent bus,\n * no listeners, no registration-order bugs.\n */\n\nimport { AegisInAppManager, type AegisInAppConfig, type InAppCampaign } from '../inapp';\nimport { AegisWidgetManager, type AegisWidgetConfig } from '../widgets';\nimport { TriggerEngine } from '../triggers/TriggerEngine';\n\nexport interface AegisMessageRuntimeConfig extends AegisInAppConfig {\n /** If set, a `TriggerEngine` from the SDK is wired to the WidgetManager\n * for its exit-intent / scroll-velocity / inactivity handlers. Leave\n * undefined to have the runtime construct one internally. */\n triggerEngine?: AegisWidgetConfig['triggerEngine'];\n /** WidgetManager prefetch toggle. Defaults to true — matches the\n * existing behaviour where spin_wheel / scratch_card prefetch their\n * configs from `/v1/widgets/config/prefetch`. */\n enableWidgetPrefetch?: boolean;\n /** Source platform for gamification attribution (shopify / woocommerce\n * / magento / mobile_sdk / web). Passed through to WidgetManager. */\n sourcePlatform?: AegisWidgetConfig['sourcePlatform'];\n}\n\n/**\n * One runtime, all in-app types. Consumers should prefer this over\n * importing AegisInAppManager / AegisWidgetManager directly. Those two\n * classes remain exported for a deprecation window — see `./deprecated.ts`.\n */\nexport class AegisMessageRuntime {\n readonly inApp: AegisInAppManager;\n readonly widgets: AegisWidgetManager;\n private initialized = false;\n private ownedTriggerEngine: TriggerEngine | null = null;\n\n constructor(config: AegisMessageRuntimeConfig) {\n const triggerEngine = config.triggerEngine ?? new TriggerEngine();\n const ownsTriggerEngine = !config.triggerEngine;\n if (ownsTriggerEngine) this.ownedTriggerEngine = triggerEngine;\n\n this.widgets = new AegisWidgetManager({\n writeKey: config.writeKey,\n apiHost: config.apiHost,\n userId: config.userId,\n contactId: config.contactId,\n organizationId: config.organizationId,\n debugMode: config.debugMode,\n triggerEngine,\n ownsTriggerEngine,\n enablePrefetch: config.enableWidgetPrefetch !== false,\n sourcePlatform: config.sourcePlatform,\n });\n\n this.inApp = new AegisInAppManager({\n writeKey: config.writeKey,\n apiHost: config.apiHost,\n userId: config.userId,\n contactId: config.contactId,\n organizationId: config.organizationId,\n propertyId: config.propertyId,\n debugMode: config.debugMode,\n enableSSE: config.enableSSE,\n // Route gamification sub_types straight to the widget renderer —\n // replaces the old CustomEvent('aegis:render-widget') bridge which\n // had no listener and silently dropped impressions.\n onInteractiveCampaign: (campaign) => {\n this.widgets.renderInteractiveCampaign(campaign);\n },\n });\n }\n\n /**\n * Boots both managers in parallel. Safe to call multiple times — the\n * second + subsequent calls are no-ops.\n */\n async initialize(): Promise<void> {\n if (this.initialized) return;\n this.initialized = true;\n await Promise.all([\n this.inApp.initialize(),\n this.widgets.initialize(),\n ]);\n }\n\n /**\n * Both managers carry contactId. Updates both so the server-side\n * targeting pipeline sees the identity for campaign eligibility AND\n * the widget prefetch includes per-contact segment configs. The\n * widgets call is async (may re-fetch prefetch configs) but we don't\n * wait — callers that care about the fetched state await on the\n * returned promise.\n */\n async updateContactId(contactId: string): Promise<void> {\n this.inApp.updateContactId?.(contactId);\n await this.widgets.updateContactId(contactId);\n }\n\n /**\n * Forward a client-side event (product_viewed, cart_idle_90s, etc.)\n * to the in-app manager's client-trigger evaluator. The WidgetManager\n * has its own TriggerEngine wiring (exit-intent, scroll-velocity) so\n * we don't forward there — events it cares about arrive through that\n * channel already.\n */\n onClientEvent(eventName: string, eventData: Record<string, unknown> = {}): void {\n this.inApp.onClientEvent?.(eventName, eventData);\n }\n\n /**\n * Conversion-aware suppression — call when the host app observes a\n * goal event (purchase / order_completed / checkout_completed / custom).\n *\n * Forwards to AegisInAppManager.notifyConversion() which:\n * - Persists the conversion in sessionStorage so subsequent page loads\n * in the same tab keep armed campaigns silenced.\n * - For every armed campaign whose\n * `frequency.suppress_after_conversion_seconds` is set, computes an\n * expiry epoch_ms and silences it until then.\n *\n * Storefronts integrate via the React provider's useCommerceEvents\n * helper which calls this after `ecom.orderCompleted(...)`. Direct SDK\n * users call it themselves.\n *\n * Added by Micro-Intent Engine P0a Task 6 (2026-04-30).\n */\n notifyConversion(goalName: string): void {\n this.inApp.notifyConversion?.(goalName);\n }\n\n /**\n * Tear down both managers. Used by React component unmounts + during\n * identity switches where we want a full reset. If the facade created\n * its own TriggerEngine, WidgetManager.destroy() will stop it;\n * caller-supplied engines are left alone.\n */\n destroy(): void {\n this.inApp.destroy?.();\n this.widgets.destroy();\n this.ownedTriggerEngine = null;\n this.initialized = false;\n }\n\n /**\n * Current armed campaigns visible to the InAppManager. Accessible for\n * the Prefetch Inspector and for debugging. WidgetManager's prefetched\n * spin_wheel / scratch_card configs are NOT in this list — they live\n * in `this.widgets` and have their own lifecycle.\n */\n getCampaigns(): InAppCampaign[] {\n // AegisInAppManager keeps `campaigns` as a private field. Expose it\n // via bracket access; the field is stable as of SDK 1.5.0. Once\n // Phase 7c unifies render paths this becomes a first-class getter.\n return ((this.inApp as unknown as { campaigns?: InAppCampaign[] }).campaigns) ?? [];\n }\n}\n","/**\n * SDK Bootstrap\n *\n * Strict origin-assertion handshake against the control-plane. Called once\n * at SDK init — resolves writeKey → propertyId, asserts origin, and returns\n * the VAPID public key + first-party cookie id the SDK needs for the rest\n * of the session.\n *\n * A failed bootstrap (401/403) aborts SDK init — the SDK refuses to emit\n * events or request push permission against an origin it cannot prove it\n * owns.\n *\n * See docs/architecture/SUBSCRIPTION_PROPERTY_ARCHITECTURE.md §5.\n */\n\nconst COOKIE_NAME = 'aegis_fpc';\nconst COOKIE_MAX_AGE_DAYS = 365 * 2;\n\nexport interface BootstrapRequest {\n writeKey: string;\n currentOrigin?: string;\n firstPartyCookieId?: string;\n attestationToken?: string;\n userAgent?: string;\n}\n\nimport type { EventGovernanceHint } from '../governance';\n\nexport interface BootstrapResult {\n propertyId: string;\n organizationId: string;\n workspaceId: string;\n propertyType: 'shopify_store' | 'hosted_commerce' | 'custom_website' | 'mobile_app';\n vapidPublicKey: string | null;\n allowedOrigins: string[];\n pushEnabled: boolean;\n inAppEnabled: boolean;\n transportMode: string;\n firstPartyCookieId: string;\n /**\n * Event-governance hint for SDK-side unique-event-name cap enforcement.\n * Null = Enterprise plan / CP outage / org has no cap. Safe to pass\n * directly to `aegis.ingestGovernanceHint()`.\n */\n eventGovernance: EventGovernanceHint | null;\n}\n\nexport class BootstrapError extends Error {\n constructor(public readonly status: number, message: string) {\n super(message);\n this.name = 'BootstrapError';\n }\n}\n\n/**\n * Read the first-party cookie id from document.cookie. Returns null if\n * unset — caller should pass undefined so the server issues a fresh one.\n */\nexport function readFirstPartyCookie(): string | null {\n if (typeof document === 'undefined') return null;\n const match = document.cookie.match(new RegExp(`(?:^|;\\\\s*)${COOKIE_NAME}=([^;]+)`));\n return match ? decodeURIComponent(match[1]) : null;\n}\n\n/**\n * Persist the first-party cookie id returned by the server. Stored as a\n * first-party cookie (readable by JS — it's not a secret, it's a device\n * id) so that the same browser hitting a second origin on the same\n * registrable domain gets the same cookie back.\n */\nexport function writeFirstPartyCookie(cookieId: string): void {\n if (typeof document === 'undefined') return;\n const expires = new Date();\n expires.setDate(expires.getDate() + COOKIE_MAX_AGE_DAYS);\n // Derive the registrable-domain boundary where possible so the cookie is\n // shared across subdomains (e.g., shop.sweettruths.com + www.sweettruths.com).\n // We conservatively use the current host without a leading dot —\n // browsers scope the cookie to that host. For cross-registrable-domain\n // siblings (Shopify myshopify.com + actii.me), each domain gets its own\n // cookie, which is the expected per-origin behavior.\n document.cookie =\n `${COOKIE_NAME}=${encodeURIComponent(cookieId)};` +\n `expires=${expires.toUTCString()};` +\n `path=/;SameSite=Lax`;\n // Also mirror into localStorage so the SDK can read it synchronously at\n // init time even in environments where document.cookie is delayed.\n try {\n window.localStorage.setItem(COOKIE_NAME, cookieId);\n } catch {\n // private mode / storage disabled — cookie alone is sufficient\n }\n}\n\n/**\n * Perform the bootstrap handshake.\n *\n * @throws BootstrapError on 4xx — the SDK should stop init and surface the\n * error to the console. 5xx are retried once.\n */\nexport async function bootstrap(\n apiHost: string,\n req: BootstrapRequest\n): Promise<BootstrapResult> {\n const body: Record<string, unknown> = { writeKey: req.writeKey };\n if (req.currentOrigin) body.currentOrigin = req.currentOrigin;\n if (req.firstPartyCookieId) body.firstPartyCookieId = req.firstPartyCookieId;\n if (req.attestationToken) body.attestationToken = req.attestationToken;\n if (req.userAgent) body.userAgent = req.userAgent;\n\n const url = `${apiHost.replace(/\\/$/, '')}/v1/sdk/bootstrap`;\n\n const doFetch = async (): Promise<Response> =>\n fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n credentials: 'omit',\n });\n\n let resp = await doFetch();\n if (resp.status >= 500) {\n await new Promise((r) => setTimeout(r, 750));\n resp = await doFetch();\n }\n\n if (resp.status === 401) {\n throw new BootstrapError(401, 'writeKey not recognized or revoked');\n }\n if (resp.status === 403) {\n throw new BootstrapError(403, 'Origin validation failed — this writeKey is bound to a different property');\n }\n if (!resp.ok) {\n throw new BootstrapError(resp.status, `Bootstrap failed: HTTP ${resp.status}`);\n }\n\n const json = (await resp.json()) as BootstrapResult;\n writeFirstPartyCookie(json.firstPartyCookieId);\n return json;\n}\n\n/**\n * Derive a deterministic device fingerprint from the first-party cookie id\n * and a few stable UA parts. This is the value sent on every push-subscribe\n * call — its stability lets the backend UPSERT on (property_id, fingerprint)\n * across re-subscribes and VAPID rotations.\n */\nexport async function deriveDeviceFingerprint(firstPartyCookieId: string): Promise<string> {\n const ua = typeof navigator !== 'undefined' ? navigator.userAgent : '';\n const platform = typeof navigator !== 'undefined' ? (navigator.platform || '') : '';\n const language = typeof navigator !== 'undefined' ? (navigator.language || '') : '';\n const input = `${firstPartyCookieId}|${ua}|${platform}|${language}`;\n\n // Prefer subtle.crypto — available in all push-capable browsers.\n if (typeof crypto !== 'undefined' && crypto.subtle) {\n const bytes = new TextEncoder().encode(input);\n const hash = await crypto.subtle.digest('SHA-256', bytes);\n const hex = Array.from(new Uint8Array(hash))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n return hex;\n }\n\n // Last-resort fallback — basic 32-bit FNV hash (non-cryptographic but\n // stable). Push-capable browsers always have subtle.crypto so this path\n // is practically unreachable; included only for completeness.\n let h = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i);\n h = (h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24))) >>> 0;\n }\n return `fnv-${h.toString(16)}`;\n}\n","import { Aegis } from './core/analytics';\n\nconst aegis = new Aegis();\n\nexport default aegis;\n\nexport { Aegis } from './core/analytics';\nexport type { AegisConfig, CellEndpoint, CellRegion } from './types/config';\nexport type {\n AegisEvent,\n TrackEvent,\n IdentifyEvent,\n PageEvent,\n GroupEvent,\n AliasEvent,\n EventContext,\n BatchPayload,\n BatchResponse,\n} from './types/events';\nexport type { Plugin, PluginRegistry } from './types/plugin';\nexport { debounce, throttle } from './utils/debounce';\nexport type {\n ConsentPreferences,\n ConsentCategory,\n ConsentStatus,\n} from './utils/consent';\n// In-app + widget types are re-exported for callers that configure\n// AegisMessageRuntime or read campaign objects. The underlying manager\n// classes are intentionally NOT exported — use AegisMessageRuntime.\nexport type { InAppCampaign, AegisInAppConfig } from './inapp';\nexport { renderPreview } from './inapp';\n\nexport { AegisPlacementManager } from './placements/AegisPlacementManager';\nexport type {\n PlacementContent,\n PlacementSlot,\n AegisPlacementConfig,\n} from './placements/AegisPlacementManager';\n\nexport type {\n WidgetConfig,\n GamificationPrize,\n AegisWidgetConfig,\n} from './widgets';\n\nexport { TriggerEngine } from './triggers';\nexport type {\n TriggerRule,\n ScrollDepthConfig,\n TimeOnPageConfig,\n ExitIntentConfig,\n InactivityConfig,\n TriggerEvent,\n} from './triggers';\n\nexport { SdkConfigPoller } from './core/sdk-config-poller';\nexport type { SdkConfig, SdkConfigPollerOptions, ConfigChangeCallback } from './core/sdk-config-poller';\n\n// Preload-first bundle (2026-04-22) — fetches armed campaigns + inbox\n// slice once at init; everything renders from memory on trigger.\nexport { PrefetchBundleClient } from './core/prefetch-bundle-client';\nexport type {\n PrefetchBundle,\n PrefetchBundleCampaign,\n PrefetchBundleInbox,\n PrefetchBundleInboxEntry,\n PrefetchBundleClientOptions,\n PrefetchBundleContext,\n PrefetchBundleListener,\n} from './core/prefetch-bundle-client';\n\n// App Inbox — persistent message-center client.\nexport { AegisInbox } from './inbox';\nexport type { AegisInboxConfig, AegisInboxEntry, InboxListener } from './inbox';\n\n// Unified message runtime — the single entry point for in-app + widgets.\n// All 20 in-app types (modal/banner/tooltip/full_screen/spin_wheel/\n// scratch_card/nps_survey/quiz/countdown_offer/star_rating/...) flow\n// through this one class. The underlying AegisInAppManager +\n// AegisWidgetManager implementations are internal to the package.\nexport { AegisMessageRuntime } from './runtime';\nexport type { AegisMessageRuntimeConfig } from './runtime';\n\nexport { AegisWebPush } from './push/AegisWebPush';\nexport type {\n AegisWebPushConfig,\n AegisAPIClient,\n ContactIdentity,\n PushEventTracker,\n} from './push/AegisWebPush';\n\nexport {\n bootstrap,\n readFirstPartyCookie,\n writeFirstPartyCookie,\n deriveDeviceFingerprint,\n BootstrapError,\n} from './core/bootstrap';\nexport type { BootstrapRequest, BootstrapResult } from './core/bootstrap';\n\nexport { RateLimiter } from './core/rate-limiter';\nexport type { RateLimiterOptions } from './core/rate-limiter';\n\n// Event-governance — SDK-side cap enforcement. The NameGovernor is wired\n// into `Aegis.captureEvent()` automatically; callers only interact with it\n// via `aegis.ingestGovernanceHint(bootstrapResult.eventGovernance)`.\nexport { NameGovernor, BloomFilter, murmurhash3_x86_32 } from './governance';\nexport type { EventGovernanceHint, DropReport, BloomFilterParams } from './governance';\n\n// NOTE: SSE-based realtime subscription is intentionally NOT exported from the\n// public SDK surface. The Aegis Web SDK uses HTTP batch uplink + HTTP polling\n// downstream (via AegisInAppManager) + Web Push (via AegisWebPush). Tenant\n// dashboards that need SSE open it directly via their own Next.js API routes,\n// not through this SDK. See RFC 2026-04-16 §A.\n\nexport { EcommerceTracker } from './ecommerce';\nexport type {\n EcommerceProduct,\n EcommerceCart,\n EcommerceCheckout,\n EcommerceOrder,\n EcommerceCoupon,\n EcommerceSearch,\n EcommerceProductList,\n EcommerceWishlist,\n EcommercePromotion,\n} from './ecommerce';\n"],"names":["goto","readAnonIdFromStorage","m","isMobile","mobileConfig"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/utils/debounce.ts","../src/inapp/renderers/carousel-cards.ts","../src/inapp/renderers/sticky-bar.ts","../src/inapp/renderers/progress-bar.ts","../src/inapp/renderers/coachmark-tour.ts","../src/inapp/renderers/product-recommendation.ts","../src/inapp/AegisInAppManager.ts","../src/inapp/renderPreview.ts","../src/placements/AegisPlacementManager.ts","../src/triggers/TriggerEngine.ts","../src/core/sdk-config-poller.ts","../src/core/prefetch-bundle-client.ts","../src/inbox/AegisInbox.ts","../src/widgets/AegisWidgetManager.ts","../src/runtime/AegisMessageRuntime.ts","../src/core/bootstrap.ts","../src/index.ts"],"sourcesContent":["export function debounce<T extends (...args: any[]) => any>(\n func: T,\n wait: number\n): (...args: Parameters<T>) => void {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n return function debounced(...args: Parameters<T>): void {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n\n timeoutId = setTimeout(() => {\n func(...args);\n timeoutId = null;\n }, wait);\n };\n}\n\nexport function throttle<T extends (...args: any[]) => any>(\n func: T,\n limit: number\n): (...args: Parameters<T>) => void {\n let inThrottle = false;\n\n return function throttled(...args: Parameters<T>): void {\n if (!inThrottle) {\n func(...args);\n inThrottle = true;\n setTimeout(() => {\n inThrottle = false;\n }, limit);\n }\n };\n}\n","/**\n * CarouselCards renderer — a swipeable / autoplaying sequence of product\n * cards. Used for post-purchase upsells, cross-sell, and \"recently viewed\"\n * surfaces. The entire card list is pre-bundled — no network call on\n * trigger; slide advance is pure client state.\n *\n * Data shape (interactive_config, populated at campaign create time and\n * validated server-side):\n * cards: Array<{ image_url?, title, body?, cta_text?, cta_url? }>\n * autoplay_ms?: number // 0 = manual advance only\n * loop?: boolean // wrap to card 0 on last-next\n */\n\nimport type { RenderContext } from './types';\n\ntype Card = {\n image_url?: string;\n title?: string;\n body?: string;\n cta_text?: string;\n cta_url?: string;\n};\n\nconst MAX_CARDS_RENDERED = 10;\n\nexport function renderCarouselCards(ctx: RenderContext): void {\n const { campaign, trackEvent, sanitizeUrl, sanitizeColor, log, addAnimationStyles } = ctx;\n const ic = (campaign.interactive_config || {}) as Record<string, unknown>;\n const rawCards = Array.isArray(ic.cards) ? (ic.cards as Card[]) : [];\n const cards = rawCards.slice(0, MAX_CARDS_RENDERED);\n\n if (cards.length === 0) {\n log('carousel_cards rendered with zero cards — skipping', 'warn');\n return;\n }\n\n const autoplay = Number(ic.autoplay_ms) || 0;\n const loop = ic.loop !== false; // default true\n\n addAnimationStyles();\n\n const bg = sanitizeColor((campaign.background_color as string) || '#ffffff');\n const fg = sanitizeColor((campaign.text_color as string) || '#0f172a');\n\n const overlay = document.createElement('div');\n overlay.className = 'aegis-in-app-carousel-overlay';\n overlay.setAttribute('data-campaign-id', campaign.id);\n overlay.style.cssText = `\n position: fixed; left: 0; right: 0; bottom: 0;\n z-index: 99999; padding: 12px 12px 20px;\n background: rgba(0,0,0,0.12); backdrop-filter: blur(8px);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n animation: aegisSlideInFromBottom 0.3s ease-out;\n `;\n\n const card = document.createElement('div');\n card.style.cssText = `\n background: ${bg}; color: ${fg}; border-radius: 16px;\n box-shadow: 0 8px 20px rgba(0,0,0,0.08); padding: 16px;\n max-width: 520px; margin: 0 auto; position: relative;\n `;\n\n const header = document.createElement('div');\n header.style.cssText = 'display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; margin-bottom: 12px;';\n\n const headerText = document.createElement('div');\n const title = document.createElement('div');\n title.textContent = campaign.title;\n title.style.cssText = 'font-weight: 700; font-size: 15px; margin-bottom: 2px;';\n const body = document.createElement('div');\n body.textContent = campaign.body;\n body.style.cssText = 'font-size: 13px; opacity: 0.75;';\n headerText.appendChild(title);\n headerText.appendChild(body);\n header.appendChild(headerText);\n\n const closeBtn = document.createElement('button');\n closeBtn.textContent = '✕';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.style.cssText = `\n background: transparent; border: none; color: inherit;\n font-size: 16px; cursor: pointer; opacity: 0.6; padding: 2px 6px;\n `;\n closeBtn.addEventListener('click', () => {\n trackEvent(campaign.id, 'dismissed');\n overlay.remove();\n });\n header.appendChild(closeBtn);\n card.appendChild(header);\n\n const track = document.createElement('div');\n track.style.cssText = `\n display: flex; gap: 10px; overflow-x: auto; scroll-snap-type: x mandatory;\n scrollbar-width: none; -ms-overflow-style: none; padding-bottom: 4px;\n `;\n (track.style as unknown as { msOverflowStyle?: string }).msOverflowStyle = 'none';\n track.addEventListener('wheel', (e) => {\n if (Math.abs(e.deltaX) < Math.abs(e.deltaY)) return;\n track.scrollLeft += e.deltaX;\n });\n\n cards.forEach((c, i) => {\n const tile = document.createElement('div');\n tile.setAttribute('data-card-index', String(i));\n tile.style.cssText = `\n flex: 0 0 auto; width: 140px; scroll-snap-align: start;\n background: ${fg}0a; border-radius: 12px; padding: 10px;\n display: flex; flex-direction: column; gap: 6px;\n cursor: ${c.cta_url ? 'pointer' : 'default'};\n `;\n if (c.image_url) {\n const img = document.createElement('img');\n const safe = sanitizeUrl(c.image_url);\n if (safe) {\n img.src = safe;\n img.alt = '';\n img.loading = 'lazy';\n img.style.cssText = 'width: 100%; height: 96px; border-radius: 8px; object-fit: cover;';\n tile.appendChild(img);\n }\n }\n if (c.title) {\n const t = document.createElement('div');\n t.textContent = c.title;\n t.style.cssText = 'font-weight: 600; font-size: 13px; line-height: 1.3;';\n tile.appendChild(t);\n }\n if (c.body) {\n const b = document.createElement('div');\n b.textContent = c.body;\n b.style.cssText = 'font-size: 11.5px; opacity: 0.72; line-height: 1.3;';\n tile.appendChild(b);\n }\n if (c.cta_text && c.cta_url) {\n const cta = document.createElement('button');\n cta.textContent = c.cta_text;\n cta.style.cssText = `\n margin-top: auto; background: ${fg}; color: ${bg};\n border: none; padding: 6px 10px; border-radius: 999px;\n font-size: 12px; font-weight: 600; cursor: pointer;\n `;\n const goto = (e: Event) => {\n e.stopPropagation();\n trackEvent(campaign.id, 'clicked');\n const safe = sanitizeUrl(c.cta_url!);\n if (safe) window.location.href = safe;\n };\n cta.addEventListener('click', goto);\n tile.appendChild(cta);\n tile.addEventListener('click', goto);\n }\n track.appendChild(tile);\n });\n card.appendChild(track);\n\n // Dots + autoplay\n const dots = document.createElement('div');\n dots.style.cssText = 'display: flex; justify-content: center; gap: 6px; margin-top: 10px;';\n const dotEls: HTMLSpanElement[] = [];\n cards.forEach(() => {\n const dot = document.createElement('span');\n dot.style.cssText = `\n width: 6px; height: 6px; border-radius: 999px; background: ${fg};\n opacity: 0.25; transition: opacity 0.2s;\n `;\n dotEls.push(dot);\n dots.appendChild(dot);\n });\n card.appendChild(dots);\n\n const setActive = (idx: number) => {\n dotEls.forEach((d, i) => (d.style.opacity = i === idx ? '0.9' : '0.25'));\n };\n setActive(0);\n\n let activeIdx = 0;\n const tiles = track.querySelectorAll<HTMLDivElement>('[data-card-index]');\n const goto = (idx: number) => {\n activeIdx = ((idx % cards.length) + cards.length) % cards.length;\n const el = tiles[activeIdx];\n if (el) {\n el.scrollIntoView({ behavior: 'smooth', inline: 'start', block: 'nearest' });\n setActive(activeIdx);\n }\n };\n\n let autoplayTimer: ReturnType<typeof setInterval> | null = null;\n if (autoplay > 0 && cards.length > 1) {\n autoplayTimer = setInterval(() => {\n const next = activeIdx + 1;\n if (next >= cards.length && !loop) {\n if (autoplayTimer) clearInterval(autoplayTimer);\n return;\n }\n goto(next);\n }, autoplay);\n }\n\n overlay.addEventListener('remove', () => {\n if (autoplayTimer) clearInterval(autoplayTimer);\n });\n\n // Observe scroll to keep dots in sync when the user swipes.\n track.addEventListener('scroll', () => {\n const approx = Math.round(track.scrollLeft / 150);\n if (approx !== activeIdx && approx >= 0 && approx < cards.length) {\n activeIdx = approx;\n setActive(activeIdx);\n }\n });\n\n overlay.appendChild(card);\n document.body.appendChild(overlay);\n}\n","/**\n * StickyBar renderer — a pinned notification strip at the top or bottom\n * of the viewport. Used for free-shipping hints, flash-sale banners,\n * cart-reminder strips. Dismissible, optionally auto-hiding.\n *\n * interactive_config:\n * sticky_position: 'top' | 'bottom' (required)\n * sticky_bg_color?: string\n * sticky_dismissible?: boolean default true\n * sticky_auto_hide_ms?: number 0 = never\n */\n\nimport type { RenderContext } from './types';\n\n// Persist per-campaign dismissal across reloads so we don't re-show a\n// bar the user already closed. Scoped per campaign ID; storage key\n// survives navigation but is cleared when the user explicitly clears site data.\nconst DISMISS_STORAGE_PREFIX = 'aegis_sticky_dismissed:';\n\nexport function renderStickyBar(ctx: RenderContext): void {\n const { campaign, trackEvent, sanitizeUrl, sanitizeColor, log, addAnimationStyles } = ctx;\n const ic = (campaign.interactive_config || {}) as Record<string, unknown>;\n\n const position = ic.sticky_position === 'top' ? 'top' : 'bottom';\n const dismissible = ic.sticky_dismissible !== false;\n const autoHide = Number(ic.sticky_auto_hide_ms) || 0;\n\n // Already dismissed this session? Skip silently — the prefetch bundle\n // keeps re-offering it, but the user's explicit close stands until TTL.\n try {\n if (\n typeof localStorage !== 'undefined' &&\n localStorage.getItem(DISMISS_STORAGE_PREFIX + campaign.id)\n ) {\n log(`sticky_bar ${campaign.id} suppressed — user dismissed earlier`);\n return;\n }\n } catch {\n // localStorage blocked — fall through and render\n }\n\n addAnimationStyles();\n\n const bg = sanitizeColor(\n (ic.sticky_bg_color as string) || (campaign.background_color as string) || '#4169e1',\n );\n const fg = sanitizeColor((campaign.text_color as string) || '#ffffff');\n\n const bar = document.createElement('div');\n bar.className = 'aegis-in-app-sticky-bar';\n bar.setAttribute('data-campaign-id', campaign.id);\n\n const positionCss =\n position === 'top'\n ? 'top: 0; left: 0; right: 0; animation: aegisSlideDown 0.3s ease-out;'\n : 'bottom: 0; left: 0; right: 0; animation: aegisSlideInFromBottom 0.3s ease-out;';\n\n bar.style.cssText = `\n position: fixed; ${positionCss}\n background: ${bg}; color: ${fg};\n padding: 10px 14px; z-index: 999998;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n display: flex; align-items: center; gap: 12px; justify-content: center;\n box-shadow: 0 ${position === 'top' ? '2px' : '-2px'} 8px rgba(0,0,0,0.08);\n `;\n\n const label = document.createElement('div');\n label.style.cssText = 'flex: 0 1 auto; font-size: 13px; font-weight: 500; text-align: center;';\n const strong = document.createElement('strong');\n strong.textContent = campaign.title;\n strong.style.cssText = 'margin-right: 6px; font-weight: 700;';\n label.appendChild(strong);\n label.appendChild(document.createTextNode(campaign.body));\n bar.appendChild(label);\n\n if (campaign.action_url && campaign.button_text) {\n const cta = document.createElement('button');\n cta.textContent = campaign.button_text;\n cta.style.cssText = `\n background: ${fg}; color: ${bg};\n border: none; padding: 6px 14px; border-radius: 999px;\n font-size: 12px; font-weight: 700; cursor: pointer; white-space: nowrap;\n `;\n cta.addEventListener('click', () => {\n trackEvent(campaign.id, 'clicked');\n const safe = sanitizeUrl(campaign.action_url!);\n if (safe) window.location.href = safe;\n });\n bar.appendChild(cta);\n }\n\n let autoHideTimer: ReturnType<typeof setTimeout> | null = null;\n const remove = (persist: boolean) => {\n if (autoHideTimer) clearTimeout(autoHideTimer);\n if (persist) {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem(DISMISS_STORAGE_PREFIX + campaign.id, '1');\n }\n } catch {\n // swallow — localStorage may be disabled\n }\n }\n bar.remove();\n };\n\n if (dismissible) {\n const close = document.createElement('button');\n close.textContent = '✕';\n close.setAttribute('aria-label', 'Dismiss');\n close.style.cssText = `\n background: transparent; border: none; color: inherit;\n font-size: 16px; cursor: pointer; padding: 0 4px; opacity: 0.75;\n `;\n close.addEventListener('click', () => {\n trackEvent(campaign.id, 'dismissed');\n remove(true);\n });\n bar.appendChild(close);\n }\n\n if (autoHide > 0) {\n autoHideTimer = setTimeout(() => remove(false), autoHide);\n }\n\n document.body.appendChild(bar);\n}\n","/**\n * ProgressBar renderer — a persistent bar that shows the user's progress\n * toward a reward threshold (free shipping, loyalty tier, referral bonus).\n *\n * Two sources of the current value:\n * 'client' — cheap: read from window.Shopify / WooCommerce / Magento\n * cart globals. Untrusted; fine for visual-only hints.\n * 'sse' — trusted: cell-plane pushes current_value via SSE to the\n * already-shipped realtime server. For cart-gated rewards\n * (must agree with server-side checkout guard), prefer SSE.\n *\n * For Phase 1 we implement CLIENT mode end-to-end. SSE mode reads\n * `window.__aegisProgressSSE[campaign.id]` if populated by a parent app\n * — higher-level integration (the SSE bridge) can push values there.\n *\n * interactive_config:\n * progress_goal_type: 'cart_total' | 'items_in_cart' | 'loyalty_points' | 'referrals'\n * progress_threshold: number\n * progress_reward_text?: string\n * progress_source?: 'client' | 'sse' default 'client'\n */\n\nimport type { RenderContext } from './types';\n\ntype GoalType = 'cart_total' | 'items_in_cart' | 'loyalty_points' | 'referrals';\n\nexport function renderProgressBar(ctx: RenderContext): void {\n const { campaign, trackEvent, sanitizeColor, log, addAnimationStyles } = ctx;\n const ic = (campaign.interactive_config || {}) as Record<string, unknown>;\n\n const goalType = (ic.progress_goal_type as GoalType) || 'cart_total';\n const threshold = Number(ic.progress_threshold);\n if (!(threshold > 0)) {\n log('progress_bar requires a positive progress_threshold — skipping', 'warn');\n return;\n }\n const rewardText =\n (ic.progress_reward_text as string) || (campaign.body as string) || 'Unlocked!';\n const source = ic.progress_source === 'sse' ? 'sse' : 'client';\n\n addAnimationStyles();\n\n const bg = sanitizeColor((campaign.background_color as string) || '#f8fafc');\n const fill = sanitizeColor((campaign.text_color as string) || '#4169e1');\n const fg = '#0f172a';\n\n const bar = document.createElement('div');\n bar.className = 'aegis-in-app-progress-bar';\n bar.setAttribute('data-campaign-id', campaign.id);\n bar.style.cssText = `\n position: fixed; left: 12px; right: 12px; bottom: 12px;\n max-width: 540px; margin: 0 auto;\n background: ${bg}; color: ${fg}; border-radius: 12px;\n padding: 10px 14px; z-index: 999997;\n box-shadow: 0 8px 20px rgba(0,0,0,0.08);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n animation: aegisSlideInFromBottom 0.3s ease-out;\n `;\n\n const label = document.createElement('div');\n label.style.cssText = 'display: flex; justify-content: space-between; font-size: 13px; font-weight: 600; margin-bottom: 6px;';\n\n const leading = document.createElement('span');\n leading.textContent = campaign.title;\n label.appendChild(leading);\n\n const numeric = document.createElement('span');\n numeric.style.cssText = 'opacity: 0.7; font-weight: 500;';\n label.appendChild(numeric);\n bar.appendChild(label);\n\n const shell = document.createElement('div');\n shell.style.cssText = `\n height: 8px; border-radius: 999px; background: ${fill}22;\n overflow: hidden;\n `;\n const fillEl = document.createElement('div');\n fillEl.style.cssText = `\n height: 100%; border-radius: 999px; background: ${fill};\n width: 0%; transition: width 0.4s cubic-bezier(.4,0,.2,1);\n `;\n shell.appendChild(fillEl);\n bar.appendChild(shell);\n\n const footnote = document.createElement('div');\n footnote.style.cssText = 'font-size: 11.5px; opacity: 0.65; margin-top: 6px;';\n bar.appendChild(footnote);\n\n const readCurrentValue = (): number => {\n if (source === 'sse') {\n const hook = (window as unknown as {\n __aegisProgressSSE?: Record<string, number>;\n }).__aegisProgressSSE;\n return (hook && typeof hook[campaign.id] === 'number' ? hook[campaign.id] : 0) as number;\n }\n // client mode — read the platform cart globals the widget manager\n // already normalises (Shopify/Woo/Magento). We peek at the same\n // locations without pulling in AegisWidgetManager's 2k-line module.\n try {\n if (goalType === 'cart_total' || goalType === 'items_in_cart') {\n const win = window as unknown as {\n Shopify?: { checkout?: { total_price?: string | number } };\n aegis_cart?: { cart_total?: number; cart_items?: unknown[] };\n localStorage?: Storage;\n };\n if (win.Shopify?.checkout) {\n const v = parseFloat(String(win.Shopify.checkout.total_price || 0));\n return goalType === 'cart_total' ? v : 0;\n }\n if (win.aegis_cart) {\n if (goalType === 'items_in_cart') {\n return Array.isArray(win.aegis_cart.cart_items) ? win.aegis_cart.cart_items.length : 0;\n }\n return Number(win.aegis_cart.cart_total || 0);\n }\n // Magento cache fallback\n try {\n const cacheStr = window.localStorage?.getItem('mage-cache-storage');\n if (cacheStr) {\n const cache = JSON.parse(cacheStr) as { cart?: { subtotalAmount?: number; items?: unknown[] } };\n const cart = cache.cart;\n if (cart) {\n return goalType === 'cart_total'\n ? Number(cart.subtotalAmount || 0)\n : Array.isArray(cart.items)\n ? cart.items.length\n : 0;\n }\n }\n } catch {\n /* noop */\n }\n }\n // loyalty_points / referrals are expected to flow via SSE/push; in\n // client mode we cannot trust a local counter.\n return 0;\n } catch {\n return 0;\n }\n };\n\n let lastFiredUnlock = false;\n const update = () => {\n const cur = readCurrentValue();\n const pct = Math.max(0, Math.min(100, (cur / threshold) * 100));\n fillEl.style.width = `${pct}%`;\n numeric.textContent = `${cur.toFixed(0)} / ${threshold.toFixed(0)}`;\n if (pct >= 100) {\n footnote.textContent = rewardText;\n if (!lastFiredUnlock) {\n lastFiredUnlock = true;\n trackEvent(campaign.id, 'clicked'); // \"unlocked\" recorded as click\n }\n } else {\n const remaining = Math.max(0, threshold - cur);\n footnote.textContent = `Add ${remaining.toFixed(0)} more to unlock: ${rewardText}`;\n }\n };\n\n update();\n\n // Client-mode cart state changes fire events on the storefront globals\n // (Shopify emits `cart:updated`, Woo emits its own). Poll fallback at\n // 1s — negligible overhead because every tick is synchronous.\n const pollTimer = setInterval(update, 1000);\n const cleanup = () => clearInterval(pollTimer);\n window.addEventListener('beforeunload', cleanup, { once: true });\n bar.addEventListener('remove', cleanup);\n\n document.body.appendChild(bar);\n}\n","/**\n * CoachmarkTour renderer — a guided, multi-step walkthrough anchored to\n * DOM elements via CSS selectors. One tooltip appears at a time with\n * next/back navigation; completion + skip are persisted per contact via\n * localStorage under the `resume_key`, so an abandoned tour resumes on\n * the next visit instead of restarting or re-bothering the user.\n *\n * interactive_config:\n * steps: Array<{\n * anchor_web?: string, // CSS selector for THIS platform\n * anchor_android?: string, // ignored on web\n * anchor_ios?: string, // ignored on web\n * title: string,\n * body: string,\n * placement?: 'top' | 'bottom' | 'left' | 'right',\n * cta_text?: string,\n * }>\n * resume_key: string,\n * allow_skip?: boolean,\n * show_progress_dots?: boolean,\n */\n\nimport type { RenderContext } from './types';\n\ntype Step = {\n anchor_web?: string;\n anchor_android?: string;\n anchor_ios?: string;\n title: string;\n body: string;\n placement?: 'top' | 'bottom' | 'left' | 'right';\n cta_text?: string;\n};\n\nconst RESUME_PREFIX = 'aegis_coachmark_progress:';\n\nfunction readResumeIdx(resumeKey: string): number {\n try {\n if (typeof localStorage === 'undefined') return 0;\n const raw = localStorage.getItem(RESUME_PREFIX + resumeKey);\n const n = raw ? parseInt(raw, 10) : 0;\n return Number.isFinite(n) && n >= 0 ? n : 0;\n } catch {\n return 0;\n }\n}\n\nfunction writeResumeIdx(resumeKey: string, idx: number): void {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem(RESUME_PREFIX + resumeKey, String(idx));\n }\n } catch {\n /* noop */\n }\n}\n\nfunction clearResume(resumeKey: string): void {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.removeItem(RESUME_PREFIX + resumeKey);\n }\n } catch {\n /* noop */\n }\n}\n\nexport function renderCoachmarkTour(ctx: RenderContext): void {\n const { campaign, trackEvent, sanitizeColor, log, addAnimationStyles } = ctx;\n const ic = (campaign.interactive_config || {}) as Record<string, unknown>;\n\n const resumeKey = ic.resume_key as string | undefined;\n if (!resumeKey) {\n log('coachmark_tour requires interactive_config.resume_key — skipping', 'warn');\n return;\n }\n\n const steps = Array.isArray(ic.steps) ? (ic.steps as Step[]) : [];\n if (steps.length === 0) {\n log('coachmark_tour has no steps — skipping', 'warn');\n return;\n }\n\n const allowSkip = ic.allow_skip !== false;\n const showDots = ic.show_progress_dots !== false;\n\n addAnimationStyles();\n\n const bg = sanitizeColor((campaign.background_color as string) || '#0f172a');\n const fg = sanitizeColor((campaign.text_color as string) || '#ffffff');\n\n // Resume or start at 0.\n let current = readResumeIdx(resumeKey);\n if (current >= steps.length) {\n log(`coachmark_tour ${resumeKey} already complete — not re-showing`);\n return;\n }\n\n // Track the single overall impression once per mount.\n trackEvent(campaign.id, 'impression');\n\n let pointerEl: HTMLElement | null = null;\n let tipEl: HTMLElement | null = null;\n let highlightEl: HTMLElement | null = null;\n\n const cleanupOne = () => {\n pointerEl?.remove();\n tipEl?.remove();\n highlightEl?.remove();\n pointerEl = null;\n tipEl = null;\n highlightEl = null;\n };\n\n const finish = (opts: { skipped: boolean }) => {\n cleanupOne();\n if (opts.skipped) {\n trackEvent(campaign.id, 'dismissed');\n } else {\n trackEvent(campaign.id, 'clicked'); // completion\n }\n // Mark tour as complete so we never restart it for this contact.\n writeResumeIdx(resumeKey, steps.length);\n };\n\n const showStep = (idx: number) => {\n cleanupOne();\n const step = steps[idx];\n if (!step) {\n finish({ skipped: false });\n return;\n }\n writeResumeIdx(resumeKey, idx);\n\n const selector = step.anchor_web;\n let anchor: Element | null = null;\n if (selector) {\n try {\n anchor = document.querySelector(selector);\n } catch {\n anchor = null;\n }\n }\n if (!anchor) {\n log(`coachmark step ${idx} — selector '${selector}' not found; advancing`, 'warn');\n showStep(idx + 1);\n return;\n }\n\n const rect = anchor.getBoundingClientRect();\n // Slight highlight around the anchor so the user's eye snaps to it.\n highlightEl = document.createElement('div');\n highlightEl.style.cssText = `\n position: fixed;\n top: ${rect.top - 6}px; left: ${rect.left - 6}px;\n width: ${rect.width + 12}px; height: ${rect.height + 12}px;\n border-radius: 10px; z-index: 999998;\n box-shadow: 0 0 0 2px ${fg}, 0 0 0 9999px rgba(0,0,0,0.4);\n pointer-events: none;\n transition: all 0.2s ease;\n `;\n document.body.appendChild(highlightEl);\n\n const placement = step.placement || 'bottom';\n tipEl = document.createElement('div');\n tipEl.setAttribute('data-campaign-id', campaign.id);\n tipEl.style.cssText = `\n position: fixed; z-index: 999999;\n background: ${bg}; color: ${fg};\n padding: 12px 14px; border-radius: 12px;\n max-width: 260px;\n box-shadow: 0 8px 24px rgba(0,0,0,0.25);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n animation: aegisFadeIn 0.2s ease;\n `;\n\n const titleEl = document.createElement('div');\n titleEl.textContent = step.title;\n titleEl.style.cssText = 'font-weight: 700; font-size: 13px; margin-bottom: 4px;';\n tipEl.appendChild(titleEl);\n\n const bodyEl = document.createElement('div');\n bodyEl.textContent = step.body;\n bodyEl.style.cssText = 'font-size: 12.5px; line-height: 1.4; opacity: 0.9;';\n tipEl.appendChild(bodyEl);\n\n const controls = document.createElement('div');\n controls.style.cssText = 'display: flex; align-items: center; justify-content: space-between; margin-top: 10px; gap: 8px;';\n\n // Dots\n if (showDots) {\n const dots = document.createElement('div');\n dots.style.cssText = 'display: flex; gap: 4px;';\n steps.forEach((_, i) => {\n const d = document.createElement('span');\n d.style.cssText = `\n width: 5px; height: 5px; border-radius: 999px;\n background: ${fg}; opacity: ${i === idx ? '0.95' : '0.3'};\n `;\n dots.appendChild(d);\n });\n controls.appendChild(dots);\n } else {\n controls.appendChild(document.createElement('span'));\n }\n\n const buttons = document.createElement('div');\n buttons.style.cssText = 'display: flex; gap: 6px;';\n\n if (allowSkip && idx < steps.length - 1) {\n const skip = document.createElement('button');\n skip.textContent = 'Skip';\n skip.style.cssText = `\n background: transparent; color: inherit; opacity: 0.7;\n border: none; font-size: 12px; cursor: pointer; padding: 6px 8px;\n `;\n skip.addEventListener('click', () => finish({ skipped: true }));\n buttons.appendChild(skip);\n }\n\n const next = document.createElement('button');\n const isLast = idx === steps.length - 1;\n next.textContent = step.cta_text || (isLast ? 'Done' : 'Next');\n next.style.cssText = `\n background: ${fg}; color: ${bg};\n border: none; padding: 6px 12px; border-radius: 999px;\n font-size: 12px; font-weight: 700; cursor: pointer;\n `;\n next.addEventListener('click', () => {\n if (isLast) {\n finish({ skipped: false });\n } else {\n showStep(idx + 1);\n }\n });\n buttons.appendChild(next);\n\n controls.appendChild(buttons);\n tipEl.appendChild(controls);\n document.body.appendChild(tipEl);\n\n // Position after insertion so we know the tip's own dimensions.\n const tipRect = tipEl.getBoundingClientRect();\n const margin = 12;\n let top = rect.bottom + margin;\n let left = rect.left;\n if (placement === 'top') {\n top = rect.top - tipRect.height - margin;\n } else if (placement === 'left') {\n top = rect.top;\n left = rect.left - tipRect.width - margin;\n } else if (placement === 'right') {\n top = rect.top;\n left = rect.right + margin;\n }\n // Clamp to viewport.\n top = Math.max(8, Math.min(window.innerHeight - tipRect.height - 8, top));\n left = Math.max(8, Math.min(window.innerWidth - tipRect.width - 8, left));\n tipEl.style.top = `${top}px`;\n tipEl.style.left = `${left}px`;\n };\n\n showStep(current);\n\n // If the host page unloads mid-tour, leave the current index persisted so\n // the next session resumes from there. Nothing else to do — writeResumeIdx\n // was called in showStep.\n // Expose a cancel hook so app code can reset the tour from Dev Tools etc.\n (window as unknown as { aegisResetTour?: (key: string) => void }).aegisResetTour = (key: string) => clearResume(key);\n}\n","/**\n * ProductRecommendation renderer — personalized product grid/row rendered\n * from `interactive_config.cards[]` that the cell-plane populated at\n * bundle-assembly time. The SDK never calls a product-API at render\n * time — the preload contract is that the recommended products are\n * already in the bundle.\n *\n * The layout is narrower than the generic carousel because product recs\n * should feel like a first-class product grid, not a marketing slider.\n * Three layouts: grid (2-col / 3-col responsive), row (horizontal-scroll),\n * carousel (same as carousel_cards but different framing copy).\n *\n * interactive_config:\n * rec_source?: 'viewed' | 'abandoned' | 'cross_sell' | 'trending' | 'personalized'\n * (metadata only — the actual product list is in `cards[]`)\n * rec_count?: number (display hint; rendering is driven by cards.length)\n * rec_layout?: 'grid' | 'row' | 'carousel' default 'grid'\n * rec_cta_text?: string default 'Shop now'\n * cards: Array<{ image_url?, title?, body?, cta_url?, metadata? }>\n */\n\nimport type { RenderContext } from './types';\n\ntype Card = {\n image_url?: string;\n title?: string;\n body?: string;\n cta_text?: string;\n cta_url?: string;\n metadata?: Record<string, unknown>;\n};\n\nconst MAX_PRODUCTS = 24;\n\nexport function renderProductRecommendation(ctx: RenderContext): void {\n const { campaign, trackEvent, sanitizeUrl, sanitizeColor, log, addAnimationStyles } = ctx;\n const ic = (campaign.interactive_config || {}) as Record<string, unknown>;\n\n const rawCards = Array.isArray(ic.cards) ? (ic.cards as Card[]) : [];\n const cards = rawCards.slice(0, MAX_PRODUCTS);\n if (cards.length === 0) {\n log('product_recommendation rendered with zero products — skipping', 'warn');\n return;\n }\n\n const layout = (ic.rec_layout as string) || 'grid';\n const ctaDefault = (ic.rec_cta_text as string) || 'Shop now';\n\n addAnimationStyles();\n\n const bg = sanitizeColor((campaign.background_color as string) || '#ffffff');\n const fg = sanitizeColor((campaign.text_color as string) || '#0f172a');\n const accent = sanitizeColor('#4169e1');\n\n const overlay = document.createElement('div');\n overlay.className = 'aegis-in-app-product-rec';\n overlay.setAttribute('data-campaign-id', campaign.id);\n overlay.style.cssText = `\n position: fixed; inset: 0;\n background: rgba(15,23,42,0.55); backdrop-filter: blur(4px);\n display: flex; align-items: flex-end; justify-content: center;\n z-index: 99999; animation: aegisFadeIn 0.25s ease;\n `;\n\n const sheet = document.createElement('div');\n sheet.style.cssText = `\n background: ${bg}; color: ${fg};\n max-width: 560px; width: 100%; max-height: 80vh; overflow-y: auto;\n border-radius: 20px 20px 0 0;\n padding: 18px 16px 22px;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n animation: aegisSlideInFromBottom 0.3s ease-out;\n box-shadow: 0 -12px 30px rgba(0,0,0,0.12);\n `;\n\n // Drag handle (decorative, for mobile context)\n const handle = document.createElement('div');\n handle.style.cssText = `\n width: 36px; height: 4px; border-radius: 999px; background: ${fg}1f;\n margin: 0 auto 12px;\n `;\n sheet.appendChild(handle);\n\n const header = document.createElement('div');\n header.style.cssText = 'display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;';\n\n const headerText = document.createElement('div');\n const title = document.createElement('div');\n title.textContent = campaign.title;\n title.style.cssText = 'font-weight: 700; font-size: 16px; margin-bottom: 2px;';\n const body = document.createElement('div');\n body.textContent = campaign.body;\n body.style.cssText = 'font-size: 13px; opacity: 0.7; line-height: 1.4;';\n headerText.appendChild(title);\n headerText.appendChild(body);\n header.appendChild(headerText);\n\n const close = document.createElement('button');\n close.textContent = '✕';\n close.setAttribute('aria-label', 'Close');\n close.style.cssText = `\n background: transparent; border: none; color: inherit;\n font-size: 18px; cursor: pointer; padding: 4px 8px; opacity: 0.7;\n `;\n close.addEventListener('click', () => {\n trackEvent(campaign.id, 'dismissed');\n overlay.remove();\n });\n header.appendChild(close);\n sheet.appendChild(header);\n\n const grid = document.createElement('div');\n if (layout === 'row' || layout === 'carousel') {\n grid.style.cssText = `\n display: flex; gap: 10px; overflow-x: auto;\n scroll-snap-type: x mandatory; padding: 14px 0 4px;\n `;\n } else {\n grid.style.cssText = `\n display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;\n padding-top: 14px;\n `;\n }\n\n cards.forEach((c) => {\n const tile = document.createElement('div');\n const isRow = layout === 'row' || layout === 'carousel';\n tile.style.cssText = `\n background: ${fg}08; border-radius: 12px;\n padding: 10px; display: flex; flex-direction: column; gap: 6px;\n cursor: ${c.cta_url ? 'pointer' : 'default'};\n ${isRow ? 'flex: 0 0 150px; scroll-snap-align: start;' : ''}\n transition: transform 0.15s ease;\n `;\n\n if (c.image_url) {\n const img = document.createElement('img');\n const safe = sanitizeUrl(c.image_url);\n if (safe) {\n img.src = safe;\n img.alt = '';\n img.loading = 'lazy';\n img.style.cssText = 'width: 100%; aspect-ratio: 1 / 1; border-radius: 8px; object-fit: cover;';\n tile.appendChild(img);\n }\n }\n\n if (c.title) {\n const t = document.createElement('div');\n t.textContent = c.title;\n t.style.cssText = 'font-weight: 600; font-size: 13px; line-height: 1.3;';\n tile.appendChild(t);\n }\n\n // Price lives in metadata.price per the dashboard schema; we show it\n // prominently if present.\n const price = c.metadata && typeof c.metadata === 'object' ? (c.metadata as Record<string, unknown>).price : undefined;\n if (price !== undefined) {\n const p = document.createElement('div');\n p.textContent = String(price);\n p.style.cssText = `color: ${accent}; font-weight: 700; font-size: 13px;`;\n tile.appendChild(p);\n } else if (c.body) {\n const b = document.createElement('div');\n b.textContent = c.body;\n b.style.cssText = 'font-size: 11.5px; opacity: 0.72; line-height: 1.3;';\n tile.appendChild(b);\n }\n\n const cta = document.createElement('button');\n cta.textContent = c.cta_text || ctaDefault;\n cta.style.cssText = `\n margin-top: auto;\n background: ${accent}; color: #fff;\n border: none; padding: 7px 10px; border-radius: 999px;\n font-size: 12px; font-weight: 600; cursor: pointer;\n `;\n const go = (e: Event) => {\n e.stopPropagation();\n trackEvent(campaign.id, 'clicked');\n if (c.cta_url) {\n const safe = sanitizeUrl(c.cta_url);\n if (safe) window.location.href = safe;\n }\n };\n cta.addEventListener('click', go);\n tile.appendChild(cta);\n if (c.cta_url) tile.addEventListener('click', go);\n\n grid.appendChild(tile);\n });\n\n sheet.appendChild(grid);\n overlay.appendChild(sheet);\n\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) {\n trackEvent(campaign.id, 'dismissed');\n overlay.remove();\n }\n });\n\n document.body.appendChild(overlay);\n}\n","/**\n * AegisInAppManager - Web SDK In-App Messaging Module\n *\n * HTTP polling 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 (RFC 2026-04-16):\n * - Polls /v1/in-app/active on initialize + on identity change\n * - Caches campaigns locally in memory\n * - Evaluates trigger rules client-side\n * - Tracks events (impression, click, dismiss) asynchronously\n *\n * NOTE: Persistent SSE for downstream delivery is disabled by default\n * (enableSSE=false). Tenant dashboards that need realtime (inbox, chat,\n * live page) open SSE directly via Next.js API routes — not via this SDK.\n * End-user storefronts use polling + Web Push for background delivery.\n */\n\nimport type { RenderContext } from './renderers';\nimport {\n renderCarouselCards,\n renderCoachmarkTour,\n renderProductRecommendation,\n renderProgressBar,\n renderStickyBar,\n} from './renderers';\nimport { Storage } from '../utils/storage';\n\n// Read the SDK's persisted anonymous_id from localStorage/cookie if available.\n// Returns undefined when called server-side (no document/window) or when no\n// id has been minted yet — caller falls through to leaving userId unset.\nfunction readAnonIdFromStorage(): string | undefined {\n if (typeof document === 'undefined') return undefined;\n try {\n const storage = new Storage();\n return storage.get('anon_id') ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nexport interface InAppCampaign {\n id: string;\n type:\n | 'modal'\n | 'banner'\n | 'tooltip'\n | 'full_screen'\n | 'half_interstitial'\n | 'alert'\n | 'pip'\n // Preload-first display types (2026-04-22 §5.4 of the expansion plan)\n | 'carousel_cards'\n | 'sticky_bar'\n | 'progress_bar'\n | 'coachmark_tour'\n | 'product_recommendation';\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 // Conversion-aware suppression — added by Micro-Intent Engine P0a (2026-04-30).\n // Mirrors cell-plane FrequencyCap. When the host app calls\n // `notifyConversion(goalName)`, every armed campaign whose\n // `suppress_after_conversion_seconds` is set gets silenced for that\n // many seconds (session-scoped via sessionStorage). Prevents the\n // \"showing 10% off to a buyer who just paid full price\" failure mode.\n suppress_after_conversion_seconds?: number;\n suppress_after_dismiss_seconds?: number;\n scope?: 'session' | 'user' | 'user_sku';\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 // Resolved by POST /v1/sdk/bootstrap — required in production. Campaigns\n // with a non-empty `target_properties` list are filtered against this on\n // the server, so passing the wrong id (or omitting it) narrows visible\n // campaigns to the property-agnostic ones only.\n propertyId?: string;\n debugMode?: boolean;\n enableSSE?: boolean;\n /**\n * Callback invoked when the manager receives an in-app campaign with\n * a gamification sub_type (spin_wheel / scratch_card). The facade\n * (AegisMessageRuntime) wires this to the widget-renderer path so\n * interactive campaigns render correctly. When this is undefined,\n * gamification campaigns are logged and skipped.\n */\n onInteractiveCampaign?: (campaign: InAppCampaign) => void;\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 propertyId?: string;\n private debugMode: boolean;\n private enableSSE: boolean;\n private onInteractiveCampaign?: (campaign: InAppCampaign) => void;\n\n private campaigns: InAppCampaign[] = [];\n private displayedCampaigns = new Set<string>();\n // Conversion-aware suppression — campaign_id -> epoch_ms when suppression expires.\n // Populated by `notifyConversion()` and rehydrated from sessionStorage in\n // `refreshCampaigns()` so a navigation between pages preserves silence.\n private suppressedUntil = new Map<string, number>();\n private eventSource?: EventSource;\n private isInitialized = false;\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n // sessionStorage key prefix — one entry per goal so we can introspect what\n // converted and when. Format: { ts: epoch_ms }.\n private static readonly CONVERSION_STORAGE_PREFIX = 'aegis_conv_';\n \n constructor(config: AegisInAppConfig) {\n this.writeKey = config.writeKey;\n this.apiHost = config.apiHost || 'https://api.aegis.ai';\n // Fall back to the SDK's persisted anonymous_id (set on first /v1/sdk/bootstrap\n // and reused across the main analytics SDK) so anonymous storefront users\n // get journey-driven in-app messages keyed to the same identity used in\n // /v1/batch payloads. Without this, polling defaults to \"anonymous\" on the\n // server and bucket-misses every per-contact priority queue.\n this.userId = config.userId ?? readAnonIdFromStorage();\n this.contactId = config.contactId;\n this.organizationId = config.organizationId;\n this.propertyId = config.propertyId;\n this.debugMode = config.debugMode || false;\n // SSE is disabled by default. Kept as opt-in capability for future tenant\n // dashboards that embed the Aegis SDK and need realtime updates. End-user\n // storefronts must NOT enable this — persistent-per-tab SSE doesn't scale.\n this.enableSSE = config.enableSSE === true;\n this.onInteractiveCampaign = config.onInteractiveCampaign;\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 /**\n * Conversion-aware suppression. Call this when the host app observes a\n * goal event (purchase, order_placed, checkout_completed, or any custom\n * goal the workspace has configured per-campaign).\n *\n * For every armed campaign whose `frequency.suppress_after_conversion_seconds`\n * is set, this:\n * 1. Persists the conversion in sessionStorage (so subsequent page\n * loads in the same tab retain silence).\n * 2. Computes an expiry epoch_ms and stores it in `suppressedUntil`.\n * 3. The two campaign-evaluation paths (`tryDisplayNextCampaign`\n * and `onClientEvent`) skip campaigns whose `suppressedUntil`\n * has not yet passed.\n *\n * Scope: only `session` is implemented in P0a. `user` and `user_sku`\n * scopes degrade to session-only with a debug log; the schema accepts\n * them so future expansion is non-breaking.\n *\n * Safe to call repeatedly for the same goal — each call refreshes the\n * sessionStorage timestamp and re-applies suppression to any campaigns\n * loaded since the last call.\n */\n notifyConversion(goalName: string): void {\n if (!goalName) {\n this.log('notifyConversion called with empty goalName; ignored', 'warn');\n return;\n }\n const ts = Date.now();\n if (typeof sessionStorage !== 'undefined') {\n try {\n sessionStorage.setItem(\n `${AegisInAppManager.CONVERSION_STORAGE_PREFIX}${goalName}`,\n JSON.stringify({ ts }),\n );\n } catch {\n // sessionStorage may be disabled (Safari private mode, blocked\n // third-party context). Suppression still applies for the\n // current page lifetime via the in-memory map.\n }\n }\n this.applySuppressionFromCampaigns(ts);\n this.log(`notifyConversion: ${goalName} — suppressing ${this.suppressedUntil.size} armed campaigns`);\n }\n\n /**\n * Compute and store `suppressedUntil` entries for every armed campaign\n * whose `frequency.suppress_after_conversion_seconds` is set. Called by\n * `notifyConversion()` and `refreshCampaigns()` (the latter rehydrates\n * suppression for newly-loaded campaigns when a prior conversion event\n * exists in sessionStorage).\n *\n * `convertedAt` is the epoch_ms of the conversion; pass `Date.now()`\n * when called from `notifyConversion`, or the `ts` recovered from\n * sessionStorage when rehydrating.\n */\n private applySuppressionFromCampaigns(convertedAt: number): void {\n for (const c of this.campaigns) {\n const seconds = c.frequency?.suppress_after_conversion_seconds;\n if (typeof seconds !== 'number' || seconds <= 0) continue;\n const scope = c.frequency?.scope ?? 'session';\n if (scope !== 'session') {\n // P0a only implements session scope. Schema accepts user / user_sku\n // so future work doesn't break wire compatibility, but for now we\n // degrade to session and log.\n this.log(\n `applySuppressionFromCampaigns: scope=${scope} not implemented; degrading to session for campaign ${c.id}`,\n 'warn',\n );\n }\n const expiresAt = convertedAt + seconds * 1000;\n // Take the max so a later/longer suppression wins over an earlier one.\n const existing = this.suppressedUntil.get(c.id);\n if (existing === undefined || existing < expiresAt) {\n this.suppressedUntil.set(c.id, expiresAt);\n }\n }\n }\n\n /**\n * Recover any prior conversion timestamps from sessionStorage and apply\n * suppression to currently-loaded campaigns. Called from\n * `refreshCampaigns()` after `this.campaigns` is populated. This is the\n * mechanism that prevents a converted buyer from seeing a discount popup\n * on the next page load within the same session.\n */\n private rehydrateSuppressionFromStorage(): void {\n if (typeof sessionStorage === 'undefined') return;\n let earliestTs: number | null = null;\n try {\n for (let i = 0; i < sessionStorage.length; i++) {\n const key = sessionStorage.key(i);\n if (!key || !key.startsWith(AegisInAppManager.CONVERSION_STORAGE_PREFIX)) continue;\n const raw = sessionStorage.getItem(key);\n if (!raw) continue;\n const parsed = JSON.parse(raw) as { ts?: number };\n if (typeof parsed.ts === 'number') {\n earliestTs = earliestTs === null ? parsed.ts : Math.min(earliestTs, parsed.ts);\n }\n }\n } catch {\n // Malformed entries are silently skipped — suppression simply\n // doesn't apply for them.\n return;\n }\n if (earliestTs !== null) {\n this.applySuppressionFromCampaigns(earliestTs);\n }\n }\n\n /**\n * Returns true if the campaign is currently suppressed (Date.now() is\n * before the stored expiry). Used by both display paths.\n */\n private isSuppressed(campaignId: string): boolean {\n const expiresAt = this.suppressedUntil.get(campaignId);\n if (expiresAt === undefined) return false;\n if (Date.now() >= expiresAt) {\n this.suppressedUntil.delete(campaignId);\n return false;\n }\n return true;\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 if (this.propertyId) {\n headers['X-Property-Id'] = this.propertyId;\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 credentials: 'include',\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch campaigns: ${response.status}`);\n }\n\n const payload = await response.json();\n // Server returns an array; defensively handle error bodies (HTML\n // from misconfigured gateways, {} from maintenance endpoints, etc.)\n // so a bad response doesn't turn `updateContactId` into a thrower.\n this.campaigns = Array.isArray(payload) ? payload : [];\n\n // Process A/B assignments from server response (Critical Fix C)\n this.processABAssignments(this.campaigns);\n\n // Rehydrate conversion suppression from sessionStorage so a buyer\n // who converted on a prior page load in the same tab does not see\n // a discount popup on this load. Must run after this.campaigns is\n // populated and BEFORE tryDisplayNextCampaign so the first display\n // attempt honors suppression.\n this.rehydrateSuppressionFromStorage();\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 // Only auto-display campaigns that DO NOT have a client_trigger.\n // Trigger-gated campaigns wait for the host app to call\n // `onClientEvent()` or for TriggerEngine to fire the matching\n // behavioural event. This preserves the preload-first contract —\n // the campaign is armed but the render is gated.\n // Conversion-aware suppression: campaigns silenced by a prior\n // notifyConversion() call (or rehydrated from sessionStorage) are\n // skipped until their suppression window expires.\n const campaign = this.campaigns.find((c) =>\n !this.displayedCampaigns.has(c.id) && !c.client_trigger && !this.isSuppressed(c.id),\n );\n\n if (campaign) {\n this.displayCampaign(campaign);\n }\n }\n\n /**\n * Evaluate the currently armed campaigns against a client-side event\n * and render any that match their `client_trigger`.\n *\n * Called by the host app (e.g., the EcommerceTracker on product_viewed),\n * or by future TriggerEngine bridges. Safe to call repeatedly for the\n * same event — dedup happens via `displayedCampaigns`.\n *\n * Supported trigger types (align with the cell-plane server-side\n * `display_rules.trigger_type`):\n * - `custom_event` : fire when eventName matches config.event\n * - `product_match` : fire on `product_viewed` when eventData.product_id\n * matches config.product_id (string or string[])\n * - `delay` : client-side setTimeout — evaluated at armeng\n * time (kicked off from `displayCampaign`), not here.\n */\n onClientEvent(eventName: string, eventData: Record<string, unknown> = {}): void {\n for (const c of this.campaigns) {\n if (this.displayedCampaigns.has(c.id)) continue;\n if (!c.client_trigger) continue;\n // Conversion-aware suppression: trigger-gated campaigns silenced by\n // a prior notifyConversion() call are skipped until expiry.\n if (this.isSuppressed(c.id)) continue;\n if (this.matchesClientTrigger(c.client_trigger, eventName, eventData)) {\n this.displayCampaign(c);\n }\n }\n }\n\n private matchesClientTrigger(\n trigger: { type: string; config?: Record<string, unknown> },\n eventName: string,\n eventData: Record<string, unknown>,\n ): boolean {\n const cfg = trigger.config || {};\n switch (trigger.type) {\n case 'custom_event':\n return typeof cfg.event === 'string' && cfg.event === eventName;\n case 'product_match': {\n if (eventName !== 'product_viewed' && eventName !== 'product_view') {\n return false;\n }\n const wantedRaw = cfg.product_id;\n const wanted: string[] = Array.isArray(wantedRaw)\n ? (wantedRaw as string[])\n : typeof wantedRaw === 'string'\n ? [wantedRaw]\n : [];\n if (wanted.length === 0) return false;\n const actual = String(\n eventData.product_id ??\n eventData.productId ??\n (eventData.product as Record<string, unknown> | undefined)?.id ??\n '',\n );\n return wanted.includes(actual);\n }\n default:\n // Unknown or server-evaluated — do not auto-fire from the client.\n return false;\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 // Preload-first display types (2026-04-22). These renderers own their\n // own impression tracking so we don't double-count alongside the\n // trailing `this.trackEvent(... 'impression')` below — return early.\n case 'carousel_cards':\n renderCarouselCards(this.buildRenderContext(campaign));\n this.trackEvent(campaign.id, 'impression');\n return;\n case 'sticky_bar':\n renderStickyBar(this.buildRenderContext(campaign));\n this.trackEvent(campaign.id, 'impression');\n return;\n case 'progress_bar':\n renderProgressBar(this.buildRenderContext(campaign));\n this.trackEvent(campaign.id, 'impression');\n return;\n case 'coachmark_tour':\n // coachmark_tour fires its own impression/dismiss/click events\n // from within its state machine — don't double-report here.\n renderCoachmarkTour(this.buildRenderContext(campaign));\n return;\n case 'product_recommendation':\n renderProductRecommendation(this.buildRenderContext(campaign));\n this.trackEvent(campaign.id, 'impression');\n return;\n }\n\n this.trackEvent(campaign.id, 'impression');\n }\n\n /**\n * Build the shared context passed into the preload-first renderers.\n * Matches the interface in `./renderers/types.ts`. Kept as a private\n * method (rather than inlined at each call-site) so future renderer\n * additions stay consistent and easy to audit.\n */\n private buildRenderContext(campaign: InAppCampaign): RenderContext {\n return {\n campaign,\n trackEvent: (id, evt) => {\n void this.trackEvent(id, evt);\n },\n sanitizeUrl: (url: string) => this.sanitizeUrl(url),\n sanitizeColor: (color: string) => this.sanitizeColor(color),\n log: (msg: string, level?: 'log' | 'warn' | 'error') => this.log(msg, level),\n addAnimationStyles: () => this.addAnimationStyles(),\n };\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 if (this.onInteractiveCampaign) {\n this.onInteractiveCampaign(campaign);\n } else {\n this.log(\n `${campaign.sub_type} campaign received but no onInteractiveCampaign handler wired — install via AegisMessageRuntime`,\n 'warn',\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 /**\n * Navigate to a campaign CTA URL.\n *\n * Dispatches a cancellable `aegis:campaign-click` CustomEvent so host\n * apps (e.g., the storefront SPA) can intercept and route in-place via\n * their client-side router, avoiding a full page reload that re-runs\n * SSR + re-renders the location picker / banner / cart drawer state.\n *\n * The host calls `event.preventDefault()` to suppress the hard nav and\n * handle the URL itself. If no listener calls preventDefault, the SDK\n * falls through to `window.location.href` so plain HTML pages without a\n * SPA still get the user to the destination.\n *\n * Industry parallel: CleverTap dispatches `clevertap-deeplink-click`,\n * MoEngage dispatches `MoE_inappRedirect`. The pattern lets the same\n * SDK serve both vanilla websites (full nav fallback) and SPAs\n * (in-place state change) without per-host configuration.\n */\n private navigateToCampaignAction(campaign: InAppCampaign, safeUrl: string): void {\n if (typeof window === 'undefined') return;\n const event = new CustomEvent('aegis:campaign-click', {\n detail: {\n campaign_id: campaign.id,\n campaign_type: campaign.type,\n action_url: safeUrl,\n },\n cancelable: true,\n });\n const proceeded = window.dispatchEvent(event);\n if (proceeded && !event.defaultPrevented) {\n window.location.href = safeUrl;\n }\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 this.navigateToCampaignAction(campaign, 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 this.navigateToCampaignAction(campaign, 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 this.navigateToCampaignAction(campaign, 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 this.navigateToCampaignAction(campaign, 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 this.navigateToCampaignAction(campaign, 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 /* Bottom-anchored slide IN (opposite of aegisSlideUp which slides OUT).\n Used by the preload-first renderers: sticky_bar (bottom),\n progress_bar, carousel_cards, product_recommendation. */\n @keyframes aegisSlideInFromBottom {\n from { transform: translateY(100%); opacity: 0; }\n to { transform: translateY(0); 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 // Use the public SDK scheme (/v1/in_app/events) — the gateway has an\n // explicit handler that auths via X-Aegis-Write-Key and forwards to\n // event-switchboard. Direct POST to /api/v1/events bypasses the SDK\n // auth model and hits the JWT preHandler → 401.\n // See docs/architecture/API_ROUTING.md §5.\n const url = `${this.apiHost}/v1/in_app/events`;\n const externalEventId = `inapp_${campaignId}_${eventType}_${Date.now()}`;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-Aegis-Write-Key': this.writeKey,\n };\n if (this.organizationId) headers['X-Organization-ID'] = this.organizationId;\n if (this.userId) headers['X-User-ID'] = this.userId;\n if (this.contactId) headers['X-Contact-ID'] = this.contactId;\n\n const body = {\n campaign_id: campaignId,\n event_type: eventType,\n user_id: this.userId,\n contact_id: this.contactId,\n anonymous_id: this.userId,\n platform: 'web',\n metadata: {\n property_id: this.propertyId,\n variant_id: this.getVariantId(campaignId) ?? undefined,\n },\n idempotency_key: externalEventId,\n };\n\n fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n credentials: 'include',\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 if (typeof document !== 'undefined') {\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\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 * renderPreview — Static Preview Renderer for Dashboard iframe (Critical Fix A)\n *\n * Used exclusively by the sandboxed iframe preview route\n * (`/api/preview/in-app/route.tsx`). Renders a single campaign into the\n * current document body using the same rendering logic as the production SDK.\n *\n * Data flow:\n * editor-sidebar.tsx → onChange → formState → postMessage({type:'preview_update', config})\n * → iframe receives message → calls renderPreview(config)\n *\n * This ensures 100% fidelity between the dashboard editor preview and\n * production rendering — both use the same SDK code.\n */\n\nimport type { InAppCampaign } from './AegisInAppManager';\nimport { AegisInAppManager } from './AegisInAppManager';\n\n/**\n * Renders a single in-app campaign into the current document for preview.\n *\n * Creates a temporary AegisInAppManager with preview-only config (no tracking,\n * no SSE, no network requests). Calls the same rendering pipeline as production.\n */\nexport function renderPreview(config: InAppCampaign & { interactive_config?: Record<string, unknown> }): void {\n // Clear previous preview\n document.querySelectorAll(\n '[class^=\"aegis-in-app-\"]'\n ).forEach((el) => {\n if (el.parentNode) {\n el.parentNode.removeChild(el);\n }\n });\n\n if (!config) return;\n\n // Create a lightweight preview-only manager\n const manager = new AegisInAppManager({\n writeKey: 'preview-mode',\n apiHost: '',\n debugMode: false,\n enableSSE: false,\n });\n\n // Override trackEvent to be a no-op in preview mode\n // Access private via any cast — preview only, not production code\n const m = manager as unknown as {\n displayCampaign: (campaign: InAppCampaign) => void;\n trackEvent: (campaignId: string, eventType: string) => Promise<void>;\n addAnimationStyles: () => void;\n };\n\n // No-op tracking for preview\n m.trackEvent = async () => {};\n\n // Ensure animation styles are injected\n m.addAnimationStyles();\n\n // Render the campaign\n m.displayCampaign(config);\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 DOMPurify (when available) with allowlisted tags/attrs; safe text-only fallback\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 // Use DOMPurify if available (recommended for production)\n const purify = (window as unknown as Record<string, unknown>).DOMPurify as\n | { sanitize: (dirty: string, cfg?: Record<string, unknown>) => string }\n | undefined;\n\n if (purify?.sanitize) {\n return purify.sanitize(html, {\n ALLOWED_TAGS: [\n 'a', 'b', 'br', 'div', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'i', 'img', 'li', 'ol', 'p', 'span', 'strong', 'u', 'ul', 'table',\n 'thead', 'tbody', 'tr', 'th', 'td', 'blockquote', 'hr', 'figure',\n 'figcaption', 'picture', 'source', 'video', 'section', 'article',\n ],\n ALLOWED_ATTR: [\n 'href', 'target', 'rel', 'src', 'alt', 'width', 'height', 'class',\n 'id', 'style', 'title', 'loading', 'srcset', 'sizes', 'type',\n 'media', 'controls', 'poster',\n ],\n ALLOW_DATA_ATTR: false,\n });\n }\n\n // Built-in fallback: strip all tags via DOM parsing, then re-allow safe subset\n this.log(\n 'DOMPurify not found — falling back to built-in sanitizer. ' +\n 'For full HTML placement support, add <script src=\"https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.2.4/purify.min.js\"></script>',\n false\n );\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 * 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","/**\n * SDK Config Poller\n *\n * Fetches non-sensitive SDK configuration from GET /v1/sdk/config\n * with ETag/If-None-Match support for 304 responses.\n *\n * Polls every 5 minutes by default. Config changes are applied\n * to push/in-app managers without re-initialization.\n */\n\nimport { logger } from '../utils/logger';\n\nexport interface SdkConfig {\n version: string;\n push: {\n enabled: boolean;\n vapid_public_key: string | null;\n platforms: string[];\n };\n in_app: {\n enabled: boolean;\n };\n consent: {\n channels_requiring_opt_in: string[];\n };\n}\n\nexport interface SdkConfigPollerOptions {\n apiHost: string;\n writeKey: string;\n organizationId?: string;\n pollIntervalMs?: number;\n}\n\nexport type ConfigChangeCallback = (config: SdkConfig) => void;\n\nexport class SdkConfigPoller {\n private options: Required<Omit<SdkConfigPollerOptions, 'organizationId'>> & { organizationId?: string };\n private currentETag: string | null = null;\n private currentConfig: SdkConfig | null = null;\n private pollTimer: ReturnType<typeof setInterval> | null = null;\n private listeners: ConfigChangeCallback[] = [];\n\n constructor(options: SdkConfigPollerOptions) {\n this.options = {\n pollIntervalMs: 300_000, // 5 minutes\n ...options,\n };\n }\n\n /**\n * Fetch config once (on init) and start polling.\n */\n async start(): Promise<SdkConfig | null> {\n const config = await this.fetchConfig();\n\n this.pollTimer = setInterval(() => {\n this.fetchConfig().catch((err) => {\n logger.warn('SDK config poll failed:', err);\n });\n }, this.options.pollIntervalMs);\n\n return config;\n }\n\n /**\n * Stop polling.\n */\n stop(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n }\n\n /**\n * Register a callback for config changes.\n */\n onChange(callback: ConfigChangeCallback): () => void {\n this.listeners.push(callback);\n return () => {\n const idx = this.listeners.indexOf(callback);\n if (idx >= 0) this.listeners.splice(idx, 1);\n };\n }\n\n /**\n * Get current cached config.\n */\n getConfig(): SdkConfig | null {\n return this.currentConfig;\n }\n\n /**\n * Fetch config with ETag/304 support.\n */\n private async fetchConfig(): Promise<SdkConfig | null> {\n try {\n const headers: Record<string, string> = {\n 'X-Aegis-Write-Key': this.options.writeKey,\n 'Accept': 'application/json',\n };\n\n if (this.options.organizationId) {\n headers['X-Organization-ID'] = this.options.organizationId;\n }\n\n if (this.currentETag) {\n headers['If-None-Match'] = this.currentETag;\n }\n\n const response = await fetch(`${this.options.apiHost}/v1/sdk/config`, {\n method: 'GET',\n headers,\n });\n\n // 304 Not Modified — config unchanged\n if (response.status === 304) {\n return this.currentConfig;\n }\n\n if (!response.ok) {\n logger.warn(`SDK config fetch failed: HTTP ${response.status}`);\n return this.currentConfig;\n }\n\n const config: SdkConfig = await response.json();\n const newETag = response.headers.get('ETag');\n\n if (newETag) {\n this.currentETag = newETag;\n }\n\n // Detect changes\n const changed = !this.currentConfig ||\n JSON.stringify(this.currentConfig) !== JSON.stringify(config);\n\n this.currentConfig = config;\n\n if (changed) {\n for (const listener of this.listeners) {\n try {\n listener(config);\n } catch (err) {\n logger.warn('SDK config change listener error:', err);\n }\n }\n }\n\n return config;\n } catch (err) {\n logger.warn('SDK config fetch error:', err);\n return this.currentConfig;\n }\n }\n}\n","/**\n * PrefetchBundleClient — unified init-time resolver for in-app state.\n *\n * Fetches /v1/sdk/prefetch-bundle at SDK init and on a 5-minute ETag\n * refresh cadence. The bundle payload carries:\n * • `campaigns[]` — eligible, property-scoped, A/B-assigned campaigns\n * armed for this contact. EVERY in-app type is in\n * here (modal, banner, spin_wheel, carousel_cards,\n * sticky_bar, progress_bar, coachmark_tour, etc.).\n * • `inbox` — first page + unread count for the notification\n * drawer; lets AegisInbox hydrate without a second\n * round-trip.\n * • `etag` — content-hashed, stable when state is unchanged;\n * 304 responses cost ~50ms and consume no body.\n * • `invalidation_topic` — SSE channel name the cell-plane publishes\n * to when a playbook arms a campaign mid-session.\n * The SDK does NOT open SSE on that topic today —\n * we rely on the 5-minute poll + an explicit\n * `refresh()` hook that app code (AegisInAppManager,\n * AegisInbox) call on relevant user actions.\n *\n * This is the cornerstone of the preload-first contract from\n * docs/architecture/IN_APP_MESSAGES_EXPANSION_PLAN.md §1. The render\n * path must NEVER hit the network at trigger time — the bundle is\n * populated at init, and everything renders from memory.\n */\n\nimport { logger } from '../utils/logger';\n\nexport interface PrefetchBundleCampaign {\n id: string;\n type: string;\n sub_type?: string;\n title: string;\n body: string;\n image_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 | null;\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 inbox_enabled?: boolean;\n}\n\nexport interface PrefetchBundleInboxEntry {\n id: string;\n source: string;\n campaign_id: string | null;\n title: string;\n body: string;\n media_url: string | null;\n cta_url: string | null;\n metadata: Record<string, unknown> | null;\n read: boolean;\n read_at: string | null;\n created_at: string | null;\n expires_at: string | null;\n}\n\nexport interface PrefetchBundleInbox {\n unread_count: number;\n page: PrefetchBundleInboxEntry[];\n cursor: string | null;\n}\n\nexport interface PrefetchBundle {\n etag: string;\n generated_at: string;\n ttl_seconds: number;\n invalidation_topic: string;\n campaigns: PrefetchBundleCampaign[];\n inbox: PrefetchBundleInbox;\n}\n\nexport interface PrefetchBundleContext {\n device_type?: string;\n page_url?: string;\n geo?: string;\n is_new_user?: boolean;\n}\n\nexport interface PrefetchBundleClientOptions {\n apiHost: string;\n writeKey: string;\n organizationId?: string;\n contactId?: string;\n userId?: string;\n propertyId?: string;\n /** Cached AB assignments from localStorage, base64-json. */\n abAssignments?: Record<string, string>;\n /** Polling cadence; defaults to the bundle's own `ttl_seconds` (300s). */\n pollIntervalMs?: number;\n /** Factory for client context — re-evaluated on each fetch so device/page\n * state stays fresh without forcing callers to re-instantiate the client. */\n contextProvider?: () => PrefetchBundleContext;\n}\n\nexport type PrefetchBundleListener = (bundle: PrefetchBundle) => void;\n\nconst DEFAULT_POLL_MS = 300_000; // 5 minutes — aligns with cell-plane TTL\n\nexport class PrefetchBundleClient {\n private apiHost: string;\n private writeKey: string;\n private organizationId?: string;\n private contactId?: string;\n private userId?: string;\n private propertyId?: string;\n private abAssignments: Record<string, string>;\n private pollIntervalMs: number;\n private contextProvider: () => PrefetchBundleContext;\n\n private currentETag: string | null = null;\n private currentBundle: PrefetchBundle | null = null;\n private pollTimer: ReturnType<typeof setInterval> | null = null;\n private listeners: PrefetchBundleListener[] = [];\n private inflightRefetch: Promise<PrefetchBundle | null> | null = null;\n\n constructor(options: PrefetchBundleClientOptions) {\n this.apiHost = options.apiHost;\n this.writeKey = options.writeKey;\n this.organizationId = options.organizationId;\n this.contactId = options.contactId;\n this.userId = options.userId;\n this.propertyId = options.propertyId;\n this.abAssignments = options.abAssignments ?? {};\n this.pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_MS;\n this.contextProvider = options.contextProvider ?? (() => ({}));\n }\n\n /**\n * Initial fetch + start the background ETag poll. Resolves to the bundle\n * (or `null` if the first fetch failed — callers should fall back to an\n * empty campaign list, not abort SDK init).\n */\n async start(): Promise<PrefetchBundle | null> {\n const bundle = await this.fetch();\n this.pollTimer = setInterval(() => {\n this.fetch().catch((err) => logger.warn('prefetch-bundle poll failed:', err));\n }, this.pollIntervalMs);\n return bundle;\n }\n\n stop(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n }\n\n getBundle(): PrefetchBundle | null {\n return this.currentBundle;\n }\n\n getCampaigns(): PrefetchBundleCampaign[] {\n return this.currentBundle?.campaigns ?? [];\n }\n\n getInbox(): PrefetchBundleInbox {\n return this.currentBundle?.inbox ?? { unread_count: 0, page: [], cursor: null };\n }\n\n /** Force a refresh (dedupes concurrent calls). Exposed so inbox mutations\n * and campaign-activation SSE messages can trigger a refetch on demand. */\n async refresh(): Promise<PrefetchBundle | null> {\n if (this.inflightRefetch) return this.inflightRefetch;\n this.inflightRefetch = this.fetch();\n try {\n return await this.inflightRefetch;\n } finally {\n this.inflightRefetch = null;\n }\n }\n\n /** Subscribe to bundle changes (emits on first fetch + on any content\n * change — ETag 304 does NOT fire the listener). Returns an unsubscribe. */\n onChange(listener: PrefetchBundleListener): () => void {\n this.listeners.push(listener);\n return () => {\n const idx = this.listeners.indexOf(listener);\n if (idx >= 0) this.listeners.splice(idx, 1);\n };\n }\n\n /**\n * Update the identity tuple — called by AegisInAppManager when the host\n * app resolves a contactId post-init (e.g., after login). Triggers an\n * immediate refresh since the eligible campaigns + inbox will differ.\n */\n updateIdentity(partial: {\n contactId?: string;\n userId?: string;\n organizationId?: string;\n propertyId?: string;\n }): void {\n let changed = false;\n if (partial.contactId !== undefined && partial.contactId !== this.contactId) {\n this.contactId = partial.contactId;\n changed = true;\n }\n if (partial.userId !== undefined && partial.userId !== this.userId) {\n this.userId = partial.userId;\n changed = true;\n }\n if (\n partial.organizationId !== undefined &&\n partial.organizationId !== this.organizationId\n ) {\n this.organizationId = partial.organizationId;\n changed = true;\n }\n if (partial.propertyId !== undefined && partial.propertyId !== this.propertyId) {\n this.propertyId = partial.propertyId;\n changed = true;\n }\n if (changed) {\n // Identity change invalidates ETag — drop the cached tag so the next\n // fetch gets a fresh payload instead of a 304 bound to the old identity.\n this.currentETag = null;\n this.refresh().catch((err) =>\n logger.warn('prefetch-bundle identity-refresh failed:', err),\n );\n }\n }\n\n /** Update cached AB assignments. Called by downstream renderers after\n * they display a variant. Persisted to localStorage by higher layers. */\n setAbAssignments(assignments: Record<string, string>): void {\n this.abAssignments = { ...assignments };\n }\n\n /**\n * Wire an already-open realtime subscriber (from `aegis.realtime.subscribe`\n * or a caller-provided EventSource) so the prefetch bundle refreshes\n * instantly when the cell-plane signals `bundle.invalidate` — covering\n * the window between an event (cart abandon, inbox write) and the\n * 5-min ETag poll.\n *\n * `subscriber.onMessage(handler)` must fire with parsed message bodies\n * from the contact's SSE stream. The handler filters for\n * `type === 'bundle.invalidate'` and calls `refresh()`. Returns an\n * unsubscribe function.\n *\n * Degrades gracefully: if the subscriber is missing or throws, the\n * 5-min poll still keeps state converging.\n */\n subscribeInvalidations(subscriber: {\n onMessage: (handler: (msg: { type?: string; [k: string]: unknown }) => void) => () => void;\n }): () => void {\n try {\n const unsub = subscriber.onMessage((msg) => {\n if (msg && msg.type === 'bundle.invalidate') {\n this.refresh().catch((err) =>\n logger.warn('prefetch-bundle invalidate-refresh failed:', err),\n );\n }\n });\n return unsub;\n } catch (err) {\n logger.warn('prefetch-bundle subscribeInvalidations failed — relying on poll:', err);\n return () => {};\n }\n }\n\n // ── internals ──────────────────────────────────────────────────────────\n\n private async fetch(): Promise<PrefetchBundle | null> {\n const ctx = this.contextProvider();\n const qs = new URLSearchParams();\n if (ctx.device_type) qs.set('device_type', ctx.device_type);\n if (ctx.page_url) qs.set('page_url', ctx.page_url);\n if (ctx.geo) qs.set('geo', ctx.geo);\n qs.set('is_new_user', ctx.is_new_user ? 'true' : 'false');\n\n const url = `${this.apiHost}/v1/sdk/prefetch-bundle?${qs.toString()}`;\n\n const headers: Record<string, string> = {\n 'X-Aegis-Write-Key': this.writeKey,\n Accept: 'application/json',\n };\n if (this.organizationId) headers['X-Organization-ID'] = this.organizationId;\n if (this.contactId) headers['X-Contact-ID'] = this.contactId;\n if (this.userId) headers['X-User-ID'] = this.userId;\n if (this.propertyId) headers['X-Property-Id'] = this.propertyId;\n if (this.currentETag) headers['If-None-Match'] = this.currentETag;\n if (Object.keys(this.abAssignments).length > 0) {\n try {\n headers['X-AB-Assignments'] = btoa(JSON.stringify(this.abAssignments));\n } catch {\n // base64 on non-ASCII campaign IDs — skip rather than 400 the request\n }\n }\n\n let response: Response;\n try {\n response = await fetch(url, { method: 'GET', headers });\n } catch (err) {\n logger.warn('prefetch-bundle fetch network error:', err);\n return this.currentBundle;\n }\n\n // 304 — same bundle; listeners are intentionally NOT fired.\n if (response.status === 304) {\n return this.currentBundle;\n }\n\n if (!response.ok) {\n logger.warn(`prefetch-bundle fetch failed: HTTP ${response.status}`);\n return this.currentBundle;\n }\n\n const etag = response.headers.get('ETag');\n let bundle: PrefetchBundle;\n try {\n bundle = (await response.json()) as PrefetchBundle;\n } catch (err) {\n logger.warn('prefetch-bundle invalid JSON:', err);\n return this.currentBundle;\n }\n\n if (etag) this.currentETag = etag;\n this.currentBundle = bundle;\n\n for (const l of this.listeners) {\n try {\n l(bundle);\n } catch (err) {\n logger.warn('prefetch-bundle listener threw:', err);\n }\n }\n\n return bundle;\n }\n}\n","/**\n * AegisInbox — client-side App Inbox (Message Center).\n *\n * Backs the notification drawer on actii.me WebView and every tenant\n * storefront that embeds the Web SDK. Operates against cell-plane's\n * /v1/in-app/inbox family of endpoints (list, unread-count, read,\n * dismiss, read-all).\n *\n * Design choices:\n * • Hydrate from the prefetch bundle at init — no extra HTTP on first\n * paint. PrefetchBundleClient seeds us; we then own the live copy.\n * • Mutations are optimistic + beacon-backed. Read / dismiss writes to\n * local state immediately, then POSTs with `keepalive: true` so an\n * in-flight dismiss survives page unload.\n * • Badge polling uses the tiny `/unread-count` endpoint on a 60-second\n * cadence — matches the `inbox_poll_interval_ms` from sdk_config's\n * TransportConfig.hybrid mode.\n * • No external dependencies; IndexedDB is optional (we gracefully fall\n * back to in-memory when unavailable, e.g., in private browsing).\n */\n\nimport type { PrefetchBundleClient } from '../core/prefetch-bundle-client';\nimport { logger } from '../utils/logger';\n\nexport interface AegisInboxEntry {\n id: string;\n source: string;\n campaign_id: string | null;\n title: string;\n body: string;\n media_url: string | null;\n cta_url: string | null;\n metadata: Record<string, unknown> | null;\n read: boolean;\n read_at: string | null;\n dismissed_at?: string | null;\n created_at: string | null;\n expires_at: string | null;\n}\n\nexport interface AegisInboxConfig {\n apiHost: string;\n writeKey: string;\n organizationId?: string;\n contactId?: string;\n propertyId?: string;\n bundleClient?: PrefetchBundleClient;\n unreadPollIntervalMs?: number;\n}\n\nexport type InboxListener = (state: { entries: AegisInboxEntry[]; unreadCount: number }) => void;\n\nconst DEFAULT_UNREAD_POLL = 60_000;\n\n/** IndexedDB schema version + constants. Offline cache is a nice-to-have,\n * so we never break the app if IDB operations fail. */\nconst IDB_NAME = 'aegis-inbox';\nconst IDB_STORE = 'messages';\nconst IDB_VERSION = 1;\n\nexport class AegisInbox {\n private apiHost: string;\n private writeKey: string;\n private organizationId?: string;\n private contactId?: string;\n private propertyId?: string;\n private bundleClient?: PrefetchBundleClient;\n private unreadPollIntervalMs: number;\n\n private entries: AegisInboxEntry[] = [];\n private unreadCount = 0;\n private cursor: string | null = null;\n private listeners: InboxListener[] = [];\n private pollTimer: ReturnType<typeof setInterval> | null = null;\n private bundleUnsub: (() => void) | null = null;\n\n constructor(config: AegisInboxConfig) {\n this.apiHost = config.apiHost;\n this.writeKey = config.writeKey;\n this.organizationId = config.organizationId;\n this.contactId = config.contactId;\n this.propertyId = config.propertyId;\n this.bundleClient = config.bundleClient;\n this.unreadPollIntervalMs = config.unreadPollIntervalMs ?? DEFAULT_UNREAD_POLL;\n }\n\n /** Hydrate from bundle (if available), restore the IDB cache (if any),\n * then start the background unread-count poll. */\n async initialize(): Promise<void> {\n // Inbox is contact-scoped — if the host app hasn't resolved a contact\n // yet, stay dormant. The host will call setIdentity() later.\n if (!this.contactId || !this.propertyId) {\n logger.warn('AegisInbox: no contact/property yet — staying dormant');\n return;\n }\n\n // Try IDB cache for instant paint on cold start.\n const cached = await this.readCache();\n if (cached.length > 0) {\n this.entries = cached;\n this.recomputeUnread();\n this.emit();\n }\n\n // Hydrate from prefetch bundle if we have one — this is the preload\n // path, no additional network round-trip.\n if (this.bundleClient) {\n const inbox = this.bundleClient.getInbox();\n this.seedFromBundle(inbox.page, inbox.unread_count);\n // Keep following bundle changes — when the bundle-poller refreshes,\n // the inbox slice refreshes too.\n this.bundleUnsub = this.bundleClient.onChange((bundle) => {\n this.seedFromBundle(bundle.inbox.page, bundle.inbox.unread_count);\n });\n } else {\n // No bundle client — do one list call to prime.\n await this.refreshList();\n }\n\n this.pollTimer = setInterval(() => {\n this.refreshUnreadCount().catch((err) =>\n logger.warn('inbox unread-count poll failed:', err),\n );\n }, this.unreadPollIntervalMs);\n }\n\n stop(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n if (this.bundleUnsub) {\n this.bundleUnsub();\n this.bundleUnsub = null;\n }\n }\n\n /** Update identity after login / property switch. Clears the local\n * inbox since it's intrinsically contact+property scoped. */\n setIdentity(partial: { contactId?: string; propertyId?: string; organizationId?: string }): void {\n let changed = false;\n if (partial.contactId !== undefined && partial.contactId !== this.contactId) {\n this.contactId = partial.contactId;\n changed = true;\n }\n if (partial.propertyId !== undefined && partial.propertyId !== this.propertyId) {\n this.propertyId = partial.propertyId;\n changed = true;\n }\n if (partial.organizationId !== undefined && partial.organizationId !== this.organizationId) {\n this.organizationId = partial.organizationId;\n changed = true;\n }\n if (changed) {\n this.entries = [];\n this.unreadCount = 0;\n this.cursor = null;\n this.emit();\n void this.clearCache();\n void this.refreshList();\n }\n }\n\n // ── Read-side API ────────────────────────────────────────────────────\n\n getEntries(): AegisInboxEntry[] {\n return this.entries;\n }\n\n getUnreadCount(): number {\n return this.unreadCount;\n }\n\n /** Pagination cursor (ISO-8601 timestamp of the oldest entry currently\n * held). Pass it back via `loadMore()` to fetch older history. */\n getCursor(): string | null {\n return this.cursor;\n }\n\n /** Append one more page of older entries using the current cursor. */\n async loadMore(): Promise<void> {\n if (!this.contactId || !this.propertyId || !this.cursor) return;\n try {\n const url = `${this.apiHost}/v1/in-app/inbox?limit=20&cursor=${encodeURIComponent(this.cursor)}`;\n const resp = await fetch(url, { headers: this.headers() });\n if (!resp.ok) return;\n const body = (await resp.json()) as {\n entries: AegisInboxEntry[];\n unread_count: number;\n cursor: string | null;\n };\n const byId = new Set(this.entries.map((e) => e.id));\n for (const e of body.entries) {\n if (!byId.has(e.id)) this.entries.push(e);\n }\n this.cursor = body.cursor;\n void this.writeCache();\n this.emit();\n } catch (err) {\n logger.warn('inbox loadMore failed:', err);\n }\n }\n\n onChange(l: InboxListener): () => void {\n this.listeners.push(l);\n return () => {\n const i = this.listeners.indexOf(l);\n if (i >= 0) this.listeners.splice(i, 1);\n };\n }\n\n async refreshList(): Promise<void> {\n if (!this.contactId || !this.propertyId) return;\n try {\n const resp = await fetch(\n `${this.apiHost}/v1/in-app/inbox?limit=20`,\n { headers: this.headers() },\n );\n if (!resp.ok) {\n logger.warn(`inbox list fetch failed: HTTP ${resp.status}`);\n return;\n }\n const body = (await resp.json()) as {\n entries: AegisInboxEntry[];\n unread_count: number;\n cursor: string | null;\n };\n this.entries = body.entries;\n this.unreadCount = body.unread_count;\n this.cursor = body.cursor;\n void this.writeCache();\n this.emit();\n } catch (err) {\n logger.warn('inbox list fetch error:', err);\n }\n }\n\n async refreshUnreadCount(): Promise<void> {\n if (!this.contactId || !this.propertyId) return;\n try {\n const resp = await fetch(\n `${this.apiHost}/v1/in-app/inbox/unread-count`,\n { headers: this.headers() },\n );\n if (!resp.ok) return;\n const body = (await resp.json()) as { unread_count: number };\n if (body.unread_count !== this.unreadCount) {\n this.unreadCount = body.unread_count;\n this.emit();\n // New messages detected — do a list refresh to get them.\n if (this.unreadCount > 0) {\n void this.refreshList();\n }\n }\n } catch {\n /* swallow — transient network */\n }\n }\n\n // ── Mutations (optimistic + beacon) ──────────────────────────────────\n\n async markRead(messageId: string): Promise<void> {\n const entry = this.entries.find((e) => e.id === messageId);\n if (!entry || entry.read) return;\n entry.read = true;\n entry.read_at = new Date().toISOString();\n this.recomputeUnread();\n void this.writeCache();\n this.emit();\n await this.postBeacon(`/v1/in-app/inbox/${messageId}/read`);\n }\n\n async dismiss(messageId: string): Promise<void> {\n const idx = this.entries.findIndex((e) => e.id === messageId);\n if (idx < 0) return;\n const [entry] = this.entries.splice(idx, 1);\n if (entry && !entry.read) {\n this.recomputeUnread();\n }\n void this.writeCache();\n this.emit();\n await this.postBeacon(`/v1/in-app/inbox/${messageId}/dismiss`);\n }\n\n async markAllRead(): Promise<void> {\n const now = new Date().toISOString();\n for (const e of this.entries) {\n if (!e.read) {\n e.read = true;\n e.read_at = now;\n }\n }\n this.unreadCount = 0;\n void this.writeCache();\n this.emit();\n await this.postBeacon('/v1/in-app/inbox/read-all');\n }\n\n // ── Internals ────────────────────────────────────────────────────────\n\n private seedFromBundle(page: AegisInboxEntry[], unreadCount: number): void {\n // Merge rather than overwrite — an entry we already marked read\n // locally should stay read even if the bundle is slightly stale.\n const byId = new Map(this.entries.map((e) => [e.id, e] as const));\n const merged = page.map((incoming) => {\n const existing = byId.get(incoming.id);\n if (existing && existing.read && !incoming.read) {\n return { ...incoming, read: true, read_at: existing.read_at };\n }\n return incoming;\n });\n // Preserve any locally-cached entries that aren't in this bundle page\n // (e.g., older history not included in the first slice).\n for (const [id, e] of byId) {\n if (!merged.find((m) => m.id === id)) merged.push(e);\n }\n merged.sort((a, b) => (b.created_at || '').localeCompare(a.created_at || ''));\n this.entries = merged;\n this.unreadCount = unreadCount;\n void this.writeCache();\n this.emit();\n }\n\n private recomputeUnread(): void {\n this.unreadCount = this.entries.filter((e) => !e.read).length;\n }\n\n private emit(): void {\n const snapshot = { entries: [...this.entries], unreadCount: this.unreadCount };\n for (const l of this.listeners) {\n try {\n l(snapshot);\n } catch (err) {\n logger.warn('inbox listener threw:', err);\n }\n }\n }\n\n private headers(): Record<string, string> {\n const h: Record<string, string> = {\n 'X-Aegis-Write-Key': this.writeKey,\n Accept: 'application/json',\n };\n if (this.organizationId) h['X-Organization-ID'] = this.organizationId;\n if (this.contactId) h['X-Contact-ID'] = this.contactId;\n if (this.propertyId) h['X-Property-Id'] = this.propertyId;\n return h;\n }\n\n /** Best-effort beacon-style POST. Uses `keepalive: true` so it survives\n * a navigation away from the current page (e.g., user taps the CTA\n * which takes them to another URL right after dismiss). */\n private async postBeacon(path: string): Promise<void> {\n if (!this.contactId || !this.propertyId) return;\n try {\n await fetch(`${this.apiHost}${path}`, {\n method: 'POST',\n headers: this.headers(),\n keepalive: true,\n });\n } catch (err) {\n // The mutation is already applied locally; failed delivery will be\n // reconciled on the next refreshList().\n logger.warn(`inbox mutation POST ${path} failed:`, err);\n }\n }\n\n // ── IndexedDB cache (non-critical) ───────────────────────────────────\n\n private async openDb(): Promise<IDBDatabase | null> {\n if (typeof indexedDB === 'undefined') return null;\n return new Promise((resolve) => {\n try {\n const req = indexedDB.open(IDB_NAME, IDB_VERSION);\n req.onerror = () => resolve(null);\n req.onupgradeneeded = () => {\n const db = req.result;\n if (!db.objectStoreNames.contains(IDB_STORE)) {\n db.createObjectStore(IDB_STORE);\n }\n };\n req.onsuccess = () => resolve(req.result);\n } catch {\n resolve(null);\n }\n });\n }\n\n private cacheKey(): string | null {\n if (!this.contactId || !this.propertyId) return null;\n return `${this.organizationId || 'default'}:${this.propertyId}:${this.contactId}`;\n }\n\n private async writeCache(): Promise<void> {\n const key = this.cacheKey();\n if (!key) return;\n const db = await this.openDb();\n if (!db) return;\n try {\n const tx = db.transaction(IDB_STORE, 'readwrite');\n tx.objectStore(IDB_STORE).put(this.entries, key);\n await new Promise<void>((res, rej) => {\n tx.oncomplete = () => res();\n tx.onerror = () => rej(tx.error);\n });\n } catch {\n /* noop */\n } finally {\n db.close();\n }\n }\n\n private async readCache(): Promise<AegisInboxEntry[]> {\n const key = this.cacheKey();\n if (!key) return [];\n const db = await this.openDb();\n if (!db) return [];\n try {\n const tx = db.transaction(IDB_STORE, 'readonly');\n const req = tx.objectStore(IDB_STORE).get(key);\n return await new Promise<AegisInboxEntry[]>((res) => {\n req.onsuccess = () => res((req.result as AegisInboxEntry[]) || []);\n req.onerror = () => res([]);\n });\n } catch {\n return [];\n } finally {\n db.close();\n }\n }\n\n private async clearCache(): Promise<void> {\n const key = this.cacheKey();\n if (!key) return;\n const db = await this.openDb();\n if (!db) return;\n try {\n const tx = db.transaction(IDB_STORE, 'readwrite');\n tx.objectStore(IDB_STORE).delete(key);\n await new Promise<void>((res) => {\n tx.oncomplete = () => res();\n tx.onerror = () => res();\n });\n } catch {\n /* noop */\n } finally {\n db.close();\n }\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';\nimport { Storage } from '../utils/storage';\n\n// Read the SDK's persisted anonymous_id from localStorage/cookie if available.\n// Returns undefined when called server-side or when no id has been minted yet.\n// See AegisInAppManager for the same pattern + canonical contract in\n// docs/architecture/API_ROUTING.md §3.\nfunction readAnonIdFromStorage(): string | undefined {\n if (typeof document === 'undefined') return undefined;\n try {\n const storage = new Storage();\n return storage.get('anon_id') ?? undefined;\n } catch {\n return undefined;\n }\n}\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 /** If true, WidgetManager takes ownership of the TriggerEngine and\n * will call `triggerEngine.stop()` on destroy(). Leave false when\n * the caller shares the engine across managers (e.g. the facade). */\n ownsTriggerEngine?: boolean;\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 private isDestroyed = false;\n private ownsTriggerEngine: boolean;\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 // Fall back to the SDK's persisted anonymous_id when callers don't pass\n // userId explicitly. Without this, /v1/widgets/config requests omit\n // X-User-ID and the cell-plane buckets the call into \"anonymous\", which\n // misses any user-targeted widget configs. Mirror in AegisInAppManager.\n this.userId = config.userId ?? readAnonIdFromStorage();\n this.contactId = config.contactId;\n this.organizationId = config.organizationId;\n this.debugMode = config.debugMode || false;\n this.triggerEngine = config.triggerEngine;\n this.ownsTriggerEngine = config.ownsTriggerEngine === true;\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 /**\n * Swap the identity that outgoing widget requests are attributed to.\n * Safe to call at any time; if prefetch is enabled and the manager\n * has already initialised, this will re-fetch the per-contact widget\n * configs so subsequent renders target the new identity. Does NOT\n * re-render already-visible widgets — a full teardown requires destroy().\n */\n async updateContactId(contactId: string | undefined): Promise<void> {\n if (this.contactId === contactId) return;\n this.contactId = contactId;\n this.log(`Contact ID updated → ${contactId ?? '(cleared)'}`);\n if (this.isInitialized && !this.isDestroyed && this.enablePrefetch && contactId) {\n await this.fetchPrefetchConfigs();\n this.preloadWidgetAssets();\n }\n }\n\n /**\n * Render an in-app campaign whose sub_type routes it to the\n * gamification-widget code path (spin_wheel / scratch_card).\n * InAppCampaign is adapted to the minimal WidgetConfig shape that\n * the internal renderers already understand — no rewrite needed.\n *\n * AegisMessageRuntime wires this method as AegisInAppManager's\n * `onInteractiveCampaign` callback so impressions from the inbox\n * prefetch bundle actually land on screen.\n */\n renderInteractiveCampaign(campaign: {\n id: string;\n title: string;\n sub_type?: string;\n priority?: number;\n interactive_config?: Record<string, unknown>;\n }): void {\n if (this.isDestroyed) return;\n if (typeof document === 'undefined') return;\n const subType = campaign.sub_type;\n if (subType !== 'spin_wheel' && subType !== 'scratch_card') {\n this.log(`renderInteractiveCampaign: unsupported sub_type \"${subType}\"`, true);\n return;\n }\n const widget: WidgetConfig = {\n widget_id: campaign.id,\n widget_type: subType,\n name: campaign.title,\n config: (campaign.interactive_config ?? {}) as Record<string, any>,\n priority: campaign.priority ?? 0,\n };\n if (this.renderedWidgets.has(widget.widget_id)) return;\n this.renderedWidgets.add(widget.widget_id);\n if (subType === 'spin_wheel') {\n this.renderSpinWheel(widget);\n } else {\n this.renderScratchCard(widget);\n }\n }\n\n /**\n * Tear down everything the manager installed: trigger listeners (if\n * we own the TriggerEngine), injected style sheets, and any rendered\n * widget roots. Further render attempts from in-flight triggers are\n * short-circuited by the `isDestroyed` flag.\n */\n destroy(): void {\n if (this.isDestroyed) return;\n this.isDestroyed = true;\n\n if (this.triggerEngine && this.ownsTriggerEngine) {\n this.triggerEngine.stop();\n }\n\n if (typeof document !== 'undefined') {\n const animationStyle = document.getElementById('aegis-widget-animations');\n animationStyle?.remove();\n document.querySelectorAll('[data-aegis-widget-root]').forEach((node) => {\n node.remove();\n });\n }\n\n this.renderedWidgets.clear();\n this.widgets = [];\n this.isInitialized = false;\n this.log('AegisWidgets destroyed');\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, credentials: 'include' });\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, credentials: 'include' });\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 credentials: 'include',\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.isDestroyed) return;\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 bubble.setAttribute('data-aegis-widget-root', '');\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 // Draw an SVG wheel that honours the tenant's configured segments.\n // Each segment's `color` + `label` is painted as a pie slice; falls\n // back to a 4-color placeholder if no segments are provided.\n const segments: Array<{ label: string; color?: string }> = Array.isArray(\n (widget.config as any).segments,\n )\n ? (widget.config as any).segments\n : [\n { label: 'Prize 1', color: '#ff6b6b' },\n { label: 'Prize 2', color: '#feca57' },\n { label: 'Prize 3', color: '#48dbfb' },\n { label: 'Prize 4', color: '#ff6348' },\n ];\n\n const SVG_NS = 'http://www.w3.org/2000/svg';\n const wheel = document.createElementNS(SVG_NS, 'svg');\n wheel.setAttribute('viewBox', '-160 -160 320 320');\n wheel.setAttribute('width', '300');\n wheel.setAttribute('height', '300');\n wheel.style.cssText = 'margin: 0 auto 24px; display: block;';\n\n const n = segments.length;\n const anglePer = (2 * Math.PI) / n;\n const radius = 140;\n for (let i = 0; i < n; i++) {\n const start = i * anglePer - Math.PI / 2;\n const end = start + anglePer;\n const x1 = Math.cos(start) * radius;\n const y1 = Math.sin(start) * radius;\n const x2 = Math.cos(end) * radius;\n const y2 = Math.sin(end) * radius;\n const largeArc = anglePer > Math.PI ? 1 : 0;\n const path = document.createElementNS(SVG_NS, 'path');\n path.setAttribute(\n 'd',\n `M 0 0 L ${x1.toFixed(2)} ${y1.toFixed(2)} A ${radius} ${radius} 0 ${largeArc} 1 ${x2.toFixed(2)} ${y2.toFixed(2)} Z`,\n );\n path.setAttribute('fill', this.sanitizeColor(segments[i].color || '#cccccc'));\n path.setAttribute('stroke', '#ffffff');\n path.setAttribute('stroke-width', '2');\n wheel.appendChild(path);\n\n const labelAngle = start + anglePer / 2;\n const lx = Math.cos(labelAngle) * radius * 0.65;\n const ly = Math.sin(labelAngle) * radius * 0.65;\n const text = document.createElementNS(SVG_NS, 'text');\n text.setAttribute('x', lx.toFixed(2));\n text.setAttribute('y', ly.toFixed(2));\n text.setAttribute('fill', '#ffffff');\n text.setAttribute('font-size', '13');\n text.setAttribute('font-weight', '600');\n text.setAttribute('text-anchor', 'middle');\n text.setAttribute('dominant-baseline', 'middle');\n text.textContent = segments[i].label || `#${i + 1}`;\n wheel.appendChild(text);\n }\n modal.appendChild(wheel);\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 wheel.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 overlay.setAttribute('data-aegis-widget-root', '');\n document.body.appendChild(overlay);\n }\n \n private renderSpinWheelWidget(widgetId: string, config: NonNullable<PrefetchWidgetConfig['spin_wheel']>): void {\n if (this.isDestroyed) return;\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 overlay.setAttribute('data-aegis-widget-root', '');\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 credentials: 'include',\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 overlay.setAttribute('data-aegis-widget-root', '');\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 toast.setAttribute('data-aegis-widget-root', '');\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 overlay.setAttribute('data-aegis-widget-root', '');\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 overlay.setAttribute('data-aegis-widget-root', '');\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 credentials: 'include',\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 credentials: 'include',\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 credentials: 'include',\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 if (this.isDestroyed) return;\n const overlay = document.createElement('div');\n overlay.className = 'aegis-exit-popup-overlay';\n overlay.setAttribute('data-widget-id', widgetId);\n overlay.setAttribute('data-aegis-widget-root', '');\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 overlay.setAttribute('data-aegis-widget-root', '');\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 if (this.isDestroyed) return;\n const overlay = document.createElement('div');\n overlay.className = 'aegis-exit-popup-overlay';\n overlay.setAttribute('data-widget-id', widgetId);\n overlay.setAttribute('data-aegis-widget-root', '');\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 overlay.setAttribute('data-aegis-widget-root', '');\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 * AegisMessageRuntime — unified facade for in-app messaging.\n *\n * The sole public entry point for all 20 in-app types (announce +\n * collect + assist buckets) plus the legacy gamification surface\n * (chat_bubble / toast / exit_intent_popup configured via\n * /v1/widgets/config). Under the hood it composes an\n * `AegisInAppManager` + `AegisWidgetManager`; callers never touch them\n * directly.\n *\n * Public API:\n * new AegisMessageRuntime({ writeKey, apiHost, ... })\n * await runtime.initialize()\n * await runtime.updateContactId(id)\n * runtime.onClientEvent(eventName, data)\n * runtime.destroy()\n *\n * Internal wiring: spin_wheel + scratch_card campaigns land in the\n * inbox prefetch bundle but need DOM renderers that live in\n * WidgetManager. The facade passes an `onInteractiveCampaign` callback\n * into the InAppManager constructor; the callback forwards to\n * `widgets.renderInteractiveCampaign(campaign)` — no CustomEvent bus,\n * no listeners, no registration-order bugs.\n */\n\nimport { AegisInAppManager, type AegisInAppConfig, type InAppCampaign } from '../inapp';\nimport { AegisWidgetManager, type AegisWidgetConfig } from '../widgets';\nimport { TriggerEngine } from '../triggers/TriggerEngine';\n\nexport interface AegisMessageRuntimeConfig extends AegisInAppConfig {\n /** If set, a `TriggerEngine` from the SDK is wired to the WidgetManager\n * for its exit-intent / scroll-velocity / inactivity handlers. Leave\n * undefined to have the runtime construct one internally. */\n triggerEngine?: AegisWidgetConfig['triggerEngine'];\n /** WidgetManager prefetch toggle. Defaults to true — matches the\n * existing behaviour where spin_wheel / scratch_card prefetch their\n * configs from `/v1/widgets/config/prefetch`. */\n enableWidgetPrefetch?: boolean;\n /** Source platform for gamification attribution (shopify / woocommerce\n * / magento / mobile_sdk / web). Passed through to WidgetManager. */\n sourcePlatform?: AegisWidgetConfig['sourcePlatform'];\n}\n\n/**\n * One runtime, all in-app types. Consumers should prefer this over\n * importing AegisInAppManager / AegisWidgetManager directly. Those two\n * classes remain exported for a deprecation window — see `./deprecated.ts`.\n */\nexport class AegisMessageRuntime {\n readonly inApp: AegisInAppManager;\n readonly widgets: AegisWidgetManager;\n private initialized = false;\n private ownedTriggerEngine: TriggerEngine | null = null;\n\n constructor(config: AegisMessageRuntimeConfig) {\n const triggerEngine = config.triggerEngine ?? new TriggerEngine();\n const ownsTriggerEngine = !config.triggerEngine;\n if (ownsTriggerEngine) this.ownedTriggerEngine = triggerEngine;\n\n this.widgets = new AegisWidgetManager({\n writeKey: config.writeKey,\n apiHost: config.apiHost,\n userId: config.userId,\n contactId: config.contactId,\n organizationId: config.organizationId,\n debugMode: config.debugMode,\n triggerEngine,\n ownsTriggerEngine,\n enablePrefetch: config.enableWidgetPrefetch !== false,\n sourcePlatform: config.sourcePlatform,\n });\n\n this.inApp = new AegisInAppManager({\n writeKey: config.writeKey,\n apiHost: config.apiHost,\n userId: config.userId,\n contactId: config.contactId,\n organizationId: config.organizationId,\n propertyId: config.propertyId,\n debugMode: config.debugMode,\n enableSSE: config.enableSSE,\n // Route gamification sub_types straight to the widget renderer —\n // replaces the old CustomEvent('aegis:render-widget') bridge which\n // had no listener and silently dropped impressions.\n onInteractiveCampaign: (campaign) => {\n this.widgets.renderInteractiveCampaign(campaign);\n },\n });\n }\n\n /**\n * Boots both managers in parallel. Safe to call multiple times — the\n * second + subsequent calls are no-ops.\n */\n async initialize(): Promise<void> {\n if (this.initialized) return;\n this.initialized = true;\n await Promise.all([\n this.inApp.initialize(),\n this.widgets.initialize(),\n ]);\n }\n\n /**\n * Both managers carry contactId. Updates both so the server-side\n * targeting pipeline sees the identity for campaign eligibility AND\n * the widget prefetch includes per-contact segment configs. The\n * widgets call is async (may re-fetch prefetch configs) but we don't\n * wait — callers that care about the fetched state await on the\n * returned promise.\n */\n async updateContactId(contactId: string): Promise<void> {\n this.inApp.updateContactId?.(contactId);\n await this.widgets.updateContactId(contactId);\n }\n\n /**\n * Forward a client-side event (product_viewed, cart_idle_90s, etc.)\n * to the in-app manager's client-trigger evaluator. The WidgetManager\n * has its own TriggerEngine wiring (exit-intent, scroll-velocity) so\n * we don't forward there — events it cares about arrive through that\n * channel already.\n */\n onClientEvent(eventName: string, eventData: Record<string, unknown> = {}): void {\n this.inApp.onClientEvent?.(eventName, eventData);\n }\n\n /**\n * Conversion-aware suppression — call when the host app observes a\n * goal event (purchase / order_completed / checkout_completed / custom).\n *\n * Forwards to AegisInAppManager.notifyConversion() which:\n * - Persists the conversion in sessionStorage so subsequent page loads\n * in the same tab keep armed campaigns silenced.\n * - For every armed campaign whose\n * `frequency.suppress_after_conversion_seconds` is set, computes an\n * expiry epoch_ms and silences it until then.\n *\n * Storefronts integrate via the React provider's useCommerceEvents\n * helper which calls this after `ecom.orderCompleted(...)`. Direct SDK\n * users call it themselves.\n *\n * Added by Micro-Intent Engine P0a Task 6 (2026-04-30).\n */\n notifyConversion(goalName: string): void {\n this.inApp.notifyConversion?.(goalName);\n }\n\n /**\n * Tear down both managers. Used by React component unmounts + during\n * identity switches where we want a full reset. If the facade created\n * its own TriggerEngine, WidgetManager.destroy() will stop it;\n * caller-supplied engines are left alone.\n */\n destroy(): void {\n this.inApp.destroy?.();\n this.widgets.destroy();\n this.ownedTriggerEngine = null;\n this.initialized = false;\n }\n\n /**\n * Current armed campaigns visible to the InAppManager. Accessible for\n * the Prefetch Inspector and for debugging. WidgetManager's prefetched\n * spin_wheel / scratch_card configs are NOT in this list — they live\n * in `this.widgets` and have their own lifecycle.\n */\n getCampaigns(): InAppCampaign[] {\n // AegisInAppManager keeps `campaigns` as a private field. Expose it\n // via bracket access; the field is stable as of SDK 1.5.0. Once\n // Phase 7c unifies render paths this becomes a first-class getter.\n return ((this.inApp as unknown as { campaigns?: InAppCampaign[] }).campaigns) ?? [];\n }\n}\n","/**\n * SDK Bootstrap\n *\n * Strict origin-assertion handshake against the control-plane. Called once\n * at SDK init — resolves writeKey → propertyId, asserts origin, and returns\n * the VAPID public key + first-party cookie id the SDK needs for the rest\n * of the session.\n *\n * A failed bootstrap (401/403) aborts SDK init — the SDK refuses to emit\n * events or request push permission against an origin it cannot prove it\n * owns.\n *\n * See docs/architecture/SUBSCRIPTION_PROPERTY_ARCHITECTURE.md §5.\n */\n\nconst COOKIE_NAME = 'aegis_fpc';\nconst COOKIE_MAX_AGE_DAYS = 365 * 2;\n\nexport interface BootstrapRequest {\n writeKey: string;\n currentOrigin?: string;\n firstPartyCookieId?: string;\n attestationToken?: string;\n userAgent?: string;\n}\n\nimport type { EventGovernanceHint } from '../governance';\n\nexport interface BootstrapResult {\n propertyId: string;\n organizationId: string;\n workspaceId: string;\n propertyType: 'shopify_store' | 'hosted_commerce' | 'custom_website' | 'mobile_app';\n vapidPublicKey: string | null;\n allowedOrigins: string[];\n pushEnabled: boolean;\n inAppEnabled: boolean;\n transportMode: string;\n firstPartyCookieId: string;\n /**\n * Event-governance hint for SDK-side unique-event-name cap enforcement.\n * Null = Enterprise plan / CP outage / org has no cap. Safe to pass\n * directly to `aegis.ingestGovernanceHint()`.\n */\n eventGovernance: EventGovernanceHint | null;\n}\n\nexport class BootstrapError extends Error {\n constructor(public readonly status: number, message: string) {\n super(message);\n this.name = 'BootstrapError';\n }\n}\n\n/**\n * Read the first-party cookie id from document.cookie. Returns null if\n * unset — caller should pass undefined so the server issues a fresh one.\n */\nexport function readFirstPartyCookie(): string | null {\n if (typeof document === 'undefined') return null;\n const match = document.cookie.match(new RegExp(`(?:^|;\\\\s*)${COOKIE_NAME}=([^;]+)`));\n return match ? decodeURIComponent(match[1]) : null;\n}\n\n/**\n * Persist the first-party cookie id returned by the server. Stored as a\n * first-party cookie (readable by JS — it's not a secret, it's a device\n * id) so that the same browser hitting a second origin on the same\n * registrable domain gets the same cookie back.\n */\nexport function writeFirstPartyCookie(cookieId: string): void {\n if (typeof document === 'undefined') return;\n const expires = new Date();\n expires.setDate(expires.getDate() + COOKIE_MAX_AGE_DAYS);\n // Derive the registrable-domain boundary where possible so the cookie is\n // shared across subdomains (e.g., shop.sweettruths.com + www.sweettruths.com).\n // We conservatively use the current host without a leading dot —\n // browsers scope the cookie to that host. For cross-registrable-domain\n // siblings (Shopify myshopify.com + actii.me), each domain gets its own\n // cookie, which is the expected per-origin behavior.\n document.cookie =\n `${COOKIE_NAME}=${encodeURIComponent(cookieId)};` +\n `expires=${expires.toUTCString()};` +\n `path=/;SameSite=Lax`;\n // Also mirror into localStorage so the SDK can read it synchronously at\n // init time even in environments where document.cookie is delayed.\n try {\n window.localStorage.setItem(COOKIE_NAME, cookieId);\n } catch {\n // private mode / storage disabled — cookie alone is sufficient\n }\n}\n\n/**\n * Perform the bootstrap handshake.\n *\n * @throws BootstrapError on 4xx — the SDK should stop init and surface the\n * error to the console. 5xx are retried once.\n */\nexport async function bootstrap(\n apiHost: string,\n req: BootstrapRequest\n): Promise<BootstrapResult> {\n const body: Record<string, unknown> = { writeKey: req.writeKey };\n if (req.currentOrigin) body.currentOrigin = req.currentOrigin;\n if (req.firstPartyCookieId) body.firstPartyCookieId = req.firstPartyCookieId;\n if (req.attestationToken) body.attestationToken = req.attestationToken;\n if (req.userAgent) body.userAgent = req.userAgent;\n\n const url = `${apiHost.replace(/\\/$/, '')}/v1/sdk/bootstrap`;\n\n const doFetch = async (): Promise<Response> =>\n fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n credentials: 'omit',\n });\n\n let resp = await doFetch();\n if (resp.status >= 500) {\n await new Promise((r) => setTimeout(r, 750));\n resp = await doFetch();\n }\n\n if (resp.status === 401) {\n throw new BootstrapError(401, 'writeKey not recognized or revoked');\n }\n if (resp.status === 403) {\n throw new BootstrapError(403, 'Origin validation failed — this writeKey is bound to a different property');\n }\n if (!resp.ok) {\n throw new BootstrapError(resp.status, `Bootstrap failed: HTTP ${resp.status}`);\n }\n\n const json = (await resp.json()) as BootstrapResult;\n writeFirstPartyCookie(json.firstPartyCookieId);\n return json;\n}\n\n/**\n * Derive a deterministic device fingerprint from the first-party cookie id\n * and a few stable UA parts. This is the value sent on every push-subscribe\n * call — its stability lets the backend UPSERT on (property_id, fingerprint)\n * across re-subscribes and VAPID rotations.\n */\nexport async function deriveDeviceFingerprint(firstPartyCookieId: string): Promise<string> {\n const ua = typeof navigator !== 'undefined' ? navigator.userAgent : '';\n const platform = typeof navigator !== 'undefined' ? (navigator.platform || '') : '';\n const language = typeof navigator !== 'undefined' ? (navigator.language || '') : '';\n const input = `${firstPartyCookieId}|${ua}|${platform}|${language}`;\n\n // Prefer subtle.crypto — available in all push-capable browsers.\n if (typeof crypto !== 'undefined' && crypto.subtle) {\n const bytes = new TextEncoder().encode(input);\n const hash = await crypto.subtle.digest('SHA-256', bytes);\n const hex = Array.from(new Uint8Array(hash))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n return hex;\n }\n\n // Last-resort fallback — basic 32-bit FNV hash (non-cryptographic but\n // stable). Push-capable browsers always have subtle.crypto so this path\n // is practically unreachable; included only for completeness.\n let h = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i);\n h = (h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24))) >>> 0;\n }\n return `fnv-${h.toString(16)}`;\n}\n","import { Aegis } from './core/analytics';\n\nconst aegis = new Aegis();\n\nexport default aegis;\n\nexport { Aegis } from './core/analytics';\nexport type { AegisConfig, CellEndpoint, CellRegion } from './types/config';\nexport type {\n AegisEvent,\n TrackEvent,\n IdentifyEvent,\n PageEvent,\n GroupEvent,\n AliasEvent,\n EventContext,\n BatchPayload,\n BatchResponse,\n} from './types/events';\nexport type { Plugin, PluginRegistry } from './types/plugin';\nexport { debounce, throttle } from './utils/debounce';\nexport type {\n ConsentPreferences,\n ConsentCategory,\n ConsentStatus,\n} from './utils/consent';\n// In-app + widget types are re-exported for callers that configure\n// AegisMessageRuntime or read campaign objects. The underlying manager\n// classes are intentionally NOT exported — use AegisMessageRuntime.\nexport type { InAppCampaign, AegisInAppConfig } from './inapp';\nexport { renderPreview } from './inapp';\n\nexport { AegisPlacementManager } from './placements/AegisPlacementManager';\nexport type {\n PlacementContent,\n PlacementSlot,\n AegisPlacementConfig,\n} from './placements/AegisPlacementManager';\n\nexport type {\n WidgetConfig,\n GamificationPrize,\n AegisWidgetConfig,\n} from './widgets';\n\nexport { TriggerEngine } from './triggers';\nexport type {\n TriggerRule,\n ScrollDepthConfig,\n TimeOnPageConfig,\n ExitIntentConfig,\n InactivityConfig,\n TriggerEvent,\n} from './triggers';\n\nexport { SdkConfigPoller } from './core/sdk-config-poller';\nexport type { SdkConfig, SdkConfigPollerOptions, ConfigChangeCallback } from './core/sdk-config-poller';\n\n// Preload-first bundle (2026-04-22) — fetches armed campaigns + inbox\n// slice once at init; everything renders from memory on trigger.\nexport { PrefetchBundleClient } from './core/prefetch-bundle-client';\nexport type {\n PrefetchBundle,\n PrefetchBundleCampaign,\n PrefetchBundleInbox,\n PrefetchBundleInboxEntry,\n PrefetchBundleClientOptions,\n PrefetchBundleContext,\n PrefetchBundleListener,\n} from './core/prefetch-bundle-client';\n\n// App Inbox — persistent message-center client.\nexport { AegisInbox } from './inbox';\nexport type { AegisInboxConfig, AegisInboxEntry, InboxListener } from './inbox';\n\n// Unified message runtime — the single entry point for in-app + widgets.\n// All 20 in-app types (modal/banner/tooltip/full_screen/spin_wheel/\n// scratch_card/nps_survey/quiz/countdown_offer/star_rating/...) flow\n// through this one class. The underlying AegisInAppManager +\n// AegisWidgetManager implementations are internal to the package.\nexport { AegisMessageRuntime } from './runtime';\nexport type { AegisMessageRuntimeConfig } from './runtime';\n\nexport { AegisWebPush } from './push/AegisWebPush';\nexport type {\n AegisWebPushConfig,\n AegisAPIClient,\n ContactIdentity,\n PushEventTracker,\n} from './push/AegisWebPush';\n\nexport {\n bootstrap,\n readFirstPartyCookie,\n writeFirstPartyCookie,\n deriveDeviceFingerprint,\n BootstrapError,\n} from './core/bootstrap';\nexport type { BootstrapRequest, BootstrapResult } from './core/bootstrap';\n\nexport { RateLimiter } from './core/rate-limiter';\nexport type { RateLimiterOptions } from './core/rate-limiter';\n\n// Event-governance — SDK-side cap enforcement. The NameGovernor is wired\n// into `Aegis.captureEvent()` automatically; callers only interact with it\n// via `aegis.ingestGovernanceHint(bootstrapResult.eventGovernance)`.\nexport { NameGovernor, BloomFilter, murmurhash3_x86_32 } from './governance';\nexport type { EventGovernanceHint, DropReport, BloomFilterParams } from './governance';\n\n// NOTE: SSE-based realtime subscription is intentionally NOT exported from the\n// public SDK surface. The Aegis Web SDK uses HTTP batch uplink + HTTP polling\n// downstream (via AegisInAppManager) + Web Push (via AegisWebPush). Tenant\n// dashboards that need SSE open it directly via their own Next.js API routes,\n// not through this SDK. See RFC 2026-04-16 §A.\n\nexport { EcommerceTracker } from './ecommerce';\nexport type {\n EcommerceProduct,\n EcommerceCart,\n EcommerceCheckout,\n EcommerceOrder,\n EcommerceCoupon,\n EcommerceSearch,\n EcommerceProductList,\n EcommerceWishlist,\n EcommercePromotion,\n} from './ecommerce';\n"],"names":["goto","readAnonIdFromStorage","m","isMobile","mobileConfig"],"mappings":"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"}
|