A highly customizable, framework-agnostic SDK for embedding Voice AI capabilities into any website. It supports "inline form" mode for quick integration and "headless" mode for complete UI control.
This frontend widget is designed to communicate with a secure backend to protect your API keys and handle high-traffic concurrency (queueing). We have built an official, production-ready middleware for this exact purpose.
👉 Get the Iqra AI Web Middleware (C# ASP.NET Core) here →
- Universal Compatibility: Works with Vanilla JS, React, Vue, WordPress, and more.
- Real-time Queueing: Handles high traffic gracefully with waiting queues.
- Audio Streaming: Robust WebSocket handling for low-latency voice interaction.
- Customizable: Configure form fields, styles, and behaviors dynamically.
- Headless Mode: Full programmatic control for building custom UIs.
Simply include the script in your HTML file.
<!-- Replace with your actual CDN URL -->
<script src="https://cdn.your-domain.com/voice-ai-widget.umd.js"></script>Coming soon.
The SDK exposes a global variable VoiceAiWidget. The primary entry point is the init method.
This mode renders a pre-built, styled form inside a container of your choice.
HTML:
<div id="voice-widget-container"></div>JavaScript:
const client = VoiceAiWidget.init({
// 1. URL of your middleware (Required)
middlewareUrl: 'https://api.your-middleware.com',
// 2. Where to render the widget (Required for UI mode)
container: '#voice-widget-container',
// 3. Campaign routing details (Required)
campaignId: 'IqraWebsiteCampaign',
regionId: 'EU-DE',
// 4. Define the form fields
formFields: [
{
name: 'firstName',
label: 'First Name',
type: 'text',
target: 'dynamicVariable', // Sends as dynamic variable to AI
required: true
},
{
name: 'email',
label: 'Email Address',
type: 'email',
target: 'metadata', // Sends as metadata to AI
required: true
}
]
});If you want to build your own button and form, simply omit the container option. The SDK will return a client instance for you to control.
// Initialize without a container
const client = VoiceAiWidget.init({
middlewareUrl: 'https://api.your-middleware.com',
campaignId: 'IqraWebsiteCampaign',
regionId: 'us-east-1'
});
// Listen to state changes to update your custom UI
client.on('stateChange', ({ state, data }) => {
console.log('Current State:', state);
// States: 'IDLE' | 'CONNECTING' | 'QUEUED' | 'CONNECTED' | 'ERROR'
if (state === 'QUEUED') {
alert(`You are #${data.queuePosition} in line.`);
}
});
// Start the session manually (e.g., on button click)
document.getElementById('my-custom-btn').addEventListener('click', () => {
client.startSession({
dynamicVariables: { firstName: 'Abdullah' },
metadata: { source: 'custom-ui' }
});
});
// Hang up manually
document.getElementById('hangup-btn').addEventListener('click', () => {
client.hangUp();
});The init(options) method accepts the following configuration object:
| Option | Type | Required | Description |
|---|---|---|---|
middlewareUrl |
string |
Yes | The base URL of your C# Middleware API (e.g., https://api.myapp.com). |
campaignId |
string |
Yes | The ID of the targeted Voice AI platform campaign routing configuration. |
regionId |
string |
Yes | The geographic availability zone for initiating the AI Agent. |
container |
string | HTMLElement |
No | CSS selector or DOM element. If provided, the UI Manager is initialized. |
formFields |
FormField[] |
No | Array of field definitions for the inline form. |
{
name: string; // Unique ID for the input
label: string; // Label text shown to user
type?: 'text' | 'email' | 'tel'; // HTML input type (default: text)
target: 'dynamicVariable' | 'metadata'; // Where to send this data in the AI payload
required?: boolean; // Is this field mandatory?
}The client instance emits the stateChange event. You can subscribe to it using client.on().
client.on('stateChange', (payload) => {
const { state, data } = payload;
// Handle updates...
});| State | Description | Data Payload |
|---|---|---|
IDLE |
Client is ready. No active call. | undefined |
CONNECTING |
Contacting middleware/server. | undefined |
QUEUED |
Waiting for an available slot. | { queuePosition: number } |
CONNECTED |
Call is live. Audio is streaming. | undefined |
ERROR |
An error occurred. | { message: string } |
- HTTPS is Required: The browser will not grant microphone access (
getUserMedia) if the site is served over HTTP. Your website and the middleware must be served over HTTPS. - Microphone Permissions: The user must explicitly grant permission for the microphone. The SDK handles the request, but if denied, the state will transition to
ERROR.
- VoiceAiClient: The core logic engine. Handles SignalR (queueing), REST API (session requests), and Web Audio API (PCM conversion/streaming).
- UIManager: A lightweight DOM manager that renders the form and handles user interactions based on the Client's state.
Before you publish, test the build locally:
- Create a new file named
test-production.htmlin your project root. - Add this code:
<!DOCTYPE html> <html lang="en"> <head> <title>Production Build Test</title> </head> <body> <h1>Production Test</h1> <div id="widget"></div> <!-- Import the built file from the dist folder --> <script src="./dist/voice-ai-widget.umd.js"></script> <script> // Check if the global variable exists if (window.VoiceAiWidget) { console.log("SDK Loaded successfully!"); VoiceAiWidget.init({ middlewareUrl: 'https://localhost:7157', // Your running middleware container: '#widget', formFields: [ { name: 'name', label: 'Name', target: 'dynamicVariable' } ] }); } else { console.error("SDK failed to load."); } </script> </body> </html>
- Open this file in your browser. Note: Because of CORS and module security, simply double-clicking the HTML file might not work. It's best to serve it using a simple server:
Then go to
npx serve .http://localhost:3000/test-production.html.
Alhamdulillah, you are now ready to deploy!