Как первые пользователи нашли два бага, которых мы сами не увидели — и что мы из этого вынесли

Зиберов
Деньги статья

В первые две недели после запуска платных тарифов в Subsly мы получили два неожиданных подарка от пользователей — два критических бага, которые наша команда упустила. Один скрывал реальные расходы в дашборде в 10 раз меньше реальности. Второй создавал 15 несуществующих подписок на 298 000 ₽ из служебных строк банковской выписки. Оба бага жили в коде месяцами и могли убить активацию десятков пользователей.

Делимся опытом — что произошло, как чинили, и почему ранние пользователи оказались дороже любого QA.

Контекст: что мы делаем

Subsly — сервис аудита SaaS-расходов для бизнеса. Загружаете банковскую выписку → видите все подписки компании, дубли, переплаты. Запустили платные тарифы в начале мая, сейчас активно тестируем гипотезы на ранних пользователях. Объявления крутим в РСЯ (Яндекс.Директ), посевы в Telegram-каналах.

Кейс 1. Валюты, спрятанные в RUB

Один из первых платных пользователей зарегистрировался, добавил 7 подписок через ручной импорт и написал нам: «продукт хороший, но в дашборде расходы как-то меньше реальных».

Открыли его кабинет. У него Anthropic Claude добавлен как 108,90 ₽. Anthropic тарифицируется в долларах — 108,90 это $108.90, что по курсу ЦБ ≈ 10 000 ₽. Дашборд показывал в 100 раз меньше реального расхода на этот сервис. Аналогично — Hostinger ($19.29 → 19,29 ₽), Hugging Face ($9.13 → 9,13 ₽).

Общий показатель «Расходы/мес» на дашборде: 1 411 ₽. Реальная сумма с правильной конверсией: 14 409 ₽.

В чём была дыра

На странице добавления подписки есть поле «Стоимость» и рядом селектор валюты с тремя опциями: RUB / USD / EUR. По умолчанию стоит RUB. Пользователь вводит «108.90», селектор остаётся на RUB, в БД сохраняется cost=108.90, currency=RUB.

На бэке функция расчёта общих расходов просто суммировала sub.cost по всем подпискам — без учёта валюты. То есть $108.90 + 100 ₽ + 7900 ₽ складывались как 8108.90. Бессмыслица, но проходила компиляцию.

Это типовая ошибка для финансовых продуктов — мы делали аналитику исходя из предположения «все в рублях», потому что 80% наших пользователей действительно в рублях.

Что починили (1 рабочий день)

Четыре фикса:

  1. Конвертация валют на бэке. Подключили API ЦБ РФ (cbr-xml-daily.ru — публичное зеркало, отдаёт JSON, работает без VPN). Кешируем курсы на 24 часа — Я.Метрика обновляется раз в день, чаще не нужно. Все агрегации (15+ мест в коде) теперь идут через единую функцию, которая знает про валюту.
  2. Tooltip с конверсией в таблице. Под валютной ценой каждой подписки появилась мелкая серая строка «≈ 9 354 ₽ по курсу ЦБ 85.90». Пользователь видит реальный рублёвый эквивалент сразу, без калькулятора.
  3. Подсказка на дашборде. Под общей суммой «Расходы/мес» теперь добавляется «из них €10 + $138 (12 935 ₽ по курсу ЦБ)» — если у пользователя есть подписки в валюте. Объясняет откуда цифра.
  4. Автовалюта по сервису — это самое важное. Добавили в каталог сервисов колонку «валюта по умолчанию». Для 73 западных SaaS проставили USD: Anthropic, OpenAI, GitHub, Cursor, Notion, Slack, Figma, Linear, AWS, Cloudflare, Stripe, HubSpot и др. Когда пользователь выбирает Anthropic из автокомплита — валюта автоматически переключается на USD. Никаких больше «108 ₽ за Claude».

Дашборд этого пользователя стал показывать 14 409 ₽ вместо 1 411 ₽. Мы написали ему отдельно, объяснили что произошло, и подарили 3 месяца тарифа Starter (1 290 ₽/мес × 3 = 3 870 ₽) бесплатно. За критический баг это самое меньшее что можно сделать.

Кейс 2. 15 фальш-подписок на 298 000 ₽

Через день после первой истории — другой пользователь. Пришёл с рекламы в Яндекс.Директе, кликнул на наше объявление про аудит SaaS-расходов, зарегистрировался, загрузил выписку из банка. И получил картину которая в реальности никак не могла быть его расходами на SaaS:

10:48 Прочие операции + 26 232 ₽/мес
22:30 Перевод СБП 25 418 ₽/мес
12:52 Оплата по QR–коду СБП 18 233 ₽/мес
12:56 Оплата по QR–коду СБП 18 033 ₽/мес
13:03 Оплата по QR–коду СБП 17 733 ₽/мес…
… и ещё 10 таких же

15 «подписок» на сумму 298 474 ₽ в месяц. Все 15 — мусор. Это не подписки на сервисы, а служебные строки выписки: переводы по СБП другим людям, оплаты по QR-коду в магазинах, разовые переводы между счетами. Парсер ошибочно сгруппировал их и сделал из них recurring-подписки.

Что мы себе представляли

Стандартный путь пользователя который мы продаём в рекламе: заходишь → загружаешь выписку → видишь свои реальные подписки → понимаешь сколько тратишь и где переплачиваешь → конвертация в платящего.

Что увидел этот человек: зашёл с рекламы → загрузил выписку → получил 15 непонятных «подписок» на 298 000 ₽ → закрыл вкладку. Полная потеря лида на финальном шаге воронки. Деньги за клик заплатили, а пользователь ушёл с впечатлением что наш продукт не понимает банковские данные.

Почему так получилось

Когда мы делали парсер, исходили из того что в выписке есть названия мерчантов: «AmoCRM», «Yandex.Cloud», «Adobe». Логика группировки простая — если одно и то же название встречается несколько раз с одинаковой суммой, это подписка. Работает для 80% случаев.

Но банки иногда выгружают выписки в которых имя мерчанта не заполнено, а вместо него — описание операции вроде «12:52 Оплата по QR-коду СБП». И таких строк может быть много с разными суммами. Парсер видел повторяющийся текст, считал что это бренд-сервис, группировал — получались фальш-подписки.

У нас в коде был список того что точно НЕ подписки — супермаркеты, рестораны, заправки, такси. Но «СБП», «QR-код», «перевод между своими счетами» в этот список не входило. Просто потому что мы сами никогда такие выписки руками не разбирали — у нас в тестах были корпоративные выписки с настоящими мерчантами.

Что починили

За полдня:

  • Добавили в список «не подписки» все типовые описания операций: переводы СБП, оплаты по QR-коду, прочие операции, пополнения счёта, снятия наличных, комиссии, возвраты — около 20 паттернов
  • Научили парсер игнорировать строки которые начинаются с временной метки (например «10:48 Прочие операции») — это явный маркер служебной строки выписки
  • Удалили 15 фальш-подписок из аккаунта этого пользователя вручную через админку — чтобы при следующем заходе он не видел мусор
  • Заодно добавили автозаполнение даты следующего списания: если парсер распознал подписку, дата прогнозируется из последней транзакции + цикла оплаты. Раньше это поле оставалось пустым, теперь сразу работает напоминание «списание через 7 дней»

Написали пользователю — объяснили что произошло, что почистили дашборд от мусора, предложили перезалить выписку. Подарили 3 месяца Starter бесплатно. История получилась хорошим уроком, а человек получил рабочий продукт за наш счёт.

Что мы из этого вынесли

1. Ранние пользователи находят то, что не найдёт QA

Оба бага существовали в коде месяцами. У нас были unit-тесты на аналитику, на парсер, на форму подписки — ни один не падал. Потому что мы тестировали свои сценарии, которые сами придумали. А пользователь заходит с реальной выпиской из своего реального банка, со своей коллекцией реальных подписок — и сразу же ломает то, что нам в голову не пришло проверить.

Никакая внутренняя QA-команда меньше чем за полгода работы с продуктом не даст той широты сценариев, которые дают первые пользователи.

2. Скорость ответа важнее красоты решения

Каждый из двух багов закрыли за один рабочий день. Не самым идеальным способом — где-то хардкодом, где-то простой регулярки вместо нормального ML-классификатора. «Правильное» решение заняло бы неделю на каждый. Но через неделю пользователь уже забыл бы про нас.

Сейчас они увидели что мы реагируем за день, получили апгрейд тарифа, остались. Через 3 месяца, если активно используют — конвертируются в платящих. Если нет — мы хотя бы заработали репутацию, что в стартапе на старте важнее перфекционизма.

3. Подарок за фидбек окупается

3 месяца Starter стоят 3 870 ₽ на каждого. Если эти пользователи останутся платящими хотя бы 6 месяцев на тарифе Solo (2 940 ₽ выручки) — мы вернём подарок чистой маржой. Плюс с большей вероятностью расскажут о Subsly коллегам и в своих чатах — это виральный канал, который не купишь рекламой.

Для сравнения: один клик в РСЯ по теме «аудит SaaS» стоит 60-120 ₽, регистрация — около 1 400 ₽. Подарок в 3 870 ₽ эквивалентен 2-3 регистрациям с рекламы. Если хотя бы 1 из 3 вернётся виральным реферралом — сделка положительная.

4. UX-дефолты — главная дыра

Оба бага в сути своей были про дефолтные значения. Валюта по умолчанию RUB — а человек добавляет долларовый сервис. Парсер по умолчанию считает всё подпиской — а в выписке половина строк не подписки.

Дефолт всегда работает против edge-кейсов. Решение в обоих случаях оказалось одно и то же — заменить «глупый дефолт» на «умный»:

  • Валюта = USD для известных западных сервисов (Anthropic, OpenAI, GitHub и 70+ других в каталоге). Юзер выбирает Anthropic — валюта сама становится USD.
  • Парсер выписки = расширенный блэклист служебных операций. Не считаем «Оплата по QR-коду СБП» подпиской ни при каких условиях.

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

Что дальше

В конце мая опубликуем open metrics за полный месяц: CAC по каналам (Яндекс.Директ, Telegram-посевы, органика), конверсии в активацию и платящего, удержание. По-честному — что зашло, что нет, без приукрашивания.

Параллельно работаем над онбордингом — гипотеза что 4 фичи которые выкатили в прошлом месяце (демо-режим, туториал по выгрузке выписки, шаринг отчёта, social proof) должны поднять конверсию из посетителя в активного пользователя в 2-3 раза. Цифры будут в майских метриках.

Если у вас есть свой опыт с ранними пользователями и неожиданными багами — расскажите в комментариях, всегда интересно сравнить.

— Команда Subsly
Subsly — аудит SaaS-подписок за 2 минуты без регистрации
Subsly inside — постоянные апдейты по цифрам, продукту и факапам

Источник:
Нет комментариев. Ваш будет первым!
Загрузка...