Skip to content

Developer reference

This page covers the HyperHelp widget's JavaScript API. If you just need to install the widget, start with the installation guide.

Initialization#

The widget is initialized via window.HyperhelpWidget.init():

<script
  src="https://app.hyperhelp.ai/widget/chat.js"
  async
  onload='window.HyperhelpWidget.init({
    "chatbotKey": "YOUR_WIDGET_KEY"
  })'
></script>

Init options#

Option Type Description
chatbotKey string Required. Your chatbot's widget key.
copy object Override any widget text string. See Copy overrides.
styleOverrides object Inline style overrides per widget element. See Style overrides.
customCss string Raw CSS injected into the widget's Shadow DOM. See Custom CSS.
customCssUrl string URL to an external CSS file injected into the widget's Shadow DOM.
callbacks object Event callback functions. See Callbacks.

Widget API#

init() returns a widget instance with programmatic control:

const widget = window.HyperhelpWidget.init({
  chatbotKey: "YOUR_WIDGET_KEY"
});

// Open the widget programmatically
widget.open();

// Close the widget
widget.close();

Common use cases:

  • Open the widget after a delay: setTimeout(() => widget.open(), 5000)
  • Open on a custom button click: document.getElementById('help-btn').addEventListener('click', () => widget.open())

Copy overrides#

Override any widget string via the copy option. You only need to include the keys you want to change — unset keys fall back to the dashboard defaults.

window.HyperhelpWidget.init({
  chatbotKey: "YOUR_WIDGET_KEY",
  copy: {
    title: "Ask Nova",
    subtitle: "Help from our docs",
    badge_label: "Chat",
    composer_placeholder: "Ask about pricing...",
    composer_send: "Send",
    empty_title: "Start the conversation",
    empty_description: "Ask your first question to see answers.",
    assistant_label: "Assistant",
    user_label: "You",
    sources_title: "Sources",
    disclaimer: "Answers are generated from this site.",
    error: "Something went wrong, please contact the site owner.",
    unavailable: "Something is not working as it should. Please contact the site owner.",
    close_label: "Close",
    new_conversation_label: "New conversation",
    copy_label: "Copy",
    copied_label: "Copied",
    lead_close_label: "Close lead form",
    lead_submit_label: "Submit",
    lead_success: "Thanks! Your details have been submitted."
  }
});

Tip: You don't need to override every key — only the ones you want to change. Unset keys fall back to the dashboard defaults.

Style overrides#

Pass inline style objects (camelCase CSS properties) to customize specific widget elements without writing CSS:

window.HyperhelpWidget.init({
  chatbotKey: "YOUR_WIDGET_KEY",
  styleOverrides: {
    panel: { boxShadow: "0 24px 60px rgba(15, 23, 42, 0.18)" },
    openButton: { backgroundColor: "#0f172a" },
    userBubble: { backgroundColor: "#4338ca", color: "#fff" },
    header: { borderBottom: "2px solid #e5e7eb" }
  }
});

Available style override keys#

Layout

Key What it styles
panel The main chat panel container
header Panel header bar
title Header title text
subtitle Header subtitle text
body Message area
footer Panel footer

Messages

Key What it styles
emptyState Empty conversation state
error Error message display
messageRow Individual message row
messageGroup Grouped messages wrapper
userBubble Visitor's message bubble
assistantBubble Bot's message bubble

Sources

Key What it styles
sources Sources section container
sourcesLabel "Sources" heading
sourcesList Sources link list
sourcesLink Individual source link

Composer

Key What it styles
composer Message input area container
composerInput Text input field
composerButton Send button

Open button

Key What it styles
openButton Floating open button
openDot Pulse indicator dot
badgeLabel Button badge text

Lead capture

Key What it styles
leadRow Lead form row container
leadCard Lead form card
leadHeadline Lead form headline
leadDescription Lead form description
leadFieldLabel Form field label
leadInput Form input field
leadError Field validation error
leadSubmitButton Form submit button

Custom CSS#

For full CSS control — hover states, media queries, animations — inject CSS directly into the widget's Shadow DOM.

Inline CSS:

window.HyperhelpWidget.init({
  chatbotKey: "YOUR_WIDGET_KEY",
  customCss: `
    .widget-panel {
      border: 2px solid #e5e7eb;
    }
    .widget-message-user {
      background: linear-gradient(135deg, #667eea, #764ba2);
    }
    .widget-open-button:hover {
      transform: scale(1.1);
    }
  `
});

External stylesheet:

window.HyperhelpWidget.init({
  chatbotKey: "YOUR_WIDGET_KEY",
  customCssUrl: "https://example.com/widget-overrides.css"
});

CSS class hooks#

These stable CSS classes are available for targeting in custom CSS. Classes prefixed with widget- are part of the public API and won't change between releases.

Layout: .widget-panel, .widget-header, .widget-title, .widget-subtitle, .widget-body, .widget-footer

Messages: .widget-message-row, .widget-message-group, .widget-message-user, .widget-message-assistant, .widget-message-copy

Sources: .widget-sources, .widget-sources-label, .widget-sources-list, .widget-sources-link

Recommendations: .widget-recommendations, .widget-recommendation

Composer: .widget-composer, .widget-composer-input, .widget-composer-button

Open button: .widget-open-button, .widget-open-dot, .widget-badge-label

Empty and error states: .widget-empty-state, .widget-error

Lead capture: .widget-lead-row, .widget-lead-card, .widget-lead-headline, .widget-lead-description, .widget-lead-field-label, .widget-lead-input, .widget-lead-error, .widget-lead-submit, .widget-lead-success

Note: These classes are stable and safe to target. Internal class names (not prefixed with widget-) may change between releases.

Callbacks#

Register callback functions to react to widget events:

window.HyperhelpWidget.init({
  chatbotKey: "YOUR_WIDGET_KEY",
  callbacks: {
    onReady(payload) {
      console.log("Widget loaded", payload);
    },
    onOpen(payload) {
      // Track widget open in analytics
    },
    onClose(payload) {
      // Track widget close
    },
    onConversationStart(payload) {
      console.log("New conversation:", payload.conversationId);
    },
    onConversationReset(payload) {
      // Visitor started a new conversation
    },
    onMessageSent(payload) {
      console.log("Visitor asked:", payload.message);
    },
    onMessageDelta(payload) {
      // Streaming chunk received (real-time)
    },
    onMessageCompleted(payload) {
      console.log("Answer:", payload.answer);
      console.log("Sources:", payload.sources);
    },
    onError(payload) {
      console.error("Widget error:", payload.error);
    },
    onStatus(payload) {
      console.log("Status:", payload.status);
    },
    onLeadShown(payload) {
      // The lead capture form appeared
    },
    onLeadSubmitted(payload) {
      console.log("Lead captured:", payload.lead.data);
    },
    onLeadDismissed(payload) {
      // Visitor skipped the lead form
    },
    onLeadError(payload) {
      console.warn("Lead rejected:", payload.lead.reason, payload.lead.invalidFields);
    }
  }
});

Callback payload#

Every callback receives a payload object with these common fields:

Field Type Description
event string The event name (e.g., "open", "messageSent")
widget object Widget API instance with open(), close(), isOpen() methods
chatbotKey string The chatbot's widget key
visitorId string Unique visitor identifier (persisted in localStorage)
conversationId string | null Current conversation ID (null before first message)
pageUrl string The page URL where the widget is embedded

Event-specific fields#

Callback Additional fields
onReady ready — boolean, status — readiness status string
onMessageSent message — the visitor's question
onMessageDelta delta — the streaming text chunk
onMessageCompleted answer — full response text, sources — array of cited sources
onError error — error description
onStatus status — current widget status string
onLeadShown lead — see Lead capture events
onLeadSubmitted lead — including the captured data
onLeadDismissed lead
onLeadError lead — including reason and invalidFields

Lead capture events#

The four onLead* callbacks let you forward captured leads to your CRM, email tool or analytics as they happen. Each receives a lead object alongside the common payload fields:

Field Type Present on Description
timing string all "startup" or "after_first_exchange" — when the form is configured to appear
fields string[] all Your form's field keys, in display order
data object onLeadSubmitted The captured values, keyed by field
submittedAt string | null onLeadSubmitted ISO 8601 timestamp of the saved lead
reason string onLeadError "validation" (input rejected) or "request" (submission failed)
invalidFields string[] onLeadError Field keys that failed validation

Use fields — not the labels shown in the form — to map values onto your own system. Field keys are fixed once saved, so renaming a label will not break your integration.

window.HyperhelpWidget.init({
  chatbotKey: "YOUR_WIDGET_KEY",
  callbacks: {
    onLeadSubmitted(payload) {
      fetch("https://your-crm.example.com/leads", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          ...payload.lead.data,
          capturedAt: payload.lead.submittedAt,
          conversationId: payload.conversationId,
          sourcePage: payload.pageUrl
        })
      });
    }
  }
});

Behavior worth knowing when you build on these:

  • onLeadShown fires each time the form appears. With after_first_exchange timing a form the visitor ignored appears again in their next conversation, and that counts as a new impression.
  • onLeadSubmitted fires only after the lead is stored, and reports the values as saved rather than what was typed. It cannot fire for a lead you will not find in your dashboard, so it is safe to trigger a CRM record or a conversion pixel from it.
  • onLeadDismissed means the visitor used your skip link. A form that closes because the lead was accepted does not report a dismissal.
  • A visitor whose details you already hold triggers nothing at all when they resubmit, so you will not get duplicates.
  • Errors in your callbacks cannot break the chat. Exceptions are caught and ignored by the widget.

Full example#

A complete embed snippet combining copy overrides, style overrides, and callbacks:

<script
  src="https://app.hyperhelp.ai/widget/chat.js"
  async
  onload='window.HyperhelpWidget.init({
    "chatbotKey": "YOUR_WIDGET_KEY",
    "copy": {
      "title": "Ask Acme",
      "subtitle": "Answers from our docs",
      "badge_label": "Help"
    },
    "styleOverrides": {
      "openButton": { "backgroundColor": "#1e40af" },
      "header": { "background": "linear-gradient(135deg, #1e40af, #3b82f6)" },
      "title": { "color": "#ffffff" },
      "subtitle": { "color": "#bfdbfe" }
    },
    "callbacks": {
      "onConversationStart": function(p) {
        analytics.track("widget_conversation", { page: p.pageUrl });
      }
    }
  })'
></script>