Guides

Embed Chat Widget

Add your AI chatbot to any website with a floating chat bubble or iframe embed.

| View as Markdown
Hunter Hodnett
Hunter Hodnett CPTO at Chipp
| 1 min read
# embed # widget # deployment # tutorials # getting-started

Add your Chipp AI chatbot to any website using either a floating chat bubble widget or an embedded iframe. Choose the option that best fits your site’s design.

Embed Options

OptionBest For
Chat WidgetFloating bubble in corner, doesn’t take page space
IframeDedicated chat section embedded in your page

Option 1: Chat Widget (Floating Bubble)

The chat widget adds a floating chat bubble to the corner of your page. When clicked, it opens your chatbot in an overlay. It’s lightweight (~5KB gzipped), uses Shadow DOM for CSS isolation, and works on any website.

Quick Start

Add a single <script> tag before the closing </body> tag on your website:

html
<script src="https://your-app.on.chipp.ai/w/chat/chipp-widget.js"></script>

That’s it. The widget auto-detects your app from the subdomain and renders a floating chat bubble in the bottom-right corner.

Getting the Widget Code

1

Go to Share Settings

Open your app and click Publish > Share in the navigation.

2

Find the Widget Card

Look for the Widget card on the Share page.

3

Copy the Code

Click the code snippet to copy it to your clipboard:

html
<script src="https://your-app.on.chipp.ai/w/chat/chipp-widget.js"></script>

4

Add to Your Website

Paste the code before the closing </body> tag on your website.

Customizing with Data Attributes

You can customize the widget by adding data-* attributes to the script tag:

html
<script
  src="https://your-app.on.chipp.ai/w/chat/chipp-widget.js"
  data-position="bottom-left"
  data-greeting="Hey! How can I help?"
  data-greeting-delay="3000"
  data-color="#ff6600"
  data-bubble-size="64"
></script>

Attribute Reference

AttributeDefaultDescription
data-app-id(auto-detected from subdomain)App slug, e.g. my-app. Required when hosting the script from a different domain
data-positionbottom-rightWidget position: bottom-right, bottom-left, top-right, top-left
data-themeautoColor theme: light, dark, auto (follows user’s OS preference)
data-greeting(none)Greeting message shown as a preview bubble above the chat button
data-greeting-delay2000Delay in milliseconds before the greeting appears (0-30000)
data-auto-open(disabled)Automatically open the chat after this many milliseconds (e.g. 5000 for 5 seconds)
data-color(app brand color)Bubble background color as a hex value (e.g. #2563EB)
data-bubble-size60Bubble diameter in pixels (48-80)
data-bubble-shapecircleBubble shape: circle or rounded (rounded rectangle)
data-icon-url(app logo)Custom icon URL for the bubble (falls back to app logo, then a chat icon)
data-z-index2147483646CSS z-index for the widget container
data-hide-on-mobilefalseSet to true to hide the widget on mobile viewports

Config Priority

Data attributes take the highest priority. If you set a value via data-*, it overrides the server-side configuration. The full priority order is:

  1. Data attributes on the <script> tag (highest)
  2. Builder widget config (saved in the Widget tab)
  3. App brand styles (logo, primary color)
  4. Defaults (lowest)

Configuring in the Builder

You can also configure the widget visually in the Builder:

  1. Open your app in the Builder
  2. Go to Publish > Widget
  3. Adjust position, size, greeting, and other settings
  4. See changes reflected in the live preview
  5. Changes save automatically and update the widget in real-time

The Builder Widget tab lets you configure all the same options as the data attributes, plus a live preview showing exactly how the widget will look on your site.

Widget Features

  • CSS isolation: Uses Shadow DOM so your site’s CSS won’t affect the widget and vice versa
  • Instant open: Preloads the chat iframe on hover, so it opens instantly when clicked
  • Greeting bubble: Optional animated preview message to encourage interaction
  • Responsive: Full-screen overlay on mobile, positioned popup on desktop
  • Accessible: Full keyboard navigation, ARIA labels, focus management, and reduced-motion support
  • Lightweight: ~5KB gzipped (compared to 42KB for legacy widget)

JavaScript API

The widget exposes a window.ChippWidget API for programmatic control. This lets you open/close the chat, identify users, and listen for events from your own JavaScript.

Basic Controls

javascript
// Open the chat
ChippWidget.open();

// Close the chat
ChippWidget.close();

// Toggle open/closed
ChippWidget.toggle();

// Check if chat is open
if (ChippWidget.isOpen()) {
  console.log("Chat is open");
}

// Remove the widget completely (cannot be undone)
ChippWidget.destroy();

User Identification

Identify users so their chat history persists across sessions and you can see who’s chatting in your dashboard.

Client-Side (Simple)

Pass the user’s email and optional name directly. This is the simplest approach for sites where the chat doesn’t require authentication:

javascript
ChippWidget.setUser({
  email: "jane@example.com",
  name: "Jane Doe"
});

Server-Side (Secure)

For apps with authentication enabled, use server-side token generation to securely identify users. This prevents spoofing and ensures the user’s identity is verified by your backend.

Step 1: Generate a token on your server

Call the Builder API from your backend to get a bearer token:

bash
curl -X POST https://your-app.on.chipp.ai/api/v1/apps/{APP_ID}/consumers/auth \
  -H "Authorization: Bearer YOUR_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "jane@example.com", "name": "Jane Doe"}'

Response:

json
{
  "data": {
    "token": "eyJhbGciOi...",
    "consumer": {
      "id": "...",
      "email": "jane@example.com",
      "name": "Jane Doe"
    }
  }
}

Step 2: Pass the token to the widget

Send the token to your frontend and pass it to setUser:

javascript
ChippWidget.setUser({
  email: "jane@example.com",
  name: "Jane Doe",
  token: "eyJhbGciOi..."  // Bearer token from your server
});

The token authenticates the user’s session inside the chat iframe without cookies, which makes it work reliably in cross-origin embeds.

ℹ️

You need a Builder API key with write scope to call the /consumers/auth endpoint. Generate one in Settings > API Keys in the Builder.

Events

Listen for widget events to react to user interactions:

javascript
// Listen for an event (returns an unsubscribe function)
const unsubscribe = ChippWidget.on("message", (data) => {
  console.log("New message:", data.role, data.content);
});

// Stop listening
unsubscribe();

// Alternative: manually remove a listener
function onOpen() { console.log("Chat opened"); }
ChippWidget.on("open", onOpen);
ChippWidget.off("open", onOpen);

Event Reference

EventPayloadDescription
open{}The chat overlay was opened
close{}The chat overlay was closed
ready{}The chat iframe finished loading and is ready to use
message{ role, content }A new message was sent or received. role is "user" or "assistant"

Full API Reference

MethodSignatureDescription
open()() => voidOpen the chat overlay
close()() => voidClose the chat overlay
toggle()() => voidToggle the chat open/closed
isOpen()() => booleanReturns true if the chat is currently open
setUser(user)(user: { email: string, name?: string, token?: string }) => voidIdentify the current user
on(event, cb)(event: string, cb: Function) => () => voidSubscribe to an event. Returns an unsubscribe function
off(event, cb)(event: string, cb: Function) => voidUnsubscribe a specific callback from an event
destroy()() => voidRemove the widget from the page entirely

Examples

Open Chat from a Custom Button

html
<button onclick="ChippWidget.open()">Chat with us</button>

<script src="https://your-app.on.chipp.ai/w/chat/chipp-widget.js"></script>

React Integration

jsx
import { useEffect } from "react";

function App() {
  useEffect(() => {
    // Load the widget script
    const script = document.createElement("script");
    script.src = "https://your-app.on.chipp.ai/w/chat/chipp-widget.js";
    script.async = true;
    document.body.appendChild(script);

    return () => {
      // Clean up on unmount
      if (window.ChippWidget) {
        window.ChippWidget.destroy();
      }
      script.remove();
    };
  }, []);

  return (
    <button onClick={() => window.ChippWidget?.open()}>
      Ask a question
    </button>
  );
}

Next.js Integration

jsx
"use client";

import Script from "next/script";

export default function ChatWidget() {
  return (
    <Script
      src="https://your-app.on.chipp.ai/w/chat/chipp-widget.js"
      strategy="lazyOnload"
      data-position="bottom-right"
      data-greeting="Need help? Ask me anything!"
    />
  );
}

Auto-Open After a Delay

Open the chat automatically after 5 seconds, useful for onboarding flows:

html
<script
  src="https://your-app.on.chipp.ai/w/chat/chipp-widget.js"
  data-auto-open="5000"
></script>

Track Conversations in Analytics

javascript
ChippWidget.on("open", () => {
  // Google Analytics
  gtag("event", "chat_opened", { event_category: "engagement" });
});

ChippWidget.on("message", (data) => {
  if (data.role === "user") {
    gtag("event", "chat_message_sent", { event_category: "engagement" });
  }
});

Conditional Widget Loading

Only load the widget for certain users or pages:

javascript
if (window.location.pathname.startsWith("/support")) {
  const script = document.createElement("script");
  script.src = "https://your-app.on.chipp.ai/w/chat/chipp-widget.js";
  script.dataset.greeting = "How can we help with your support issue?";
  document.body.appendChild(script);
}

Server-Side Auth with React

jsx
import { useEffect } from "react";

function ChatWidget({ user }) {
  useEffect(() => {
    if (!user || !window.ChippWidget) return;

    // Call your backend to get a widget token
    fetch("/api/chat-token", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ email: user.email, name: user.name }),
    })
      .then((res) => res.json())
      .then(({ token }) => {
        window.ChippWidget.setUser({
          email: user.email,
          name: user.name,
          token,
        });
      });
  }, [user]);

  return null;
}

Option 2: Iframe Embed

The iframe embeds your chatbot directly into your page layout. Use this when you want the chat to be a fixed part of the page rather than a floating overlay.

Getting the Iframe Code

1

Go to Share Settings

Open your app and click Publish > Share in the navigation.

2

Find the Iframe Card

Look for the Iframe card on the Share page.

3

Copy the Code

Click the code snippet to copy it:

html
<iframe src="https://your-app.on.chipp.ai" height="800px" width="100%" frameborder="0" allow="microphone; clipboard-write; screen-wake-lock" title="Your App Name"></iframe>

The allow="microphone; clipboard-write; screen-wake-lock" attribute is required for voice mode to work properly on mobile devices. Without screen-wake-lock, the phone screen will lock during a voice call and end the conversation.

4

Add to Your Website

Paste the iframe code into your website’s HTML where you want the chat to appear.

Customizing the Iframe

Adjust dimensions:

html
<iframe
  src="https://your-app.on.chipp.ai"
  height="600px"
  width="400px"
  frameborder="0"
  allow="microphone; clipboard-write; screen-wake-lock"
  title="Chat"
></iframe>

Responsive container:

html
<div style="width: 100%; height: 80vh; min-height: 400px;">
  <iframe
    src="https://your-app.on.chipp.ai"
    style="width: 100%; height: 100%; border: none;"
    allow="microphone; clipboard-write; screen-wake-lock"
  ></iframe>
</div>

Platform-Specific Instructions

WordPress

For Widget:

  1. Go to Appearance > Theme Editor (or use a plugin like “Insert Headers and Footers”)
  2. Add the widget code before </body> in your theme’s footer

For Iframe:

  1. Edit your page or post
  2. Add a Custom HTML block
  3. Paste the iframe code

Webflow

  1. Go to Project Settings > Custom Code
  2. For widget: Paste in “Footer Code”
  3. For iframe: Add an Embed element to your page

Squarespace

For Widget:

  1. Go to Settings > Advanced > Code Injection
  2. Paste in the “Footer” section

For Iframe:

  1. Add a Code Block to your page
  2. Paste the iframe code

Shopify

For Widget:

  1. Go to Online Store > Themes > Edit code
  2. Find theme.liquid and paste before </body>

For Iframe:

  1. Edit the page where you want the chat
  2. Add a Custom Liquid section
  3. Paste the iframe code

Wix

For Widget:

  1. Go to Settings > Custom Code
  2. Click Add Code in the Body - End
  3. Paste the widget script tag

For Iframe:

  1. Add an HTML iframe element to your page
  2. Set the source URL to your app URL

Framer

For Widget:

  1. Go to Site Settings > Custom Code
  2. Add the widget script in the “End of <body> tag” section

For Iframe:

  1. Add a Code component
  2. Paste the iframe embed code

Cookies & Cross-Origin Embeds

Chipp automatically handles cross-origin cookie restrictions for iframe and widget embeds. When your chatbot detects it’s running inside an iframe on a different domain, it sets cookies with SameSite=None so the browser allows them in the cross-site context. This means both anonymous and authenticated chat work out of the box in iframe embeds — no extra configuration needed.

ℹ️

Some browsers (notably Safari with Intelligent Tracking Prevention) may still block third-party cookies in certain configurations. If you notice users having trouble maintaining their chat sessions in an iframe embed, consider one of these alternatives:

  1. Set up a custom domain that’s a subdomain of your website (best for iframe embeds — same-site cookies just work)
  2. Use server-side auth with setUser() to pass a bearer token via PostMessage (bypasses cookies entirely)

For apps with authentication enabled, or for maximum compatibility with strict browser privacy settings, the setUser({ token }) approach avoids cookies entirely:

  1. Your server calls POST /api/v1/apps/{APP_ID}/consumers/auth with the user’s email
  2. The API returns a bearer token
  3. Your frontend passes the token to ChippWidget.setUser()
  4. The widget sends the token to the iframe via PostMessage
  5. The iframe uses the bearer token for authentication instead of cookies

This works in cross-origin contexts because PostMessage is not affected by cookie restrictions.

You can configure these settings in:

  • Settings page for custom domains
  • Access page for authentication settings

Content Security Policy (CSP)

If your website uses a strict Content Security Policy, you’ll need to allow the widget’s script and iframe:

plaintext
frame-src *.on.chipp.ai;
script-src your-app.on.chipp.ai;

Replace with your custom domain if you have one configured.

If you’re using a nonce-based CSP, add the nonce to the script tag:

html
<script nonce="YOUR_NONCE" src="https://your-app.on.chipp.ai/w/chat/chipp-widget.js"></script>

Troubleshooting

Widget Not Appearing

  1. Check code placement: Widget code should be before </body>, not inside <head>
  2. Check for conflicts: Other scripts may interfere — check browser console for errors
  3. Check app status: Ensure your app is published and active
  4. Check CSP: Your site’s Content Security Policy may block the script or iframe
  5. Check mobile: If data-hide-on-mobile="true" is set, the widget won’t appear on mobile

Widget Appears But Chat Won’t Open

  1. Check the console: Look for network errors or CORS issues
  2. Check the app URL: Ensure the app is reachable at the URL in the script src
  3. Check authentication: If auth is enabled, use setUser() with a token or set up a custom domain

Iframe Shows “Session Not Found” Error

This typically means the browser is blocking cookies in the cross-origin iframe context. Chipp handles this automatically, but some strict privacy settings can still interfere:

  1. Safari ITP: Safari aggressively blocks third-party cookies. Use a custom domain (subdomain of your site) or server-side auth with setUser({ token })
  2. Chrome Incognito: Third-party cookies may be blocked by default in Incognito mode
  3. Browser extensions: Privacy extensions (uBlock Origin, Privacy Badger) may block cross-site cookies

Iframe Not Loading

  1. Check the URL: Make sure the iframe src matches your app’s URL exactly
  2. CSP headers: Your site’s Content Security Policy may block iframes
  3. X-Frame-Options: Some hosting providers set X-Frame-Options: DENY by default

Styling Issues

  1. Z-index conflicts: Use the data-z-index attribute to adjust widget stacking order
  2. Container overflow: For iframe, make sure parent elements don’t have overflow: hidden
  3. Mobile display: Use data-hide-on-mobile="true" if the widget conflicts with your mobile layout
  4. Double widget: If you see two widgets, make sure the script tag is only included once. The widget prevents double-initialization, but old v1 and new v2 scripts can coexist

User Identity Not Working

  1. Check setUser timing: Call setUser() after the widget script has loaded. Listen for the ready event if needed:
    javascript
    ChippWidget.on("ready", () => {
      ChippWidget.setUser({ email: "user@example.com" });
    });
  2. Check token validity: Server-side tokens expire. Generate a fresh token on each page load
  3. Check API key scope: The Builder API key must have write scope to call /consumers/auth