Element vs iframe
How to reach the player in each embed mode, and what the iframe does not expose
The player ships in two embed modes, and the choice shapes everything else in this documentation: how you get a reference to the player, and which features you can reach at all.
The custom element puts <vturb-smartplayer> directly in your page. The iframe loads the player from converteai.net in a separate browsing context, and the SDK bridges the two.
Getting a reference to the player
On the custom element, the player is an element in your own DOM, so you query for it:
const player = document.querySelector("vturb-smartplayer");
player.addEventListener("video:play", (event) => {
console.log("video:play");
// the player reference is available on the event
console.log(event.target);
// use it to call the player methods
event.target.play();
});
You still have to wait for player:ready before calling methods — the element exists in the DOM before the player behind it is initialized.
On the iframe, your page cannot reach inside. The SDK dispatches iframe:connected on the <iframe>, bubbling up to document, once the bridge is up, and hands you an IframePlayer in event.detail.player:
// don't call methods before the connection:
// window.vturbSdk.get("PLAYER_ID") returns undefined until then,
// and window.vturbSdk itself is undefined until the SDK script loads
document.addEventListener("iframe:connected", (event) => {
// identify which player connected
if (event.detail.id !== "PLAYER_ID") return;
const player = event.detail.player;
// the iframe player is connected now
player.fullscreen();
});
// or, listening on the iframe element itself
const iframe = document.getElementById("ifr_PLAYER_ID");
iframe.addEventListener("iframe:connected", (event) => {
const player = event.detail.player;
// do something
});
Because the event fires for every player on the page, event.detail.id is how you tell them apart.
player:ready never fires on the iframe, and iframe:connected never fires on the element. Code
that waits for the wrong one waits forever.
What the iframe does not expose
Everything below works on the custom element and is unavailable — or behaves differently — inside an iframe. Not by omission: the browser's cross-origin rules make most of it impossible.
| Feature | Element | Iframe |
|---|---|---|
| Events and methods | yes | yes, after iframe:connected |
player:ready | yes | no, use iframe:connected |
| CSS variables | yes | no, cross-origin |
fluid, pauseonetouch | yes | no |
injectUrlUpdater | yes | no |
| Headline custom JS | yes | yes, but not under a CSP |
If you need to restyle the player, the custom element is the only mode that allows it. Styling is the most common reason teams move off the iframe embed.
Which one to use
Reach for the iframe when you cannot control the host page well enough to add a script tag, or when the page belongs to a platform that strips custom elements. Everywhere else the custom element is the better default: same API surface, no bridge to wait for, and the customization and attributes stay available.