Embed the widget
Copy the embed code from the app and add it to your website, via cdn.xicbot.de or your own path on your domain, with enablement, a domain list and a load check.
In plain language
One line of code puts the chat window on your website. This page shows where to find the code in the app. It says what has to be set first. This includes switching the window on and the list of allowed domains. There are two ways to embed it. The code can come from our server or from your own domain. Last, you check that the window has reached your page.
All documentation topics
A single line of code puts the chat window on your website. This page shows where to find the embed code in the app, which settings have to be in place first, how the two embedding routes differ and how to tell that the window has actually reached your site.
Where to find the embed code
In the app, open Work › Assistants (app.xicbot.de/assistenten) and click Edit next to the assistant. With the Read role the button is labelled View. The expanded area contains the section Chat window on your website, with the note *The chat window runs in its own frame. It can neither read nor change the page it sits on.* This is where you find the enable switch, the domain list, your own path, both embed codes, the embedding status, the preview and the public key. The Assistants area only opens once your email address is confirmed; until then the app reports This area stays locked until the email address is confirmed.
| Role | What you can do in this section |
|---|---|
| Read | View the settings, copy the embed code, open the preview. The fields are locked and the app shows *With the Read role this area is view-only. Changes need at least the Edit role.* |
| Edit | In addition, change every field and apply it with Save. |
| Administration, Owner | In addition, Generate a new key. |
These actions share one limit of 30 per minute per signed-in user: Save in this section and under Basics, Generate a new key, creating assistants, publishing and restoring versions, creating and changing tools, and creating and changing check questions and starting runs in Acceptance. Beyond that the app reports Too many attempts. Please wait a moment. A whole run in Acceptance counts as one action, and so does each time a check question is switched on or off. Anyone who toggles many check questions within a minute may then have to wait up to a minute before Save works again. Roles are assigned under Team and roles.
Onto your website in six steps
-
Step 1
Set the assistant to active
Under Basics, choose active in the Status field and apply it there with Save. A new assistant starts as Draft, with the chat window switched off and a first version already in place. With Draft or paused, the embed code responds as if the key did not exist.
-
Step 2
Enable the chat window
Tick Enable chat window and press Save. The app explains: *Only with this setting does the snippet answer on other sites. Without it, it stays inert.* Once saved, the app shows Saved.
-
Step 3
Add domains if you want to
Under Allowed domains, list the websites on which conversations may start. An empty field allows any website.
-
Step 4
Copy the embed code
Press Copy embed code under Embed code via our address or Embed code via your own address. The app confirms with Embed code copied.
-
Step 5
Add the code to your pages
Place the line in the
<head>of every page the window should appear on, usually through your site's page template. -
Step 6
Check the embedding
Open a page that carries the code in your browser, then reopen the assistant in the app. If the box Embedding on your website shows Last loaded: with a time, the window has arrived.
The two embedding routes
The app shows two embed codes side by side. Both load the same chat window; they differ in which address the visitor fetches it from.
| Aspect | Embed code via our address | Embed code via your own address |
|---|---|---|
| Address in the code | https://cdn.xicbot.de/einbetten.js | Your own path, for example https://example.com/chat/einbetten.js |
| Prerequisite | no setup on your server | a saved own path that your server forwards to XICBOT |
| Addresses the visitor contacts | cdn.xicbot.de and the XICBOT interface | only your domain |
| Interface address | data-api in the code | not needed, the loader derives it from the path |
| Shown in the app | as soon as the current state has loaded | only after an own path has been saved |
index.html html
<!-- Embed code via our address -->
<script src="https://cdn.xicbot.de/einbetten.js" data-xicbot="…" data-api="…" defer></script>
<!-- Embed code via your own address, path https://example.com/chat -->
<script src="https://example.com/chat/einbetten.js" data-xicbot="…" data-basis="https://example.com/chat" defer></script>The ellipses stand for your key and the interface address. Copy the code from the app instead of typing it: all values are written out in full there.
| Attribute | Meaning |
|---|---|
src | Address of the loader einbetten.js. The directory of this address is the base the chat window is loaded from. Only http and https are accepted. |
data-xicbot | The assistant's public key. Without it, the loader builds nothing. |
data-api | Address of the interface. Only present in the embed code via our address. |
data-basis | Base for the chat window. Only present in the embed code via your own address; it keeps the window in the right place even if einbetten.js is later served from somewhere else. The base also applies to the interface only if protocol, host name and port match the page the code sits on. |
data-einwilligung="erforderlich" | Added as soon as Consent before the first conversation is switched on and saved. Nothing then loads on its own before consent is given, see Consent and visitor rights. |
defer | The browser runs the loader only after it has parsed the page. |
Further attributes on the code, such as colour, position or language, are described in Script attributes. The window fetches its appearance, texts and position from the server when it loads, so changes under Widget settings take effect without new code. You only need to replace the code after generating a new key, switching Consent before the first conversation on or off, or changing your own path.
Delivery via cdn.xicbot.de works as follows:
- After the first visit, the browser only contacts cdn.xicbot.de over an encrypted connection for one year.
- Search engines are asked not to index the files and not to follow their links.
- No header forbids embedding in other sites. Isolation from your page comes from the sandboxed frame.
- If delivery does not respond, cdn.xicbot.de gives up with an error after 3 seconds of connecting or 10 seconds of waiting instead of keeping the request open. Thanks to
defer, your page does not wait for the loader.
Enablement and status
The chat window only works when all four conditions are met:
- Enable chat window is ticked and saved.
- The assistant's Status is active, not Draft or paused.
- Your account is active.
- For a demo account, its period has not expired.
If any of them is missing, the chat window treats this like an unknown key. On your website the loader then removes the launcher and the chat window as soon as the window has fetched its settings after your page has loaded. If the code carries data-einwilligung="erforderlich", this only happens after consent or a click on the launcher; the preview in the app shows This chat is not available. If the assistant is active but has no active version yet, the window appears with This assistant is not ready yet. Versions are managed under Assistants.
Allowed domains
The Allowed domains field takes up to 500 characters. The app notes: *One per line. Subdomains are included. Empty means any website may embed the window.*
- One entry per line; a comma also separates entries. Case does not matter and surrounding spaces are removed.
- Enter the host name only, for example
example.com. The comparison uses the bare host name of the page withouthttps://, path or port, so an entry that contains any of these matches no page. example.comalso coversshop.example.comandwww.example.com. The reverse does not hold:www.example.comdoes not coverexample.com.- If the window reports no host name, the page counts as not enabled whenever the list is filled in.
- An empty field means no restriction.
The list is checked when a visitor opens the window and the conversation starts. If the code requires consent, the conversation, and with it the check, only starts after consent has been given. The window itself reports the address of the page. If it is not on the list, the visitor reads This chat is not enabled for this website. The launcher still appears on such a page, and Embedding on your website records it as well. The key remains readable in the page source; the list controls where conversations can start. If the page is allowed but the visitor's address is blocked, they read This chat is currently not available to you., and the input field and send button stay locked, see Conversations.
Your own path on your domain
With Your own path on your domain, the window and its requests run through your domain. The app calls this *The recommended route: window and requests run through your domain, the visitor talks to no external address.* For this, your web server forwards a path to XICBOT. The field accepts:
- An absolute address with
https://orhttp://and a host name, for examplehttps://example.com/chat. - The field is an address field: the browser does not submit an entry without a scheme, such as
example.com/chat. Schemes other thanhttps://orhttp://are only rejected by the service when saving. - At most 200 characters.
- No query (
?…) and no fragment (#…). - A trailing slash and surrounding spaces are removed on saving.
- An empty field means no own path is set up. The matching embed code then disappears.
- If the service rejects the value when saving, the app states the reason directly below the field, for example The address of your own path must not contain “?” or “#”. If the service rejected only marked fields, the app also reports Please check the marked fields.
Embed code via your own address only appears after saving. Until then the app shows *As soon as an own path is entered above and saved, the matching embed code appears here.* This code has no data-api: the loader only uses the path for the interface as well if protocol, host name and port of the path exactly match the page it sits on. So enter the path with the host name your pages run under; for https://www.example.com that is https://www.example.com/chat.
What your server forwards
| Request on your domain | Target at XICBOT | Requirement |
|---|---|---|
/chat/ and everything below it, including files with version names such as rahmen.<version>.js | Widget delivery, without the /chat prefix | Header X-Xicbot-Base set to exactly the address from the field, for example https://example.com/chat |
/chat/api/ | Interface under /api/ | no buffering and no caching, read timeout 300 seconds: the response to …/send arrives as an event stream |
- Your server sets
X-Xicbot-Baseitself and does not pass through a visitor's header of the same name. The chat window's security policy is built from this header. - You only need
X-Xicbot-Apiif the interface does not sit under the same path. Without it,X-Xicbot-Basealso applies to the interface. Your server sets or clears this header itself, too. - Both headers contain an address made of
http://orhttps://, a lower-case host name, an optional port and path, at most 200 characters. A header that is set but unusable is rejected with status 400 instead of silently falling back to the default address. - Delivery answers unknown version names with 404.
- Do not set the delivery headers (caching, origin, content type, security policy) a second time. They come from XICBOT and would otherwise appear twice in the response.
How the loader starts
einbetten.jsonly builds the chat window once your page has finished loading.- If the embed code appears twice on a page, the second copy has no effect. There is one chat window per page.
- The loader itself makes no network requests. Everything that fetches data runs inside the chat window.
- The chat window is a frame from a different origin with
sandbox="allow-scripts allow-popups allow-popups-to-escape-sandbox"and withoutallow-same-origin. Your page cannot read its content, and the window cannot read your page. The loader, however, keeps the conversation ID in your page's storage; anyone who knows it can retrieve the history, including scripts on your page. - The frame loads without a referrer (
referrerpolicy="no-referrer"). Its parameters, including your page's origin, travel in the fragment of the address, and a fragment is not sent to the server when the frame loads. The window then reports your page's host name to the service itself, for the embedding status and for Allowed domains. - The window sits in the browser's top layer. In browsers without a top layer it stays above your page with the stacking value
2147483647. - If Consent before the first conversation is switched on, nothing loads on its own before consent. A click on the launcher builds the window.
- How your page can control the window by script is covered in JavaScript and storage.
Your page's content security policy
If your page has a content security policy, the following applies to the widget:
- Your policy has to allow the loader from the address in the embed code and the chat window as a frame from the same base. With your own path, that is your own domain.
- Your policy needs no entry for the interface: the requests come from the chat window, not from your page.
- The loader does not insert a
<style>element but sets each property on the element directly, so a strict style rule does not block it. - The launcher image is delivered as a
data:address. If your policy does not allow that for images, the launcher shows the brand dots instead. - The chat window brings its own policy. It allows embedding on any page; where conversations can start is controlled by Allowed domains.
Check the embedding
The box Embedding on your website shows either Last loaded: with date and time, followed by Page: with the host name the window last loaded on, or The window has never loaded on your website. Below it the app explains: *What is recorded is when the window last loaded on an external page - not the first conversation. The preview on this page does not count.*
- The entry is written as soon as the chat window fetches its settings, even for an assistant without an active version. If the visitor has reached the request limit, that fetch writes no entry.
- What is recorded is the page's host name in lower case, at most 120 characters.
- If the window loads again on the same host name, the service rewrites the time at most every five minutes. A different host name is recorded at once.
- If the embed code carries
data-einwilligung="erforderlich", the entry only appears once a visitor consents or clicks the launcher. - Without enablement, without the status active or while the account is inactive, no entry is written.
- Sites outside Allowed domains are counted too, because the list is only checked when a conversation starts.
- If the app cannot load the state, it shows The current state could not be loaded.
- The app reads the display when you open the assistant, after saving and after a new key. To see a newer state, close the assistant and open it again.
Show preview opens the window inside the app; the preview does not answer and does not count as an embedding, see Preview in the app for details. It loads via our address even if you have entered your own path. Whether your path works only shows when you open your own page. How to test answers before embedding is covered in Test and acceptance.
Public key
Public key shows the 32-character identifier (digits and a to f) that appears in the embed code as data-xicbot. The app notes: *It appears in plain text on every foreign page. It only permits using this one chat window.* The key is created together with the assistant and cannot be entered by hand.
Generate a new key is available to the Administration and Owner roles; other roles see *Generating a new key needs the Administration or Owner role.* After the click the app asks: *Generate a new key? The current embed code stops working immediately.* Confirm with Generate a new key or back out with Cancel.
- The old key stops working at that moment. Every page with the old code loses its launcher as soon as the chat window loads there.
- The app fetches the embed code again, shows Loading … in the meantime and then reports The new key is active. Please replace the embed code everywhere. If you collapse and expand the assistant again during the rotation, depending on the timing the new embed code only arrives with the expanding; the message may then already appear while Loading … is still shown.
- If the new embed code does not arrive afterwards, the key has still been replaced. Instead of an error message the app then shows The new key is active and the previous embed code no longer loads. The new embed code could not be loaded. Open the assistant again to see it, then replace it everywhere. In place of the codes it shows The current state could not be loaded.
- If the assistant is no longer open when the rotation finishes, for example because you have opened another one in the meantime, the app names it: The new key for “…” is active and the previous embed code no longer loads. Open that assistant to see the new embed code, then replace it everywhere.
- The audit log records who rotated the key and when. The key itself, old or new, is not stored there.
- If the audit log entry cannot be written, the old key stays in place and the app reports Not saved: the entry in the audit log could not be written. Please try again.
Messages
| Message | Where | Meaning |
|---|---|---|
| This chat is not available. | Preview in the app, chat window | Unknown key, chat window not enabled, status not active, account inactive or demo period expired. On your website the launcher disappears instead of showing the sentence. |
| This assistant is not ready yet. | Chat window | The assistant has no active version yet. |
| This chat is not enabled for this website. | Chat window, on opening | The site is not on Allowed domains. |
| This chat is currently not available to you. | Chat window, on opening or sending | The visitor's address is blocked. When sending, a block with this conversation only chosen under What is blocked is enough as well, see Conversations. The input field and send button stay locked. |
| The chat could not be started. | Chat window, on opening | The service refused to start the conversation for another reason. |
| Too many requests right now. Trying again in … . | Chat window | A limit has been reached. The window retries on its own after the stated wait, shown in minutes from 90 seconds on. See API limits. |
| The chat cannot be reached right now. Trying again in … . | Chat window | Service or network disruption. While loading, the window tries up to six times with pauses from 15 seconds to 4 minutes; when starting a conversation it retries up to three times, after 15, 30 and 60 seconds. After that it shows The chat cannot be reached right now. without another attempt. |
| The chat cannot be reached right now. | Chat window, while loading | If this appears at once, without a waiting time, the interface address returned a response that did not come from the chat, for example a “not found” page or an HTML page from your server on your own path. The window does not retry in that case. Server errors (status 500 and above), by contrast, are retried with a waiting time. |
| Saved. | App | The settings have been applied. The app then reloads the embed code. |
| Saved. The embed code for “…” could not be reloaded afterwards. Open that assistant again to see it. | App | The settings have been saved; only the new embed code did not arrive. Instead of the codes the app shows The current state could not be loaded. |
| The new key is active and the previous embed code no longer loads. The new embed code could not be loaded. Open the assistant again to see it, then replace it everywhere. | App | The new key is already valid; only the new embed code did not arrive afterwards. Instead of the codes the app shows The current state could not be loaded. |
| The new key for “…” is active and the previous embed code no longer loads. Open that assistant to see the new embed code, then replace it everywhere. | App | The key has been rotated, but this assistant was no longer open when the rotation finished, for example because you had opened another one in the meantime. The ellipsis stands for its name. |
| Embed code copied. | App | The code is on the clipboard. |
| Copying was not possible. Please select the text by hand. | App | The browser refused access to the clipboard. The field with the code can still be selected. |
| The delivered widget file could not be read. The embed code is shown, but the delivery itself should be checked. | App, below the code | The embed code is still shown. Whether the window loads on your website is not settled by this; Embedding on your website shows that. Please let us know at mail@xicbot.de. |
| The current state could not be loaded. | App | The embed code or the embedding state did not arrive. If this appears right after Save, the settings have still been saved; if it appears after Generate a new key, the new key is already valid. Open the assistant again. |
| Too many attempts. Please wait a moment. | App | More than 30 of the actions listed above under “Where to find the embed code” per minute, such as saves, key rotations or a run in Acceptance. |
| This entry no longer exists. Reload the page to see the current state. | App | The assistant no longer exists, for example because it was deleted in another window. The message appears on Save or Generate a new key. |
| That did not work. Please check your entries. | App | The service rejected the change, and the app cannot assign the reason to a field. |
| Please check the marked fields. | App | The service rejected values when saving; the reason is shown below each field concerned, for example below Your own path on your domain. |
| The service reported an error. Please try again later. | App | The service reported a server error while saving, rotating the key or loading the embed code. |
| Not saved: the entry in the audit log could not be written. Please try again. | App | The audit log entry could not be written while saving or rotating the key. The change has not been applied; after a failed key rotation the old key remains valid. |
| This area stays locked until the email address is confirmed. | App | Your email address has not been confirmed yet. |
Further reading
- Widget settings: title, colour, position, size and prompts.
- Script attributes: every attribute of the embed code.
- Consent and visitor rights: consent gate and withdrawal.
- Widget delivery: files, versions and caching.
- Chat in the widget: what the visitor experiences in the window.
- Widget API: the chat window's public endpoints.
- Conversations: reading conversations and blocking visitors.
Frequent questions
Why does the chat window not appear on my website?
Check that Enable chat window is ticked and saved and that the Status is active. If either is missing, the loader removes the launcher as soon as the chat window has fetched its settings after the page has loaded. With Consent before the first conversation, nothing loads on its own before consent. If Embedding on your website says The window has never loaded on your website., no chat window on a page has fetched its settings yet: the code is missing from the page, one of the two settings is missing, or, with consent switched on, no visitor has consented or clicked the launcher yet. The preview in the app does not count.
What does the message that the chat is not enabled for this website mean?
The site is not on Allowed domains. Enter the host name without https:// and without a path, for example example.com; subdomains are then included. After Save, the list applies to the next conversation.
Why does the chat window immediately say the chat cannot be reached?
If The chat cannot be reached right now. appears as soon as the window loads, with no waiting time, the interface address returned a response that did not come from the chat, such as a “not found” page or an HTML page. With your own path, check that your server also forwards the requests under …/api/. If the message states a waiting time, there is a disruption and the window retries on its own.
Do I have to replace the embed code after every change?
No. The window fetches its appearance and texts from the server when it loads. You only need new code after generating a new key, after switching Consent before the first conversation on or off, and after changing your own path.
Can I use the same chat window on several websites?
Yes. The same code works on every website that Allowed domains permits, and on any website if the list is empty. Embedding on your website only shows the site the window last loaded on.
Which of the two embedding routes suits me?
Embed code via our address needs no change to your server. Embed code via your own address needs a path that your server forwards to XICBOT; in return the visitor only talks to your domain. The app calls this the recommended route.
Ask it yourself, Assistant of this website
Automated assistant