Confirm the iframe has loaded, its src points to Visiroll, and the embedding hostname is allowed. Commands are queued only while the API waits for the player handshake.
DEVELOPER REFERENCE
Control the player.
React to playback.
Drive the embedded player from the page around it. Start and stop playback, build your own mute button, and react to events — including the moment a viewer finishes the video.
Quick start
Load the script, point it at your iframe, and call methods on the returned player. Every method returns a promise.
<iframe id="video" src="https://visiroll.com/v/VIDEO_ID"
title="Campaign video" width="1920" height="1080"
allow="autoplay; fullscreen; picture-in-picture" allowfullscreen
loading="lazy"
style="border:0;aspect-ratio:1920/1080;width:100%;height:auto"></iframe>
<script src="https://visiroll.com/player.js"></script>
<script>
var player = new Visiroll.Player(document.getElementById("video"));
player.on("ended", function () {
console.log("the viewer finished the video");
});
player.play();
</script>Commands sent before the iframe finishes loading are queued and delivered as soon as it is ready, so calling play() immediately after construction is safe.
The iframe
The constructor accepts an iframe element or a CSS selector. The allowattribute matters: without autoplay, a programmatic play() is refused by the browser, and without fullscreen the fullscreen button does nothing.
var player = new Visiroll.Player("#video"); // selector
var player = new Visiroll.Player(iframeElement); // elementCopy a ready-made embed from the video’s Share tab in the studio.
Publish in WordPress or Webflow
The iframe is enough for normal playback. The JavaScript API is optional and is needed only when the surrounding page must control playback or react to player events.
- WordPress guide — Custom HTML block, permissions, domains and common sanitization problems.
- Webflow guide — Code Embed, staging hostname, components and CMS use.
Both guides preserve the video’s real aspect ratio, including square and vertical content.
Methods
play()Promise<null>Starts playback. Rejects when the browser blocks it, typically autoplay with sound.pause()Promise<null>Pauses playback.getPaused()Promise<boolean>Whether playback is currently paused.setMuted(muted)Promise<boolean>Mutes or unmutes. Returns the resulting state.getMuted()Promise<boolean>Current mute state.setVolume(volume)Promise<number>Volume between 0 and 1. Values outside the range are clamped.getVolume()Promise<number>Current volume between 0 and 1.setCurrentTime(seconds)Promise<number>Seeks to a position in seconds.getCurrentTime()Promise<number>Current position in seconds.getDuration()Promise<number>Total duration in seconds, or 0 before metadata loads.setPlaybackRate(rate)Promise<number>Playback speed, where 1 is normal.player.getDuration().then(function (seconds) {
console.log("duration", seconds);
});
player.setVolume(0.4)
.then(function (volume) { console.log("volume is now", volume); })
.catch(function (error) { console.error(error); });Events
Subscribe with on(name, listener) and remove with off(name, listener), or off(name) to drop every listener for that event. Each listener receives a single data object.
loaded{ duration }Metadata is available. Fires once the player is ready to accept commands.play{ currentTime }Playback started or resumed.pause{ currentTime }Playback paused.ended{ duration }The viewer reached the end. Use this to unlock a next step or a reward.timeupdate{ currentTime, duration }Position changed. Fires several times per second while playing.volumechange{ volume, muted }Volume or mute state changed, from your code or from the player controls.seeked{ currentTime }A seek finished.These browser events are for your page logic. Visiroll’s qualified views, engaged views and retention are calculated independently; see analytics definitions.
Call player.destroy() when you remove the iframe, to detach the listeners.
Worked example
A common pattern: play inside a modal, keep a custom mute button outside the player, and unlock the next step only once the video has actually finished.
var player = new Visiroll.Player("#video");
var soundButton = document.querySelector(".sound-btn");
player.on("loaded", function () {
player.setMuted(true);
player.play();
});
soundButton.addEventListener("click", function () {
player.getMuted().then(function (muted) {
player.setMuted(!muted);
soundButton.classList.toggle("is-muted", !muted);
});
});
player.on("volumechange", function (data) {
soundButton.classList.toggle("is-muted", data.muted);
});
player.on("ended", function () {
closeModal();
unlockReward();
});Domains and security
The player only accepts commands from pages whose origin appears in that website’s allowed domains, wildcards included. Replies and events are posted back to that exact origin, never to *. A page that is not on the list can neither embed the video nor control it.
Add every staging or production hostname that will contain the player. Remove obsolete hostnames as soon as a publishing destination is retired.
Allowed domains are managed per website under Websites → Settings → Allowed domains.
Troubleshooting
play() rejectsThe browser blocked autoplay with sound. Start muted or call play from a user gesture such as a click.
Create one Player instance for the correct iframe and keep it alive. Do not remove the iframe before calling destroy().
Keep both the iframe permission allow="fullscreen" and the allowfullscreen attribute.