ServicesTour

Tour

Product tours and onboarding progress tracking. Platform admins publish versioned tour definitions - ordered steps with semantic UI targets, prerequisites, branching rules, A/B variants, and reset policies - and clients record progress events while the server tracks per-user completion flags server-side, so progress follows the user across devices.

When to reach for it: onboarding checklists that resume correctly on any device, feature-discovery tours, "saw this panel" UI flags, tutorials that branch by experiment variant or prior choices, drop-off analytics on activation funnels.

When not to: gameplay progression with objectives and reward payouts belongs to Quest; one-off milestone badges belong to Achievements; gating features by environment or audience belongs to Remote Config - tour flags record what a user has seen, not what they may use.

Concepts

  • Definitions vs progress - a tour definition (steps, branching, variants) is admin-owned and versioned; progress is computed per user from a bitfield of completion flags, scoped to one definition version.
  • Steps carry completion flags - each step names a completion_flag; completing the step sets that bit. The definition fixes each flag's bit offset per version, so only declared flags exist.
  • Prerequisites gate availability - a step becomes available only once every flag in its prerequisites list is set; completing out of order is rejected, not reordered.
  • The current step is computed - branching rules are evaluated first; if none match, the first available step in index order is current.
  • Versions - replacing a definition's steps bumps its version and applies the reset policy to every participant.
  • Variants - deterministic A/B bucketing (SHA-256 of experiment, user, and version): stable within a version, re-rolled on version change.
  • Admin vs user - defining, updating, deleting, analytics, and acting on another user's progress require a platform admin token.

Define a tour

Creation takes a JSON file with the full definition and requires a platform admin token:

snug tour create --file new-user-setup.json
# {"tour_id": "CDqLNRRwSXuZRPuZqBpj", "name": "docs4_new_user_setup", "version": 1, ...}

snug tour list --query setup --status active
snug tour get --tour CDqLNRRwSXuZRPuZqBpj
snug tour update --tour CDqLNRRwSXuZRPuZqBpj --status paused
snug tour delete --tour CDqLNRRwSXuZRPuZqBpj

The tour_id is server-generated - keep it from the create response; the name is a searchable label, not an address. The definition file format has its own page: Defining tours. Listing speaks the shared search query grammar and shows only active tours to non-admins; admins can pass --include-versions to also see draft, paused, and deprecated definitions.

Record progress events

Clients report what the user did; the server derives everything else:

snug tour event --tour CDqLNRRwSXuZRPuZqBpj --event-type started
snug tour event --tour CDqLNRRwSXuZRPuZqBpj --event-type step_completed --step step_welcome

Event types are started, step_seen, step_completed, flag_set, dismissed, and abandoned. Over HTTP the same call is a POST returning 202 with the recomputed progress; captured live:

curl -X POST -H "Authorization: Bearer $SNUG_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"event_type": "step_completed", "step_id": "step_welcome"}' \
  http://localhost:4000/api/v1/tours/CDqLNRRwSXuZRPuZqBpj/events
{
  "status": 202,
  "msg": "Accepted",
  "data": {
    "tour_id": "CDqLNRRwSXuZRPuZqBpj",
    "definition_version": 1,
    "current_step_id": "step_profile",
    "completed_steps": ["step_welcome"],
    "mandatory_complete": false
  }
}

Completing a step whose prerequisites are unmet fails with 400 prerequisites_not_met; an unknown step_id is 404 step_not_found (both reproduced). Event metadata is free-form JSON but capped - a 9 KB payload was rejected with 400 limit_exceeded.

Read progress

snug --output json tour status docs-wave --tour CDqLNRRwSXuZRPuZqBpj
{
  "state": "in_progress",
  "current_step_id": "step_profile",
  "available_steps": ["step_profile", "step_advanced"],
  "completed_steps": ["step_welcome"],
  "seen_flags": ["saw_welcome"],
  "variant": "power",
  "mandatory_complete": false, "...": "..."
}

The CLI requires the user argument; pass your own subject. Over HTTP, GET /tours/{tour_id}/status defaults to the caller, and asking for someone else with ?user= is admin-only - a regular token gets 403 insufficient_permissions (reproduced). States are not_started, in_progress, completed, reset, and blocked; the moment every mandatory step's flag is set, state flips to completed even with non-mandatory steps remaining (verified live).

UI completion flags

Flags can also be set or cleared directly, without a step event:

snug tour flag-set --tour CDqLNRRwSXuZRPuZqBpj --flag sent_invite
snug tour flag-set --tour CDqLNRRwSXuZRPuZqBpj --clear sent_invite

Only flags declared in the definition exist - an undeclared name is 404 flag_not_found (reproduced) - and admins may pass --user to act on another user.

Resets

snug tour reset --tour CDqLNRRwSXuZRPuZqBpj --scope user      # yourself
snug tour reset --tour CDqLNRRwSXuZRPuZqBpj --scope version   # admin only
snug tour reset --tour CDqLNRRwSXuZRPuZqBpj --scope tour      # admin only

user scope resets the caller (admins may target --user someone else); version and tour scopes sweep every participant and require a platform admin token - a regular token gets 403 insufficient_permissions (reproduced). Version-change resets happen automatically; see reset policies for what each mode actually preserves.

Funnel analytics

Analytics require a platform admin token; a regular token gets 403 insufficient_permissions (reproduced):

snug tour analytics --tour CDqLNRRwSXuZRPuZqBpj                      # all-time
snug tour analytics --tour CDqLNRRwSXuZRPuZqBpj --window 2026-08-28  # one day

The response reports started/completed totals, per-step seen/completed/drop_off, per-variant completion rates, and how often each branching rule fired. Counters are pre-aggregated into an all-time window ("all") plus daily YYYY-MM-DD windows, scoped per definition version (--version selects an older one; the active version is default).

Limits and configuration

Definitions are bounded at 200 steps, 512 flags, 100 branch rules, and 8 KiB of event metadata by default - tunable via the TOUR_* variables in the Tour CONFIG reference.

Reference

On this page