bubuu/api/docs
API Documentation·Frontend SDK
03 · The embeddable chat

Lead
Widget

A 2 KB facade that paints on first frame. The full widget streams in behind it. Embedded into any page, framework, or CMS in two lines of HTML.

Web ComponentShadow-isolatedDrop-in scriptEN · DE

At a glance

Bubuu's lead widget is a Custom Element — <bubuu-chat> — that drops a guided real-estate conversation into any page. It mounts inside a Shadow DOM, inheriting none of the host site's CSS and leaking none of its own. No frameworks to align, no global styles to fight.

The widget ships in two halves. A 2 KB loader renders the chat bubble on first paint; the full bundle preloads in the background and takes over on click. Visitors on cold connections still see the bubble before the page finishes settling.

Loader bundle
~2 KB over the wire
Widget bundle
~210 KB over the wire
Element
<bubuu-chat>
Distribution
Hosted JS · drop-in
Isolation
Shadow DOM
Languages
English · German
Themes
Light · Dark · Auto

Install

Two scripts, one element. Drop the loader on every page where the widget should be reachable; the chat bubble renders immediately and the full widget streams in behind it.

01

Facade loader

Recommended

Renders the chat bubble in ~2 KB. The full bubuu-chat.js bundle preloads in the background and is promoted on click or hover.

<script src="https://chat.bubuu.ai/bubuu-loader.js" async></script>
<bubuu-chat partner-id="your-partner-id"></bubuu-chat>
02

Direct embed

Full bundle

Use this when the page is a conversion target and you want the widget interactive on first paint. Ships the full ~210 KB bundle up-front — skip if you care about Core Web Vitals on cold visits.

<script src="https://chat.bubuu.ai/bubuu-chat.js" async></script>
<bubuu-chat partner-id="your-partner-id"></bubuu-chat>

Architecture

Two scripts, in sequence. The loader is tiny enough to be inlined on every page; the widget is large enough that you would not want it on every page. The facade pattern lets both be true.

  1. 01

    Loader registers the element

    bubuu-loader.js defines <bubuu-chat> as a 2 KB facade and renders a chat bubble inside a Shadow DOM. The full bundle starts preloading immediately.

  2. 02

    Bubble paints on first frame

    No framework boot, no hydration cost. The bubble is a single button with inline styles, so it shows up even on cold cache and slow connections.

  3. 03

    Visitor opens the chat

    On hover, the preloaded widget bundle is already cached. On click, the cached bundle is promoted from background to foreground.

  4. 04

    Widget takes over in place

    The full widget upgrades the same DOM node, inheriting every attribute you set on it. The conversation opens immediately — visitors never see a second click.

Attributes

Every option is a plain HTML attribute on <bubuu-chat>. Set them once in the markup or change them at runtime with element.setAttribute(…). Attributes flagged reactive re-render the widget without losing chat state.

partner-idstringrequired

Identifies your account on the Bubuu backend. Every chat and lead created by this instance is attributed to this partner.

chat-idstring

Resumes an existing conversation by its server-issued ID. When omitted, a new chat is created on the first user message. Useful for deep-linking back into a previous session from email or a CRM.

lang'en' | 'de'default · enreactive

UI language. Changing this at runtime swaps the locale without clearing messages — the conversation continues in the new language.

theme'light' | 'dark' | 'auto'default · lightreactive

Color scheme. auto follows the host page's prefers-color-scheme and reacts to system theme changes. The widget runs inside a Shadow DOM, so this never affects host styles.

regionstringreactive

ISO country or region code used to pick locale-specific copy, phone formats, and address parsers. Defaults to the partner's configured region when absent.

avatar-urlstring (URL)

Override the agent avatar shown next to assistant messages. Falls back to the partner's brand avatar when omitted.

contextJSON stringreactive

Page, visitor, and metadata context for the AI as a JSON object — { page, visitor, metadata }. Sent with every message so answers stay grounded in what the visitor is viewing. Malformed JSON is ignored with a console warning; the widget still loads. For objects from JS or a framework, prefer the context property or setContext() — see Context.

Context

Tell the AI what the visitor is looking at. Attach page, visitor, free-form metadata, and the page content itself, and the widget sends it on every message, so the assistant grounds its answers in the exact listing on screen and can pre-fill lead capture. Context rides the existing chat channel — no extra requests, and it survives the facade→full-widget upgrade.

page{ url, title, referrer }

What the visitor is viewing. Auto-derived from the host page (location.href, document.title, document.referrer) when you omit it; anything you pass wins per field.

visitor{ id, name, email }

Known visitor identity. Used to pre-fill the lead form. user is accepted as a friendly alias for visitor.

metadataRecord<string, string>

Free-form key/value bag. Put listing identifiers here — listingId, an OpenImmo or RESO ref, price, location — and the backend resolves them into the matched property. Values are coerced to strings; the backend sanitizes and size-limits them.

pageContentstring | { body, type }

The page content the AI should read, handed straight to the backend so it can skip scraping the page. Pass a string (treated as the body) or { body, type }, where type is a format hint (e.g. markdown vs HTML). Omit it to let the backend fetch the page itself.

Three ways to set it

Use the context attribute for static, server-rendered markup; the context property to bind an object (it replaces the current context); and setContext(patch) to merge a partial update at runtime. getContext() returns the current value. All three reach the same place. Malformed JSON in the attribute is ignored with a console warning — the widget still loads.

<bubuu-chat
  partner-id="acme-real-estate"
  context='{"metadata":{"listingId":"AT-1234"}}'
></bubuu-chat>

In your framework

Frameworks bind objects to the element's context property. React 19, Vue, Angular, Svelte, and Preact all do this for you. React 18 and below stringify object props, so reach for a ref and call setContext() instead.

// React 19 binds an object prop to the element's "context" property.
<bubuu-chat partner-id="acme-real-estate" context={ctx} />

Timing is automatic: context set before the chat opens lands on the first message, and an update pushed mid-session applies to the next one. setContext merges, so when the page changes (e.g. SPA navigation) send the new pageContent in full — a partial patch keeps the previous page's body. Updating context never clears the thread or drops the connection — it behaves like the reactive lang and theme attributes. The widget only reads window and document; it adds nothing to the host's global scope.

Theming

The widget paints inside a Shadow DOM — host styles can't bleed in, widget styles can't bleed out. Click a mode to retheme the live widget; the switch lands in place, no reload.

<bubuu-chat partner-id="your-partner-id" theme="auto"></bubuu-chat>

Language

Pick a locale to flip the live widget. UI strings re-render in place — the chat thread, the open WebSocket, and scroll position survive the switch.

const widget = document.querySelector('bubuu-chat-full, bubuu-chat');

widget?.setAttribute('lang', 'de');

Cookbook

A few patterns that cover most production embeds. Each one stands on its own — copy, swap in your IDs, ship.

01

Use in any framework

<bubuu-chat> is a standard Custom Element. Load the loader once, then render the tag anywhere — React, Vue, Svelte, Angular, or plain HTML all treat it as a native element.

01 — Load the loader
<script src="https://chat.bubuu.ai/bubuu-loader.js" async></script>
02 — Render the tag
<bubuu-chat partner-id="your-partner-id" theme="auto"></bubuu-chat>
02

Resume a chat from a link

Drop the visitor straight back into their last conversation. Pass chat-id when linking from email follow-ups or saved-search alerts and the widget restores the thread.

<bubuu-chat
  partner-id="acme-real-estate"
  chat-id="chat_01HXYZ..."
></bubuu-chat>
03

Ground the AI in the property

On a listing page, push the property the visitor is viewing. The assistant answers about that listing and the lead is saved with it. Re-run setContext whenever the listing changes — the thread and connection stay put.

import { useEffect, useRef } from 'react';

export function ListingChat({ listing }: { listing: Listing }) {
  const ref = useRef<(HTMLElement & { setContext(c: object): void }) | null>(null);

  // Re-ground the AI whenever the visitor opens a different listing.
  useEffect(() => {
    ref.current?.setContext({
      page: { url: location.href, title: document.title },
      metadata: {
        listingId: listing.id,
        price: String(listing.price),
        city: listing.city,
      },
    });
  }, [listing]);

  return <bubuu-chat ref={ref} partner-id="acme-real-estate" />;
}