Duolingo спрашивает «Зачем ты учишь язык?» и показывает разный контент в зависимости от ответа. Headspace — «Что тебя беспокоит?» и предлагает соответствующие медитации. Это не просто UX-паттерн — это механизм, который значительно увеличивает вероятность возврата пользователя: приложение с первых секунд релевантно именно ему. Без персонализации пользователь видит одинаковый интерфейс, а контент не соответствует его ожиданиям. Анкета решает эту проблему: она собирает ключевые данные и сразу настраивает приложение. В результате retention вырастает на 20–40%, а стоимость привлечения пользователя окупается быстрее.
С нами вы получаете 10+ лет опыта в мобильной разработке и более 50 реализованных проектов с персонализированным онбордингом.
Почему персонализированный онбординг важен для мобильного приложения?
По данным Localytics, персонализированный онбординг увеличивает retention на 25%. Когда пользователь видит релевантный контент с первого запуска, вероятность повторного визита растёт. Анкета — эффективный инструмент сбора данных: она занимает 30–60 секунд, но даёт профиль, который определяет поведение приложения на недели вперёд.
Архитектура анкеты
Анкета персонализации — это не просто набор экранов с кнопками «Далее». Это поток с ветвлением: ответ на вопрос 2 может определять, какой вопрос будет третьим. И результат — не просто сохранённые ответы, а набор параметров, влияющих на начальное состояние приложения.
Data-driven конфигурация. Каждый вопрос — объект с метаданными:
struct OnboardingQuestion { let id: String let type: QuestionType // .singleChoice, .multiChoice, .slider, .text let title: String let subtitle: String? let options: [QuestionOption] let nextQuestionId: [String: String] // optionId -> nextQuestionId, или "default" let analyticsKey: String } Логика ветвления через словарь nextQuestionId: если пользователь выбрал опцию «Снижение стресса» — следующий вопрос q_stress_level, если «Лучший сон» — q_sleep_problems. «default» — для вопросов без ветвления. Конфигурация загружается с сервера или бандлится в приложении как JSON-файл.
QuestionnaireCoordinator управляет стеком вопросов: history: [String] для поддержки кнопки «Назад», currentQuestionId: String, answers: [String: Any] для накопления ответов. При нажатии «Назад» — history.popLast() и переход к предыдущему вопросу с сохранением выбранного ответа.
Как реализовать ветвление вопросов на Swift?
В центре — QuestionnaireCoordinator. Он получает конфигурацию, управляет историей и определяет следующий вопрос. Пример:
class QuestionnaireCoordinator { private var history: [String] = [] private var currentQuestionId: String = "q_goal" private var answers: [String: Any] = [:] private let configuration: [String: OnboardingQuestion] func goToNext(selectedOptionId: String) { guard let question = configuration[currentQuestionId], let nextId = question.nextQuestionId[selectedOptionId] ?? question.nextQuestionId["default"] else { return } history.append(currentQuestionId) currentQuestionId = nextId } func goBack() { guard let previous = history.popLast() else { return } currentQuestionId = previous } func currentQuestion() -> OnboardingQuestion? { configuration[currentQuestionId] } } UI анкеты
Навигация между вопросами
Переход между экранами вопросов — горизонтальная анимация. На iOS: UIPageViewController в .scroll стиле или UIView.transition(with:duration:options:animations:) с .transitionCurlUp для необычного ощущения. В SwiftUI — TabView с tabViewStyle(.page) при фиксированном selection не даёт автосвайп назад пользователем — это нужно контролировать через interactiveDismissDisabled.
Лучший вариант — кастомная анимация через withAnimation(.spring(response: 0.4, dampingFraction: 0.8)) с offset и opacity. Дает полный контроль: вперёд — слайд влево, назад — слайд вправо.
Типы вопросов
Single choice — список карточек или пунктов, тап немедленно переходит к следующему вопросу (без «Далее»). Haptic .selection при выборе. Выбранная карточка — анимированное изменение background и border.
Multi choice — чекбоксы или карточки с multiple selection. Кнопка «Далее» появляется после выбора хотя бы одного варианта. LazyVGrid / FlowLayout для карточек с тегами.
Slider — UISlider / Slider в SwiftUI для числовых значений (возраст, частота, уровень). Лейблы по краям для понятного контекста. Haptic .selection при кратных значениях.
Progress indicator
Прогресс-бар сверху показывает положение в анкете. Анимированный LinearProgressView / LinearProgressIndicator. Не показываем точный шаг («3 из 7») — пользователь видит конец и может бросить. Показываем только bar без числовых меток.
Сравнение линейной и ветвящейся анкеты
| Параметр | Линейная анкета | Анкета с ветвлением |
|---|---|---|
| Количество вопросов | Фиксированное (5-7) | Зависит от ответов (3-10) |
| Конфигурация | Хардкод | Server-driven JSON |
| Аналитика | Минимальная | Детальная (Firebase Analytics) |
| Срок разработки | 2 дня | 3 дня |
Компоненты UI по платформам
| Компонент | iOS | Android |
|---|---|---|
| Single choice | SwiftUI List + onTapGesture |
Jetpack Compose LazyColumn + clickable |
| Multi choice | SwiftUI LazyVGrid с чекбоксами |
Compose LazyVerticalGrid с Checkbox |
| Slider | SwiftUI Slider |
Compose Slider |
| Progress bar | SwiftUI ProgressView |
Compose LinearProgressIndicator |
Пример конфигурационного JSON
{ "questions": [ { "id": "q_goal", "type": "singleChoice", "title": "Зачем вы используете приложение?", "options": [ { "id": "stress", "title": "Снижение стресса" }, { "id": "sleep", "title": "Лучший сон" } ], "nextQuestionId": { "stress": "q_stress_level", "sleep": "q_sleep_problems", "default": "q_time" }, "analyticsKey": "goal_selection" } ] } Персонализация результата и аналитика
После завершения анкеты собираем UserProfile из ответов:
struct UserProfile { let primaryGoal: Goal // из вопроса q_goal let experienceLevel: Level // из вопроса q_experience let preferredTopics: [Topic] // из вопроса q_topics (multi) let availableTime: Int // минут в день из вопроса q_time } Этот профиль определяет: какой контент показывается на главном экране, какие push-уведомления отправляются, какие разделы скрыты/показаны, с каким уровнем сложности начинается пользователь. Профиль сохраняется локально (UserDefaults / DataStore) и синхронизируется с сервером — чтобы при переустановке или смене устройства пользователь не проходил анкету снова.
Аналитика. Firebase Analytics: questionnaire_started, questionnaire_step_completed (с step_id и time_spent), questionnaire_skipped (с at_step), questionnaire_completed. По этим данным видно — на каком вопросе пользователи уходят, какие ответы самые популярные, как влияет анкета на retention. Firebase Analytics — рекомендуемый инструмент для мониторинга.
Пропуск анкеты и редактирование
Кнопка «Пропустить» — всегда. Не все хотят рассказывать о себе. Пропустившим показываем дефолтный контент и периодически (через 3–7 дней) ненавязчиво предлагаем заполнить «для лучших рекомендаций».
Возможность изменить ответы позже — в настройках профиля. Не запирать пользователя в первоначальном выборе. OnboardingQuestionnaireView переиспользуется в settings с режимом edit — те же компоненты, но с pre-filled ответами и другим completion-action (обновление профиля вместо перехода к главному экрану).
Что входит в работу
- Конфигурационный JSON-файл анкеты с поддержкой ветвления
-
QuestionnaireCoordinatorна Swift или Kotlin - UI-компоненты (SingleChoice, MultiChoice, Slider, ProgressBar)
- Интеграция аналитики Firebase
- Возможность редактирования профиля в настройках
- Документация по использованию
Срок: 2–3 дня. Линейная анкета из 5–7 вопросов с simple choice и применением результата к начальному контенту — 2 дня. Анкета с ветвлением, server-driven конфигурацией, несколькими типами вопросов, аналитикой и редактированием в профиле — 3 дня. Свяжитесь с нами для оценки проекта. Получите консультацию по онбордингу бесплатно.







