Docs/Guides/Publish & Share

    Embed Chat Widget

    Last updated · MAR 2026·Read as Markdown

    Drop your AVCodex agent onto any web page: a customer support portal, an integrator's client microsite, an internal tech-services dashboard, or the QR-code landing page taped inside a conference room.

    Two embed options. Pick the one that fits your layout.

    Option Best For
    Chat Widget Floating bubble in a corner, doesn't take page space
    Iframe Dedicated chat panel inside a page (room support page, integrator portal, internal wiki)

    The chat widget adds a floating chat bubble to the corner of any page. Click it and your AVCodex agent opens in an overlay. It's lightweight (~5KB gzipped), uses Shadow DOM for CSS isolation, and runs on any site (WordPress, Webflow, an integrator's marketing page, an internal SharePoint page, a Q-SYS web UI).

    Quick Start#

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

    html
    <script src="https://your-agent.app.avcodex.com/w/chat/avcodex-widget.js"></script>

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

    Getting the Widget Code#

    1. Open Share Settings

    In your AVCodex agent, 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-agent.app.avcodex.com/w/chat/avcodex-widget.js"></script>

    4. Add to Your Site

    Paste the code before the closing </body> tag.

    Customizing with Data Attributes#

    Customize the widget with data-* attributes on the script tag:

    html
    <script
      src="https://your-agent.app.avcodex.com/w/chat/avcodex-widget.js"
      data-position="bottom-left"
      data-greeting="Need a hand with the room?"
      data-greeting-delay="3000"
      data-color="#0E5C66"
      data-bubble-size="64"
    ></script>

    #### Attribute Reference

    Attribute Default Description
    data-app-id *(auto-detected from subdomain)* Agent slug, e.g. room-support. Required when hosting the script from a different domain
    data-position bottom-right Widget position: bottom-right, bottom-left, top-right, top-left
    data-theme auto Color theme: light, dark, auto (follows the user's OS preference)
    data-greeting *(none)* Greeting message shown as a preview bubble above the chat button
    data-greeting-delay 2000 Delay 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 *(agent brand color)* Bubble background color as a hex value (e.g. #0E5C66)
    data-bubble-size 60 Bubble diameter in pixels (48-80)
    data-bubble-shape circle Bubble shape: circle or rounded (rounded rectangle)
    data-icon-url *(agent logo)* Custom icon URL for the bubble (falls back to agent logo, then a chat icon)
    data-z-index 2147483646 CSS z-index for the widget container
    data-hide-on-mobile false Set to true to hide the widget on mobile viewports

    #### Config Priority

    Data attributes win. If you set a value via data-*, it overrides server-side configuration. Full priority order:

    1. Data attributes on the <script> tag (highest)
    2. Builder widget config (saved in the Widget tab)
    3. Agent 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 agent 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 covers the same options as data attributes, plus a live preview showing how the widget will look on the host site.

    Widget Features#

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

    The widget exposes a window.AVCodexWidget API for programmatic control. Use it to open and close the chat, identify users, and listen for events from your own JavaScript.

    Basic Controls#

    javascript
    // Open the chat
    AVCodexWidget.open();
    
    // Close the chat
    AVCodexWidget.close();
    
    // Toggle open/closed
    AVCodexWidget.toggle();
    
    // Check if chat is open
    if (AVCodexWidget.isOpen()) {
      console.log("Chat is open");
    }
    
    // Remove the widget completely (cannot be undone)
    AVCodexWidget.destroy();

    User Identification#

    Identify users so chat history persists across sessions and you can see who's chatting in your dashboard. Useful when the agent is sitting on a logged-in integrator portal or a tech-services console.

    #### Client-Side (Simple)

    Pass the user's email and optional name directly. Simplest path for sites where the chat doesn't require authentication, like a public room-support page reached by QR code:

    javascript
    AVCodexWidget.setUser({
      email: "tech@integrator.example",
      name: "Field Tech"
    });

    #### Server-Side (Secure)

    For agents with authentication enabled, use server-side token generation to verify the user's identity from your backend. Prevents spoofing.

    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-agent.app.avcodex.com/api/v1/apps/{APP_ID}/consumers/auth \
      -H "Authorization: Bearer YOUR_BUILDER_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"email": "programmer@integrator.example", "name": "Lead Programmer"}'

    Response:

    json
    {
      "data": {
        "token": "eyJhbGciOi...",
        "consumer": {
          "id": "...",
          "email": "programmer@integrator.example",
          "name": "Lead Programmer"
        }
      }
    }

    Step 2: Pass the token to the widget

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

    javascript
    AVCodexWidget.setUser({
      email: "programmer@integrator.example",
      name: "Lead Programmer",
      token: "eyJhbGciOi..."  // Bearer token from your server
    });

    The token authenticates the chat session inside the iframe without cookies, which keeps things working in cross-origin embeds (an integrator portal hosting an AVCodex agent on a different domain).

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

    Events#

    Listen for widget events to react to user interactions:

    javascript
    // Listen for an event (returns an unsubscribe function)
    const unsubscribe = AVCodexWidget.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"); }
    AVCodexWidget.on("open", onOpen);
    AVCodexWidget.off("open", onOpen);

    #### Event Reference

    Event Payload Description
    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#

    Method Signature Description
    open() () => void Open the chat overlay
    close() () => void Close the chat overlay
    toggle() () => void Toggle the chat open/closed
    isOpen() () => boolean Returns true if the chat is currently open
    setUser(user) (user: { email: string, name?: string, token?: string }) => void Identify the current user
    on(event, cb) (event: string, cb: Function) => () => void Subscribe to an event. Returns an unsubscribe function
    off(event, cb) (event: string, cb: Function) => void Unsubscribe a specific callback from an event
    destroy() () => void Remove the widget from the page entirely

    Open the Agent from a Custom Button#

    Useful on a room-support page where the user expects to tap a "Get Help" button rather than hunt for a floating bubble:

    html
    <button onclick="AVCodexWidget.open()">Get help with this room</button>
    
    <script src="https://your-agent.app.avcodex.com/w/chat/avcodex-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-agent.app.avcodex.com/w/chat/avcodex-widget.js";
        script.async = true;
        document.body.appendChild(script);
    
        return () => {
          // Clean up on unmount
          if (window.AVCodexWidget) {
            window.AVCodexWidget.destroy();
          }
          script.remove();
        };
      }, []);
    
      return (
        <button onClick={() => window.AVCodexWidget?.open()}>
          Ask the room agent
        </button>
      );
    }

    Next.js Integration#

    jsx
    "use client";
    
    import Script from "next/script";
    
    export default function ChatWidget() {
      return (
        <Script
          src="https://your-agent.app.avcodex.com/w/chat/avcodex-widget.js"
          strategy="afterInteractive"
          data-greeting="Need help with the conference room?"
        />
      );
    }

    Auto-Open After a Delay#

    Open the chat automatically after 5 seconds. Handy on a new-hire onboarding page for AV programmers:

    html
    <script
      src="https://your-agent.app.avcodex.com/w/chat/avcodex-widget.js"
      data-auto-open="5000"
    ></script>

    Track Conversations in Analytics#

    javascript
    AVCodexWidget.on("open", () => {
      // Google Analytics
      gtag("event", "chat_opened", { event_category: "engagement" });
    });
    
    AVCodexWidget.on("message", (data) => {
      if (data.role === "user") {
        gtag("event", "chat_message_sent", { event_category: "engagement" });
      }
    });

    Conditional Widget Loading#

    Only load the widget on certain pages. Example: only on the support section of a managed-services portal.

    javascript
    if (window.location.pathname.startsWith("/support")) {
      const script = document.createElement("script");
      script.src = "https://your-agent.app.avcodex.com/w/chat/avcodex-widget.js";
      script.dataset.greeting = "Having trouble with a room? Tell us what's happening.";
      document.body.appendChild(script);
    }

    Server-Side Auth with React#

    jsx
    import { useEffect } from "react";
    
    function ChatWidget({ user }) {
      useEffect(() => {
        if (!user || !window.AVCodexWidget) 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.AVCodexWidget.setUser({
              email: user.email,
              name: user.name,
              token,
            });
          });
      }, [user]);
    
      return null;
    }

    The iframe embeds your AVCodex agent directly in the page layout. Use this when you want the chat to be a fixed part of the page (a dedicated "Ask the Room Agent" panel inside a building's conference-room landing page) rather than a floating overlay.

    Getting the Iframe Code#

    1. Open Share Settings

    In your AVCodex agent, 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-agent.app.avcodex.com" height="800px" width="100%" frameborder="0" title="Your Agent Name"></iframe>

    4. Add to Your Site

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

    Customizing the Iframe#

    Adjust dimensions:

    html
    <iframe
      src="https://your-agent.app.avcodex.com"
      height="600px"
      width="400px"
      frameborder="0"
      title="Room Support Chat"
    ></iframe>

    Responsive container:

    html
    <div style="width: 100%; height: 80vh; min-height: 400px;">
      <iframe
        src="https://your-agent.app.avcodex.com"
        style="width: 100%; height: 100%; border: none;"
      ></iframe>
    </div>

    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 agent 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

    AVCodex automatically handles cross-origin cookie restrictions for iframe and widget embeds. When the agent 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. Both anonymous and authenticated chat work out of the box in iframe embeds, no extra configuration required.

    Note: Some browsers (notably Safari with Intelligent Tracking Prevention) may still block third-party cookies in certain configurations. If users have trouble keeping their chat sessions in an iframe embed, consider: 1. Set up a custom domain that's a subdomain of your site (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 agents 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 AVCodexWidget.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

    If your site uses a strict Content Security Policy, allow the widget script and iframe:

    code
    frame-src *.app.avcodex.com;
    script-src your-agent.app.avcodex.com;

    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-agent.app.avcodex.com/w/chat/avcodex-widget.js"></script>

    Widget Not Appearing#

    1. Check code placement: Widget code goes before </body>, not inside <head>.
    2. Check for conflicts: Other scripts may interfere. Check the browser console for errors.
    3. Check agent status: Ensure your agent 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 agent URL: Confirm the agent 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"#

    This usually means the browser is blocking cookies in a cross-origin iframe context. AVCodex handles this automatically, but strict privacy settings can still get in the way:

    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.
    3. Browser extensions: Privacy extensions (uBlock Origin, Privacy Badger) may block cross-site cookies.

    Iframe Not Loading#

    1. Check the URL: The iframe src must match your agent'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, ensure 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 AVCodexWidget.on("ready", () => { AVCodexWidget.setUser({ email: "tech@integrator.example" }); }); ``

    1. Check token validity: Server-side tokens expire. Generate a fresh token on each page load.
    2. Check API key scope: The Builder API key must have write scope to call /consumers/auth.

    *AVCodex · Your AV expertise. Amplified by AI.*

    Was this helpful?
    Edit this page →