Embed the Chat Widget (Developer Guide)
Widget Embed Guide
The widget is a Web Component (<web-chat-agent>) that loads asynchronously and runs on any site — no framework, no build step. The script renders a floating chat button; visitors click it to open the chat window.
Embed Code
Paste this right before the closing </body> tag:
<script src="https://webchatagent.com/widget/web-chat-agent.js" async></script>
<web-chat-agent
chatbot-id="YOUR_CHATBOT_ID"
></web-chat-agent>
Replace YOUR_CHATBOT_ID with your Chatbot ID, found in Dashboard → Chatbot → Widget Customization, where the embed code is pre-filled with your ID. Copy it from there to avoid typos.
The widget calls the API on the same origin it was loaded from. Load the script from webchatagent.com and the chat requests go to webchatagent.com/api/... automatically — you never configure an API URL by hand.
How It Works
- The
asyncscript loads in the background and does not block page rendering. - The
<web-chat-agent>element renders a floating chat button. - The widget fetches your dashboard settings (colors, texts, tools, welcome message) and applies them. No extra attributes needed.
- A visitor clicks the button, the chat window opens, and messages go to your AI chatbot.
HTML Attributes
Every visual setting from the Widget Customization page is applied automatically. HTML attributes on the element are optional overrides — use them only for per-page tweaks (e.g. a different position on one landing page). Attribute names are kebab-case (the widget maps theme-color to the themeColor prop internally).
Defaults below are the widget's built-in fallbacks. In practice most attributes are left unset and inherit the value you configured in the dashboard.
Basic Settings
| Attribute | Type | Default | Description |
|---|---|---|---|
chatbot-id | string | — | Required. Your Chatbot ID (UUID). |
theme | string | default | Widget theme: default or modern. |
title | string | from translations | Title shown in the chat header. |
initially-open | boolean | false | Open the chat window automatically on page load. |
width | number | CSS default | Chat window width in pixels. If unset, the responsive default applies. |
height | number | CSS default | Chat window height in pixels. If unset, the responsive default applies. |
font-family | string | inherit | Google Font name (e.g. Roboto, Open Sans); loaded automatically. If unset, inherits the page font. |
Colors
All color attributes accept any valid CSS color (hex like #2563eb, rgb(), hsl()). When unset, the widget uses your dashboard value or its built-in fallback (the brand default is blue, #2563eb).
| Attribute | Description |
|---|---|
theme-color | Header and accent background color. |
theme-text-color | Header text color. |
bot-message-color | Bot message bubble background. |
bot-message-text-color | Bot message text color. |
user-message-color | User message bubble background. |
user-message-text-color | User message text color. |
bubble-color | Floating chat button background. |
bubble-text-color | Floating chat button icon color. |
Images
| Attribute | Description |
|---|---|
avatar-src | URL to an avatar image shown in the chat header. |
chat-bubble-image | URL to a custom image for the floating chat button (replaces the default icon). |
welcome-image | URL to an image shown above the welcome message (e.g. a company logo). |
Positioning
| Attribute | Type | Default | Description |
|---|---|---|---|
offset-x | number | 20 | Horizontal offset from the right edge (desktop), in pixels. |
offset-y | number | 20 | Vertical offset from the bottom edge (desktop), in pixels. |
mobile-offset-x | number | 20 | Horizontal offset from the right edge (mobile), in pixels. |
mobile-offset-y | number | 20 | Vertical offset from the bottom edge (mobile), in pixels. |
Content & Behavior
| Attribute | Type | Default | Description |
|---|---|---|---|
welcome-message | string | from config | HTML welcome message shown when the chat opens. |
speech-bubble-text | string | none | HTML text for the speech bubble next to the chat button. If unset, no bubble appears. |
privacy-policy-html | string | none | HTML block (bold, links) for a privacy notice inside the widget. |
disable-voice-input | boolean | false | Hide the microphone / voice input button. |
hide-branding | boolean | false | Hide the "Powered by WebChatAgent" link (Standard plan and higher). |
lang-detection-source | string | browser | How the widget picks its UI language: browser (navigator language) or html (reads <html lang="...">). |
tracking-consent | string | unknown | Optional consent signal for persistent personalization: unknown, denied, or granted. Missing and invalid values are treated as unknown. |
context-data | string | none | Session context from the embedding page (CRM record, logged-in user, case number). Simple format Key=Value;Key2=Value2 or a JSON object. See Session Context Data. |
Updating consent at runtime
window.dispatchEvent(
new CustomEvent('webchatagent:consent', {
detail: { tracking: 'granted' }
})
)
Dispatch denied when consent is rejected or revoked. Anonymous local triggers remain available. See the Cookie Consent guide for the trigger matrix and CMP adapters.
Prompt Buttons
Quick-action buttons rendered under the message list. Each button has a visible title and an action (the text sent as the user's message when clicked). Pass a JSON array as the attribute value:
<web-chat-agent
chatbot-id="YOUR_CHATBOT_ID"
prompt-buttons='[{"title":"Talk to support","action":"I need help with my order"},{"title":"Pricing","action":"What does it cost?"}]'
></web-chat-agent>
| Attribute | Type | Description |
|---|---|---|
prompt-buttons | JSON | Array of { "title": string, "action": string }. A non-empty value overrides buttons configured in the dashboard. |
Session Context Data
When the widget runs inside a system that already knows the visitor — a CRM, a customer portal, a logged-in area — the embedding page can pass that knowledge to the chatbot. The AI sees the values, references them in its answers, and uses them to fill matching arguments of API connector and MCP tool calls. A visitor whose case number is already on screen should never have to type it again.
Context data is sent with every chat request of the session, is injected into the AI prompt for that request only, and is not stored as its own record.
Passing context via the HTML attribute
Two formats are accepted. The simple format needs no JSON knowledge — semicolon-separated Key=Value pairs:
<web-chat-agent
chatbot-id="YOUR_CHATBOT_ID"
context-data="Customer=Jane Doe;Company=Acme GmbH;OrderID=A-1023"
></web-chat-agent>
Only the first = in each pair separates key and value, so values containing = (e.g. base64 tokens) stay intact. A value cannot contain a semicolon in this format — use JSON for that:
<web-chat-agent
chatbot-id="YOUR_CHATBOT_ID"
context-data='{"Customer":"Jane Doe","Note":"VIP; priority support","OrderID":"A-1023"}'
></web-chat-agent>
With JSON, wrap the attribute value in single quotes so the double quotes inside survive.
Passing context via JavaScript
If you prefer JavaScript over the attribute (or need it, e.g. on WordPress), set the global variable window.webchatagentContext. It is safe to set before the widget script has loaded — the widget picks it up when it initializes, so script load order does not matter:
<script>
window.webchatagentContext = {
Customer: 'Jane Doe',
OrderID: 'A-1023',
userToken: 'opaque-token-validated-by-your-backend'
}
</script>
<script src="https://webchatagent.com/widget/web-chat-agent.js" async></script>
Updating context at runtime
When the data changes while the widget is already running (login, switching to another case), dispatch the webchatagent:context event with a plain object:
window.dispatchEvent(
new CustomEvent('webchatagent:context', {
detail: {
Topic: 'billing',
OrderID: 'A-1023'
}
})
)
Each event replaces the full context; detail: null or {} clears it. Precedence at load time: the context-data attribute is applied first, then window.webchatagentContext (if set), then any events. The context lives in the page — after a reload, set it again.
White-label deployments: the brand-neutral aliases window.chatWidgetContext (global) and chat-widget:context (event) work identically, so embedding pages never need to reference the platform name.
Limits
At most 20 keys, key names up to 64 characters, values up to 500 characters (numbers and booleans are converted to strings), 4,000 characters total. Line breaks and the characters < > are stripped from keys and values. Responses to requests carrying context data are never served from the answer cache.
Security: context data is not authentication
The values come from the visitor's browser. Anyone can open DevTools and send arbitrary context, so the AI is instructed to treat it as unverified background data — never build authorization on it.
Two rules for production use:
- Restrict
allowedDomainsfor your chatbot in the dashboard. Without it, any page can embed your bot and feed it context. - For personal data lookups, pass an opaque token instead of plain identity. Generate a short-lived token for the logged-in user server-side, pass it as a context value (e.g.
userToken=...), and let your API connector endpoint validate the token before returning user data. The AI forwards the token in the API call; your backend decides what it unlocks. A forged token then returns nothing.
WordPress
The WordPress plugin (from its next release) supports context data server-side: the webchatagent_context_data filter supplies it for the floating widget (and as a default for inline embeds), and the inline shortcode accepts a context-data attribute:
add_filter('webchatagent_context_data', function () {
$user = wp_get_current_user();
return $user->exists() ? 'Customer=' . $user->display_name : '';
});
[webchatagent_inline context-data="Topic=Support;OrderID=A-1023"]
On older plugin versions, set window.webchatagentContext or dispatch the webchatagent:context event instead — both work on any platform.
Example: Full Customization
<script src="https://webchatagent.com/widget/web-chat-agent.js" async></script>
<web-chat-agent
chatbot-id="abc-123-def"
theme="modern"
title="Support Chat"
theme-color="#4f46e5"
theme-text-color="#ffffff"
user-message-color="#4f46e5"
bubble-color="#4f46e5"
font-family="Inter"
initially-open="false"
offset-x="30"
offset-y="30"
></web-chat-agent>
Dashboard vs. HTML Attributes
Dashboard settings are stored server-side and loaded when the widget initializes. HTML attributes override them for that page only.
Recommendation: Do all visual customization in the dashboard. Reach for HTML attributes only when one page needs to differ — different positioning, a forced theme, or page-specific prompt buttons.
Custom CSS
For changes that go beyond the attributes above, target the widget's internal elements with your own CSS. Every styleable element carries a stable .wca-* class (for example .wca-header, .wca-message, .wca-bubble), so your selectors keep working across widget updates and don't need !important. You add the CSS in the dashboard, and it is injected into the widget's shadow DOM. See Custom CSS.
Inline Widget
To render the chat inside your page layout instead of as a floating button, use the inline variant. It loads a different script and a different element (<web-chat-agent-inline>):
<script src="https://webchatagent.com/widget/chat-widget-inline.js" async></script>
<web-chat-agent-inline chatbot-id="YOUR_CHATBOT_ID"></web-chat-agent-inline>
The inline element takes chatbot-id, an optional container-height, plus tracking-consent and context-data (see Session Context Data — attribute and runtime event work identically here); all other settings come from its own dashboard configuration. Place the element wherever you want the chat to appear, and size it with the surrounding container. See Inline Widget for details.
WordPress
On WordPress, use the official WebChatAgent WordPress Plugin instead of pasting the script manually. It handles the embed and updates for you. See WordPress Plugin.
Single Page Applications (SPA)
The widget works with React, Vue, Angular, and other SPAs out of the box. Add the script tag to index.html and place the <web-chat-agent> element in your app shell (e.g. the root layout). The widget persists across client-side route changes — you do not re-mount it on navigation.
