Interactive Avatar: Add the widget to your website
The managed widget is the Synthesia-hosted way to add an Interactive Avatar to your website. Create a deployment in Studio, paste its snippet into your page, and Synthesia runs the experience end to end: the widget, the conversation and the call. You don’t need API keys, an LLM or a room of your own.
For full control over the avatar’s brain (your own LLM and speech stack) and over room management, use the bring-your-own integration instead.
Add the widget
Adding the widget takes three steps. You do the first two in Studio and the last one on your page.
1. Create a deployment
In Studio, create a deployment for your avatar. A deployment holds the widget’s settings, such as which avatar to show, how it looks and which sites may use it. Its type decides which snippet you get on the Deploy tab. Both snippets load the same widget, but they give you different options:
Use an Embed if your page allows frames but not third-party scripts. Otherwise, use a Widget. An Embed is always open in place, so the deployment’s corner, starting state and logo settings don’t apply to it.
2. Allow your site’s origin
The widget only runs on sites you allow, so a copy of your snippet on someone else’s site stays blank. Add every origin that shows the widget to the deployment’s allowed origins. The match is exact, so https://www.example.com and https://example.com are two different origins. If your site uses both, add both.
A subdomain pattern such as https://*.example.com covers the subdomains of example.com, but not example.com itself. You can’t use * on its own to allow any origin, so list each origin or use a subdomain pattern.
On an origin that isn’t allowed, the browser refuses to show the widget frame (see Errors for what your page gets). If another site shows your page inside its own frame, read Frames and page builders too.
3. Paste the snippet into your page
Copy the snippet from the Deploy tab and paste it into your page. A Widget’s script snippet looks like this:
An Embed gives you an iframe snippet instead, described in Embed with an iframe. If your site sends security headers, check Security policies before you go live.
Script snippet attributes
The script snippet reads its settings from data- attributes on the script tag. The snippet from Studio already has the deployment ID. Add the other attributes when you need them:
You set the bubble’s corner, colors and logo on the deployment in Studio, not with attributes.
The bubble shows above your page’s content, whatever its z-index. Dialogs and popovers your page opens later show above the bubble. On screens narrower than 640 pixels, such as phones, the bubble starts minimized and opens full screen.
The bubble can cover a cookie banner in the same corner. Pick another corner in Studio, or use consent deferral.
Use the custom element
The script also defines a custom element, <synthesia-interactive-avatar>. It’s often easier to work with than a script tag if you use a framework or a CMS block, because you can add and remove it like any other element. Load the script without a deployment ID, and give the element the same attributes without the data- prefix:
In inline mode, the frame goes inside the element. In bubble mode, the element stays empty and the bubble floats over the page.
Single-page apps
Here’s how the widget behaves when your app changes routes or replaces parts of the page:
- If your app inserts a script tag later, its widget mounts when the tag is inserted. If your app renders the same tag again while the widget is on the page, nothing changes, and a call in progress keeps going.
- When an element leaves the page, its widget is destroyed. The exception is an element your app puts back synchronously, in the same task, as frameworks do when they move an element. A new element with the same deployment ID that takes its place in the same task mounts as well. Moving an inline element reloads its frame, because browsers reload any iframe that moves.
- Each deployment mounts once per page. A second tag or element with the same deployment ID is ignored while the first one’s widget is on the page, and takes over once that widget is gone.
Navigations that replace the page body
Some libraries navigate by replacing the page’s <body> instead of loading a new page. Here’s what happens to the widget with the common ones:
- With Turbo Drive, you get a new, idle widget in the new body, and a call in progress ends with the old body. A tag with consent deferral comes back deferred, so call
init()again, as on the first page load. - With htmx’s
hx-boost, the body’s content is replaced and the tag in it runs again, with the same result. Keep the tag inside the body. - Swup, jquery-pjax and Barba swap a container rather than the whole body, so the bubble stays where it is.
- When the browser restores a cached copy of the page on a back navigation, the widget mounts once, without a second bubble.
An inline frame inside a data-target container moves with that container. If your app takes the container out of the page and puts it back, the frame comes back with it, reloaded. After a body swap, a tag with the same deployment ID in the new body takes over and places the frame where its own data-target says. If the new body has no such container, the frame goes right after the tag, as on a first load of that page.
Embed with an iframe
The iframe snippet is a single tag with no script on your page. It loads https://interactive-avatars.synthesia-embeds.io/v1/dep_… in a 400 × 620 frame.
Keep the allow and referrerpolicy attributes the snippet comes with. allow gives the widget the microphone and autoplay, and referrerpolicy lets it check your origin. Security policies explains both.
Frames and page builders
If another site shows your page inside a frame, the origin check covers that site too, not only your page. The widget stays blank unless that site’s origin is allowed as well. This happens in:
- Page builder editors and previews, such as Webflow Designer, the WordPress or Elementor customizer and the Shopify theme editor.
- Learning management systems, intranet portals and other sites that show your page in a frame.
Add those origins to the deployment as well. Each frame between the top page and the widget also needs:
allow="microphone". A frame can only pass on the microphone it was given, so one missing attribute blocks the microphone.- No
sandboxattribute, or one that includes bothallow-scriptsandallow-same-origin. Without them, the widget can’t run.
Shopify
Shopify serves your store on two origins, so allow both. Add your custom domain and your store’s exact https://your-store.myshopify.com origin. You can’t use a *.myshopify.com pattern, because every Shopify store shares the myshopify.com domain.
Load the script from our URL
Always load runtime.js from https://interactive-avatars.synthesia-embeds.io/v1/runtime.js. Don’t copy it to your server, bundle it into your app or serve it through a proxy. The script reads its own URL to find the widget, so a copy on your origin points the frame at your origin and the widget doesn’t load.
We also ship fixes to runtime.js without any change to your page, and a copy never gets them. Browsers and our edge each cache it for up to five minutes, so a fix reaches your visitors within about ten minutes.
Don’t add an integrity attribute (Subresource Integrity). The file changes with every release, so a pinned hash stops the widget from loading after our next release. crossorigin="anonymous" is fine, because we serve the script with CORS headers.
Supported browsers
The widget needs a current browser with WebRTC and microphone access, such as Chrome, Edge, Firefox or Safari. Internet Explorer isn’t supported. Your page must use HTTPS, because browsers only give the microphone to secure pages.
Next steps
Once the widget is on your page, these pages help you control it, keep it compliant and plan for updates.