Skip to main content

Hosted Widget Customization

Customize the ready-made interface loaded by https://chattybox.ai/widget.js. For canonical framework and platform installation examples, see Installation Guides.

Before You Customize​

Create the project, index its content, and verify representative answers in Test chatbot before spending time on presentation. See Getting Started for the complete sequence.

Configure the Hosted Widget​

  1. Go to your Dashboard and select your project.
  2. Navigate to Customize → Appearance to edit the widget's appearance, branding, and Language settings.
  3. Check the relevant autosave status; correct validation errors or retry failed saves before testing the installed widget.

Installation code and public keys are managed under Install. When you are ready to install:

  1. Open Install → Keys & domains to inspect or create a public browser key and check its origin settings.
  2. Under Install → Website installation, select a suitable key and copy the generated snippet. A key created without restrictions works across origins; a key prepared for a website can already be restricted to that site's origin. Check the selected key before using staging or localhost.
  3. Optionally enable exact origin restrictions for defense in depth; these do not authenticate visitors.
  4. Follow the Installation Guides for your platform.
<script
src="https://chattybox.ai/widget.js"
data-api-key="YOUR_API_KEY"
data-api-url="https://adorable-woodpecker-629.convex.site/chat"
async
></script>
tip

Widget presentation changes saved in the dashboard apply on the next widget initialization without replacing the snippet. Already-open pages do not update live; reload to fetch the saved settings.


Visual Customization​

The dashboard editor lets you adjust the supported widget colors, placement, icon, and text without editing your site's code. Verify the result in the hosted widget, since the preview and loader are not identical.

Dashboard Controls​

  1. Accent Color - Pick your brand's primary color. This affects the launcher, key highlights, and user messages.

  2. Position - Choose where the widget appears on the screen.

  3. Header Title - Set the title shown at the top of the chat window.

  4. Welcome Message - Customize the first message visitors see when they open the chat.

  5. ChattyBox Branding - Starter and higher plans can turn off the “Powered by ChattyBox” footer. Branding remains enabled on Free.

The editor also has Widget Background and Text Color controls, plus a default robot, emoji, image URL, or uploaded image for the widget icon. The Icon Size control appears when you choose an image URL or upload an image. Uploaded icons must be at most 512 KiB and use an accepted image MIME type (PNG, JPEG, WebP, SVG, GIF, or ICO). The current-source hosted v16 loader uses iconSize to size the launcher and icon; verify the deployed loader before relying on that behavior.

note

Confirm the relevant autosave status, then reload the installed page to verify changes. The dashboard preview is a mock, not the hosted widget itself. For config-locked projects, appearance and locale fields are managed by config-as-code; entitled projects can still save branding separately.

Configuration Defaults​

These are the defaults returned by a successful public widget-config request when no custom value exists:

FieldDefault
enabledtrue, unless disabled on the project
themeColor#3b82f6
chatBgColor#0f172a
textColor#f8fafc
positionbottom-right; all four corners are supported
iconType, iconSizedefault, medium; current-source hosted v16 uses size for the launcher and icon
iconEmoji, iconUrlSpeech-balloon emoji, null
headerTitleChat with us
welcomeMessageHi! 👋 How can I help you today?
showBrandingtrue; forced on for Free projects
localeMode, defaultLocale, allowLocaleOverrideauto, en, true

In the current-source hosted loader, a failed or invalid configuration fetch leaves the widget unavailable rather than rendering a fallback UI. A successful config response with enabled: false also prevents rendering; the chat API rejects a disabled widget with HTTP 403, including SDK requests. Verify the deployed loader version before relying on current-source behavior.

The current-source hosted v16 loader requests config with Authorization: Bearer and retries once using a query-string key only after HTTP 400. Published SDK 0.1.4 mirrors that config-only fallback when the page exposes window.ChattyboxSDK. Hosted v16 separately retries its startup config and translation GETs for retryable failures. Chat messages use the hosted loader's own transport. For SDK mounting, published SDK 0.1.4 shares only identical options and rejects a changed key, endpoint, script URL, locale, or debug setting until all matching handles are removed. Verify the deployed loader before relying on current-source behavior.

Advanced Options​

Dashboard Settings vs Script Attributes​

Most widget behavior should be managed from the dashboard so you do not need to redeploy your website for simple changes.

Use the dashboard for colors, position, icon, header title, welcome message, language defaults, public key management, scraping, and analytics.

If you explicitly enable a public-key origin restriction, keep its exact origins in sync with the domains where the widget is installed. Origin is optional defense-in-depth, not authentication.

Use script attributes only for values the widget needs at page load:

  • data-api-key identifies the public widget key.
  • data-api-url tells the widget where to send requests. In production this is a stable https://...convex.site/chat URL from your dashboard.
  • data-locale requests a specific widget UI language if project overrides are allowed. The current-source loader also observes changes to this attribute.
  • data-color and data-position override saved accent color and position after a successful config fetch. Prefer dashboard values; these attributes can mask later dashboard changes.
  • data-debug="true" enables console diagnostics; it is off by default.

For a new message, the current-source hosted widget attempts to include the current HTTP(S) page's origin and path for Popular Triggers analytics, without checking whether the page is public. Invalid or over-length context is omitted; retries retain the original request's context. It removes query strings, fragments, and credentials, but paths can contain sensitive identifiers. The widget also respects prefers-reduced-motion, provides a labelled message input and live announcements, and exposes citations through a keyboard-accessible Sources disclosure.

Page context is taken from the current HTTP(S) URL, not from a test of whether the page is public. Do not load it on sensitive routes solely because query strings are stripped. The loader may also send initialization/configuration/translation/chat errors to /widget-error using a beacon or fetch, including bounded error details, locale, version, and page origin/path. Debug mode is not required for these reports.

Chat uses complete JSON responses rather than token streaming. Current-source hosted v16 creates an idempotency key per message and makes at most 10 automatic transport attempts for network errors, interrupted successful response bodies, HTTP 429, HTTP 5xx, and 409 responses with a readable Retry-After header. It schedules no further retry if the delay would exceed the 30-second budget; this is not a hard timeout for an in-flight request. Browser CORS can hide Retry-After. This retry behavior is not provided by headless sendMessage(); the hosted startup GET retries and SDK 0.1.4 config-400 fallback are separate, limited behaviors. Conversation state stays in memory for that widget instance and is lost on reload or reinitialization; stored server messages may remain. Sources are deduplicated and limited to three displayed entries; fallback answers can have no sources. Verify the deployed loader version before relying on current-source behavior.

If the widget does not appear after installation, see Troubleshooting.

For platform-specific examples, start with Docusaurus, MkDocs, VitePress, WordPress, or GitBook.

Hide the Widget on Specific Pages​

To visually hide the widget, apply the following CSS only on the selected pages (globally applying it hides the widget everywhere):

.chattybox-widget {
display: none;
}

CSS hiding does not stop initialization, API requests, or error reporting and is not a consent or privacy control. The loader does not make a consent decision: gate script insertion until required consent and prevent reinsertion on revocation or excluded routes. For client-side route transitions or consent revocation, current-source hosted widget.js v16 provides window.ChattyBox.destroy(). SDK 0.1.4 mount handles are reference-counted: remove every matching handle to signal final teardown. Verify that the deployed loader supports teardown; removing only a script tag is insufficient. Teardown removes owned UI/styles and cancels pending work, but cannot undo requests already processed by the server.

Browser Controls​

In current-source hosted v16, window.ChattyBox exists during startup with status: 'loading' and destroy(). After successful initialization, check window.ChattyBox?.status === 'ready' before calling open(), close(), toggle(), or sendMessage(text). destroy() removes the owned widget and styles, aborts its lifetime work, and clears the global; it cannot undo a request already processed by the server. close() only closes the chat panel; it leaves the launcher present. sendMessage(text) returns a UI-operation promise, not an answer promise; sends while another message is pending are ignored. This global is distinct from the SDK constructors on window.ChattyboxSDK. Verify the deployed loader version before relying on this behavior.

Site-controlled day/night themes (current source)​

The current-source config-as-code workflow supports optional widget.theme.light and widget.theme.dark palettes. Each accepts primaryColor, backgroundColor, and textColor as six-digit hex colors; omitted colors inherit the base widget.theme. Existing single-theme configurations continue to work unchanged. This requires the current-source CLI/backend and hosted loader v16; published CLI/config 0.3.1 does not accept these new fields.

Set data-theme="light" or data-theme="dark" on the loader script before it runs to select the initial palette. Then connect your site's toggle to the browser API:

window.ChattyBox?.setTheme('light');
window.ChattyBox?.setTheme('dark');
window.ChattyBox?.setTheme(null); // Restore the configured base appearance.

The widget updates its existing styles without resetting messages, sources, draft text, or a pending request. Theme selection cannot change widget enablement or remove attribution. Your site owns preference persistence and OS-theme behavior; the widget only selects the configured palette.

Custom Integrations​

Need a more tailored setup than the hosted widget? Build your own interface with the JavaScript SDK, or contact support@chattybox.ai for architecture help.

Multilingual Support​

The current-source ChattyBox widget resolves a UI locale according to the project's fixed or auto mode. It observes changes to <html lang> and the loader script's data-locale, updating labels in place without resetting the conversation, draft, or pending retry. Navigation alone does not select a language; update one of those attributes when appropriate. Dashboard setting changes still require reinitialization.

Officially Supported Languages​

The widget has translation catalogs for 14 languages. All current catalogs use left-to-right layout. Project-authored text and AI-generated answers are not translated by the UI catalogs.

LanguageCode
Englishen
Frenchfr
Germande
Spanishes
Italianit
Dutchnl
Portuguesept
Polishpl
Swedishsv
Indonesianid
Estonianet
Finnishfi
Welshcy
Czechcs

:::note UI Language vs Answers The current-source hosted loader sends its resolved UI locale with chat requests. The backend detects language from the question and attempts language-aware retrieval and generation. A recognized question-language signal takes precedence over UI locale for product-owned fallback messages; if detection is inconclusive or relies only on the ASCII English heuristic, UI locale can select their language. It does not translate project-authored fallback text or change AI-generated output. Answer quality and available languages depend on indexed content and the configured model; the UI catalogs are not a response-quality guarantee. :::

How Language Detection Works​

The widget uses a cascading detection system:

  1. Allowed script override - A supported data-locale wins only when allowLocaleOverride is not false, even in fixed mode.
  2. Fixed mode - Without a supported allowed override, use defaultLocale and ignore page/browser language.
  3. Auto mode - Try page <html lang>, navigator.language, each entry of navigator.languages, legacy userLanguage, then defaultLocale, selecting the first supported language.
  4. Normalization - Matching ignores case and recognized regional values such as fr-CA reduce to their supported base language. Unsupported candidates are skipped; if none is supported, use English. Defaults are auto mode, English, and script overrides allowed.

Custom header titles and welcome messages are displayed verbatim, not translated automatically. Current-source default titles and welcome messages use localized labels. If translations fail to load, built-in English labels remain.

Manual Language Override​

To request a specific language regardless of browser settings, enable Allow Script Override and add a supported data-locale to the loader script:

<script
src="https://chattybox.ai/widget.js"
data-api-key="YOUR_API_KEY"
data-locale="de"
data-api-url="https://adorable-woodpecker-629.convex.site/chat"
async
></script>

:::tip Use Case This is particularly useful if you have a multilingual website where each language version has its own URL (e.g., /de/, /fr/). Set data-locale to match each page's language for consistent user experience. :::

Dashboard Language Settings​

The app dashboard allows you to configure widget language preferences per project:

  • Auto-detect - Uses the page language before the visitor's browser language
  • Fixed - Uses the configured default language unless an allowed script override is present
  • Allow script override - Enable/disable the data-locale attribute override

Access these settings in your Dashboard → Project → Customize → Appearance → Language. Confirm the language autosave status and resolve errors before testing.

Content Language Matching​

For the best multilingual experience, index useful content in the languages your visitors ask about:

  1. Scrape all language versions of your documentation using the sitemap.xml file
  2. The scraper attempts to detect page language; inspect extracted content and citations rather than assuming detection is always correct
  3. Retrieval attempts to prefer the query's detected language but can fall back to other indexed content; test rather than assuming a language match

Setup in App Dashboard: When configuring scraping, use your sitemap.xml URL (e.g., https://yourdocs.com/sitemap.xml) to discover language versions, then verify the indexed pages. Sitemaps do not bypass crawl limits or exclusions.

Troubleshooting​

Widget Still Shows English​

  • Hard refresh as a diagnostic - Reload with Ctrl+F5 or Cmd+Shift+R, then check the browser network panel for widget and translation requests
  • Check data-locale - Verify the attribute is set correctly with a supported language code
  • Check project mode and override permission - Fixed mode and disabled overrides can intentionally ignore browser language or data-locale
  • Verify browser language - Check that your browser's preferred language is set correctly
  • Check page HTML lang - Ensure your page has <html lang="de"> (or appropriate code)

Sources Are in Wrong Language​

  • Re-scrape your content - Ensure all language versions are indexed
  • Use sitemap.xml - Include the desired language URLs and confirm they were actually indexed; crawl limits and exclusions can omit pages
  • Check query language - The AI attempts to match response language to query language

Missing Translations​

  • Check supported languages and requests - Only the 14 codes listed above have catalogs; missing keys use built-in fallbacks

Best Practices​

  1. Set <html lang> on your pages - Helps with accessibility and widget detection
  2. Test with data-locale during development - Verify each language renders correctly
  3. Scrape all language versions - Use sitemap.xml for comprehensive multilingual indexing
  4. Review real questions - Inspect conversations for language-specific content gaps; the dashboard does not currently expose a widget-locale distribution report