Visitor identification
Pass data-user-id (or id via setUserAttributes). It's the single
most important thing you can do for StepsKit, because every
"per-visitor" rule keys on it.
Why id matters
- Frequency capping. "Show once per visitor" requires a stable visitor identifier — see Frequency capping.
- Analytics. Per-user funnel views and tour-completion rates roll up
by
id. - Per-user targeting. Targeting a specific person (
email = me@…) during testing needs anidto attribute the impression correctly.
Anonymous visitors
If you don't set an id, StepsKit treats the visitor as anonymous:
- Targeting rules that require a specific user attribute will not match.
- Rules that target all visitors (the default) still match.
- "Show once" falls back to a session-scoped check using browser storage. It works within a session but resets across devices and after clearing site data.
This is a reasonable default for marketing sites or signed-out screens.
It's the wrong default for an authenticated SaaS app — pass id as
early as you can.
The init/refresh race condition
There's a subtle ordering issue worth knowing about when you identify
the user client-side (e.g., from a Next.js <Script onLoad> or after a
React auth callback):
- The StepsKit script loads.
- It fetches the active tours for your project — but without a
visitor_id, because you haven't identified yet. - Your
onLoad(or auth callback) fires and callssetUserAttributes({ id, ... }, { autoRefresh: true }). - The first fetch is still in flight.
If StepsKit didn't handle this, a "show once" tour could play between steps 2 and 3, even for a visitor who has already seen it.
It does handle it. When you call setUserAttributes with
autoRefresh: true, the embed marks the first fetch as stale. When the
stale fetch resolves, it's discarded — playback is suppressed. The
fresh fetch (with the correct visitor_id) replaces it.
You don't need to do anything special. The only practical advice: always
pass autoRefresh: true when identifying the user, so the embed knows
the previous fetch is no longer authoritative.
Choosing an id
Use your internal user ID — whatever value uniquely identifies a user in your app. It can be a UUID, an integer, a Stripe customer ID, anything that's stable per user across sessions. Don't use email (changes), and don't use session IDs (rotate too often).