Перейти к содержанию

Поведение пользователей: первый сводный анализ

Снэпшот данных

Анализ построен на полной выгрузке prod-БД на 2026-05-07. Период данных: пользовательская активность собирается с 2026-03-30 (старт трекинга), пользователи — с 2025-04-29. Источники: analytics_events (1 899 записей), audit_log (12 355), users (31 active), transactions (41), investments (27), sessions (11).

Анализ — нулевая итерация: цифры в этом срезе ещё не несут user_id в событиях, не отделяют внутренний QA-трафик и не имеют stack trace для ошибок. Фиксы трекинга (см. раздел 8) задеплоены 2026-05-07 — следующая итерация уже будет на «чистых» данных.

TL;DR

  • 31 активный клиент, из них 12 (38.7 %) проинвестировали хотя бы раз; остальные 19 — лурекры, зашли но не дошли до депозита.
  • AUM = $115 661 в активных инвестициях, но $81 288 (70 %) держит один клиент (#341957). Остальные 11 инвесторов делят $34 373 ⇒ платформа критически зависит от одного якорного клиента.
  • Депозит и инвестиция — атомарны. Автоинвест триггерится сразу после completed депозита, если итоговый баланс ≥ порога автоинвеста. Из 12 реальных инвесторов все оказались в стратегии в течение секунд-минут после первого депозита. Конверсия «положил → разместил» = 100 %.
  • 38 % клиентов депонируют в день регистрации, ещё 23 % — в первый день. Затягивают единицы.
  • Воронка лендинга узкая: 338 сессий → 161 viewed landing → 56 saw login → 34 logged in → 7 скопировали deposit-адрес. Топ потерь — между «открыл сайт» и «дошёл до логина».
  • UX-боль зафиксирована: 46 показов «пустого withdrawal»; 4 app_error за полтора месяца (2 ChunkLoadError, 1 разовый server_error при отправке magic link, 1 TypeError на /analytics/).
  • Трекинг-долг устранён 2026-05-07: analytics_events.user_id теперь пробрасывается из HttpOnly cookie, в app_error добавлены error_message + error_stack, есть whitelist внутренних IP. Историческая часть данных в этом отчёте — без этих улучшений; следующая итерация анализа уже сможет строить per-user воронки.

Источники данных и их ограничения

Таблица Объём Что даёт Ограничения
analytics_events 1 899 Действия в UI, секции лендинга, навигация, экраны логина и депозита, выбор сети/графика user_id пуст в 100 % исторических записей; пробрасывается с 2026-05-07. До этого связь только через session_id + client_ip.
audit_log 12 355 Действия админов и системы. Иммутабельный лог. Пользовательских записей: 1. Для user-аналитики практически бесполезен.
sessions 11 Активные backend-JWT сессии Только текущие (TTL 24 ч), не полная история.
users 31 active + 1 system Кто, когда зарегистрирован, статус mfa_enabled — фронтовый preference-флаг, не отражает реальный TOTP setup; источник истины — Supabase auth.
transactions 41 Депозиты, выводы Канонический финансовый источник.
investments 27 Размещения в стратегии Сейчас только basic.

Ключевое ограничение этого среза

Трекинг событий запущен 2026-03-30, а первые регистрации — с 2025-04-29. Из 32 пользователей 24 зарегистрированы до старта трекинга — для них setup-events, landing-сессии и onboarding-воронка просто отсутствуют в analytics_events. Поэтому сегментные числа («только N из 32 завершили setup») здесь корректно интерпретировать только относительно когорты после 2026-03-30.


1. Общая картина платформы

1.1 Пользователи и сегменты

Сегмент Кол-во Доля
Всего активных 31 100 %
Лурекры (без депозита и инвестиций) 19 61.3 %
Только депозит, без инвестиций 0 0 %
Проинвестировали хотя бы раз 12 38.7 %
Делали вывод 1 3.2 %

1.2 Динамика регистраций (по неделям)

2025-04-28 ▍1   ← anchor-клиент (#341957)
2025-12-01 ▍1
2025-12-08 ▍1
2025-12-15 ▎2
2025-12-22 ▍1
2026-01-12 ▎2
2026-01-19 ▍1
2026-01-26 ▎2
2026-02-16 ▍1
2026-03-02 ▎2
2026-03-16 ████████ 8   ← очевидный пик (запуск/кампания)
2026-03-23 ▎2
2026-03-30 ▍1
2026-04-06 ▎2
2026-04-20 ▎2
2026-04-27 ▍1
2026-05-04 ▎2

Пик 2026-03-16 (8 регистраций за неделю) — единственный заметный всплеск; затем стабильные 1–2 регистрации в неделю. Платформа ещё не запустила маховик роста — в среднем 1.5 нового клиента в неделю.

1.3 Активность по дням и часам

По дням недели (Europe/Moscow):

Mon  ███████ 334
Tue  ███████ 336
Wed  █████████ 457    ← пик
Thu  ███████ 339
Fri  ██ 106           ← провал
Sat  ███ 118
Sun  ████ 209

Вс — необычно высоко по сравнению с пятницей-субботой; пользователи проверяют доходность перед началом недели.

По часам (МСК) — ярко выраженный пик в рабочее время:

00 ▎ 21      08 ███ 90       16 ████████ 242   ← глобальный пик
01 ▍ 58      09 █████ 150    17 ██ 57
02 ▏  8      10 █████ 168    18 ████ 110
03 ▏  7      11 ████ 112     19 ███ 82
04 ▏  5      12 ██ 60        20 ███ 94
05 ▏ 17      13 ██ 76        21 ▍ 36
06 ▏  7      14 █████ 140    22 ▍ 49
07 ▍ 53      15 █████ 140    23 ████ 117

Вывод: аудитория — профессиональная, активность концентрируется в рабочие часы. Это типично для retail-инвесторов в B2C-DeFi из СНГ.

1.4 Устройства

Device События Сессии
Desktop 146 133 (82 %)
Mobile 30 29 (18 %)

Mobile — серьёзно недоинвестированный сегмент; для таких объёмов сделок desktop оправдан, но для роста аудитории нужно усиливать мобильный UX.

1.5 Returning vs new (по landing_viewed)

  • New: 144 сессии (88 %)
  • Returning: 19 сессий (12 %)

Большинство трафика на лендинге — первый визит. Удержание (retention) на лендинге низкое — 12 % возвращаемости говорит о том, что страница не «зацепляет» для возврата без триггера (письма, нотификации).

1.6 Распределение продолжительности сессий

Длительность Сессий Avg events
< 1 минуты 269 (79.5 %) 3.2
1–5 минут 35 11.1
5–15 минут 5 20.8
15–60 минут 7 10.6
1–24 часа 7 15.3
> 1 дня 15 23.9

80 % сессий — отскоки до минуты. Глубокое взаимодействие — у крошечного ядра.

1.7 DAU-прокси (с 2026-04-01)

Колебания: 1–32 distinct sessions в день. Медиана последней недели ≈ 10. Заметные пики: 2026-04-23 (32 сессии, 168 событий) и 2026-04-22 (17, 121) — стоит свериться с маркетинговым календарём.


2. Воронка активации

Распределение сессий по достигнутым шагам (по событиям фронтенда):

Открыли любой экран        338 ████████████████████ 100 %
Видели landing             161 █████████░░░░░░░░░░░  47.6 %
Видели login screen         56 ███░░░░░░░░░░░░░░░░░  16.6 %
Пытались логиниться         54 ███░░░░░░░░░░░░░░░░░  16.0 %
Залогинились                34 ██░░░░░░░░░░░░░░░░░░  10.1 %
Видели 2FA-экран            21 █░░░░░░░░░░░░░░░░░░░   6.2 %
Submit 2FA                  34 ██░░░░░░░░░░░░░░░░░░  10.1 %  ← включает повторные попытки
Видели deposit page         47 ███░░░░░░░░░░░░░░░░░  13.9 %
Скопировали адрес            7 ▍░░░░░░░░░░░░░░░░░░░   2.1 %
Видели analytics-страницу  171 █████████░░░░░░░░░░░  50.6 %
Видели withdrawal           31 ██░░░░░░░░░░░░░░░░░░   9.2 %

Конверсии (на сессионном уровне)

Шаг Конверсия
landing → login screen 34.8 %
login screen → login completed 60.7 %
login → deposit page ~138 % (deposit видят и без явного логина)
deposit page → copy address 14.9 %
landing → copy address 4.3 %

Где ломается воронка

Главные две точки:

  1. Лендинг → логин (35 %) — две трети посетителей даже не нажимают «Войти». Лендинг либо не доносит ценность, либо CTA-расположение неоптимально.
  2. Deposit page → copy address (15 %) — большинство, дойдя до экрана депозита, не доходит до фактического действия. Возможные причины: непонятен выбор сети, страх «куда отправлять», нет уверенности в адресе.

Сети депозитов: интерес vs реальные приходы

«Какую сеть выбрали в селекторе» (UI-клик deposit_network_selected) и «куда реально пришли деньги» — разные вещи. Сравнение:

Сеть Кликов в селекторе Скопировали адрес Реальных депозитов Сумма
Tron (TRC20) 4 7 19 $107 268
Ethereum 7 1 8 $8 994
Base 3 1 $505
Solana 2 1 $7.50
TON 5 1 $10.02

Главные выводы: Ethereum чаще кликают в селекторе, но деньги приходят почти всегда через Tron/USDT (90 % AUM). TON хайпят в UI (5 кликов), но дойти до отправки хочет один энтузиаст и тот на $10. Multichain важен только для acquisition-впечатления; в проде оптимизируем под TRC20/USDT.


3. Финансовое поведение

3.1 Концентрация AUM

Бакет инвестиции Инвесторов Сумма Доля AUM
≥ $20 000 1 $81 288 70.3 %
$5 000–20 000 2 $20 000 17.3 %
$1 000–5 000 7 $9 062 7.8 %
$500–999 6 $6 001 5.2 %
$100–499 1 $400 0.3 %
< $100 3 $33 <0.1 %

Концентрационный риск

Один клиент удерживает 70 % всех активов. Если он выходит — платформа теряет почти весь AUM, а юнит-экономика рушится. Бизнес-приоритет: диверсифицировать книгу (привлечь 5–10 клиентов с чеком $5–20k) и держать anchor-клиента вовлечённым.

3.2 Распределение размеров депозитов

Бакет Депозитов Уник. клиентов Сумма
< $100 6 3 $33
$100–499 2 1 $400
$500–999 9 6 $6 001
$1k–5k 7 7 $9 062
$5k–20k 4 2 $20 000
≥ $20k 2 1 $81 288

«Sweet spot» для платформы — клиенты с чеком $500–5000: их 13, они дают $15k — это самый воспроизводимый сегмент. На него и должен смотреть рост.

3.3 Time-to-deposit (от регистрации)

Дней Клиентов
0 5
1 3
12 1
20 1
25 1
37 1
43 1

8 из 13 (61.5 %) депонируют в первый день. Если человек прожил неделю без депозита — вероятность очень падает; именно для этой группы нужен retention-механизм (письмо, гайд по DeFi, прямой контакт).

3.4 Time-to-invest (от первого депозита)

Инвестиция в Saga — не отдельный шаг пользователя, а автоматический эффект подтверждённого депозита: автоинвест триггерится сразу по приходу транзакции (см. памятку в CLAUDE.md, секция «Депозит → автоинвест»). Поэтому:

Клиент Депозит → инвестиция
Все 12 реальных инвесторов секунды (внутри одного backend-flow)

Полезный вывод: выбора стратегии в пути клиента нет — все деньги уходят в basic автоматически. Работа над конверсией должна идти на «положить деньги», а не на «довести до инвестиции».

3.5 Выводы (withdrawals)

1 успешный вывод за всю историю — клиент #868313, $100. Это значит, что либо:

  • клиенты держат позиции долго (хороший сигнал) — скорее всего, учитывая возраст книги;
  • либо UX вывода настолько неочевиден, что им не пользуются (нужна качественная проверка через usability test).

4. Поведенческие паттерны

4.1 Что чаще всего смотрят (по навигации)

analytics    ██████████ 86 кликов / 49 сессий
deposit      ███████ 64 / 40
operations   ██████ 58 / 44
withdrawal   █████ 44 / 29
profile      ▏ 1 / 1

analytics — главная вкладка по интересу. Пользователи приходят считать прибыль, а не управлять счётом. Это диктует приоритет UI: верхняя страница должна показывать наглядный yield, а не «рекламные» баннеры.

4.2 Какие графики смотрят

График Кол-во переключений
profit 62
balance 7

Соотношение 9 : 1 в пользу прибыли. Дашборд по умолчанию должен открываться на графике прибыли. (Сейчас по умолчанию balance — стоит поменять.)

4.3 Какие периоды выбирают

Период Выбирают
all 29
year 13
month 5

Долгосрочный взгляд доминирует — это согласуется с продуктовой позицией «пассивный доход».

4.4 Кто реально возвращается (по IP-эвристике)

Уникальных IP Сессий Доля
174 1 сессия 75 %
33 IP 2–5 сессий 19 %
10 IP > 5 сессий 6 %

Реальное активное ядро — 10 IP. По соответствию с числом инвесторов (12) можно осторожно сказать, что активное ядро = реальные инвесторы ≈ 10–15 человек.

Топ-IP по числу сессий: 81.4.162.70 (37 сессий, 35 дней), 93.109.242.214 (24, 22 дня), 62.228.131.38 (17), 213.7.35.146 (8). Часть из них почти наверняка внутренние (см. раздел «Известные аномалии и внутренний трафик» ниже).


5. UX-боль и ошибки

5.1 «Пустой withdrawal»

withdrawal_empty_state_viewed — событие, которое срабатывает, когда пользователь зашёл на страницу вывода без баланса. 46 показов с 19 разных IP.

Это, видимо, совмещение двух сценариев:

  1. Любопытство «как тут вообще снимают деньги» — нормально, но требует понятного onboarding-блока на странице («чтобы здесь были деньги — сначала депозит и инвестиция»).
  2. Фрустрация активного клиента — например, если он только что проинвестировал и не понимает, когда сможет снять.

Сегмент с самыми многочисленными показами (IP 93.109.242.214, 11 раз) — почти наверняка внутренний пользователь, тестирующий UX.

5.2 Технические ошибки

За полтора месяца — 5 событий app_error / login_error_occurred:

Дата Тип Страница IP Что было
2026-04-06 22:40, 23:36 ChunkLoadError ×2 /deposit/ 109.252.108.2 Не удалось загрузить JS-чанк. Один и тот же клиент, два захода через час. Через 3 дня IP вернулся и нормально пользовался — то есть баг сам «рассосался». В коде уже есть auto-retry на ChunkLoadError, эти два события — до его внедрения.
2026-04-07 15:55 login_error_occurred (server_error, email) login 81.4.162.70 (внутренний) Magic link не ушёл с первой попытки. Через 14 секунд пользователь нажал «отправить» ещё раз — magic_link_sent пришёл, юзер дошёл до login_completed через минуту. Разовый сбой, не системный.
2026-04-08 16:38 UnhandledPromiseRejection / 81.4.162.70 Один кадр у того же внутреннего IP, без последствий.
2026-05-03 20:13 TypeError /analytics/ 80.244.26.23 Без stack trace диагностировать невозможно. Фикс уже задеплоен 2026-05-07: в track('app_error', …) добавлены error_message и error_stack (топ-3 кадра). Следующий же повтор придёт с трассой и будет починен.

Главный вывод — системных ошибочных паттернов нет: каждый случай объясняется разовым сетевым/инфраструктурным фактором или внутренним тестированием. Качество клиентского опыта по этой метрике в норме.

5.3 2FA-показатели

2fa_screen_viewed     32 (21 уникальная сессия)
2fa_code_submitted    40 (34 сессии)
2fa_qr_viewed          8
2fa_setup_completed    5

Что важно держать в голове: трекинг запущен 2026-03-30, а 24 из 32 пользователей зарегистрированы раньше — для них setup-эпизоды просто не видны. Из 8 пользователей когорты «после трекинга» 5 завершили 2fa_setup_completed в первый день — это нормальная конверсия принудительного TOTP-онбординга, а не «дыра в безопасности».

2fa_code_submitted за полтора месяца — 40 событий из 34 уникальных сессий: TOTP реально вводится практически на каждом логине, что и подтверждает, что 2FA работает на всей активной базе.

cookie_consent_accepted — 14 раз. Соотношение к 161 landing-просмотру — 8.7 %. Либо большая часть посетителей баннер игнорирует, либо событие не пишется при отказе (стоит проверить трекинг и согласие).


6. Известные аномалии и внутренний трафик

Сигнал Что это Что делать
Клиент #341957: $81 288 (70 % AUM), регистрация 2025-04-29 Anchor / founder / институциональный клиент Изолировать в отчётности, считать метрики и с ним, и без него
Клиент #100000: 3 депозита ($7.5 + $1000 + $0.001), 0 инвестиций Админский / тестовый аккаунт команды. Малые суммы не дотягивают до порога автоинвеста Исключать из бизнес-конверсий
IP 81.4.162.70 — 37 сессий за 35 дней, withdrawal-empty 5 раз Внутренний QA / разработчик ✅ Добавлен в ANALYTICS_INTERNAL_IPS 2026-05-07 — события помечаются _internal: true
IP 93.109.242.214 — 24 сессии, 132 события в одной сессии за 15 дней Внутренний пользователь ✅ Добавлен туда же
Один админ (4b5d…) сделал 11 952 действий за 1.5 месяца Бэкенд-сервис ходит под админ-токеном (пустой actor_id → actor_type=admin старый дефолт) ✅ Дефолт actor_type изменён 2026-05-07: пустой actor_id → system; добавлен helper NewServiceAuditEntry

Историческая часть выгрузки до 2026-05-07 ещё содержит этот шум — для прод-метрик фильтруйте WHERE COALESCE(properties->>'_internal','false') <> 'true' и WHERE actor_type <> 'system' соответственно.


7. Бизнес-инсайты и рекомендации

Что подтвердилось

  1. Saga = сберкнижка с прозрачной доходностью. Депозит и инвестиция — атомарны, а главная вкладка интереса — analytics с графиком profit. Продукт точно попадает в нишу «пассивный доход».
  2. Onboarding до депозита уже хорошо для тех, кто доходит. 8 из 13 депонируют в первый день — значит, после логина продукт убеждает.
  3. Long-term thinking аудитории — большинство выбирает period=all, графики profit, и только 1 пользователь сделал вывод. Книга «спокойная».

Что требует фикса (в порядке приоритета)

  1. 🔴 Концентрационный риск AUM — план привлечения 5–10 mid-size клиентов (чек $5–20k) на ближайший квартал.
  2. 🟠 Воронка лендинг → логин (35 %). Нужно usability-исследование лендинга и A/B на CTA. Это самая большая утечка верхней воронки.
  3. 🟠 Default-график analytics — поменять на profit. Поведенческое соотношение 9:1 уже подсказывает.
  4. 🟠 Withdrawal empty state переписать в onboarding-блок («ещё нет средств — вот что нужно сделать»), а не пустой экран.
  5. 🟡 Дождаться следующего повтора TypeError на /analytics/ — теперь с stack trace, можно будет починить точечно.

8. Tracking-долг — устранён 2026-05-07

Минимальный список доработок, который раньше был открыт, закрыт в этом срезе данных. Поведенческие выводы в текущем отчёте всё ещё построены на старых данных (без user_id, без internal-флага, без stack-trace), но новые события начнут приходить уже с этими полями и следующая итерация анализа будет принципиально точнее.

# Пункт Статус Что сделано
1 analytics_events.user_id для залогиненных extractUserIDFromAuthCookie читает auth_token HttpOnly cookie в HandleTrack (sendBeacon её не теряет)
2 Whitelist внутренних IP analytics.Service.SetInternalIPs + env ANALYTICS_INTERNAL_IPS. События с этих IP помечаются _internal: true
3 actor_type='service' для машинных вызовов Дефолт в audit_log_repository.Record: пустой actor_idactor_type=system; добавлен helper NewServiceAuditEntry
4 Stack trace для app_error В ClientProviders.tsx: error_message + error_stack (топ-3 кадра, по 200 символов)
5 Событие deposit_intent_started открыт Отложено до следующей итерации продуктового трекинга
6 Серверные события депозита/инвестиции в analytics_events открыт То же

Следующая итерация анализа (через 2–4 недели накопления данных с новыми полями) сможет ответить на: «кто из 19 лурекров ещё спасаем», «какой контент на лендинге конвертит», «почему пользователь X пришёл и не вернулся» — то, что в этом срезе доступно только косвенно.


Приложение: запросы для воспроизводимости

Все цифры в документе получены из локального snapshot prod-БД (make db-sync-prod). Ключевые запросы:

Сегментация пользователей
WITH classif AS (
  SELECT u.id,
    EXISTS (SELECT 1 FROM transactions t
            WHERE t.user_id=u.id AND t.type='deposit' AND t.status='completed') AS has_deposit,
    EXISTS (SELECT 1 FROM investments i WHERE i.user_id=u.id) AS has_invest,
    EXISTS (SELECT 1 FROM transactions t
            WHERE t.user_id=u.id AND t.type='withdrawal' AND t.status='completed') AS has_wd,
    u.mfa_enabled
  FROM users u WHERE u.status='active'
)
SELECT
  COUNT(*)                                           AS total,
  COUNT(*) FILTER (WHERE NOT has_deposit AND NOT has_invest) AS lurkers,
  COUNT(*) FILTER (WHERE has_deposit AND NOT has_invest)     AS deposited_only,
  COUNT(*) FILTER (WHERE has_invest)                         AS invested,
  COUNT(*) FILTER (WHERE has_wd)                             AS withdrew,
  COUNT(*) FILTER (WHERE mfa_enabled)                        AS mfa_enabled
FROM classif;
Воронка по сессиям
WITH s AS (
  SELECT session_id,
    bool_or(event_type = 'landing_viewed')                       AS landed,
    bool_or(event_type = 'login_screen_viewed')                  AS saw_login,
    bool_or(event_type = 'login_completed')                      AS logged_in,
    bool_or(event_type = 'deposit_viewed')                       AS saw_deposit,
    bool_or(event_type = 'deposit_address_copied')               AS copied_address,
    bool_or(event_type = 'analytics_viewed')                     AS saw_analytics,
    bool_or(event_type = 'withdrawal_viewed')                    AS saw_withdrawal
  FROM analytics_events GROUP BY session_id
)
SELECT
  COUNT(*)                                            AS total_sessions,
  COUNT(*) FILTER (WHERE landed)                      AS landed,
  COUNT(*) FILTER (WHERE saw_login)                   AS saw_login,
  COUNT(*) FILTER (WHERE logged_in)                   AS logged_in,
  COUNT(*) FILTER (WHERE saw_deposit)                 AS saw_deposit,
  COUNT(*) FILTER (WHERE copied_address)              AS copied_address,
  COUNT(*) FILTER (WHERE saw_analytics)               AS saw_analytics,
  COUNT(*) FILTER (WHERE saw_withdrawal)              AS saw_withdrawal
FROM s;
Финансовая сводка по клиенту
WITH t AS (
  SELECT user_id,
    COUNT(*) FILTER (WHERE type='deposit'    AND status='completed') AS deposits_count,
    SUM(amount) FILTER (WHERE type='deposit' AND status='completed') AS deposits_total,
    COUNT(*) FILTER (WHERE type='withdrawal' AND status='completed') AS wd_count,
    SUM(amount) FILTER (WHERE type='withdrawal' AND status='completed') AS wd_total
  FROM transactions GROUP BY user_id
),
i AS (
  SELECT user_id, COUNT(*) AS inv_count, SUM(amount) AS inv_total
  FROM investments GROUP BY user_id
)
SELECT u.client_number,
       COALESCE(t.deposits_count, 0)  AS deposits_n,
       COALESCE(t.deposits_total, 0)  AS deposits_usd,
       COALESCE(i.inv_count, 0)       AS inv_n,
       COALESCE(i.inv_total, 0)       AS inv_usd,
       COALESCE(t.wd_count, 0)        AS wd_n,
       COALESCE(t.wd_total, 0)        AS wd_usd,
       u.created_at::date             AS signup,
       u.mfa_enabled
FROM users u
LEFT JOIN t ON t.user_id = u.id
LEFT JOIN i ON i.user_id = u.id
WHERE u.status = 'active'
ORDER BY COALESCE(i.inv_total, 0) DESC NULLS LAST;

Подготовлено: 2026-05-07. Следующая итерация — после внедрения связки analytics_events.user_id.