WidgetConfig Schema
Every field of the widget runtime config you can inject via the embed
WidgetConfig is the resolved configuration the widget runs on. The dashboard produces it; you can also inject a pre-resolved InjectableWidgetConfig through the embed (config prop / wexioSettings.config) to skip the bootstrap fetch.
type InjectableWidgetConfig =
Omit<WidgetConfig, "branding" | "status" | "security"> & {
security?: InjectableWidgetSecurity;
};Top-level fields
| Field | Type | Default | Meaning |
|---|---|---|---|
status | "active" | "disabled" | "plan_blocked" | active | Backend-owned; not host-overridable. |
defaultTab | WidgetTab | home | Initial tab. |
localeStrategy | "AUTO" | "WEBSITE" | "DEFAULT" | AUTO | How the active locale is chosen. |
defaultLocale | string (BCP-47) | en | Canonical / fallback language. |
supportedLocales | string[] | [] | Content allow-list; empty = no filter. |
contentLocaleFallback | boolean | true | Render fallback-locale content when untranslated. |
security | WidgetSecurity | — | Auth config (see below). |
features | WidgetFeatures | all on | Tab toggles. |
theme | WidgetTheme | null | null | Palette, radii, launcher, font. |
themeMode | "light" | "dark" | "auto" | auto | Default mode. |
operatorAvatars | { src; alt }[] | — | Up to 3 header avatars. |
organizationLogo | { light; dark } | null | — | Per-mode header logo. |
greeting | { headline; subheadline } | "Hi there 👋" | Home top copy; empty hides it. |
homeLayout | HomeBlock[] | null | null | Ordered Home blocks (null = default layout). |
prechatForm | WidgetPrechatForm | null | disabled | Prechat gate. |
branding | WidgetBranding | null | null | Badge visibility (not injectable). |
sounds | WidgetSounds | null | — | Notification sounds. |
messenger | WidgetMessengerConfig | null | — | Messenger copy & behaviour. |
botProtection | WidgetBotProtection | null | — | Turnstile config. |
integrationId, name, publicKey, and allowedOrigins are not part of WidgetConfig — they're internal/admin fields.
Enums
type WidgetTab = "home" | "messages" | "help" | "news" | "profile";
type WidgetLocaleStrategy = "AUTO" | "WEBSITE" | "DEFAULT";
type LauncherPosition = "RIGHT_BOTTOM" | "LEFT_BOTTOM";
type PrechatFieldKind = "NAME" | "EMAIL" | "PHONE" | "CUSTOM_TEXT";
type WidgetMessengerMessageKind = "HINT" | "SYSTEM";features
interface WidgetFeatures {
home: boolean;
messenger: boolean;
help: boolean;
news: boolean;
profile?: boolean; // default false — operator opts in
}If defaultTab points at a disabled feature, the widget falls through to the first enabled tab. With a single feature enabled, the bottom nav disappears.
theme
interface WidgetTheme {
light?: WidgetThemePalette;
dark?: WidgetThemePalette;
radii?: { sm?: number; md?: number; lg?: number; xl?: number };
launcherPosition?: LauncherPosition;
fontFamily?: string;
}WidgetThemePalette keys (all optional strings): background, surface, surfaceElevated, text, textMuted, textSubtle, border, borderStrong, primary, primaryHover, primaryForeground, launcherBackground, launcherForeground, success, danger. See Theming for the CSS-variable mapping.
security
interface WidgetSecurity {
requireAuth: boolean;
google: { enabled: boolean; clientId: string | null };
passkey: { enabled: boolean };
}In InjectableWidgetConfig, security is the slimmer InjectableWidgetSecurity — requireAuth?, google.enabled?, passkey.enabled?. The Google clientId is not host-injectable (the backend reads it from the integration).
prechatForm
interface WidgetPrechatForm {
enabled: boolean;
fields: {
kind: PrechatFieldKind; // NAME | EMAIL | PHONE | CUSTOM_TEXT
key: string; // /^[a-z0-9_]{1,32}$/
label: string; // empty → localized default
required: boolean;
}[];
}messenger
interface WidgetMessengerConfig {
title: string | null; // ≤120, null → localized default
description: string | null; // ≤500, null → localized default
aiAssistantAvatar: string | null;
commands: string[]; // ≤20, each /^\/[a-zA-Z0-9_-]{1,32}$/
messages: { kind: "HINT" | "SYSTEM"; text: string }[]; // ≤10
showRelatedNews: boolean;
showRelatedHelpArticles: boolean;
showReactionCounts: boolean;
}sounds
interface WidgetSounds {
enabled: boolean;
inboundSoundId: string | null; // preset id or full URL
outboundSoundId: string | null;
volume: number; // 0.0 … 1.0
}botProtection
interface WidgetBotProtection {
turnstile: { enabled: boolean; siteKey: string | null };
}Home blocks
homeLayout is an ordered array of blocks (max 12). The renderer skips unknown kinds.
type HomeBlock =
| { kind: "quick-actions"; buttons: HomeQuickActionButton[]; layout?: "stacked" | "inline" }
| { kind: "help-search"; placeholder?: string; suggestions: HomeHelpSuggestionsConfig }
| { kind: "pinned-articles"; articleIds: string[]; title?: string }
| { kind: "news-preview"; maxItems?: number; title?: string }
| { kind: "team-status"; showResponseTime: boolean; showOperatorAvatars: boolean }
| { kind: "divider" }
| { kind: "rich-text"; markdown: string }
| { kind: "ask-question"; title?: string; subtitle?: string; action?: "open-messenger" | "open-help" | "open-news" }
| { kind: "recent-message"; title?: string }
| { kind: "featured-article"; newsId?: string; ctaLabel?: string };
interface HomeQuickActionButton {
label?: string; // ≥1 of label/icon required
icon?: { kind: "named"; name: string; colored?: boolean } | { kind: "media"; url: string };
action: "open-messenger" | "open-help" | "open-news" | "open-url";
url?: string; // required for "open-url"
style?: "default" | "primary" | "ghost"; // max 1 "primary" per block
}
interface HomeHelpSuggestionsConfig {
mode: "popular" | "recent" | "category" | "manual";
maxItems: number; // 3–8
categoryId?: string; // required for "category"
articleIds?: string[]; // required for "manual"
}