Chatbot Integration
This document covers how to open and interact with the chatbot from your own custom elements, buttons, links, search bars, or any other UI.
Prerequisites
The chatbot script must be loaded on the page:
<script src="https://scripts.dialogintelligens.dk/universal-chatbot.js?id=YOUR_CHATBOT_ID"></script>Option 1: JavaScript API (window.DialogIntelligens)
The chatbot script exposes a global window.DialogIntelligens object with the following methods:
| Method | Description |
|---|---|
open() | Opens the chat window |
open(message) | Opens the chat window and sends a pre-filled message |
open({ image, message? }) | Opens the chat and sends an image with optional text |
hide() | Hides the chat button and iframe completely |
show() | Shows the chat button (closed state) |
setMetadata(metadata) | Attaches metadata to the visitor's session (deep-merged) |
setSignedMetadata(token) | Attaches verified metadata from a backend-signed RS256 JWT |
destroy() | Removes the chatbot from the page entirely |
Examples
Custom button:<button onclick="window.DialogIntelligens.open()">Chat with us</button><a href="#" onclick="event.preventDefault(); window.DialogIntelligens.open()">Need help?</a><button onclick="window.DialogIntelligens.open('I need help with my order')">Order support</button>Open with an image
Your site owns the upload interface. Pass the image selected by the visitor as a browser File;
Diverge opens the chatbot and sends it as the first message. Text is optional, so image-only
conversations are supported.
<input id="product-image" type="file" accept="image/*" />
<button id="find-similar">Find similar products</button>
<script>
document.querySelector("#find-similar").addEventListener("click", () => {
const image = document.querySelector("#product-image").files[0];
if (!image) return;
window.DialogIntelligens.open({
image,
message: "Find products similar to this", // Optional
});
});
</script>The call is safe before the widget has finished initializing. Images must be valid image files no larger than 5 MB. Diverge resizes large images before passing them into the normal chatbot image flow. Invalid or oversized files are rejected and a reason is written to the browser console.
Attaching session metadata
Use setMetadata() to attach context from your page to the visitor's chat session — for example
a customer id, plan, or cart state:
<script>
window.DialogIntelligens.setMetadata({
customer: {
id: "cust-123",
plan: "premium",
},
});
</script>- Safe to call as soon as the chatbot script has loaded — even before the widget finishes initializing. Patches are queued and delivered once the widget is ready.
- Repeated calls deep-merge into the existing session metadata: nested objects merge, scalars and arrays are replaced. There is no way to delete a key.
- The merged metadata is limited to 32 KiB (JSON-encoded) and 20 levels of nesting. The keys
__proto__,prototype, andconstructorare rejected. destroy()drops patches that have not been delivered yet; metadata that already reached the server stays on the session.
Delivery: the session metadata appears as session.metadata in every livechat webhook event
and in the livechat agent context (including the Intercom bridge), exactly like metadata set
through the server-side Chatbot API (PATCH /api/v1/chat/session/metadata).
To have Diverge call your API during a conversation (for example order or delivery lookups), see Universal API Integration. Metadata is for session context on webhooks and livechat; runtime variables on that guide are what forward browser tokens into outbound API requests.
Verified (signed) metadata
When downstream systems must be able to trust metadata — for example an account id used to
look up orders — have your backend sign it as an RS256 JWT and pass the token through the widget
with setSignedMetadata(). Our API verifies the signature against a public key you configure and
stores the claims separately as verified_metadata, so consumers can always distinguish trusted
from untrusted data.
1. Generate a keypair (keep the private key on your backend; you will paste only the public key into the dashboard):
openssl genrsa -out signed-metadata-private.pem 2048
openssl rsa -in signed-metadata-private.pem -pubout -out signed-metadata-public.pem2. Configure the public key in the dashboard under Developer → Signed metadata, per chatbot and environment. Signed metadata is enabled as soon as a key is saved and disabled when the key is removed.
3. Sign a token on your backend when the visitor is authenticated. The token's claims become the verified metadata:
import jwt from "jsonwebtoken";
const token = jwt.sign(
{
sub: "account-123",
logged_in: true,
store: "sweden",
},
privateKeyPem,
{ algorithm: "RS256", expiresIn: "10m" },
);4. Pass the token through the widget on the page:
<script>
window.DialogIntelligens.setSignedMetadata(token);
</script>- Signed with RS256 using the private key matching the configured public key.
- Must include
expandiat, with a lifetime of 15 minutes or less (exp - iat ≤ 900). - Registered claims (
iss,aud,exp,iat,nbf,jti) are stripped;suband all custom claims are kept and deep-merged intoverified_metadata. - The same 32 KiB / 20-level / blocked-key limits as
setMetadata()apply to the merged result.
Semantics: queueing and retry behave like setMetadata() — safe to call before the widget is
ready. A token that fails verification (bad signature, expired, oversized) is rejected once and
not retried; sign a fresh token and call setSignedMetadata() again.
Delivery: verified claims appear as session.verified_metadata — alongside but separate from
session.metadata — in every livechat webhook event and the livechat agent context. In the
Intercom bridge, a verified sub (or user_id) claim becomes the Intercom contact external_id
so the conversation attaches to the contact you already have for that user, verified email/name
take precedence for the contact identity, and top-level scalar claims are exposed as
di_verified_* attributes. Client-side setMetadata() calls can
never write into verified_metadata.
Option 2: URL Parameters
Append ?chat=open to any page URL where the chatbot is loaded. The chatbot will automatically
open on page load and the parameters are stripped from the URL.
https://example.com/page?chat=openYou can also include a chatbot_message parameter to send a pre-filled message when the chat opens:
https://example.com/page?chat=open&chatbot_message=I+need+help+with+my+orderUsing chatbot_message alone (without chat=open) also works. The chat will open automatically:
https://example.com/page?chatbot_message=What+are+your+opening+hours%3FThis is useful for email campaigns, QR codes, FAQ links, or any link where you want the chat to open with a specific question.
Option 3: Inline Search Bar Widget
An inline search bar can be embedded anywhere on the page. When the user types a question and presses Enter or clicks send, the chatbot opens and receives the message.
Setup
- Load the search bar script after the chatbot script:
<script src="https://scripts.dialogintelligens.dk/universal-chatbot.js?id=YOUR_CHATBOT_ID"></script>
<script src="https://dialogintelligens.github.io/scripts/inline-search-bar.js"></script>- Add a container element where you want the search bar to appear:
<div class="chatbot-search-widget" data-placeholder="Ask us anything..."></div>Or use a class for multiple instances:
<div class="chatbot-search-widget"></div>Wrapping the search word in a fixed sentence
By default the search bar sends exactly what the user typed. Use data-message-template to wrap
the search word in a fixed sentence before it is sent, so the chatbot gets some context.
{query} is replaced with whatever the user typed:
<div
class="chatbot-search-widget"
data-placeholder="Search for a product..."
data-message-template='I am looking for sizing help with "{query}", can you help me?'
></div>A user searching for wine makes the chatbot receive:
I am looking for sizing help with "wine", can you help me?If you only need text before and/or after the search word, use data-message-prefix and
data-message-suffix instead:
<div
class="chatbot-search-widget"
data-message-prefix="What is the delivery time on "
data-message-suffix="?"
></div>A user searching for wine makes the chatbot receive What is the delivery time on wine?.
Notes:
- The attributes are set per widget, so different search bars on the same page can use different sentences.
{query}may appear multiple times in the template — every occurrence is replaced.data-message-templatetakes precedence overdata-message-prefix/data-message-suffixwhen both are set.- If
data-message-templateis set but does not contain{query}, the raw search word is sent and a warning is logged to the console. - All three attributes are optional. When none of them are set, the search bar behaves exactly as before and sends the raw search word, so existing integrations are unaffected.
Manual initialization with custom config
<script>
window.initChatbotSearchWidget("#my-custom-element", {
placeholder: "How can we help?",
messageTemplate: 'I am looking for sizing help with "{query}", can you help me?',
sendIconColor: "#333",
borderRadius: "10px",
maxWidth: "500px",
});
</script>messagePrefix and messageSuffix are available here too. Values set as data-attributes on the
container take precedence over the config object.
Option 4: Send a Message via postMessage
You can open the chatbot and send a pre-filled message by posting a message directly to the chatbot iframe. This is how the inline search bar works internally.
<script>
function openChatWithMessage(message) {
window.DialogIntelligens.open();
setTimeout(() => {
const iframe = document.getElementById("chat-iframe");
if (iframe && iframe.contentWindow) {
iframe.contentWindow.postMessage(
{
action: "externalMessage",
message: message,
source: "custom-widget",
},
"*",
);
}
}, 1000);
}
</script>
<button onclick="openChatWithMessage('I need help with my order')">Order support</button>Option 5: Inline Chatbot Embed
Use the inline embed when the chatbot should render directly in the page instead of as a floating widget.
Setup
<div id="chatbot-placeholder" data-chatbot-id="YOUR_CHATBOT_ID"></div>
<script src="https://scripts.dialogintelligens.dk/chatbotinline.js?id=YOUR_CHATBOT_ID"></script>If #chatbot-placeholder is missing, the script appends the chatbot next to the script tag.
Inline Options
Set window.__CHATBOT_INLINE_OVERRIDES__ before loading chatbotinline.js to override inline-only behavior for that embed instance.
<div id="chatbot-placeholder"></div>
<script>
window.__CHATBOT_INLINE_OVERRIDES__ = {
inlineWelcomeMessage: "Hvordan kan vi hjælpe dig i dag?",
};
</script>
<script src="https://scripts.dialogintelligens.dk/chatbotinline.js?id=YOUR_CHATBOT_ID"></script>Supported inline override keys:
inlineWelcomeMessage: text shown above the input before the first question in inline/minimal modefullscreenStartOpen: set totrueto skip the collapsed search-bar landing state and start directly in the expanded chat view, with the chatbot's first message shown. Defaults tofalse, so existing integrations keep the search-bar-first behavior.
<div id="chatbot-placeholder"></div>
<script>
window.__CHATBOT_INLINE_OVERRIDES__ = {
fullscreenStartOpen: true,
};
</script>
<script src="https://scripts.dialogintelligens.dk/chatbotinline.js?id=YOUR_CHATBOT_ID"></script>Notes
window.DialogIntelligensis available as soon as the chatbot script loads.- The
open()method is safe to call even if the chatbot is already open. It will not toggle it closed. open(message)opens the chat and sends the message. If the chat is already open, the message is still delivered.setMetadata(metadata)is safe to call at any time after the script loads; patches are queued until the widget is ready and retried until delivered.- The
?chat=openand?chatbot_message=URL parameters only trigger once per page load and are removed from the URL bar. - When using
postMessageto send a message, use a timeout of roughly1000msto let the iframe initialize after opening.