Docs/Configuring Your Agent/Embed Chat to Website

Embed Chat to Website

Embed the Qlar chat widget on your website so visitors can talk to your agent without leaving your page. By the end of this tutorial you will have a working chat widget — either embedded inline inside a container or as a floating button fixed to a corner of the viewport — in a plain HTML file or a React/TypeScript application.


How It Works

The Qlar widget is a standard Web Component (<pusaka-container>). You load one script tag from Qlar's CDN and then place the <pusaka-container> element anywhere in your HTML or JSX. No build step, no npm package, and no changes to your backend are required.

When the element renders it connects to your agent and handles the entire conversation UI. You control its appearance and behaviour through HTML attributes.


Prerequisites

  • A Qlar account with at least one agent created and published.
  • A website or application where you can add a <script> tag to the page <head>.

Step 1 — Open the Widget Page

In the Qlar CMS, click the hamburger menu (☰) in the top-left corner to open the sidebar, then click Widget.

The Widget page opens and shows the embed documentation for the currently active agent, including its Agent ID — you will need this value in the next step.


Step 2 — Copy Your Agent ID

Your Agent ID is a unique identifier that tells the widget which agent to connect to.

On the Widget page, locate the code snippets shown. The data-agent-id attribute in every snippet already contains your active agent's ID. Copy that value — it looks like a UUID, for example a1b2c3d4-e5f6-7890-abcd-ef1234567890.

Alternative: You can also find the Agent ID on the agent's Settings page.


Step 3 — Add the Script Tag

Add the Qlar Container script to the <head> of your HTML page. This registers the <pusaka-container> custom element in the browser.

<script
  type="module"
  crossorigin
  src="https://app-container-prod.pusaka.ai/pusaka-container.mjs"
></script>

Load the script once per page — you can then place as many <pusaka-container> elements as you need in the <body>.


Step 4 — Embed as an Inline Widget

The inline mode renders the widget inside a container you control. The element fills the width and height of its parent element, so wrap it in a <div> with explicit dimensions.

Here is a complete working HTML page:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>My Website</title>
    <script
      type="module"
      crossorigin
      src="https://app-container-prod.pusaka.ai/pusaka-container.mjs"
    ></script>
  </head>
  <body>
    <!-- Give the parent a size so the widget has space to render -->
    <div style="width: 400px; height: 600px;">
      <pusaka-container
        data-agent-id="YOUR_AGENT_ID"
        data-theme="system"
        data-app-mode="chat"
      ></pusaka-container>
    </div>
  </body>
</html>

Replace YOUR_AGENT_ID with the value you copied in Step 2.

Open the page in a browser — you should see the chat interface appear inside the <div>.


Step 5 — Embed as a Floating Widget

The floating mode renders a FAB (Floating Action Button) fixed to a corner of the viewport. The button is always visible while scrolling; clicking it opens or closes an animated chat panel. The <pusaka-container> element itself takes up no space in the document flow, so you can drop it anywhere in <body> without a wrapper.

Minimal example

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>My Website</title>
    <script
      type="module"
      crossorigin
      src="https://app-container-prod.pusaka.ai/pusaka-container.mjs"
    ></script>
  </head>
  <body>
    <!-- Your page content here -->

    <pusaka-container
      data-agent-id="YOUR_AGENT_ID"
      data-mode="floating"
      data-position="bottom-right"
      data-chat-title="Your Agent Name"
    ></pusaka-container>
  </body>
</html>

Fully customized example

<pusaka-container
  data-agent-id="YOUR_AGENT_ID"
  data-theme="dark"
  data-app-mode="chat"
  data-mode="floating"
  data-position="bottom-right"
  data-offset-x="24px"
  data-offset-y="24px"
  data-chat-width="400px"
  data-chat-height="600px"
  data-chat-title="Your Agent Name"
></pusaka-container>

Tip: On viewports narrower than 480 px the floating panel automatically fills the entire screen regardless of data-chat-width and data-chat-height, so it works on mobile without extra configuration.


Step 6 — Customize Appearance

All <pusaka-container> attributes are listed below.

AttributeDefaultOptions / Notes
data-agent-id(required)The Agent ID copied in Step 2.
data-themesystemsystem · light · dark
data-app-modefull-appfull-app (chat + top bar) · chat (chat only)
data-enable-autofocustruetrue · false — whether the chat input receives focus automatically on load and after each agent reply. Set to false to prevent the page from scrolling to the widget.
data-mode(inline)floating — renders a fixed FAB. Omit for inline mode.
data-positionbottom-rightbottom-right · bottom-left · top-right · top-left — floating only.
data-offset-x20pxAny CSS length — horizontal gap between FAB and viewport edge. Floating only.
data-offset-y20pxAny CSS length — vertical gap between FAB and viewport edge. Floating only.
data-chat-width380pxAny CSS length — width of the floating chat panel. Floating only.
data-chat-height580pxAny CSS length — height of the floating chat panel. Floating only.
data-chat-titleChatText shown in the floating panel header. Floating only.

Note: data-mode controls the container layout (inline vs floating). data-app-mode controls the chat interface display (full app vs chat-only). They are independent of each other.


Step 7 — Embed in a React App (Vite / CRA — TypeScript)

React does not recognise custom HTML elements by default. Follow the four sub-steps below.

7A — Add the script to public/index.html

In your React project, open public/index.html and add the script inside <head>:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>React App</title>
    <script
      type="module"
      crossorigin
      src="https://app-container-prod.pusaka.ai/pusaka-container.mjs"
    ></script>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

7B — Declare the custom element type

Create (or edit) src/custom-elements.d.ts to tell TypeScript about the <pusaka-container> element:

/// <reference types="vite/client" />
import React from "react";

declare global {
  namespace JSX {
    interface IntrinsicElements {
      "pusaka-container": React.DetailedHTMLProps<
        React.HTMLAttributes<HTMLElement>,
        HTMLElement
      > & {
        "data-agent-id"?: string;
        "data-theme"?: string;
        "data-app-mode"?: string;
        "data-enable-autofocus"?: string;
        "data-mode"?: string;
        "data-position"?: string;
        "data-offset-x"?: string;
        "data-offset-y"?: string;
        "data-chat-width"?: string;
        "data-chat-height"?: string;
        "data-chat-title"?: string;
      };
    }
  }
}

export {};

7C — Use <pusaka-container> in a component

Here is a complete example of a chat panel with manual open/expand/close controls:

import { useState } from "react";
import { MessageCircle, X, Maximize2, Minimize2 } from "lucide-react";

export default function ChatAgent() {
  const [isOpen, setIsOpen] = useState(false);
  const [isExpanded, setIsExpanded] = useState(false);

  return (
    <div className="fixed bottom-4 right-4 z-50">
      <button
        onClick={() => setIsOpen((prev) => !prev)}
        className="bg-purple-600 text-white p-3 rounded-full shadow-lg hover:bg-purple-700 transition-colors"
      >
        {isOpen ? <X size={24} /> : <MessageCircle size={24} />}
      </button>

      <div
        className={`${
          isExpanded
            ? "fixed inset-0 w-full h-full bg-white"
            : "fixed bottom-20 right-4 w-full max-w-xs sm:max-w-sm md:max-w-md h-[500px]"
        } rounded-lg shadow-xl flex flex-col transition-all duration-300 ${
          isOpen ? "block" : "hidden"
        }`}
      >
        {/* Header */}
        <div className="flex items-center justify-between p-4 bg-purple-600 text-white">
          <h3 className="font-semibold">Chat with Your Agent</h3>
          <div className="flex items-center space-x-2">
            <button
              onClick={() => setIsExpanded((prev) => !prev)}
              className="hover:text-purple-300"
            >
              {isExpanded ? <Minimize2 size={20} /> : <Maximize2 size={20} />}
            </button>
            <button
              onClick={() => setIsOpen(false)}
              className="hover:text-purple-300"
            >
              <X size={20} />
            </button>
          </div>
        </div>

        <div className="flex-1 overflow-hidden">
          <pusaka-container
            data-agent-id="YOUR_AGENT_ID"
            data-app-mode="chat"
            data-theme="dark"
          ></pusaka-container>
        </div>
      </div>
    </div>
  );
}

7D — Or use the built-in floating mode

If you do not need a custom wrapper, use data-mode="floating" as a simple drop-in. Place the tag anywhere in your JSX — the widget handles everything:

export default function App() {
  return (
    <>
      {/* Your app content */}

      <pusaka-container
        data-agent-id="YOUR_AGENT_ID"
        data-mode="floating"
        data-position="bottom-right"
        data-chat-title="Your Agent Name"
      ></pusaka-container>
    </>
  );
}

Next Steps

  • Test the widget — use the Simulation section in Qlar CMS to verify your agent's responses before going live.
  • Refine your agent's personality — adjust the tone, mission, and interaction style in the Persona & Behavior section.
  • Connect more channels — add your agent to WhatsApp or Instagram via the Channel section in the CMS sidebar.