Web widget

Add AI chat and voice capabilities to any website with a simple embeddable widget

Overview

Add a complete AI chat and voice interface to your website with a single line of code. The Vapi Web Widget provides a customizable, floating chat interface that supports both text chat and voice conversations.

What You’ll Build:

  • Embeddable chat widget with voice and text capabilities
  • Customizable themes, colors, and positioning
  • Real-time conversations with context management
  • Cross-platform compatibility with minimal setup

Widget Features:

  • Voice Mode - Full voice conversations with transcription
  • Chat Mode - Text-based conversations like ChatGPT
  • Custom Styling - Match your website’s design

View the complete source code and examples on GitHub.

Prerequisites

  • A Vapi account with a public API key
  • An existing assistant or willingness to create one
  • A website where you want to embed the widget

Scenario

We’ll add a customer support widget to “TechFlow’s” website that allows visitors to get help through both voice and text conversations.


1. Get Your Public API Key

1

Open the Vapi Dashboard

Go to dashboard.vapi.ai and log in to your account.

3

Copy your Public API Key

Copy your Public API Key. This is safe to use in client-side code.

Unlike private keys, public keys are safe to expose in your website code.

4

Get your Assistant ID

Navigate to Assistants in the left sidebar and copy the ID of the assistant you want to use.


2. Install the Widget

Add the widget script to your HTML page:

index.html
1<!DOCTYPE html>
2<html>
3<head>
4 <title>Your Website</title>
5</head>
6<body>
7 <!-- Your website content -->
8
9 <!-- Add Vapi Widget -->
10 <script src="https://unpkg.com/@vapi-ai/client-sdk-react/dist/embed/widget.umd.js" async type="text/javascript"></script>
11
12 <vapi-widget
13 public-key="your-public-key"
14 assistant-id="your-assistant-id"
15 mode="chat"
16 theme="light"
17 ></vapi-widget>
18</body>
19</html>

3. Configure Widget Modes

1

Choose the right mode for your use case

The widget supports two interaction modes:

Voice Mode - Voice-only conversations

1<vapi-widget
2 public-key="your-public-key"
3 assistant-id="your-assistant-id"
4 mode="voice"
5 size="compact"
6></vapi-widget>

Chat Mode - Text-only conversations

1<vapi-widget
2 public-key="your-public-key"
3 assistant-id="your-assistant-id"
4 mode="chat"
5 size="full"
6></vapi-widget>
2

Test the widget

Open your website and click the floating widget button to test the integration.


4. Customize Appearance

1

Choose theme and colors

Customize the widget to match your website’s design:

Custom Styling
1<vapi-widget
2 public-key="your-public-key"
3 assistant-id="your-assistant-id"
4 mode="chat"
5 theme="dark"
6 size="full"
7 radius="large"
8 base-color="#1a1a1a"
9 accent-color="#3B82F6"
10 button-base-color="#000000"
11 button-accent-color="#FFFFFF"
12></vapi-widget>
2

Customize labels and messages

Set custom text for better user experience:

Custom Labels
1<vapi-widget
2 public-key="your-public-key"
3 assistant-id="your-assistant-id"
4 mode="chat"
5 main-label="Chat with Support"
6 start-button-text="Start Voice Chat"
7 end-button-text="End Call"
8 empty-chat-message="Hi! How can I help you today?"
9 empty-voice-message="Click to start a voice conversation"
10></vapi-widget>

5. Handle Events and Callbacks

1

Add event listeners for the widget

Handle widget events to integrate with your application:

Event Handling
1<script>
2 document.addEventListener('DOMContentLoaded', function() {
3 const widget = document.querySelector('vapi-widget');
4
5 // Listen for call events
6 widget.addEventListener('call-start', function(event) {
7 console.log('Voice call started');
8 // Track analytics, update UI, etc.
9 });
10
11 widget.addEventListener('call-end', function(event) {
12 console.log('Voice call ended');
13 // Update UI, save conversation, etc.
14 });
15
16 widget.addEventListener('message', function(event) {
17 console.log('Message received:', event.detail);
18 // Process message, update state, etc.
19 });
20
21 widget.addEventListener('error', function(event) {
22 console.error('Widget error:', event.detail);
23 // Handle errors, show fallback UI, etc.
24 });
25 });
26</script>
2

React event handling

Handle events in React components:

React Events
1import { VapiWidget } from '@vapi-ai/client-sdk-react';
2
3function App() {
4 const handleCallStart = () => {
5 console.log('Voice call started');
6 // Update state, track analytics, etc.
7 };
8
9 const handleCallEnd = () => {
10 console.log('Voice call ended');
11 // Update state, save conversation, etc.
12 };
13
14 const handleMessage = (message: any) => {
15 console.log('Message received:', message);
16 // Process message, update state, etc.
17 };
18
19 const handleError = (error: Error) => {
20 console.error('Widget error:', error);
21 // Handle errors, show fallback UI, etc.
22 };
23
24 return (
25 <VapiWidget
26 publicKey="your-public-key"
27 assistantId="your-assistant-id"
28 mode="voice"
29 onCallStart={handleCallStart}
30 onCallEnd={handleCallEnd}
31 onMessage={handleMessage}
32 onError={handleError}
33 />
34 );
35}

6. Advanced Configuration

1

Use dynamic assistant configuration

Configure the assistant directly without pre-creating it:

The assistant configuration is only supported in voice mode. For chat mode, use assistant-id with optional assistant-overrides.

Inline Assistant Configuration
1<vapi-widget
2 public-key="your-public-key"
3 mode="voice"
4 assistant='{
5 "model": {
6 "provider": "openai",
7 "model": "gpt-4.1-mini",
8 "messages": [
9 {
10 "role": "system",
11 "content": "You are a helpful customer support agent for TechFlow. Be friendly and helpful."
12 }
13 ]
14 }
15 }'
16></vapi-widget>
2

Override assistant settings

Modify existing assistant behavior with overrides:

Assistant Overrides
1<vapi-widget
2 public-key="your-public-key"
3 assistant-id="your-assistant-id"
4 mode="chat"
5 assistant-overrides='{
6 "variableValues": {
7 "customerName": "John Doe",
8 "customerTier": "Premium"
9 }
10 }'
11></vapi-widget>

7. Production Considerations

1

Optimize for performance

Consider these optimizations for production:

Performance Optimizations
1<vapi-widget
2 public-key="your-public-key"
3 assistant-id="your-assistant-id"
4 mode="chat"
5 size="compact"
6 show-transcript="false"
7></vapi-widget>
2

Handle errors gracefully

Implement proper error handling:

Error Handling
1document.addEventListener('DOMContentLoaded', function() {
2 const widget = document.querySelector('vapi-widget');
3
4 widget.addEventListener('error', function(event) {
5 const error = event.detail;
6
7 // Log error for debugging
8 console.error('Widget error:', error);
9
10 // Show user-friendly message
11 if (error.message.includes('microphone')) {
12 alert('Please allow microphone access to use voice features.');
13 } else if (error.message.includes('network')) {
14 alert('Connection error. Please check your internet connection.');
15 } else {
16 alert('Something went wrong. Please try again.');
17 }
18 });
19});

Configuration Reference

Required Props

PropTypeDescription
public-keystringYour Vapi public API key

Assistant Configuration

PropTypeDescription
assistant-idstringID of your Vapi assistant
assistantobjectFull assistant configuration (JSON string) - Voice mode only
assistant-overridesobjectOverride existing assistant settings (JSON string)

You must provide either assistant-id, assistant, or both assistant-id and assistant-overrides. The assistant prop is only supported in voice mode.

Appearance Options

PropTypeDefaultDescription
modevoice | chatchatWidget interaction mode
themelight | darklightColor theme
positionbottom-right | bottom-left | top-right | top-leftbottom-rightScreen position
sizetiny | compact | fullfullWidget size
radiusnone | small | medium | largemediumBorder radius

Styling Options

PropTypeDefaultDescription
base-colorstring-Main background color
accent-colorstring#14B8A6Primary accent color
button-base-colorstring#000000Floating button background
button-accent-colorstring#FFFFFFFloating button text/icon color

Text Customization

PropTypeDefaultDescription
main-labelstringTalk with AIWidget header text
start-button-textstringStartVoice call start button text
end-button-textstringEnd CallVoice call end button text
empty-chat-messagestring-Message when chat is empty
empty-voice-messagestring-Message when voice mode is empty

Advanced Options

PropTypeDefaultDescription
require-consentbooleanfalseShow consent form before first use
terms-contentstring-Custom consent form text
local-storage-keystringvapi_widget_consentKey for storing consent
show-transcriptbooleantrueShow/hide voice transcript

Browser Support

  • Chrome/Edge 79+
  • Firefox 86+
  • Safari 14.1+
  • Mobile browsers with WebRTC support

Requirements

  • Microphone access for voice mode
  • HTTPS required in production
  • Vapi account and API key

Next Steps

Enhance your widget integration:

The widget automatically handles microphone permissions, audio processing, and cross-browser compatibility. For custom implementations, consider using the Web SDK directly.

Need help? Chat with the team on our Discord or mention us on X/Twitter.