Web Chat Embed & SDK
Embed MaiAgent Web Chat into any website: embed code, window modes, user identification, full configuration reference, and the JavaScript SDK API
Add a snippet of embed code to your web page to put MaiAgent's AI assistant on your website. Once the embed code loads embed.min.js (hereafter "the SDK"), the SDK creates a chat button and an iframe chat window on the page, and exposes a global MaiAgent JavaScript API for programmatic control.
This page is the complete technical reference for Web Chat embedding. Related topics:
Web Chat MaiGPT Mode Embedding — a ChatGPT-like, full-featured conversation interface
WebChat Page Context Injection — inject page information into the LLM System Prompt
Contact Identity Sync and Token Refresh — create contacts and credentials from the backend
Software Vendor Integration Guide (End-to-End) — the complete journey of embedding plus permission integration (batch backfill, login sync, logout revocation)
1. Quick Start
Add the following before </body> on your page:
<script>
window.maiagentChatbotConfig = {
webChatId: 'your-web-chat-id',
baseUrl: 'https://chat.maiagent.ai/web-chats',
primaryColor: '#1890ff',
}
</script>
<script src="https://chat.maiagent.ai/js/embed.min.js" defer></script>Get
webChatIdfrom the Web Chat settings page in the admin console (see Connecting Chat Platforms: Website; the embed code generated by the console fills it in automatically)The
baseUrland SDK URL above use the SaaS environment (chat.maiagent.ai) as an example; for private cloud / on-premises deployments, replace them with your environment's domainwindow.maiagentChatbotConfigmust be defined before the SDK script loads
Default behavior: a chat button appears at the bottom-right of the page. Clicking it opens a floating chat window, and the user can switch between the floating and sidebar window modes.
Initialization Timing
After loading, the SDK registers a document.body.onload handler to run initialization; normally no manual intervention is needed. When you need to control the initialization timing (for example, waiting for an SPA container to mount, or deferring rendering):
Lazy-load the script: dynamically insert the
embed.min.js<script>tag only when appropriateTrigger manually: set up
window.maiagentChatbotConfigfirst, then calldocument.body.onload()
The SDK initializes only once per page; duplicate loads are ignored.
2. Window Modes
The enabledWindowModes array determines which window modes are available to the user; the first element is the default mode. When unset, it is equivalent to ['floating', 'sidebar'].
floating
A floating window overlaid at the bottom-right of the page; the button is draggable and the window is resizable (320×400 to 900×900 px)
General customer service, consultations
sidebar
A sidebar docked to the right edge of the viewport (width 320–800 px, drag to resize); page content automatically shrinks to make room
Work scenarios where users chat while viewing the page
maigpt
A ChatGPT-like full interface (conversation history sidebar, search, settings) that fills the specified container or the whole screen
Main page feature areas, a site-wide AI entry point; see MaiGPT Mode
When the array contains two or more modes, a mode-switch button appears in the chat window;
allowWindowModeSwitch: falsehides itWhen
maigptis the first element, MaiGPT mode is used and the remaining elements are ignored (that mode does not offer switching)The legacy
defaultWindowModefield is deprecated: it still works (treated asenabledWindowModes: [value]), but a deprecation warning is shown in the console
What the Three Modes Look Like
3. Identifying Users
Web Chat has three identity levels, based on whether a Contact is bound:
Anonymous
Set nothing
Kept per browser
✖
Frontend auth
Config carries auth: { sourceId, ... }; the SDK automatically creates or matches a contact
Follows the contact, works across devices
✔
Backend integration
Backend calls the identity sync API to get a contactId; config carries contactId
Follows the contact, works across devices
✔
Frontend auth: After the SDK finishes initializing, it automatically calls MaiAgent's identity sync API (setup-contact-credentials) with the contents of auth, creating or matching a contact by sourceId:
If this Web Chat's login settings enable "Allow embedded clients to chat without logging in using Source ID" and signature mode is selected, ts and sig are required. If either is missing or verification fails, the user is redirected to the login page. These two fields are also accepted when calling MaiAgent.auth.setup() manually.
Backend integration: Your backend calls the same API when the user logs in (it can bind MCP tool credentials at the same time), stores the returned contactId in the member record, and the frontend passes only contactId.
How to choose between the two:
If you only need to "recognize the user and keep conversations across devices" → frontend auth is the simplest
If you need to bind the user's Access Token into MCP tool credentials (so the AI calls your APIs with the user's permissions) and don't want the token to appear in the frontend page source → backend integration
Both use the same underlying contact mechanism; the same
sourceIdis treated as the same contact, and they can be mixed
Security Notes
contactId is an identity credential: anyone who has it can chat as that user and see their conversation history. Only output contactId to the user themselves on post-login pages, and never put it in the source of public pages.
The requirements for auth.sourceId depend on whether signature verification is enabled:
Signature verification disabled: Identity sync is a public endpoint, so a guessable
sourceIdis equivalent to an impersonatable identity. Use an unguessable value (such as a UUID), not a sequential number, email address, or phone number.Signature verification enabled: Security comes from the signature rather than the
sourceIditself, so readable values such as student IDs, employee IDs, and registered email addresses can be used directly. The secret exists only on your server; without it, knowing thesourceIdis not enough to calculate a valid signature.
Signature Verification
In Web Chat's login settings, you can enable "Allow embedded clients to chat without logging in using Source ID" so users already logged in to your website do not need to log in again in the chat window. The switch and secret are on the Login Settings tab in the admin console. For instructions, see Chat Without Login Using a Contact Source ID in the user manual.
Two verification methods are available; signature mode is recommended:
Require signature verification
ts and sig must be provided, and access is granted only after the signature passes verification
Source ID only
No signature verification; access is granted whenever sourceId is provided. Suitable only for testing or closed intranet environments
Signature algorithm
Send the result as a lowercase hex string. ts is Unix time in seconds (UTC). The platform generates the secret in the admin console. Store it only in your server's environment variables; never include it in frontend code.
Verification rules
Validity period
Configurable to 1, 5, or 15 minutes in the admin console; the default is 5 minutes
Clock tolerance
Allows a 60-second offset; timestamps more than 60 seconds in the future are always rejected
One-time use
The same signature can be used successfully only once; the signature itself serves as the anti-replay nonce
Web Chat binding
The signature includes webChatId, so a signature for another Web Chat in the same organization cannot be reused
Rejection response
All failures return the same external response, revealing neither the reason nor whether the sourceId exists
A signature is valid for one use only. Recalculate it every time the user enters; never cache it. The validity period limits how long the signature can be exchanged for a contact identity, not how long the conversation lasts. After the identity is obtained, the conversation is not interrupted when the signature expires.
Relationship between expiration and logout
The resulting contactId does not expire, and the platform currently has no endpoint for invalidating it. After a user logs out of your website, you can stop issuing new signatures. The frontend can call MaiAgent.auth.signOut() to return the chat window to anonymous mode. To revoke tool credentials, see Logout and Credential Revocation.
Troubleshooting signature verification failures
"View Signature Verification Failure Logs" in the admin login settings lists recent failures and their causes for troubleshooting:
Signature expired
The server clock is offset, or the frontend cached the signature
Timestamp exceeds the allowed future range
The server clock is more than 60 seconds fast
Signature mismatch
The secrets differ, or the signature string was assembled incorrectly (the separator must be an ASCII period)
Missing timestamp or signature
ts or sig was not provided
Signature already used
The same signature was submitted a second time
Source ID maps to multiple contacts
This Web Chat contains duplicate contact records with the same sourceId
Allowed Embedding Domains
Web Chat's "allowed embedding domains" list restricts which websites can complete identity sync (both auth and the backend's setup-contact-credentials are subject to it). This list is currently configured for you by the MaiAgent team: please provide the list of domains to allow to your integration contact.
Empty list (default)
No origin restriction
Lists https://example.com
Exact match on scheme + host (+ port)
Lists *.example.com
Covers example.com and all its subdomains (any scheme / port)
List has entries but all are invalid
Rejects all origins (fail closed); it does not silently fall back to unrestricted
For any Web Chat embedded externally that uses identity features, we recommend always configuring this list to narrow down where contactId can be obtained.
4. Configuration Reference
All fields supported by window.maiagentChatbotConfig. Setting unknown fields does not raise errors, but the console shows a [maiagent] Unknown config options: ... warning to help catch typos.
Basic
webChatId
string
✅
The Web Chat's unique identifier
baseUrl
string
✅
The Web Chat service URL; for SaaS it is https://chat.maiagent.ai/web-chats
auth
object
Frontend identity settings: sourceId (required), name, contextData, mcpCredentials, plus ts and sig (required when signature verification is enabled; see Signature Verification). The SDK automatically runs auth.setup() once it is ready
queryMetadata
object or string
Knowledge base retrieval scope filter (does not enter the LLM prompt)
locale
string
Interface language (such as zh-TW, en); for the supported list see MaiGPT Mode, Section 5. Priority: config > user's last selection > browser language > zh-TW
In the current version, passing auth causes the console to incorrectly report Unknown config options: auth. Functionality is unaffected; you can ignore that warning.
Window Modes and Behavior
enabledWindowModes
string[]
['floating', 'sidebar']
Available window modes; the first entry is the default. See Window Modes
allowWindowModeSwitch
boolean
true
Whether to show the window mode switch button (only meaningful when two or more modes are enabled)
showButton
boolean
true
Whether to show the chat button. When false, open the chat programmatically via MaiAgent.control.open()
showChatNotification
boolean
false
Whether to show a notification next to the button when a reply arrives while the window is closed
chatNotificationTitle
string
Title text of the notification
preventIosInputZoom
boolean
Prevent iOS Safari from auto-zooming the page when the input field is focused
maigptTitle
string
MaiGPT mode only: the sidebar brand title, defaults to MaiGPT
Appearance
Size fields accept a number (treated as px), or an 'Npx' or 'Nrem' string.
primaryColor
string
#1890ff
Theme color (button and primary interface color)
buttonSize
string or number
3rem
Chat button size
buttonRadius
string
50%
Chat button corner radius
buttonIcon
string
Image URL for the button icon (takes precedence over openIconHtml)
openIconHtml
string
Built-in SVG
Custom HTML for the button's "open" state
closeIconHtml
string
Built-in SVG
Custom HTML for the button's "closed" state
windowWidth
string or number
24rem
Floating window width
windowHeight
string or number
40rem
Floating window height
windowRadius
string
0.75rem
Floating window corner radius
boxShadow
string
0.125rem 0.125rem 0.5rem #00000044
Button and window shadow
Position
buttonPositionBottom
string or number
16 (px)
Button distance from the bottom of the viewport
buttonPositionRight
string or number
16 (px)
Button distance from the right of the viewport
windowPositionBottom
string
5rem
Floating window distance from the bottom
windowPositionRight
string
1rem
Floating window distance from the right
windowPosition
string
Set to 'center' to center the floating window
The chat button supports drag-and-drop repositioning, and the position is remembered in the browser. On the next load, if the remembered position falls outside the current viewport, it automatically returns to a safe position.
5. SDK API
After the SDK initializes, use the global MaiAgent object. All methods should be called after the SDK is ready (see the availability check in Troubleshooting).
Window Control MaiAgent.control
open()
Open the chat window
close()
Close the chat window
isOpen()
Return whether the chat window is open (boolean)
Equivalent global shortcuts are also available: window.maiagentOpenChat() / window.maiagentCloseChat().
Messages MaiAgent.chat
send(content)
Send a text message as the user
clearHistory()
Clear the current conversation's message history
newConversation()
Start a new conversation
Events MaiAgent.events
on(eventType, callback)
Register an event listener
off(eventType, callback)
Remove an event listener (must pass the same callback reference)
Available events:
messageReply
A reply is received from the AI assistant
A parsed object: { content: string, sender?: { name, avatar }, timestamp?: number, ... }
sdkReady
SDK initialization completes
—
authReady
auth.setup() completes
—
iframeReady
The chat window iframe is ready
—
Locale and Speech
MaiAgent.locale.set(lang)
Switch the interface language, such as 'zh-TW', 'zh-CN', 'en'; for the supported list see MaiGPT Mode, Section 5
MaiAgent.speech.set(lang, provider?)
Set the language for speech recognition and synthesis; provider can specify the speech service provider (such as 'azure')
locale only affects the interface text, not the language of the AI's answers; for configuring the AI's reply language, see Multi-Language Support.
Identity MaiAgent.auth
setup(authConfig)
Create or match a contact and apply the identity; returns Promise<string | null> (the contactId on success). authConfig has the same fields as the config's auth
signOut()
Sign out of the current identity, return to anonymous, and clear contextData. Frontend only; tool credentials already bound on the backend must be revoked separately, see Logout and Credential Revocation
When the config contains auth, the SDK calls setup() automatically—no manual call needed. Call it manually only when the user logs in / out in an SPA, or when you need to update contextData.
6. Complete Example
7. Troubleshooting
The button doesn't appear
Whether maiagentChatbotConfig is defined before the SDK script; whether webChatId / baseUrl are correct; whether there are errors in the console
Console shows Unknown config options: ...
Check field spelling against the Configuration Reference (the false positive for auth can be ignored)
MaiAgent is not defined
The SDK has not finished loading; call after DOMContentLoaded, or first check typeof MaiAgent !== 'undefined'
Event listeners don't fire
Confirm the event name is correct (use the MaiAgent.EVENT_TYPES constants); off() must receive the same function reference passed to on()
Conversations disappear on another device
Anonymous conversations are kept per browser; for cross-device continuity set auth or contactId (see Identifying Users)
Identity doesn't take effect after setting auth (400 error)
If the Web Chat has "allowed embedding domains" configured, only pages on listed domains can complete identity sync; confirm the embedding page's domain is on the list
Button position is off
Check whether page CSS conflicts with the button styles; whether position parameter formats are correct (number, px, or rem)
Calling the SDK safely:
Last updated
Was this helpful?
