Configure your session parameters, then hit Reload Preview to load the replay player inline.
Press Enter as a shortcut
Configure your session parameters, then hit Reload Preview to load the replay player inline.
Press Enter as a shortcutA User-level JWT is a bearer credential scoped to specific scenes/versions and to a project/participant, and it expires.
Best practice: load the iframe with no token in the URL and hand the JWT over from your parent page with Window.postMessage().
Pass the JWT in dynamically, per user. Your parent
site should get the token from its own API request — a call to your
backend service, which mints a short-lived JWT with the narrowest
scene/version claims that user needs — and set
JWT from that response at runtime. Don't hard-code a
token into page source or a build artifact; that exposes it to every
visitor. Keep it in memory only: no localStorage,
cookies, analytics payloads, or logs. The literal
JWT value below is filled in for a quick console test.
{ tokenRequired: true } as soon as
it is listening, then { iframeReady: true } once the
player is up.
{ config: { apiKey: "<jwt>" } } — an
apiKey-only push merges into the live config, so camera and
playback state survive a token swap.
{ tokenRefreshRequired: true, status: 401 } and holds
its requests for 30s. Answer by requesting a new token from your
backend and pushing it — never hold a second static token, and
note that a repeat of the rejected token is ignored.
'*', and pick the iframe by that origin rather than
by a name match — an injected iframe with a similar
src would otherwise receive your token. Pin it with
frame-src in your CSP. On inbound messages, check
both event.source and event.origin.
This keeps the credential out of URLs, logs, and shared links. It does not defend against XSS: any script running on your page can request a token, so keep the CSP tight and untrusted third-party scripts off the pages that mint them.
Paste this into your parent page and modify it based on your scenario:
Drop this into your page to embed the replay with the settings you
configured. The allow list is what lets the player
start audio, go fullscreen, and read XR pose data.
The URL below carries your credential in
config.apiKey, which is fine for an
Organization Key in a development page but not for
a User-level JWT — provide a JWT above and this snippet drops the
token from the URL.
The URL below carries no
config.apiKey: with a User-Level JWT provided, the
token stays out of the src and your parent page pushes it to the
iframe over postMessage. This snippet only mounts the frame — pair
it with
Example Code for generating JWT, which handles the
tokenRequired handshake that actually authenticates it.
The viewer applies each { config } message as a
complete replacement, not a merge — there's no way to send just
{ renderConfig: { ui: false } } and have everything
else stay put. Always resend the whole config
object with only the field(s) you want changed, which means your
parent page has to keep its own live copy of it.
This snippet seeds that copy from the session you've configured
here (including the current credential, for a quick console
test — see the JWT snippet's own caveat about hard-coding
tokens), keeps it in sync from the viewer's
clientConfig messages, and exposes two console
helpers matching the toggles below:
SR_setUIControls(false) — hide the built-in
header/menu chrome (renderConfig.ui).
SR_setFirstPersonCamera(true) — switch Camera
Controls to First Person; false restores whatever
control type was active when this snippet was generated.
Paste this into your parent page's console (with the Session Replay iframe already on the page) and modify it based on your scenario: