Реалізація Onboarding Wizard для SaaS-застосунку

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація Onboarding Wizard для SaaS-застосунку
Середня
~3-5 робочих днів
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

SaaS онбординг-візард

Онбординг визначає activation rate — відсоток користувачів, які доходять до моменту усвідомлення цінності продукту. Wizard — пошаговий сценарій, що веде користувача до першого успіху.

Проектування кроків

Завдання онбордингу — дістати до «aha moment» за мінімальний час. Кожен зайвий крок зменшує completion rate.

Крок 1: Профіль компанії (назва, тип, розмір)
Крок 2: Запросити першого члена команди
Крок 3: Створити перший проект (ключова дія)
Крок 4: Підключити інтеграцію (Slack/GitHub/Jira)
→ Aha moment: перший активний проект з командою

Схема даних

model OnboardingProgress {
  id          String   @id @default(cuid())
  tenantId    String   @unique
  currentStep Int      @default(0)
  completedAt DateTime?
  steps       Json     // { "profile": true, "invite": false, "project": false, "integration": false }
  startedAt   DateTime @default(now())

  tenant Tenant @relation(fields: [tenantId], references: [id])
}

Компонент візарда

// components/onboarding/OnboardingWizard.tsx
'use client';

import { useState } from 'react';
import { useRouter } from 'next/navigation';

interface Step {
  id: string;
  title: string;
  component: React.ComponentType<StepProps>;
  optional?: boolean;
}

const STEPS: Step[] = [
  { id: 'profile', title: 'Про вашу компанію', component: ProfileStep },
  { id: 'invite', title: 'Запросити команду', component: InviteStep, optional: true },
  { id: 'project', title: 'Перший проект', component: CreateProjectStep },
  { id: 'integration', title: 'Підключити інструменти', component: IntegrationStep, optional: true },
];

export function OnboardingWizard({
  initialStep,
  completedSteps,
}: {
  initialStep: number;
  completedSteps: Record<string, boolean>;
}) {
  const [currentStep, setCurrentStep] = useState(initialStep);
  const [completed, setCompleted] = useState(completedSteps);
  const router = useRouter();

  const step = STEPS[currentStep];
  const StepComponent = step.component;

  const handleNext = async (skipValidation = false) => {
    if (!skipValidation) {
      // Відмічаємо крок виконаним
      await updateStepProgress(step.id);
      setCompleted(prev => ({ ...prev, [step.id]: true }));
    }

    if (currentStep < STEPS.length - 1) {
      setCurrentStep(prev => prev + 1);
    } else {
      // Онбординг завершен
      await completeOnboarding();
      router.push('/dashboard');
    }
  };

  return (
    <div className="max-w-2xl mx-auto py-12 px-4">
      {/* Panelka progress */}
      <div className="mb-8">
        <div className="flex items-center gap-2">
          {STEPS.map((s, idx) => (
            <div key={s.id} className="flex items-center gap-2">
              <div className={`
                w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium
                ${completed[s.id]
                  ? 'bg-green-500 text-white'
                  : idx === currentStep
                  ? 'bg-blue-600 text-white'
                  : 'bg-gray-200 text-gray-500'
                }
              `}>
                {completed[s.id] ? '✓' : idx + 1}
              </div>
              {idx < STEPS.length - 1 && (
                <div className={`flex-1 h-0.5 ${completed[s.id] ? 'bg-green-500' : 'bg-gray-200'}`} />
              )}
            </div>
          ))}
        </div>
        <p className="mt-2 text-sm text-gray-500">
          Крок {currentStep + 1} з {STEPS.length}: {step.title}
        </p>
      </div>

      {/* Контент кроку */}
      <StepComponent
        onNext={handleNext}
        onSkip={step.optional ? () => handleNext(true) : undefined}
      />
    </div>
  );
}

Кроки візарда

// components/onboarding/steps/ProfileStep.tsx
export function ProfileStep({ onNext }: StepProps) {
  const form = useForm<ProfileForm>({
    resolver: zodResolver(profileSchema),
  });

  const onSubmit = async (data: ProfileForm) => {
    await updateOrganizationProfile(data);
    onNext();
  };

  return (
    <form onSubmit={form.handleSubmit(onSubmit)}>
      <h2 className="text-2xl font-bold mb-6">Розповідьте про вашу компанію</h2>

      <FormField
        label="Назва компанії"
        error={form.formState.errors.name?.message}
      >
        <Input {...form.register('name')} placeholder="Acme Corp" autoFocus />
      </FormField>

      <FormField label="Тип команди" error={form.formState.errors.teamType?.message}>
        <Select {...form.register('teamType')}>
          <option value="startup">Стартап</option>
          <option value="agency">Агентство</option>
          <option value="enterprise">Enterprise</option>
          <option value="freelancer">Фрилансер</option>
        </Select>
      </FormField>

      <FormField label="Розмір команди">
        <Select {...form.register('teamSize')}>
          <option value="1">Тільки я</option>
          <option value="2-10">2–10 осіб</option>
          <option value="11-50">11–50 осіб</option>
          <option value="50+">Більше 50</option>
        </Select>
      </FormField>

      <Button type="submit" className="w-full mt-6" isLoading={form.formState.isSubmitting}>
        Продовжити
      </Button>
    </form>
  );
}

Трекінг онбордингу

// Відстеження completion rate по кроках
export async function trackOnboardingStep(step: string, tenantId: string) {
  posthog.capture('onboarding_step_completed', {
    distinct_id: tenantId,
    step,
    timestamp: new Date().toISOString(),
  });
}

// В аналітиці переглядаємо funnel:
// onboarding_started → profile_completed → team_invited → project_created
// Знаходимо, де найбільший drop-off

Повторний онбординг

// Прогрес зберігається — користувач може повернутися пізніше
// При кожному вході перевіряємо статус онбордингу

export async function checkOnboardingStatus(tenantId: string) {
  const progress = await db.onboardingProgress.findUnique({
    where: { tenantId }
  });

  if (!progress?.completedAt) {
    // Редиректимо на наступний невиконаний крок
    return {
      completed: false,
      currentStep: progress?.currentStep ?? 0,
    };
  }

  return { completed: true };
}

Розробка онбординг-візарда з трекингом та відновленням прогресу — 3–5 робочих днів.