You can make your website display a notification bubble when your bot sends a new message. The notification bubble is only displayed if the Webchat window is closed when you receive the message. You can then:
  • Open the notification (by clicking it or pressing Enter / Space)
  • Dismiss the notification (by clicking ×)
  • Open Webchat using the FAB (which dismisses the notification automatically)
You will need:
Since Webchat uses Markdown for rich text in messages, some messages may not render properly in the notification bubble without further processing.

Step 1: Add a Hook to your bot

  1. In the Studio, navigate to the Hooks section.
  2. Select Create Hook and set its type to Before Outgoing.
  3. Paste the following code into the Hook:
await actions.webchat.customEvent({
  conversationId: event.conversationId,
  event: JSON.stringify({
    eventType: 'notification',
    message: outgoingEvent.preview,
  })
})
This Hook notifies your website every time your bot sends a new message—that way, your website can display a notification bubble.

Step 2: Configure your website

Now, you can configure your website to display the notification bubble.

Add the bubble HTML element

First, add the bubble element somewhere in your website’s HTML:
<!-- Notification Bubble -->
<div id="msgDiv" class="cb tri-right btm-right" role="button" tabindex="0" aria-live="polite" aria-label="Notification" style="display:none">
  <span id="msgText"></span>
  <button class="close-chip" type="button" aria-label="Dismiss">×</button>
</div>

Add JavaScript

Then, add the following snippet to your website’s JavaScript:
function openNotification() {
    if (window.botpress) {
        window.botpress.open();
    } else {
        alert('Botpress integration not available.');
    }
}

(function () {
    const msgDiv = document.getElementById('msgDiv');
    const msgText = document.getElementById('msgText');
    const closeBtn = msgDiv?.querySelector('.close-chip');

    function showBubble(text) {
        if (!msgDiv || !msgText) return;

        // Display the notification bubble
        msgText.textContent = text || '';
        msgDiv.style.display = 'block';

        // Avoid stacking handlers on repeated events
        msgDiv.onclick = () => openNotification();

        // Keyboard access
        msgDiv.focus();
        msgDiv.onkeydown = (e) => {
            if (e.key === 'Enter' || e.key === ' ') {
                e.preventDefault();
                openNotification();
            }
        };

        // Hide the notification bubble if Webchat is opened
        window.botpress.on('webchat:opened', () => {
            if (msgDiv) msgDiv.style.display = 'none';
        });

        // Optional auto-hide after a period
        setTimeout(() => (msgDiv.style.display = 'none'), 15000);
    }

    // Close/dismiss without action
    if (closeBtn) {
        closeBtn.addEventListener('click', (e) => {
            e.stopPropagation();
            msgDiv.style.display = 'none';
        });
    }

    // Extract payload from event
    function extractPayload(raw) {
        let data = raw;

        // If the data is a string
        if (typeof data === 'string') {
            try { data = JSON.parse(data); } catch { /* ignore */ }
        }

        // Handle both strings and objects as event types
        if (data && typeof data.event === 'string') {
            try { data = JSON.parse(data.event); } catch { data = { eventType: data.eventType, ...data }; }
        } else if (data && typeof data.event === 'object') {
            data = data.event;
        }

        return data || {};
    }

    if (window.botpress?.on) {

        // Listen for custom events from the bot
        window.botpress.on('customEvent', (payload) => {
            const webchat = document.querySelector('iframe[title="Botpress"]');
            const data = extractPayload(payload);

            // Show the notification bubble if the Webchat window is closed
            if (data?.eventType === 'notification' && webchat && webchat.classList.contains('bpClose')) {
                showBubble(data.message);
            }
        });
    }
})();
This handles the behaviour of the notification bubble. For example:
  • Displays the message received from the event’s payload
  • Remains visible for 15 seconds before automatically closing
  • Can be selected by clicking or pressing Enter / Space
You can configure the behaviour to suit your needs by modifying the code snippet.

Add CSS

Finally, add this CSS snippet to your website’s stylesheet:
:root {
  /* Change these to match your page's brand */
  --bubble-bg: #ccddfa;   /* background */
  --bubble-fg: #173569;   /* text */
}

.cb {
  position: fixed;
  right: 24px;
  bottom: 102px;
  z-index: 9999;

  display: none; /* shown by JS */
  background: var(--bubble-bg);
  color: var(--bubble-fg);
  border-radius: 16px;
  padding: 14px 42px 14px 16px;
  max-width: 340px;
  line-height: 1.35;
  box-shadow: 0 10px 25px rgba(0, 0, 0, .18);
  cursor: pointer;

  font-family: Roboto, system-ui, -apple-system, Segoe UI, Roboto, "Helvetica Neue", Arial;
  font-size: 15px;
  transition: transform .2s ease, box-shadow .2s ease, opacity .2s ease;
  animation: bubble-in .28s cubic-bezier(.2, .8, .2, 1) both;
}

.cb:hover {
  transform: translateY(-1px);
  box-shadow: 0 12px 30px rgba(0, 0, 0, .22);
}

.cb:focus {
  outline: none;
}

/* Chat tail */
.tri-right.btm-right::after {
  content: "";
  position: absolute;
  right: 22px;
  bottom: -8px;
  width: 16px;
  height: 16px;
  background: var(--bubble-bg);
  transform: rotate(45deg);
  box-shadow: 0 10px 25px rgba(0, 0, 0, .18);
  border-bottom-right-radius: 4px;
}

/* Close chip (optional, inside the bubble) */
.cb .close-chip {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 26px;
  height: 26px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .18);
  color: var(--bubble-fg);
  border: 0;
  cursor: pointer;
  line-height: 1;
  font-size: 16px;
}

.cb .close-chip:hover {
  background: rgba(255, 255, 255, .28);
}

@keyframes bubble-in {
  from { transform: translateY(10px) scale(.98); opacity: 0; }
  to   { transform: translateY(0)   scale(1);   opacity: 1; }
}
You can modify the styling as needed.
Now, your website will display a notification bubble when your bot sends a new message.