Widget configuration Live
Three layers control how the widget behaves: dashboard settings (persistent, per workspace), data attributes on the script tag (per page), and runtime API calls (per visitor). Each layer overrides the one above it.
Most teams never write a line of widget code. The dashboard at /settings/chats/customization covers colour, position, welcome message, and pre-chat fields. Code paths exist for the cases where one page needs to deviate.
Configuration layers
- Workspace defaults from the dashboard. Synced through the public config endpoint.
- Site-specific overrides. A site holds its own colour, greeting, and availability rules. The bundle picks the site whose hostname matches.
- Data attributes on the
<script>tag. Override anything for a single page load. - Runtime calls through
window.Message. Pass per-visitor context that changes during the session.
Data attributes
All overrides are namespaced with data- to keep them HTML5-valid. They are read once at boot and snapshot into the bundle config.
<script src="https://app.message.com/widget.js"
data-workspace="abc123"
data-position="right"
data-bottom-spacing="20"
data-side-spacing="20"
data-color="#FF4D1F"
data-locale="en"
data-no-launcher="false"
data-greeting="Hi! Need a hand?"
></script>| Field | Type | Description |
|---|---|---|
| data-workspacerequired | string | Your workspace ID. Public identifier from Settings → Chats → Installation. |
| data-positionoptional | enum | One of right or left. Default right. |
| data-bottom-spacingoptional | integer | Pixels from the bottom edge of the viewport. Default 20. |
| data-side-spacingoptional | integer | Pixels from the chosen side edge. Default 20. |
| data-coloroptional | string | Hex colour for the launcher and primary buttons. Overrides the workspace primary. |
| data-localeoptional | string | BCP 47 locale code, for example en or es-MX. Falls back to workspace default. |
| data-no-launcheroptional | boolean | If true, no launcher renders. You drive open/close via Message.open(). |
| data-greetingoptional | string | Override the welcome message for this page only. |
Runtime configuration
Once the bundle has loaded, window.Message exposes calls that push session context. These do not persist on the server; they describe the current visitor and page.
// Update workspace context without re-identifying the visitor.
window.Message.update({
pageUrl: location.href,
route: '/checkout',
cartValue: 129.95
});
// Push a custom event the dashboard and AI can see.
window.Message.track('checkout_started', { cartValue: 129.95 });See the full surface in JavaScript API. For events you can subscribe to (open, close, message received, conversation started), see Widget events.
Public config endpoint
The bundle reads its initial config from a public endpoint. No authentication is required because the endpoint only returns the public half of the configuration. Useful if you need to inspect the live state for debugging.
GET /api/v1/widget-config?embedId=<id>
{
"workspaceId": "abc123",
"primaryColor": "#FF4D1F",
"position": "right",
"greeting": "Hi! Need a hand?",
"locale": "en",
"availability": "online",
"agentsOnline": 3,
"logoUrl": "https://...",
"preChatForm": { "enabled": true, "fields": [...] }
}Replace <id> with the embed ID rendered in your script tag. The response is cached at the edge for 60 seconds, so changes in the dashboard take up to a minute to propagate to live sites.
Multi-site workspaces
One workspace can hold many sites. The bundle picks the matching site by hostname, then merges the site config over the workspace default. This is how you customise the widget per brand without managing separate workspaces.
If no site matches the hostname (for example, on staging or localhost) the workspace default applies. Add staging hostnames in Settings → Sites to get site-specific behaviour during development.
Common pitfalls
- Cache invalidation. The public config endpoint is cached for 60 seconds. If you flip a setting in the dashboard and reload, the old value may stick around briefly.
- Hex colour contrast. Picking a very dark or very light brand colour can crush text contrast inside the launcher. The widget auto-derives a contrasting text colour, but consider running a contrast checker on your choice.
- Locale fallback. Unsupported locales silently fall back to
en. To see the active locale, inspectwindow.Message.config.locale. - Headless mode. If you set
data-no-launcher="true", you must wireMessage.open()to a button on your page. Otherwise the widget is silent.