Skip to main content

JavaScript player API

The embed script creates window.atomicplayer on the page. Use it to read the playhead and to show a button, a form, or another block when the viewer reaches a time. Each video on the page has its own handle.

Wait until a player is ready​

<div class="atomic-player" id="pitch" data-player-id="PLAYER_ID"></div>
<script>
window.atomicplayer = window.atomicplayer || {};
window.atomicplayer.q = window.atomicplayer.q || [];
window.atomicplayer.q.push(function (players) {
players.ready(function (player) {
if (player.element.id !== "pitch") return;
player.on("timeupdate", function (event) {
if (event.currentTime >= 30) document.getElementById("offer").hidden = false;
});
});
});
</script>
<script async src="https://embed.atomicplayer.ai/player/v1.js"></script>

If the runtime script is already on the page, call atomicplayer.ready directly. The queue above is only needed when your script runs first.

Several videos​

atomicplayer.players is the list of embeds currently on the page. atomicplayer.get(id) returns one handle when id is that embed's instance id, its element id, its player id, or its video id. If two embeds share the same player id, get returns nothing for that shared id. Use query and pick the element you mean:

const pitches = atomicplayer.query({ playerId: "PLAYER_ID" });
const sidebar = atomicplayer.get("sidebar");

Set data-atomicplayer-instance="pitch-1" on the container when you want a stable name. The value may contain letters, numbers, _, and -.

What you can read and call​

MemberWhat it does
currentTimePlayhead, in seconds.
durationLength, in seconds. 0 before the media is known.
percentcurrentTime as a percentage of duration.
paused, ended, readyPlayback state.
play()Starts playback. The returned promise rejects when the browser blocks autoplay.
pause()Pauses. Returns false when pause is locked in Player Studio.
seek(seconds)Moves the playhead. Returns false when seeking is locked, or when seconds is not a finite number. The time is kept inside the video.
on(type, fn)Subscribes to one player. Returns a function that removes the listener.
off(type, fn)Removes that listener.

atomicplayer.on listens to every current and future embed. A listener that throws does not stop the video.

Events​

timeupdate carries currentTime, duration, percent, paused, instanceId, playerId, and videoId. It fires when the whole second changes, and at most four times a second between those changes.

The same payload is used for ready, play, pause, ended, and cta. A CTA event also includes buttonId. It does not include the button label, the destination, or anything the viewer typed.

These DOM events still fire on the container, and bubble to the page: atomicplayer:play, atomicplayer:pause, atomicplayer:complete, atomicplayer:timeupdate, and atomicplayer:cta. complete on the DOM is ended on window.atomicplayer.

A player inside an iframe also posts { type: "atomicplayer:event", signal, currentTime, duration, percent } to the parent page. The message does not include a viewer id or a media URL.

Studio callbacks​

Player Studio can still name a function on the page, such as window.hostCallbacks.onPlay. That function receives the same kind of playback detail. Prefer window.atomicplayer when the page has more than one video, or when you need the current time while it is playing.

Frequently asked questions​

Can I show a button at a specific second?

Yes. Subscribe to timeupdate and compare event.currentTime with that second. Hide the button until the comparison is true.

Why does get return nothing when two players use the same player id?

The id is ambiguous, so the API will not control the wrong video. Use the element id, data-atomicplayer-instance, or query.

Why does seek or pause do nothing?

Player Studio can lock seeking and pause. Those locks apply to this API as well. seek also rejects a value that is not a finite number.