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 Chat before spending time on presentation. See Getting Started for the complete sequence.
Configure the Hosted Widget
- Go to your Dashboard and select your project.
- Navigate to the Embed tab.
- Preview and save the widget's appearance and language behavior.
The Embed tab controls presentation and generates installation code, but public keys are managed separately. When you are ready to install:
- Open Public Keys and create a browser key.
- Return to Embed, select the key, and copy the generated snippet. The key works across production, previews, staging, and localhost by default.
- Optionally open Public Keys > Edit origins and enable an exact origin restriction for defense in depth.
- 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>
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
-
Accent Color - Pick your brand's primary color. This affects the launcher, key highlights, and user messages.
-
Position - Choose where the widget appears on the screen.
-
Header Title - Set the title shown at the top of the chat window.
-
Welcome Message - Customize the first message visitors see when they open the chat.
-
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. Uploaded icons must be at most 512 KiB and use an accepted image MIME type (PNG, JPEG, WebP, SVG, GIF, or ICO). Although the editor stores an icon size, the current hosted loader does not read iconSize; do not expect small/medium/large to resize it.
Save changes, then reload the installed page to verify them. 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:
| Field | Default |
|---|---|
enabled | true, unless disabled on the project |
themeColor | #3b82f6 |
chatBgColor | #0f172a |
textColor | #f8fafc |
position | bottom-right; all four corners are supported |
iconType, iconSize | default, medium (size is not consumed by the hosted loader) |
iconEmoji, iconUrl | Speech-balloon emoji, null |
headerTitle | Chat with us |
welcomeMessage | Hi! 👋 How can I help you today? |
showBranding | true; forced on for Free projects |
localeMode, defaultLocale, allowLocaleOverride | auto, en, true |
If configuration cannot be fetched, the loader still renders a fallback UI with ChattyBox AI as the title and Hi! How can I help you today? as the welcome message. A visible launcher therefore does not prove the key or origin is valid. A successful config response with enabled: false prevents rendering; the chat API also rejects a disabled widget with HTTP 403, including SDK requests.
The standalone 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 v15 also retries only its startup config and translation GETs for retryable failures. Chat messages still 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.
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-keyidentifies the public widget key.data-api-urltells the widget where to send requests. In production this is a stablehttps://...convex.site/chatURL from your dashboard.data-localerequests a specific widget UI language at initialization only if project overrides are allowed.data-coloranddata-positionoverride 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.
The hosted widget sends the current public page's validated origin and path with each chat request for Popular Pages analytics. It removes query strings, fragments, and credentials. 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. The hosted v15 loader creates an idempotency key per message and makes at most 10 total transport attempts within a 30-second automatic retry window for network errors, HTTP 429, HTTP 5xx, and 409 responses with a readable Retry-After header. Browser CORS can hide that header. This retry behavior is not provided by headless sendMessage(); the v15 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. Sources are deduplicated and limited to three displayed entries; fallback answers can have no sources.
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. To prevent loading, exclude the script on those page requests. For client-side route transitions or consent revocation, hosted widget.js v15 provides window.ChattyBox.destroy(). SDK 0.1.4 remove() sends the same teardown signal before removing the script, destroying owned UI/styles and cancelling pending initialization, retries, and in-flight chat.
Browser Controls
After initialization completes, the hosted loader exposes window.ChattyBox.open(), close(), toggle(), sendMessage(text), and (v15) destroy(). 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) opens the panel and starts sending but returns no answer promise, and sends while another message is pending are ignored. Check that window.ChattyBox exists before calling it; script load alone does not guarantee config and translations have finished. This global is distinct from the SDK constructors on window.ChattyboxSDK.
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 ChattyBox widget resolves a UI locale at initialization according to the project's fixed or auto mode. It does not watch locale attributes or client-side navigation for changes.
Officially Supported Languages
The widget has translation catalogs for 14 languages. All current catalogs use left-to-right layout. Catalog coverage does not mean every visible or accessible string is translated: the current loader retains English for some labels, including the send-message label and the chat-log label.
| Language | Code |
|---|---|
| English | en |
| French | fr |
| German | de |
| Spanish | es |
| Italian | it |
| Dutch | nl |
| Portuguese | pt |
| Polish | pl |
| Swedish | sv |
| Indonesian | id |
| Estonian | et |
| Finnish | fi |
| Welsh | cy |
| Czech | cs |
:::note UI Language vs Answers The UI locale is not sent as a chat-language parameter. The backend detects language from the question and attempts language-aware retrieval and generation. 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:
- Allowed script override - A nonempty
data-localewins only whenallowLocaleOverrideis not false, even in fixed mode. - Fixed mode - Without an allowed override, use
defaultLocaleand ignore page/browser language. - Auto mode - Use the first nonempty value from page
<html lang>, browsernavigator.language(or legacyuserLanguage), thendefaultLocale. - Normalization - Recognized regional values such as
fr-CAreduce to their supported base language. An unsupported value becomes English immediately; detection does not continue to the next candidate. Use lowercase base codes, since normalization is not fully case-insensitive. Defaults are auto mode, English, and script overrides allowed.
The header title and any nonblank configured welcome message are displayed verbatim, not translated automatically. The public config endpoint supplies an English welcome message even for an empty saved value; clearing that field in the dashboard does not currently select the localized welcome.default label. 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 data-locale before the loader runs:
<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 Language - Uses the configured default language unless an allowed script override is present
- Allow Script Override - Enable/disable the
data-localeattribute override
Access these settings in your Dashboard → Project → Embed tab → Widget Language section.
Content Language Matching
For the best multilingual experience, index useful content in the languages your visitors ask about:
- Scrape all language versions of your documentation using the
sitemap.xmlfile - The scraper attempts to detect page language; inspect extracted content and citations rather than assuming detection is always correct
- 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
- Set
<html lang>on your pages - Helps with accessibility and widget detection - Test with
data-localeduring development - Verify each language renders correctly - Scrape all language versions - Use
sitemap.xmlfor comprehensive multilingual indexing - Review real questions - Inspect conversations for language-specific content gaps; the dashboard does not currently expose a widget-locale distribution report