Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

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:

MethodDescription
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>
Link/anchor:
<a href="#" onclick="event.preventDefault(); window.DialogIntelligens.open()">Need help?</a>
Open with a pre-filled message:
<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>
Semantics:
  • 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, and constructor are 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.pem

2. 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>
Token requirements:
  • Signed with RS256 using the private key matching the configured public key.
  • Must include exp and iat, with a lifetime of 15 minutes or less (exp - iat ≤ 900).
  • Registered claims (iss, aud, exp, iat, nbf, jti) are stripped; sub and all custom claims are kept and deep-merged into verified_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=open

You 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+order

Using chatbot_message alone (without chat=open) also works. The chat will open automatically:

https://example.com/page?chatbot_message=What+are+your+opening+hours%3F

This 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

  1. 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>
  1. 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-template takes precedence over data-message-prefix/data-message-suffix when both are set.
  • If data-message-template is 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 mode
  • fullscreenStartOpen: set to true to skip the collapsed search-bar landing state and start directly in the expanded chat view, with the chatbot's first message shown. Defaults to false, 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.DialogIntelligens is 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=open and ?chatbot_message= URL parameters only trigger once per page load and are removed from the URL bar.
  • When using postMessage to send a message, use a timeout of roughly 1000ms to let the iframe initialize after opening.