# Оценка гипотезы: упрощение TMA-онбординга

**Дата:** 2026-05-07
**Статус:** анализ завершён, гипотеза не подтверждена данными

## Гипотеза

> Если оставить в воронке для новых пользователей только обязательные поля настройки поиска, конверсия на шаге заполнения профиля вырастет на 70%.

**Предложение:** экран выбора режима: «Больше кастингов» (5 базовых фильтров) / «Больше точность» (+16 продвинутых фильтров).

## Ключевые находки

**Сквозная конверсия started → onboarded упала на ~15 п.п. при переходе на TMA:**

- **Бот-онбординг** (янв–фев 2026): 65–67%
- **TMA-онбординг** (апр–май 2026): 50–54%

Падение реально, но его причина — не сложность фильтров.

**Где теряются пользователи (когорта апрель 2026, 961 чел.):**

```
Started в боте              961  (100%)
    │
    │  ~50% — не открыли TMA / ушли до конца шага 1
    ▼
Вошли в TMA (шаг ≥ 2)      ~488
    │
    │  ~6% — застряли на фильтрах (шаги 2–3): 91 чел.
    ▼
Дошли до контактов          ~401
    │
    │  ~12% — застряли на email (шаг 6): 182 чел.
    ▼
Завершили                    487  (50.7%)
```

- **~50% потерь** — пользователи не открывают TMA или уходят до завершения шага 1 (ФИО, пол, город, возраст). Это основной провал воронки, и гипотеза его не затрагивает
- **~12% потерь** — обязательный email на шаге 6 «Контакты». 182 человека заполнили ВСЕ фильтры и остановились на единственном обязательном поле — email
- **~6% потерь** — шаги 2–3 (типы кастингов + внешность) — единственное, на что влияет гипотеза

**Максимальный эффект от упрощения фильтров: +9%**, не +70%.

## Почему двухрежимный экран — не решение

**UX-проблема:** новый пользователь не может осознанно выбрать между «Больше кастингов» и «Больше точность» — он ещё не получал кастинги и не понимает разницу. Это ложный выбор без контекста.

**Принцип первого экрана:** заполнение полей проще, чем принятие решения. Экран с конкретными полями (имя, пол, город) сподвигает к действию — пользователь видит простую задачу и начинает заполнять. Экран с выбором режима требует осмысления абстрактных последствий, что создаёт когнитивную нагрузку и повышает вероятность ухода. Первый экран должен вовлекать через действие, а не через выбор.

**Риск режима «5 фильтров»:** без фильтрации по внешности пользователь получит поток нерелевантных кастингов. Стопворды на внешность — 58.7% всех пользовательских исключений (этничность, телосложение, волосы — самые частые). Это приведёт к низкому like rate и повышенному churn, что съест выигрыш от конверсии.

**Альтернатива:** оставить текущие шаги, но добавить кнопку «Пропустить» на необязательных (внешность, профессиональное, дополнительное). Пользователь может пройти онбординг за 3 шага вместо 6, а продвинутые фильтры заполнить позже в профиле.

## Рекомендации (по impact)

1. **Конверсия «started → открыл TMA»** — ~50% потерь до шага 1. Рычаги: повторные nudge, deeplink, упрощение входа. Самый большой пул
2. ~~**Добавить логирование user_id при создании TMA-сессии**~~ — **DONE 2026-05-07** (`session.py:79`, `session.py:112`). Логирует `user_id` и `platform` при создании сессии (initData и auth token пути). Данные для анализа слепой зоны будут доступны через ~неделю
3. **Убрать обязательность email** на шаге 6 — потенциально +182 завершения, конверсия внутри TMA 82.6% → 93.8%. Самый дешёвый фикс
4. **Добавить «Пропустить» на необязательных шагах** (внешность, профессиональное, дополнительное) — спасёт ~37–91 чел. без ущерба качеству для тех, кто заполнит

---

## Детали: определение шагов и трекинг воронки

### Как определяется прохождение шага

Поле `users.onboarding_step` записывается в БД при вызове `PUT /api/v1/tma/filters` из фронтенда (`saveAndAdvance(fields, nextStep)`). Значение — номер **следующего** шага (т.е. `onboarding_step = 3` означает "шаг 2 завершён, пользователь на шаге 3"). Минимальное значение в БД — `2` (шаг 1 завершён).

| onboarding_step в БД | Название шага | Что значит | Что заполнено |
|---|---|---|---|
| `NULL` | — | Не начинал ИЛИ открыл TMA, но не завершил шаг 1 | Ничего (или частично шаг 1) |
| `2` | Типы кастингов | Завершил шаг 1 «Базовая информация» | ФИО, пол, город, возраст, диапазон |
| `3` | Внешность | Завершил шаг 2 «Типы кастингов» | + типы проектов, роли, ставка |
| `4` | Профессиональное | Завершил шаг 3 «Внешность» | + рост, этничность, телосложение, волосы |
| `5` | Дополнительное | Завершил шаг 4 «Профессиональное» | + опыт, образование (необязательный) |
| `6` | Контакты | Завершил шаг 5 «Дополнительное» | + цвет глаз, навыки (необязательный) |
| `7` | Завершён | Завершил онбординг | + email (обязательный), контакты |

### Слепая зона: welcome screen и шаг 1

```
Открыл TMA ──→ Welcome screen (step 0) ──→ Шаг 1 (ФИО, пол, город, возраст)
     │              │                              │
     │         setStep(1)                    saveAndAdvance(_, 2)
     │         НЕТ записи в БД              ПЕРВАЯ запись в БД
     │              │                              │
     └──────────────┴── onboarding_step = NULL ────┘
                    неотличимы от "не открывал TMA"
```

- **Открытие TMA** (`POST /tma/session`) — логируется в Docker-лог **с user_id** (добавлено 2026-05-07, `session.py:79`)
- **Welcome screen → шаг 1** — `setStep(1)` — только локальный state, без API
- **Шаг 1 → шаг 2** — `saveAndAdvance(fields, 2)` — первая запись в БД

### Шаги онбординга — обязательные поля

| Шаг | Название экрана | Прогресс | Обязательные поля | Необязательные поля |
|---|---|---|---|---|
| 0 | Welcome | 0% | — (кнопка "Начать регистрацию") | — |
| 1 | Базовая информация | 20% | ФИО, пол, город, возраст, диапазон возраста | готовность к командировкам, города поиска |
| 2 | Типы кастингов | 45% | типы проектов (1+), роли (1+) | мин. ставка, показывать без оплаты, некоммерческие, агентские |
| 3 | Внешность | 65% | рост, этничность (1+), телосложение (1+), цвет волос, длина волос | размер одежды, размер обуви |
| 4 | Профессиональное | 75% | — (весь шаг необязательный) | опыт, образование, налоговый статус |
| 5 | Дополнительное | 90% | — (весь шаг необязательный) | цвет глаз, особые приметы, навыки, языки |
| 6 | Контакты и материалы | 100% | email | портфолио, видео, телефон, VK |

### Цепочка записи в БД

```
Frontend: saveAndAdvance(stepFields, nextStep)
    ↓
PUT /api/v1/tma/filters  →  payload.onboarding_step = nextStep
    ↓
create_user_for_platform(session, user_id, platform)   ← get-or-create в таблице users
    ↓
apply_filter_settings_update(user, payload)
    ↓  filters.py:274 → user.onboarding_step = payload.onboarding_step
    ↓
await session.commit()   ← filters.py:149, UPDATE users SET ... WHERE telegram_id = X
```

Модель `User` — SQLAlchemy-маппинг таблицы `users`. Все поля (фильтры + onboarding_step) пишутся в одну строку одним UPDATE.

## Детали: данные воронки (снимок 2026-05-07)

### Всего в БД (users)

| Сегмент | Количество | % |
|---|---|---|
| `onboarding_step = NULL` — не начинали (или ушли до конца шага 1) | 13 542 | 89.3% |
| `onboarding_step 2–6` — начали, не завершили | 281 | 1.9% |
| `onboarding_step = 7` — завершили | 1 339 | 8.8% |
| **Итого** | **15 163** | |

### Где застревают (281 незавершённых)

| Шаг | Название | Кол-во | % от незавершённых | Активная подписка | Блокер |
|---|---|---|---|---|---|
| 2 | Типы кастингов | 54 | 19.2% | 8 | выбор типов проектов (1+) + ролей (1+) |
| 3 | Внешность | 37 | 13.2% | 12 | рост, этничность, телосложение, волосы |
| 4 | Профессиональное | 2 | 0.7% | 0 | — (шаг необязательный) |
| 5 | Дополнительное | 6 | 2.1% | 2 | — (шаг необязательный) |
| **6** | **Контакты** | **182** | **64.8%** | **6** | **email (единственное обязательное)** |

28 пользователей с незавершённым онбордингом имеют активную подписку — платят, но получают плохо фильтрованные кастинги.

### Когортный анализ: started → завершение онбординга

Когорта — месяц первого action `started` в user_logs. Событие `started` = нажатие /start в боте (вход). Для до-TMA когорт конверсия считается по `registered` (завершение старого бот-онбординга), для TMA-когорт — по `onboarded` (завершение TMA-онбординга).

| Когорта | Started | Завершили | Конверсия | Тип онбординга |
|---|---|---|---|---|
| 2026-01 | 122 | 79 | **64.8%** | бот (registered) |
| 2026-02 | 312 | 209 | **67.0%** | бот (registered) |
| 2026-04 | 961 | 487 | **50.7%** | TMA (onboarded) |
| 2026-05 (неполный) | 156 | 84 | **53.8%** | TMA (onboarded) |

Март 2026 — переходный период (TMA запущен в середине месяца), данные нерепрезентативны.

### Docker logs (10 апреля — 7 мая 2026, ~27 дней)

- **1 879** успешных сессий TMA (POST /tma/session 200)
- **30** неудачных попыток (401 Unauthorized — протухший initData; 29 telegram, 1 max)
- **9** сессий через auth token (POST /tma/session/token — fallback для устройств без initData)
- **749** уникальных пользователей завершили шаг 1
- **604** уникальных пользователей завершили онбординг
- Конверсия шаг 1 → complete: **80.6%**
- Failed rate: 30 / 1 909 = **1.6%** — не значимый фактор

### Перекрёстная проверка числа завершивших

- **`onboarding_step = 7`** в `users` — 1 339
- **`tma_onboarded = true`** в `users` — 1 340 (+1: ручной сброс или баг)
- **`action = 'onboarded'`** в `user_logs` — 1 326 (−13: ранние пользователи до добавления логирования)

Наиболее надёжный источник — `onboarding_step = 7` (записывается в одном `session.commit()` с данными профиля).

## Файлы

- Фронтенд онбординга: `tma_profile/frontend/src/pages/OnboardingPage.tsx`
- Бекенд сессий: `tma_profile/backend/app/api/v1/session.py`
- Бекенд фильтров: `tma_profile/backend/app/api/v1/filters.py`
- Сервис фильтров: `tma_profile/backend/app/services/filters.py`
