SDK reference
Web SDK
Every method of @playstep/web and the script-tag build, with examples.
The same API is available as window.playstep (script tag) and as the playstep export of @playstep/web. Every method is safe to call before the SDK has loaded, and none of them ever throws into your app.
init
Starts PlayStep. Call it once; later calls are ignored.
import { playstep } from '@playstep/web'
playstep.init({
appKey: 'ps_pub_prod_your_key',
locale: 'pt-BR',
autoPageViews: true,
onEvent: (event) => analytics.capture(`playstep_${event.type}`, event),
})
| Option | Default | What it does |
|---|---|---|
appKey | required | Your publishable key, ps_pub_…. |
apiBase | https://cdn.playstep.app | Where configs and events live (self-hosting and tests). |
locale | The browser language | Picks the guide text. |
autoPageViews | true | Report a page view on client-side navigation. |
onEvent | none | Called for every guide event, to pipe them into your own analytics. |
config | none | Use this config instead of fetching one. Nothing is sent (preview mode). |
preview | false | Preview mode: nothing is sent. Set automatically by ?playstep_preview= links. |
With the script tag, init runs for you from data-app-key; data-api and data-locale set apiBase and locale.
<script async src="https://cdn.playstep.app/sdk/v1/loader.js" data-app-key="ps_pub_prod_your_key" data-locale="en"></script>
Pin a version
/sdk/v1/ always serves the latest release, so fixes reach you without a deploy. To control upgrades yourself, load a version's immutable path with its Subresource Integrity hash. Each release lists its files, their hashes and the exact snippet at https://cdn.playstep.app/sdk/<version>/manifest.json:
<script async src="https://cdn.playstep.app/sdk/0.1.0/loader.js" integrity="sha384-…" crossorigin="anonymous"
data-app-key="ps_pub_prod_your_key"></script>
The loader carries the hashes of the chunks it loads (the guide UI and the launcher button) and adds them with integrity too; the launcher chunk carries the hash of the capture chunk. A changed file never runs: the browser refuses it and your app carries on without guides.
Preview and capture links
?playstep_preview=… on any page loads a draft from the dashboard's Open in my app, or, for a Generate with AI capture link, shows the capture panel instead of guides. Either lasts for the tab's session across page loads, until it expires or you press Finish. Nothing in a preview is counted. Mark elements whose labels must never leave the page with data-private; capture skips them and everything inside.
identify
Tells PlayStep who the user is. The id is hashed with SHA-256 in the browser before it is sent. Traits are used by segments and stay on the device.
playstep.identify(user.id, { plan: 'pro', role: 'admin', guides: 0 })
track
Reports one of your events. It can start a guide with an event trigger and complete an event step.
playstep.track('invoice_page_opened')
start
Starts a guide now, by id, even if the user has finished it before.
helpButton.addEventListener('click', () => playstep.start('create-first-invoice'))
complete
Completes the current step if its id matches. Use it for manual steps.
await saveClient()
playstep.complete('fill-client')
page
Reports a page or screen view. Only needed with autoPageViews: false, or for screens that do not change the URL.
playstep.page('/invoices/new')
openLauncher
Opens the "?" launcher panel, which lists the guides people can replay.
menu.on('help', () => playstep.openLauncher())
reset
Forgets the user and their guide progress on this device. Call it on sign-out.
async function signOut() {
await api.signOut()
playstep.reset()
}
version
The SDK version, for support requests.
console.log(playstep.version)
Events
onEvent receives the same events the dashboard counts: guide_shown, step_shown, step_completed, clip_loaded, clip_played, clip_unmuted, guide_completed, guide_dismissed, anchor_missing and sdk_error. Events are sent in batches with sendBeacon, and only after a guide has been shown: a visitor who never sees a guide costs one config request and nothing else.