Table of Contents
Why Embed an AI Assistant?
An embedded AI assistant behaves like a first-class citizen on your website. It answers FAQs 24/7, qualifies leads, books demos, and even closes small sales—all without adding headcount.
Placing the assistant in-context (a pricing page, a docs section, a checkout flow) keeps users engaged instead of sending them to a separate chat window.
From an engineering standpoint, you avoid maintaining a full frontend and backend chat service while still shipping interactive features.
Four Ways to Embed
| Method | When to Use | Complexity |
|---|---|---|
| JavaScript Widget | Single-page apps, minimal dependencies | Low |
| React Integration | Modern React apps, TypeScript | Low |
| iframe | Legacy pages, third-party CMS, sandboxing | Low |
| REST API + UI | Full control, custom UX, analytics | Medium |
Below we build the same assistant in all four styles so you can pick what fits your stack.
1. JavaScript Widget (Vanilla JS)
A widget is a `` plus a small script that mounts an iframe or a lightweight Web Component.
Step-by-Step
- Create a container
- Inject a `` tag
- Pass configuration
(function () {
const config = {
apiKey: 'YOUR_API_KEY',
assistantId: 'support-bot-42',
userId: 'user_' + Math.random().toString(36).slice(2),
baseUrl: 'https://api.your-ai.com/v1',
greeting: 'How can I help you today?',
color: '#4f46e5',
position: 'bottom-right'
};
const script = document.createElement('script');
script.src = 'https://cdn.your-ai.com/widget.js';
script.dataset.config = JSON.stringify(config);
document.body.appendChild(script);
})();
widget.js (CDN)
// widget.js
(() => {
const conf = JSON.parse(document.currentScript.dataset.config);
const root = document.getElementById('ai-assistant');
const iframe = document.createElement('iframe');
iframe.src = `${conf.baseUrl}/widget?apiKey=${conf.apiKey}&assistantId=${conf.assistantId}&userId=${conf.userId}`;
iframe.style = `
position: fixed;
bottom: 24px;
right: 24px;
width: 360px;
height: 500px;
border: 0;
border-radius: 12px;
box-shadow: 0 10px 25px rgba(0,0,0,0.15);
background: white;
z-index: 1000;
`;
root.appendChild(iframe);
})();Custom Events
To communicate from inside the iframe back to the host page:
// Inside the iframe (chat-iframe.js)
window.addEventListener('message', (e) => {
if (e.origin !== 'https://api.your-ai.com') return;
if (e.data.type === 'assistant.closed') {
root.style.display = 'none';
}
});2. React Integration
If your site is built with React, you can mount the same iframe with hooks and TypeScript.
Install
npm i @your-ai/react-sdkUsage
// AssistantWidget.tsx
import React, { useEffect } from 'react';
import { useAIAssistant } from '@your-ai/react-sdk';
export const AssistantWidget = () => {
const { open, close, toggle } = useAIAssistant({
apiKey: 'YOUR_API_KEY',
assistantId: 'support-bot-42',
userId: 'user_' + Math.random().toString(36).slice(2),
greeting: 'How can I help?',
color: '#4f46e5'
});
return (
🤖 Assistant
{open && (
)}
);
};TypeScript Support
// types.ts
export interface AssistantConfig {
apiKey: string;
assistantId: string;
userId: string;
greeting?: string;
color?: string;
baseUrl?: string;
}SSR / SSG
Wrap the component in next/dynamic or React.lazy to avoid including the iframe on the server.
// pages/_app.tsx
import dynamic from 'next/dynamic';
const AssistantWidget = dynamic(() => import('../components/AssistantWidget'), {
ssr: false
});3. Embed as iframe
The simplest cross-platform option is a raw iframe. You lose some styling control, but you gain zero-maintenance embedding.
Markup
Responsive iframe
.ai-frame {
position: relative;
overflow: hidden;
width: 100%;
padding-top: 136%; /* 360/500 ≈ 0.72 → 72% */
}
.ai-frame iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}Sandboxing
To prevent the embedded page from navigating the parent, add sandbox="allow-scripts allow-same-origin".
4. REST API + Custom UI
If you want pixel-perfect control, call the assistant’s REST endpoint and render your own chat UI.
Endpoint
POST https://api.your-ai.com/v1/assistants/support-bot-42/messages
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{
"userId": "user_123",
"message": "I need help with my order",
"context": {
"path": "/checkout",
"referrer": "https://example.com/pricing"
}
}React Hook
// useAssistant.ts
import { useState } from 'react';
export const useAssistant = (config: AssistantConfig) => {
const [messages, setMessages] = useState([]);
const [input, setInput] = useState('');
const ask = async () => {
const res = await fetch(`${config.baseUrl}/assistants/${config.assistantId}/messages`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${config.apiKey}`
},
body: JSON.stringify({
userId: config.userId,
message: input,
context: { path: window.location.pathname }
})
});
const data = await res.json();
setMessages(prev => [...prev, data]);
setInput('');
};
return { messages, input, setInput, ask };
};Message Component
// Message.tsx
export const Message = ({ text, isUser }: { text: string; isUser: boolean }) => (
{text}
);Security & Performance Tips
- CORS: Whitelist your domains in the AI provider’s dashboard.
- Rate limiting: Add a debounce to the input field to prevent burst requests.
- User tracking: Use the
userIdyou generate to maintain conversation history. - Lazy load: Load the widget script only after the page is interactive (
domInteractive). - Content Security Policy: Allow
https://api.your-ai.cominframe-srcandscript-src. - Fallback: Provide a `` block with a link to a standalone chat page.
Debugging Common Issues
| Symptom | Likely Cause | Fix |
|---|---|---|
| 403 Forbidden | Wrong API key | Regenerate key in provider dashboard |
| iframe not appearing | CSP blocking frame | Add frame-src https://api.your-ai.com |
| Mixed-content error | iframe served over http | Switch to https everywhere |
| Messages not syncing | userId mismatch | Ensure same userId across sessions |
| Slow load | Large bundle | Enable Brotli compression on CDN |
Wrapping Up
Embedding an AI assistant is no longer a multi-month project. Pick the integration that matches your current stack—drop-in JavaScript, React components, a simple iframe, or a full REST + custom UI approach—and you can ship an interactive assistant in under an hour. Start with the widget or iframe to validate demand and metrics, then consider a custom React UI once you need pixel-perfect analytics or deep integration with your design system.