Channel

Adding the widget to your website

This guide shows how to add the Breezaro chat to any website by pasting a short snippet into your site's HTML.

  • Works on any platform where you can edit HTML or add a custom code block.
  • No development skills needed. Copy, paste, publish.
  • Live in a few minutes.
Step-by-step

Installation steps

Follow these steps to add the Breezaro widget to your website.

1. Open your site's HTML or custom code editor

A website builder's custom code settings

2. Paste the Breezaro snippet

Adding the snippet to a custom code block
<script data-app-id="YOUR_APP_ID" src="https://breezaro.com/breezaro-widget.js" defer></script>

3. Insert it on every page, just before the closing body tag

Choosing where the snippet runs
Choosing where the snippet runs

4. Save and publish

The widget live on a website
Step-by-step

Driving the widget from your site

The widget exposes a small JavaScript API. Use it to open the chat from your own button, or to tell the assistant who the signed-in visitor is.

identify
Signs a visitor in so the assistant can act on their verified identity.
open
Opens the chat window.
close
Closes the chat window.
reset
Ends the conversation the current identity is bound to. Call it on logout or account switch. After a reset, an untagged identify is refused until the page reloads, so pass the current resetId as the fourth argument when you identify again on the same page.

Calling after the widget has loaded

Once the loader script has run, window.breezaro is ready and you can call any command directly. This is the usual case for a single-page app, or when the visitor signs in without a full page reload.

JavaScript
breezaro('open');

Calling before the widget has loaded

If the call has to happen earlier, for example when the page is rendered server-side and already knows who the visitor is, put the queue stub above the loader script. It records the calls and replays them once the widget is ready.

HTML
<script>
  window.breezaro =
    window.breezaro ||
    function () {
      (window.breezaro.q = window.breezaro.q || []).push(arguments);
    };
  breezaro('open');

  // Queue 'identify' only WITH the current resetId. An untagged queued
  // identify is refused once this browser has ever signed out, because
  // nothing bounds when it was pushed.
  breezaro('identify', identity, undefined, { resetId: breezaroResetId() });
</script>

Refreshing the signature on a long-lived page

The window is checked when the widget posts the payload, not when you call identify. A visitor who loads a page, leaves the tab in the background and opens the chat hours later presents an hours-old signature, and it is refused — the assistant asks them for an e-mail code instead.

Ordinary browsing refreshes it for free, because every page load mints a new signature. A single-page app, or a page left open all afternoon, does not. Fetch a fresh one from your own backend and call identify again when the tab comes back to the foreground.

Read the reset generation before the request goes out and hand it back as the fourth argument. A sign-out that lands while the request is in flight moves that generation, and the widget then refuses the late payload instead of writing the previous account's identity into the conversation the next visitor already has open.

JavaScript
const BREEZARO_APP_ID = 'YOUR_APP_ID';

function breezaroResetId() {
  try {
    const reset = JSON.parse(
      localStorage.getItem('breezaro-widget_reset_' + BREEZARO_APP_ID),
    );

    return typeof reset?.id === 'string' ? reset.id : null;
  } catch {
    return null;
  }
}

document.addEventListener('visibilitychange', async () => {
  if (document.visibilityState !== 'visible') return;

  // Read the generation BEFORE the round trip, not after it.
  const resetId = breezaroResetId();

  // Your own endpoint: it signs a fresh payload server-side, where the
  // secret lives, and returns { email, name, externalId, issuedAt, nonce, hmac }.
  const identity = await fetch('/my-api/breezaro-identity').then((r) => r.json());

  breezaro('identify', identity, undefined, { resetId });
});

Reset the widget when the visitor signs out

Call reset the moment someone signs out, then complete your own sign-out regardless of the widget's answer: a blocked or unmounted loader must never trap the visitor in a session they ended. If the reset is not confirmed as durable within a short timeout, write a fresh reset marker to the widget's reset key yourself, as the example does, so the next page load starts a clean conversation. Reset as well whenever the signed-in person changes, for example when a visitor switches accounts without a full page load, and when a session expires on its own.

JavaScript
async function signOut() {
  // Ask the widget to reset, then sign out no matter what it answers: a blocked
  // or unmounted loader must never trap the user in a session they ended.
  const confirmed = await new Promise((resolve) => {
    const done = setTimeout(() => resolve(false), 500);

    breezaro('reset', undefined, (result) => {
      clearTimeout(done);
      resolve(Boolean(result?.ok && result.durable));
    });
  });

  // If the widget could not confirm a durable reset (ad blocker, storage error,
  // never mounted), write the marker the loader reads on the next load so the
  // next visitor starts a clean conversation instead of restoring this one.
  if (!confirmed) {
    try {
      localStorage.setItem(
        'breezaro-widget_reset_' + BREEZARO_APP_ID,
        JSON.stringify({ id: crypto.randomUUID(), at: Date.now() }),
      );
    } catch (_) {}
  }

  await fetch('/my-api/sign-out', { method: 'POST' });
  window.location.assign('/');
}