/** * Outbound extension types — mirror the backend action-layer contract * (see docs/modules/outbound-messaging.md and app/src/entities/outbound/model). * Only the SDK-facing delivery + event shapes live here. */ export interface OutboundWidgetConfig { /** Opt-in for v1 — the banner only renders when explicitly enabled. */ enabled?: boolean; } export type OutboundSurface = "banner" | "post" | "carousel" | "nudge" | "launcher"; export type OutboundTheme = "brand" | "neutral" | "dark"; /** * How the banner occupies the page. * - `overlay` (default): fixed to the viewport edge, floats over page content. * - `push`: rendered in normal document flow so the page content shifts to * make room for it (no overlap). */ export type BannerDisplayMode = "overlay" | "push"; export interface BannerContent { position?: "top" | "bottom"; displayMode?: BannerDisplayMode; text: string; dismissible?: boolean; theme?: OutboundTheme; } export type OutboundCtaType = "open_url" | "start_chat" | "collect_email" | "dismiss" | "custom_event"; export interface OutboundCta { id: string; type: OutboundCtaType; label?: string; href?: string; target?: "_blank" | "_self"; message?: string; event_name?: string; properties?: Record; } export interface OutboundTrigger { type: string; value?: number; } /** Slim message the decide endpoint returns for the SDK to render. */ export interface OutboundDelivery { id: string; surface: OutboundSurface; content: BannerContent; cta: OutboundCta[]; priority: number; triggers: OutboundTrigger[]; } export interface DecideResponse { messages: OutboundDelivery[]; } export type OutboundEventType = "impression" | "engagement" | "cta_click" | "dismiss" | "conversion"; export interface OutboundEventPayload { message_id: string; surface: OutboundSurface; distinct_id: string; person_id?: string; session_id?: string; event_type: OutboundEventType; cta_id?: string; url?: string; properties?: Record; }