Chatbot Overview

This page covers the ways to add your BusinessDash chatbot to an externally-hosted site — your own site, your framework, your hosting — through the @businessdash/sdk.

This is about the chatbot on your own, externally-hosted site, connected through the SDK. The chatbot that appears on a site built with BusinessDash's internal Site Builder is placed and managed inside the builder itself — you don't need the SDK for it.

In every case the chatbot is configured first in your BusinessDash dashboard — its system prompt, knowledge base, model, live front-desk handoff, file-upload entitlement, and email capture. The SDK never re-implements any of that; it renders (or hands you the data for) a chat whose brain already lives in BusinessDash. What changes between approaches is how much of the UI you build yourself.

There are three ways to include it, from zero-effort to total control:

ApproachWhere it rendersYou buildReach for it when
<Chatbot>A BusinessDash-hosted iframeNothingYou want the fastest possible drop-in and don't need it to match your design system exactly.
<ChatbotInline>Your DOM, styled defaultStyling only (optional)You want it to live in your page (layout, SEO) and match your look — without writing chat logic.
useChatbot()Your DOM, your markupThe entire UIYou need total control over every pixel and interaction.

All three authenticate the same way — a publishable API key scoped to your org — and all three talk to the same package API, so the chatbot behaves identically no matter which you choose. The only difference is how much markup you own.

1. <Chatbot> — the hosted iframe drop-in

The fastest integration. BusinessDash renders the entire chat experience — bubbles, input, the live front-desk presence strip, inline forms, and file uploads — inside a sandboxed iframe on your page. You write no chat UI and get every feature automatically, including ones added later (you inherit them on your next page load, with no SDK bump).

import { Chatbot } from "@businessdash/sdk/react"

export function SupportWidget() {
  return (
    <Chatbot
      apiKey={process.env.NEXT_PUBLIC_BD_KEY!}
      baseUrl="https://app.businessdash.us"
      title="Assistant"
      style={{ height: 600 }}
      onAssistantMessage={(text) => console.log("bot:", text)}
    />
  )
}

Expected behavior

  • Renders an iframe pointing at BusinessDash's hosted chatbot page; the SDK mints a short-lived signed session token for you.
  • File uploads, email capture, live front-desk handoff, and inline forms all work out of the box — they're part of the hosted UI and respect the same org settings + entitlements described below.
  • You can react to events with onEvent / onAssistantMessage, but you cannot restyle the inside of the iframe. Use className / style to size and place the frame; supply loadingFallback / errorFallback for the surrounding states.

Because the UI is hosted, the <Chatbot> iframe is the only surface that picks up new chatbot features without updating your @businessdash/sdk version.

2. <ChatbotInline> — the in-DOM component

Renders the chat in your own DOM (no iframe), so it participates in your page layout, your scroll, and your bundle. It ships a polished default theme out of the box, and everything is restylable — the defaults are zero-specificity :where() rules keyed to data-slot attributes, so any classNames you pass already win, and accent/surface colors read from the --bd-chatbot-accent / --bd-chatbot-bg CSS variables. For full control of a slot, pass a renderMessage / renderPresenceStrip render-prop.

import { ChatbotInline } from "@businessdash/sdk/react"

export function InPageChat() {
  return (
    <ChatbotInline
      apiKey={process.env.NEXT_PUBLIC_BD_KEY!}
      baseUrl="https://app.businessdash.us"
      welcomeMessage="Hi! How can we help?"
      classNames={{ root: "h-[600px] rounded-2xl border" }}
    />
  )
}

Expected behavior

  • The chat lives in your DOM — better for layout, theming, and SEO than an iframe.
  • File uploads show a paperclip + a staged preview when the org has the chat.file_uploads entitlement (the component reads getConfig() for you); the file uploads and posts with the text on send.
  • Email capture is honored automatically: "request" shows a skippable ask, "require" blocks the first message until an email is given.
  • Live front-desk presence is polled (availabilityPollMs, default 30s) and rendered as a presence strip; inline forms surface in place.
  • Set unstyled to opt out of the default theme entirely and start from bare markup.

3. useChatbot() — the headless hook

When you want to build 100% of the UI yourself, the hook gives you the state and actions and nothing else. This is the most work and the most control.

import { useChatbot } from "@businessdash/sdk/react"

function MyChat() {
  const {
    messages, send, isPending, error,
    availability, getConfig, getForm, submitForm, uploadFile,
  } = useChatbot({
    apiKey: process.env.NEXT_PUBLIC_BD_KEY!,
    baseUrl: "https://app.businessdash.us",
  })
  // …render `messages`, call `send(text)`, etc.
}

Expected behavior

  • send(text) runs the org's chatbot (system prompt + knowledge base + model) and appends the reply to messages; availability + refreshAvailability() drive a "Talk to a person" CTA.
  • A show_form action resolves through getForm(slug) → render → submitForm(slug, …) (which carries the transcript).
  • uploadFile({ sessionId, file }) presigns a direct-to-R2 upload (gated by the chat.file_uploads entitlement) and returns a { url, name, type, size } ref you attach to your own message UI.
  • Nothing is rendered for you — you own every bubble, the composer, uploads, and the email gate.

Behaviors shared by every approach

These are configured in the dashboard and apply to all three surfaces:

  • Auth — a publishable, org-scoped API key. No secrets ship to the browser; the key only unlocks the surfaces you've entitled.
  • File uploads — gated by the chat.file_uploads entitlement and exposed as getConfig().fileUploadsEnabled. The iframe and <ChatbotInline> surface the affordance for you; with the hook you call uploadFile yourself. Visitor files land in the org's chatUploads Files & Media folder (2-day TTL unless saved), capped at 7 MB and 5 files/hour per chat, with active-content types refused.
  • Email capture — getConfig().emailCaptureMode is "off" | "request" | "require". Captured emails are stored with the conversation (and uploads) for provenance.
  • Live front-desk — when the org is on a plan with live handoff, availability reports staff presence + a wait-time hint so you can offer "Talk to a person."
  • Inline forms — the bot can recommend a dashboard form mid-conversation; the iframe and <ChatbotInline> render it in place, and the hook hands you the show_form action to render yourself.

Start with <Chatbot> to ship in minutes. Move to <ChatbotInline> when you want it in your DOM and on-brand. Drop to useChatbot() only when you need to own the whole interface.