Skip to main content

New-Company Onboarding

Audience: Sales · Support · QA · Engineering · Management · Where in app: /onboarding (auto-redirected for new web-owners) · Plan availability: All plans (runs before/around subscription)

Onboarding is the full-screen wizard a brand-new company is forced through before they reach the main dashboard. It collects account details, scans their website, trains the AI agent, lets them review the generated agent, then walks them through customizing the widget, setting call routing, trying a playground, and finally installing the widget snippet on their site. Progress is saved per-step on the company record so users can leave and resume — and can even start on mobile and finish on desktop via an emailed magic link.

What it does

  • Forces setup for new web-owners. The router redirects any web_owner whose user.onboarding_completed is false to /onboarding (router/index.js).
  • Walks an ordered list of steps, persisting completion per step (company.onboarding_steps[]).
  • Resumes intelligently: with no ?step in the URL it jumps to the step after the last completed one; if all are done it lands on the first config sub-step.
  • Adapts to screen size: a mobile-only "complete" step hands the user off to desktop to finish widget install.
  • Finishes by stamping onboarding_completed on both the user and company and routing to the dashboard.

How it works

The wizard shell is onboarding/index.vue; step order and visibility live in the Pinia store store/onboarding.js (ALL_ONBOARDING_STEPS). The current step is derived from ?step=<n> in the URL, kept in sync via browser back/forward.

Steps (in order)

IDLabelIn progress bar?ComponentPurpose
accountAccountYessteps/AccountStep.vueName, company name, phone, password, timezone. Skipped on load if already complete (see below).
websiteWebsiteYessteps/WebsiteStep.vueConnect/scan the company website to seed AI knowledge.
trainingTrainingNosteps/TrainingStep.vueTrains the AI agent (driven by its own CTA, hidden from the progress bar).
industryIndustryYessteps/IndustryStep.vuePick the business type (uses helpers/industryTemplates.js).
detailsDetailsYessteps/DetailsStep.vueBusiness details that feed the agent's persona.
reviewReviewYessteps/ReviewStep.vue"Meet {agent}. It's ready" — review the generated agent personality/flow.
mobile-completeCompleteNo (mobile only)steps/MobileCompleteStep.vueMobile success screen; hands off to desktop.
config_widgetCustomize WidgetNoConfigurationScreen.vueWidget appearance/layout.
config_routingCall RoutingNoConfigurationScreen.vueCall handling/routing defaults.
config_playgroundPlaygroundNoConfigurationScreen.vueTry the widget live in a sandbox.
installInstallNoInstallScreen.vueCopy the widget snippet / email it to a developer; finish.

The three config_* steps share one component (ConfigurationScreen.vue); it derives which section to render from the current step ID, and the same component reference is reused across the three keys so Vue keeps it mounted between them (no re-mount flicker).

Progress bar vs hidden steps

The horizontal stepper only shows steps with showInProgressBar: true (progressBarSteps): Account, Website, Industry, Details, Review. training, all config_*, install, and mobile-complete are hidden and driven by their own screens' CTAs.

Account-step skip

On load, the store snapshots whether account info is already complete (captureAccountStepState). "Complete" means: first name, company name, phone number, a set password (or social login), and the company timezone is not still the backend default (Pacific/Auckland) when the user's system timezone differs. If complete at load, the account step is removed from activeSteps for the whole session (the snapshot prevents the step from vanishing mid-session after the user saves it).

Install screen

InstallScreen.vue shows the embed snippet:

<script>
// Knock Knock Widget
window.company_id = '<company._id>'
var newScript = document.createElement('script')
newScript.src = '<API_URL>/widget/widget.js'
document.getElementsByTagName('HEAD')[0].appendChild(newScript)
</script>

From here the user can:

  • Copy Code to the clipboard.
  • Email to Developer — opens a modal, collects developer emails (FormMultipleEmails), and posts the install email via POST /email-send/<company._id>. The email body is white-label aware (omits the hello@knockknockapp.ai support line for white-labeled companies).
  • Email Me Setup Link (mobile) — sends the same instructions to the signed-in user so they can continue on desktop; shows a "what to do next" magic-link modal.
  • Go to Dashboard — calls finishOnboarding().

It notes the snippet can always be retrieved later under Settings → Widget → Installation.

Finishing

finishOnboarding() (store):

  1. PUT /user/<id> { onboarding_completed: true }
  2. PUT /company/<id> { onboarding_completed: true }
  3. Optional auto-trial: if a registered_package_id (or localStorage register_pkg) resolves to a package with affiliate_program && trial_without_card && free_trial === 'yes', it creates a trial subscription (POST /subscription, trial: true), reloads the subscription + company, and clears the local register keys.
  4. Toasts "Setup complete!" and routes to dashboardalways landing on the dashboard so users can explore.

Configuration & options

What gets written, and where:

StepPersisted toMechanism
Per-step completioncompany.onboarding_steps[]POST /company/complete-onboarding-step (completeStep)
Step data (account/industry/details/config)company.*PUT /company/<id> with the step payload, then complete-onboarding-step
Final completionuser.onboarding_completed, company.onboarding_completedPUT /user/<id>, PUT /company/<id>
Install email(email only — no DB write)POST /email-send/<company._id>

skipStep(stepId) marks a step complete with an empty payload (no data saved) — used where a step can be passed without input.

Behaviors & edge cases

  • Resume after leaving: with no ?step, the store resumes at the step after the last completed one; if everything is complete it opens config_widget.
  • Browser back/forward: each step pushes a history entry (updateUrlWithStep), and index.vue watches route.query.step to re-sync.
  • Mobile→desktop handoff: mobile-complete is mobileOnly. On desktop, findNextValidStepIndex skips it; on mobile it's shown and routes users to email themselves the desktop magic link.
  • Theme + logout are available in the onboarding header; the header/progress bar are hidden on the full-viewport config_* and install steps (showInProgressBar === false).
  • White-label branding: logo, name, store links, and email copy resolve through useAppBranding / appStore.brandingName (agency name first). White-labeled flows must not surface the Knock Knock support address.
  • Router exit guard: once user.onboarding_completed is true, the router prevents bouncing back into /onboarding (see router/index.js).

Plan & limits

Onboarding runs for all new web-owner accounts regardless of plan. The only plan-adjacent behavior is the auto-trial branch in finishOnboarding (affiliate packages with card-free trials). Exact package eligibility is data-driven (the package record's affiliate_program/trial_without_card/free_trial flags) — confirm specifics with billing/product (verify).

Technical implementation

  • Shell view: frontend/src/views/onboarding/index.vue
  • Step components: frontend/src/views/onboarding/steps/* (Account, Website, Training, Industry, Details, Review, MobileComplete)
  • Shared config screen: frontend/src/views/onboarding/ConfigurationScreen.vue
  • Install screen: frontend/src/views/onboarding/InstallScreen.vue
  • Supporting components: onboarding/components/* (Playground*, StepNavigation, DynamicField, MobileStepHeader)
  • Helpers: onboarding/helpers/industryTemplates.js, masterVoiceTemplate.js
  • Store: frontend/src/store/onboarding.js (ALL_ONBOARDING_STEPS, completeStep, skipStep, finishOnboarding, URL sync)
  • Route: name onboarding, path /onboarding (auth required, onboarding check skipped); redirect logic in frontend/src/router/index.js
  • Backend: POST /company/complete-onboarding-step, PUT /company/<id>, PUT /user/<id>, POST /subscription, POST /email-send/<id>. See services/backend.