Zodiac Tech CRM Docs

How guided onboarding works

The onboarding state machine — how each wizard step derives from real app state, how skips auto-upgrade, and what Super Admin can see.

everyone Medium ⏱ 10 min Updated 2026-10-05

How guided onboarding works

The guided setup wizard is not a checklist that trusts you — it is a state resolver. Every step is recalculated from real system state, so "done" can only mean "the thing actually exists". That design choice explains almost every behaviour you will observe, including why some steps you thought you finished can flip back, and why skipped steps complete themselves later.

The idea in plain language

  • The wizard walks a workspace through the 12 frozen client steps (Client onboarding from zero).
  • Behind the scenes, a resolver asks the database one question per step: "is the real condition for this step true right now?"
  • The answer becomes a status: NOT_STARTED, IN_PROGRESS, COMPLETED, SKIPPED (you chose to skip) or BLOCKED (Meta needs attention).
  • Completion is one-way: once the resolver sees real state, the step stays completed.
  • Zodiac Tech sees the whole picture on the client onboarding dashboard — including skips and stuck steps — and the workspace is notified when you finish.
stateDiagram-v2
    [*] --> NOT_STARTED
    NOT_STARTED --> IN_PROGRESS: you open/provide the step
    IN_PROGRESS --> COMPLETED: real condition true
    IN_PROGRESS --> BLOCKED: Meta needs attention
    BLOCKED --> IN_PROGRESS: connection fixed
    IN_PROGRESS --> SKIPPED: you skip (skippable steps only)
    SKIPPED --> COMPLETED: condition met later (auto-upgrade)
    COMPLETED --> [*]: wizard completes when all required steps settle

The 12 client steps and their real conditions

# Step key Completes when… Required / Skippable
1 business Business name and business type are set Required · not skippable
2 industry Industry is set and a pipeline exists Required · not skippable
3 meta_connect A Meta connection exists (BLOCKED if error/needs-reauth) Required · not skippable
4 meta_assets A Page and an ad account are stored on the connection Required · not skippable
5 lead_forms Form ids are selected and the mapping is confirmed Required · skippable
6 sales_process The largest pipeline has ≥ 2 stages Required · not skippable
7 lead_routing Assignment mode is off/specific/round-robin Required · not skippable
8 followups An enabled lead_created automation exists Required · not skippable
9 team The workspace has more than one user Optional · skippable
10 whatsapp A WhatsApp connection is in state connected Optional · skippable
11 mobile A device registered or manual confirmation stored Optional · skippable
12 test_lead test_lead_verified_at is set by the test run Required · skippable

Why step 5 is skippable A Page with no lead forms yet must not lock a client out of the CRM forever. Skip settles the step as SKIPPED; the resolver auto-upgrades it to COMPLETED as soon as forms are actually selected.

The technical trace

  1. Definitions are frozen. App\Support\OnboardingSteps::CLIENT_STEPS (plus INTERNAL_STEPS for the Zodiac Tech checklist) is the single map of keys, labels, and required/skippable flags. Every consumer — resolver, wizard UI, SA dashboard, drawer, backfill, tests — reads this map; no step key is hard-coded elsewhere.
  2. Seeding. App\Services\GuidedOnboarding\OnboardingService::ensure() creates the header row (business_onboarding) and all step rows (business_onboarding_steps) for a workspace.
  3. Resolution. OnboardingStateResolver::clientStepStatus() computes each step's status + client-safe detail from real state (table above). Meta steps can return BLOCKED when the connection is in an error/needs-reauth state or the token expired.
  4. Sync. OnboardingService::sync() re-derives all client steps inside a transaction, persists statuses, and audits changes (guided_onboarding.step_status, guided_onboarding.completed). It sends the one-time setup complete notification to the internal team.
  5. Progress + UI. progress() is the floor of completed/total — the top-bar chip (App\Livewire\GuidedSetupChip, "Setup NN%") and the drawer render from it. The drawer shows a per-step icon: ✓ completed, ↷ skipped, ⚠ blocked, ● in progress, ○ not started.
  6. Gating. App\Http\Middleware\RedirectToOnboarding sends workspace owner/admins to /admin/guided-setup until the header row is COMPLETED (billing pages, profile, and the wizard itself are exempt). Members are never redirected.
  7. Completion. When required steps are settled (completed or skipped), the header flips to COMPLETED; the wizard shows the completion screen and the chip disappears.
  8. Recovery nets.
    • Backfill: php artisan leadhub:guided-onboarding-sync seeds/repairs step rows for existing workspaces (e.g. after migrations or for workspaces created before the feature).
    • Stuck sweep: DetectStuckOnboarding runs daily at 08:15 and flags steps that have been settled too long, so the SA team can reach out.
  9. Super Admin visibility. /super-admin/meta-ads/client-onboarding lists every workspace with progress, current step, payment state, Meta connection health, and a ⚠ stuck flag (24h+). Request Action sends the client an in-app + email prompt — and clients can be given signed 72-hour onboarding links (/guided-onboarding/{tenant}) that resume the wizard without a password.

Troubleshooting notes

Symptom Likely cause Explanation
A completed step shows as unfinished again The real condition stopped being true (e.g. Meta token expired → BLOCKED) The resolver reflects reality; fix the underlying state
Skipped step never auto-completes The real action never happened Do it for real; sync picks it up
Progress % seems behind your click-through Steps count only when their condition is verified, not when you click Expected behaviour
Workspace owner stuck at the wizard with everything done One required step is technically unsettled Open the drawer; the unfinished step is marked
Steps missing entirely Onboarding rows were never seeded (old workspace) Run php artisan leadhub:guided-onboarding-sync

Was this page helpful?