Documentation

All Docs

Widget

Embedding a chat widget on your website.

What is the Widget?

The Widget lets you embed a customer care chat powered by your Neuron bot on any website. Visitors can chat with your AI bot directly from the page — no WhatsApp required. Optionally, visitors can verify their WhatsApp number via OTP to link the web conversation with WhatsApp, allowing them to continue on either channel seamlessly.

Setting Up the Widget

Enable the widget and embed it on your site in three steps:

  1. 1

    Enable the widget

    Go to Dashboard > Bots > [Your Bot] > Widget tab. Click "Enable Widget". This creates a public token for your widget.

  2. 2

    Configure appearance and behavior

    Customize the widget's colors, title, greeting message, and behavior options. You can require WhatsApp verification, choose the launcher position, and set an offline message.

  3. 3

    Copy the embed snippet

    Copy the generated script tag and paste it into your website's HTML, just before the closing </body> tag. The widget will appear as a floating chat button.

If your site has a strict Content Security Policy (CSP), add your Neuron domain to frame-src and connect-src directives.

Embed Snippet

The widget loads from a single script tag. It auto-detects its origin so self-hosted deployments work without extra configuration.

Basic embed

<script
  src="http://localhost:4000/widget/neuron-widget.js"
  data-nw-token="nrn_pub_your_token"
  async
></script>

Data Attributes

You can override widget settings directly on the script tag using data attributes. These take effect without changing the dashboard config. Available attributes: data-nw-token (required), data-nw-primary-color, data-nw-position (bottom-right or bottom-left), data-nw-dark-mode (light, dark, or auto), data-nw-title, data-nw-greeting, data-nw-require-auth (true/false), data-nw-contact-name, data-nw-contact-phone, data-nw-contact-email.

Embed with overrides

<script
  src="http://localhost:4000/widget/neuron-widget.js"
  data-nw-token="nrn_pub_your_token"
  data-nw-primary-color="#e11d48"
  data-nw-title="Support"
  data-nw-greeting="Hey! How can we help?"
  data-nw-contact-name="Amara Okafor"
  data-nw-contact-email="[email protected]"
  async
></script>

JavaScript API

For dynamic control, use the NeuronWidget JavaScript API. JS API options take priority over data attributes. Call NeuronWidget.init() to initialize programmatically instead of using data-nw-token auto-init.

Programmatic initialization

NeuronWidget.init({
  token: "nrn_pub_your_token",
  config: {
    theme: { primaryColor: "#e11d48" },
    content: { title: "Support" },
  },
  contact: {
    name: "Amara Okafor",
    phone: "+2348012345678",
    email: "[email protected]",
    meta: { plan: "pro", customerId: "cust_789" },
  },
});

Lifecycle Methods

Control the widget programmatically with these methods: NeuronWidget.open() opens the chat panel (optionally with a pre-filled message via { message: "..." }), .close() minimizes to the launcher, .hide() hides the launcher entirely, .show() restores a hidden launcher, .destroy() removes the widget from the DOM, .logout() clears the session and resets to anonymous, .endConversation() closes the current conversation so the next message starts fresh, and .reset() combines logout + endConversation and returns to the initial greeting state.

Examples

// Open with a pre-filled message
NeuronWidget.open({ message: "I need help with my order" });

// Close the panel (conversation persists)
NeuronWidget.close();

// Hide the launcher completely
NeuronWidget.hide();

// Clean up everything
NeuronWidget.destroy();

Context & Event Injection

Push contextual data to the AI without showing it in the chat. This is useful for passing page context, user activity, or business data so the bot can give more relevant responses. Context events are capped at 20 per session and expire after 24 hours.

Injecting context

// Silent context for AI (not visible in chat)
NeuronWidget.pushContext({
  event: "page_viewed",
  data: { page: "/pricing", plan: "business" },
});

// Visible system message in chat
NeuronWidget.pushMessage({
  type: "system",
  content: "Your order #ORD-1234 has been confirmed!",
});

// Update contact metadata
NeuronWidget.updateContact({
  name: "Amara",
  meta: { lastOrder: "ORD-1234", lifetimeValue: 45000 },
});

Client-Side Events

Listen to widget events to react in your application code. Available events: "ready" (widget fully loaded), "open" (chat panel opened), "close" (chat panel closed), "message:sent" (visitor sent a message), "message:received" (bot or agent responded), "auth:verified" (WhatsApp OTP verified), "conversation:ended" (conversation closed).

Listening to events

NeuronWidget.on("message:received", (data) => {
  console.log("Bot replied:", data);
});

NeuronWidget.on("auth:verified", () => {
  console.log("User verified their WhatsApp!");
});

WhatsApp OTP Verification

Visitors can verify their WhatsApp number to link the web conversation with WhatsApp. When require-auth is enabled, visitors must verify before sending messages. The flow is: visitor enters their phone number, receives a 6-digit OTP via WhatsApp, and enters the code in the widget. After verification, the visitor's conversation history is linked to their WhatsApp number — they can continue the same conversation on either the widget or WhatsApp.

If you pass contact.phone via the JS API or data-nw-contact-phone, the phone field is pre-filled in the OTP screen so the visitor only needs to confirm.

Anonymous vs Authenticated

Anonymous sessions are web-only — messages are stored in Neuron but not delivered to WhatsApp. Anonymous sessions expire after 24 hours of inactivity. Authenticated sessions (after OTP verification) are linked to the visitor's WhatsApp number. Bot responses are delivered to both the widget and WhatsApp. The visitor can continue the conversation on either channel. The identity anchor is the verified phone number, not the device — clearing localStorage and re-verifying with the same number restores the full conversation history.

Widget Configuration

The full configuration is organized into four groups. Theme: primaryColor, textColor, backgroundColor, fontFamily, borderRadius, and darkMode (light/dark/auto). Launcher: position (bottom-right or bottom-left), offsetX, offsetY, and size. Behavior: greetingDelay, showBranding ("Powered by Neuron"), collectEmail, requireAuth, and offlineMessage. Content: title, subtitle, greetingMessage, inputPlaceholder, and authPrompt. Additionally, allowedOrigins restricts which domains can embed the widget (empty means allow all).

Configuration Priority

Widget configuration is merged from three sources (highest priority first): (1) JavaScript API options passed to NeuronWidget.init(), (2) data attributes on the script tag, (3) dashboard configuration. This lets site owners override specific settings per page without changing the dashboard config.

Custom CSS can only be set from the dashboard for security reasons. It cannot be injected via the JS API or data attributes.

Public Tokens

Widget tokens use a "nrn_pub_" prefix and can only access widget endpoints. They cannot be used on regular Bot API endpoints — attempting to do so returns 403 Forbidden. Create and revoke public tokens from the Widget tab in the dashboard. If you configure allowedOrigins, requests from unlisted origins are also rejected.

Allowed Origins

By default, the widget can be embedded on any website. To restrict embedding to specific domains, add origins to the "Allowed Origins" list in the Widget tab (e.g., https://example.com, https://app.example.com). Requests from unlisted origins will be rejected. Leave the list empty to allow all origins.

Content Security Policy

If your site uses strict CSP headers, you need to allow the Neuron domain for both iframes and API connections.

CSP directives to add

frame-src http://localhost:4000/widget;
connect-src http://localhost:4000/widget wss://"prod-09i-soketi.letschop.io":"443";

Rate Limits

Widget endpoints have their own rate limits: /init is limited to 10 requests/minute per IP, sending messages to 20/minute per session, loading message history to 60/minute per session, OTP requests to 3 per 15 minutes per phone number, media uploads to 5/minute per session, and all other endpoints to 30/minute per session.

Real-Time Messaging

The widget uses Pusher (or Soketi) for real-time message delivery. When the bot or an agent responds, the message appears in the widget instantly without polling. Authenticated sessions also receive messages sent via WhatsApp in real-time, so the chat stays in sync across both channels.

Agent Takeover

When a human agent takes over a conversation from the dashboard, their messages appear in the widget in real-time. The visitor sees a seamless conversation — they don't need to know whether the bot or a human is responding. When the agent releases the conversation, the bot resumes automatically.