Skip to main content
MindStudio
Pricing
Blog About
My Workspace

How to Embed an AI Voice Agent Widget on Your Website with ElevenLabs

Add a voice agent to your website in minutes using ElevenLabs' widget embed code and Claude Code. Includes security best practices and cost controls.

MindStudio Team RSS
How to Embed an AI Voice Agent Widget on Your Website with ElevenLabs

What You Need Before You Start

Adding a voice agent widget to your website used to require a backend team, a telephony provider, and weeks of integration work. ElevenLabs has compressed that into a snippet of HTML you can paste into any page. Pair that with Claude Code to handle the implementation, and you can embed an AI voice agent widget on your website in an afternoon.

This guide walks through the full process: creating an ElevenLabs Conversational AI agent, getting the widget embed code, placing it on your site using Claude Code, locking down security, and setting spending limits so you don’t wake up to a surprise bill.


What ElevenLabs Conversational AI Actually Is

ElevenLabs is best known for its text-to-speech API, but their Conversational AI product is a separate offering. It lets you build agents that can hold real-time spoken conversations — listening with speech recognition, reasoning with a language model, and responding in a cloned or synthetic voice.

The widget is a pre-built browser component that handles all the WebSocket audio streaming between your visitor’s microphone and ElevenLabs’ servers. You don’t need to write any audio processing code. The widget connects, handles interruptions, manages turn-taking, and displays a simple UI element your users can click to start speaking.

What makes it practical for websites:

  • Works entirely client-side — no server required to proxy audio
  • Configurable with system prompts, voice selection, and LLM model choice
  • Supports first-message triggers (the agent speaks first when the widget opens)
  • Can call custom tools via webhook or server-side functions

Plans first. Then code.

PROJECTYOUR APP
SCREENS12
DB TABLES6
BUILT BYREMY
1280 px · TYP.
yourapp.msagent.ai
A · UI · FRONT END

Remy writes the spec, manages the build, and ships the app.

Prerequisites

Before writing a single line of code, you need a few things in place.

An ElevenLabs account — Sign up at ElevenLabs and subscribe to at least the Starter plan. The free tier has limited character credits and doesn’t include Conversational AI access on all endpoints.

A defined agent purpose — Know what your voice agent is for. Customer support? Lead qualification? Product FAQ? This shapes your system prompt and determines how permissive or constrained your agent should be.

Access to your website’s code — You need to be able to edit the HTML of at least one page. This works with any setup: plain HTML files, a CMS like WordPress or Webflow, a React or Next.js app, or a static site generator.

Claude Code (optional but recommended) — If you’re not a developer, Claude Code can write and place the integration code for you. It’s worth using even if you are a developer, since it handles the boilerplate quickly.


Step 1: Create Your ElevenLabs Conversational Agent

Log in to ElevenLabs and navigate to the Conversational AI section in the left sidebar.

Configure the agent basics

Click Create agent and choose a blank template or one of the prebuilt options (customer support, booking assistant, etc.). The prebuilt templates give you a working system prompt you can modify rather than starting from scratch.

You’ll configure:

  • Name — Internal label for your agent
  • System prompt — Instructions that define the agent’s persona, knowledge scope, and behavior
  • First message — What the agent says when a conversation starts (optional but increases engagement)
  • Language — ElevenLabs supports 30+ languages with automatic detection available

Choose your LLM

ElevenLabs lets you pick which model powers the reasoning layer. Options include Claude (via Anthropic), GPT-4o, Gemini, and others. For customer-facing agents, Claude tends to perform well on instruction-following and staying within defined scope — useful when you want the agent to avoid going off-topic.

Choose a voice

Select from ElevenLabs’ library of pre-made voices or use a cloned voice if you’ve created one. Pick something that matches your brand tone. You can preview voices directly in the interface before committing.

Set the knowledge base (optional)

You can upload documents, paste URLs, or add plain text that the agent uses as reference material. This is how you ground the agent in your specific product, policies, or FAQ content without cramming everything into the system prompt.


Step 2: Get the Widget Embed Code

Once your agent is configured, go to the Widget tab inside your agent settings.

ElevenLabs generates a self-contained embed snippet that looks something like this:

<elevenlabs-convai agent-id="your-agent-id-here"></elevenlabs-convai>
<script src="https://elevenlabs.io/convai-widget/index.js" async type="text/javascript"></script>

That’s genuinely it for a basic embed. The custom element <elevenlabs-convai> is registered by the script, renders the widget UI, and handles the connection lifecycle.

Widget customization attributes

The widget element accepts several attributes you can add directly in HTML:

  • agent-id — Required. Your agent’s unique identifier.
  • action-text — The label shown on the widget button before a conversation starts.
  • start-call-text — Text shown on the call initiation button.
  • end-call-text — Text shown to end the call.

Remy is new. The platform isn't.

Remy
Product Manager Agent
THE PLATFORM
200+ models 1,000+ integrations Managed DB Auth Payments Deploy
BUILT BY MINDSTUDIO
Shipping agent infrastructure since 2021

Remy is the latest expression of years of platform work. Not a hastily wrapped LLM.

For visual customization, ElevenLabs exposes CSS custom properties you can override in your stylesheet to match your brand colors and positioning.


Step 3: Use Claude Code to Implement the Widget

If you’re working with a more complex codebase — a React app, a Next.js project, a CMS with templating — Claude Code is the fastest way to get this in correctly.

What to ask Claude Code

Open Claude Code and give it your context clearly. Here’s an example prompt structure:

“I have a Next.js 14 app using the App Router. I want to add an ElevenLabs Conversational AI widget to the bottom-right corner of every page. The embed snippet is: [paste your snippet]. It should only load on the client side. Please add it to the root layout and make sure it doesn’t interfere with server-side rendering.”

Claude Code will:

  1. Identify the correct file to modify (layout.tsx or _app.tsx depending on your setup)
  2. Wrap the script in a useEffect or use Next.js’s Script component with strategy="lazyOnload" to avoid SSR issues
  3. Position the widget using CSS without breaking your existing layout

For plain HTML sites

The implementation is simpler. Paste both lines before the closing </body> tag on any page where you want the widget. Claude Code can handle this too if you share the HTML file structure and want it placed consistently across pages.

For WordPress

Claude Code can write the PHP snippet to enqueue the script properly, either via functions.php or as a plugin. Ask it to hook into wp_footer to load the script at the right point in the page lifecycle.


Step 4: Handle Authentication and Signed URLs

By default, the widget uses your agent ID, which is visible in the page source to anyone who looks. For most use cases — a public-facing customer support widget — this is acceptable. The agent ID alone doesn’t give someone billing access or the ability to change your agent’s configuration.

But if you want tighter control over who can initiate conversations, ElevenLabs supports signed URLs for widget authentication.

How signed URL auth works

Instead of using the agent-id attribute directly, your server generates a short-lived signed URL using your ElevenLabs API key. The widget receives this URL through your frontend and uses it to establish the WebSocket connection.

The flow looks like this:

  1. User loads your page
  2. Your frontend requests a signed URL from your backend
  3. Your backend calls the ElevenLabs API with your secret key to generate the signed URL
  4. Frontend passes the URL to the widget via JavaScript
  5. Widget connects using the signed URL

This keeps your API key server-side and lets you add your own authentication layer — only issue signed URLs to logged-in users, users who’ve passed a CAPTCHA, or users who meet other criteria.

Claude Code can scaffold this endpoint quickly. A minimal Express.js version might look like:

app.get('/api/voice-token', authenticateUser, async (req, res) => {
  const response = await fetch(
    `https://api.elevenlabs.io/v1/convai/conversation/get_signed_url?agent_id=${process.env.AGENT_ID}`,
    { headers: { 'xi-api-key': process.env.ELEVENLABS_API_KEY } }
  );
  const data = await response.json();
  res.json({ signedUrl: data.signed_url });
});
TIME SPENT BUILDING REAL SOFTWARE
5%
95%
5% Typing the code
95% Knowing what to build · Coordinating agents · Debugging + integrating · Shipping to production

Coding agents automate the 5%. Remy runs the 95%.

The bottleneck was never typing the code. It was knowing what to build.

Ask Claude Code to write the full implementation including error handling, token expiry logic, and the frontend JavaScript to consume it.


Step 5: Security Best Practices

A voice widget that’s open to the public internet has some real attack surfaces. A few things to lock down before you go live.

Rate-limit conversation starts

Without rate limiting, someone can write a script that starts hundreds of conversations per hour, burning through your ElevenLabs credits. If you’re using signed URLs, add rate limiting on your token endpoint — most backend frameworks have middleware for this (express-rate-limit for Node, Flask-Limiter for Python).

If you’re using the direct embed without auth, ElevenLabs has some built-in abuse protections, but they’re not a replacement for your own limits.

Restrict allowed origins (if using your API)

If you built a backend endpoint to generate signed URLs, set CORS headers to only accept requests from your own domain. This prevents other sites from using your endpoint.

Scope your system prompt tightly

Prompt injection is a real concern with voice agents. Users can try to talk the agent out of its defined behavior. Write your system prompt defensively:

  • State explicitly what the agent will and won’t discuss
  • Tell the agent to stay on topic if asked about unrelated things
  • Use phrases like “You are only authorized to help with [specific topic]“

Keep your API key out of the frontend

Never include your ElevenLabs API key in client-side JavaScript. It will be visible in your page source. Always keep it on the server.


Step 6: Set Up Cost Controls

ElevenLabs bills conversational AI by the minute. An uncontrolled widget can run up costs fast if it gets significant traffic or if someone leaves a session open.

Set a conversation time limit

In your agent settings under Advanced, you can configure a maximum conversation duration. Setting this to 5–10 minutes is reasonable for most customer support use cases and prevents runaway sessions.

Set monthly usage limits

Under your ElevenLabs account billing settings, you can configure usage alerts and hard caps. Set an alert at 50% of your expected monthly spend and a hard stop at your maximum budget. This won’t pause individual conversations mid-sentence, but it will stop new conversations from starting once you hit the limit.

Monitor usage by agent

ElevenLabs shows per-agent usage in the dashboard. If you run multiple agents, this helps you see which ones are consuming the most credits and where optimization is worth the time.

Consider restricting hours

If your use case is business support, you might only want the voice agent active during business hours. You can wrap the widget in JavaScript that checks the current time and only renders the embed element during defined hours. Claude Code can write this in about two minutes.


Extend Your Voice Agent with MindStudio Workflows

The ElevenLabs widget handles the conversation layer well, but voice alone has limits. Real customer support often needs to do something: create a support ticket, look up an order status, send a follow-up email, update a CRM record.

Day one: idea. Day one: app.

DAY
1
DELIVERED

Not a sprint plan. Not a quarterly OKR. A finished product by end of day.

This is where connecting your voice agent to backend workflows becomes valuable. MindStudio is a no-code platform for building AI agents and automated workflows, and it’s well-suited for handling the backend logic your voice agent surfaces.

Here’s a practical pattern: your ElevenLabs agent collects information from the user through conversation — their email, their issue, their account number. At the end of the conversation (or at a defined trigger point), a webhook fires to a MindStudio workflow. That workflow can:

  • Create a ticket in Zendesk or Freshdesk
  • Look up an order in your database via API
  • Send a summary email to your support team
  • Update a Salesforce contact record
  • Notify a Slack channel with conversation details

MindStudio connects to 1,000+ business tools out of the box, so you’re not writing individual API integrations from scratch. You build the workflow visually, set the webhook URL, and your ElevenLabs agent fires it at the right moment using a tool call.

You can also flip the architecture: build the full support agent in MindStudio (which supports Claude, GPT-4o, and other models), then use ElevenLabs purely as the voice layer on top. MindStudio’s webhook/API endpoint agents can receive requests from any external system, making them easy to connect to a conversational front-end.

MindStudio is free to start at mindstudio.ai.


Troubleshooting Common Issues

The widget doesn’t appear on the page

Check that the script tag is loading correctly. Open your browser’s developer console and look for network errors on the ElevenLabs script URL. If you’re on a CMS with a Content Security Policy, you may need to add https://elevenlabs.io to your CSP script-src and connect-src directives.

The agent connects but audio doesn’t work

Microphone access requires HTTPS. If you’re testing on http://localhost, some browsers will block mic access. Use a tool like ngrok to test over HTTPS locally, or deploy to a staging environment.

The widget works on desktop but not mobile

iOS Safari and some Android browsers handle microphone permissions differently. Make sure you’re requesting permission in response to a direct user gesture (the widget does this correctly by default). If you’re triggering conversation programmatically, move that trigger to a button click handler.

SSR errors in Next.js or Remix

The ElevenLabs widget registers a custom HTML element, which requires access to the browser’s customElements API. This doesn’t exist in Node.js. Wrap any import or direct usage in a useEffect hook, or use Next.js’s dynamic() with ssr: false.


Frequently Asked Questions

How much does ElevenLabs Conversational AI cost?

ElevenLabs charges for conversational AI by the minute of conversation. Pricing varies by plan, but most plans bundle some conversational AI minutes with the subscription. Additional minutes are billed at a per-minute rate. You can find current pricing on the ElevenLabs pricing page. Setting monthly caps in your account prevents unexpected charges.

Can I use the ElevenLabs voice widget without any backend?

Yes, for basic use cases. The direct embed with just your agent ID requires no backend. You paste the snippet into your HTML and it works. You only need a backend if you want signed URL authentication, rate limiting, or integration with other systems.

Is the ElevenLabs widget accessible?

Other agents ship a demo. Remy ships an app.

UI
React + Tailwind ✓ LIVE
API
REST · typed contracts ✓ LIVE
DATABASE
real SQL, not mocked ✓ LIVE
AUTH
roles · sessions · tokens ✓ LIVE
DEPLOY
git-backed, live URL ✓ LIVE

Real backend. Real database. Real auth. Real plumbing. Remy has it all.

ElevenLabs’ widget is designed to be keyboard-navigable and works with screen readers for the visual UI elements. The voice interface itself is inherently multimodal. If accessibility is critical for your use case, test with your specific assistive technology setup and consider providing an equivalent text-based support path.

Can I style the widget to match my website?

Yes. ElevenLabs exposes CSS custom properties for colors, border radius, and positioning. You can also hide the default widget entirely and trigger conversations programmatically using the widget’s JavaScript API, building your own UI elements that call the start/stop methods.

What LLMs can power an ElevenLabs voice agent?

ElevenLabs supports several model options including Claude (via Anthropic), GPT-4o and GPT-4o mini (via OpenAI), Gemini models, and their own optimized models. Model choice affects both response quality and latency — lighter models respond faster, which matters for voice where pauses feel awkward.

How do I handle languages other than English?

ElevenLabs supports multilingual conversations. You can set a specific language in your agent settings or enable automatic language detection, which lets the agent respond in the language the user speaks. Voice quality and model performance vary by language, so test your target languages before going live.


Key Takeaways

  • The ElevenLabs Conversational AI widget embeds with a two-line HTML snippet — no audio processing code required.
  • Claude Code significantly speeds up implementation, especially for framework-based sites (Next.js, React, WordPress) where placement and SSR considerations add complexity.
  • Signed URL authentication is the right approach for production deployments where you want to control who initiates conversations.
  • Set a maximum conversation duration and monthly spending cap before going live — these are the two most important cost controls.
  • For voice agents that need to trigger real actions (creating tickets, updating CRMs, sending emails), connecting to a workflow platform like MindStudio via webhook is the most practical approach without custom backend development.

Voice agents are no longer a feature only large companies can deploy. With the right tooling, you can add a working voice agent to your website today — and iterate on it without waiting for an engineering sprint.

Presented by MindStudio

No spam. Unsubscribe anytime.