Платформа автоматизации маркетинга: десктоп → Telegram → веб
Платформа управления рекламными кампаниями для собственных рекламных проектов. Начинал в 2024 с десктопа на Tkinter для личного использования — вырос в полноценный продукт с 80+ функциями, Telegram-ботом и рабочим веб-приложением на Next.js + FastAPI с правами доступа по ролям и шифрованным хранилищем токенов. К сентябрю 2026 в репозитории 826 коммитов: 13 вкладок десктопа, 228 точек API в веб-версии, расход двух рекламных сетей уходит в трекер по часовому поясу площадки, отчёты доводят клик до объявления и сводят «регистрация → первая оплата» по приложению, стране и офферу.
Запуск одной кампании = 2 часа ручной работы
В закупке рекламы запуск одной кампании — это 9 связанных шагов: составить название по схеме (магазин, продукт, страна, специалист, ниша), подобрать лендинг и офферы в Keitaro, сделать короткую ссылку через Cutt.ly, прописать OG-теги, привязать Facebook Pixel и токен доступа, создать пост на странице в FB, добавить первые комментарии.
На каждом шаге легко ошибиться: имя ссылки повторяется с прошлой кампанией, не тот идентификатор пикселя, забытая UTM-метка — и учёт конверсий ломается, бюджет идёт в никуда. При запуске 5–10 рекламных наборов в день вся команда тратит больше времени на копирование и вставку, чем на работу с креативами.
Готовых решений нет: платные сервисы привязаны к одной партнёрской сети, а чужие внутренние инструменты заточены под чужие процессы. Нужен был инструмент, который понимает нашу структуру неймингов, наши интеграции и эволюционирует под потребности команды.
Четыре итерации, три интерфейса
Приложение на Tkinter для macOS — для себя
Python, Tkinter и родное меню правки macOS (отменить, вырезать, копировать, вставить). Личный рабочий инструмент: одна форма с автоподбором лендингов и офферов, проверкой полей, сохранением шаблонов и локальной историей в SQLite. ~2000 строк на Python, собиралось в .app-пакет.
Telegram-бот для команды — работа прямо в чате
python-telegram-bot 20 и собственный конечный автомат состояний: пошаговый опрос всех полей кнопками прямо в переписке. Бизнес-логика переиспользована из десктопной версии через общие модули. Специалист по рекламе создаёт кампанию с телефона, прямо из чата.
Рабочее веб-приложение с правами доступа по ролям
Полностью переписан с нуля как полноценный сервис: Next.js 14 (App Router, TypeScript, Tailwind, shadcn/ui) + FastAPI (async SQLAlchemy 2 + Pydantic v2) + PostgreSQL 16 + Celery + Redis 7.
Шифрованное хранилище токенов на Fernet (AES-128-CBC + HMAC-SHA256) — в браузер токены не попадают никогда. Вход по JWT, пароли под bcrypt. Журнал каждого действия в базе. Развёрнуто через Docker compose на сервере Vultr, адрес сервера скрыт за Cloudflare.
Лето 2026: паритет интерфейсов и слой данных
С июня по сентябрь — 178 коммитов. Первая часть работы — паритет десктопа и веб-версии: шесть проходов аудита (Pass-38 … Pass-43, 24 коммита с 6 по 14 июня). Каждый проход: параллельный аудит по кластерам вкладок, сводный список расхождений, затем исправления с правилом «один файл — один исполнитель»: два параллельных редактора одного файла молча откатывают работу друг друга. Один проход пришлось откатить: проверка типов и сборка прошли, страница отдавала 200, при этом в браузере каждая авторизованная страница падала — компонент кнопки передавал обёртке Radix двух потомков, обёртка принимает ровно одного. Через два дня проход вернули, и перед каждой выкладкой теперь выполняется предварительный рендер всех страниц.
Вторая часть — данные. Расход рекламных сетей уходит в трекер по часовому поясу площадки: для Meta — по поясу каждого рекламного кабинета, для Unity Ads — почасовые данные складываются в сутки по Лос-Анджелесу, по которым считает трекер. Поверх — атрибуция клика до объявления по fbclid, сводки «регистрация → первая оплата» по приложению × стране × офферу, выкачка базы офферов партнёрских сетей и движок правил, который предлагает вердикты по связкам.
Что внутри — топ-10 функций из 80+
Таблица с прямым редактированием, автонумерация постов, полоса прогресса рядом с каждой строкой, итог по каждой: успех или ошибка.
Fernet (AES-128-CBC + HMAC-SHA256), главный ключ в переменных окружения, отдельная роль vault-admin. Токены не выходят за пределы сервера.
«Вы обычно используете Hershey's с Kisses», подсказки по времени («14:00 — ваше обычное время публикации»).
Форма автосохраняется в БД. При сбое браузера/приложения — восстановление из последнего сохранения, кнопка «очистить черновик».
Красная или зелёная рамка поля, кнопка блокируется при совпадении. В пакетном режиме имя правится само (добавляет -2, -3 или случайное слово).
Группировка по стране и магазину, применение в одно нажатие, предпросмотр перед применением, импорт и экспорт JSON, шаблоном можно поделиться с командой.
Каждое изменение пишется со временем, поиск и фильтры (кампания, пост, объявления, ошибки), фильтр по датам, выгрузка в CSV или JSON, переход к кампании одним нажатием.
Хранятся последние 10 копий, копию можно сделать вручную кнопкой в меню, время последнего сохранения видно в строке состояния.
Предупреждение при попытке создать кампанию с тем же магазином, продуктом и страной, что у существующей; рядом показывается сравнение с прошлой версией.
Cmd+1/2/3 переключение табов, Cmd+N новая кампания, Cmd+H история, Cmd+Q панель быстрых действий. Полная навигация с клавиатуры.
Это моя личная разработка — внутренний инструмент для собственной работы. Показал её как пример того, что я умею собирать в одиночку: продукт с тремя интерфейсами, выкладка в рабочую среду, права доступа по ролям, ~80 проработанных функций. К сентябрю 2026 — 13 вкладок десктопа, 33 экрана веб-версии, 85 служебных скриптов. В клиентских проектах тот же уровень внимания к деталям переношу на вашу задачу — инструменты подбираю под неё.
Технологии, на которых это собрано
- Next.js 14 (App Router)
- React 18 + TypeScript
- Tailwind CSS + shadcn/ui
- Компоненты Radix UI
- react-hook-form + Zod валидация
- Sonner для всплывающих уведомлений
- FastAPI 0.115 (async)
- SQLAlchemy 2 (async) и миграции Alembic
- Pydantic v2 для всех схем
- JWT (jose, HS256, 24h TTL)
- bcrypt для паролей
- Fernet (AES + HMAC) для хранилища токенов
- PostgreSQL 16 (pgcrypto, uuid-ossp)
- Celery 5 для фоновых задач
- Redis 7 как брокер очередей и кэш
- SQLite (десктоп / Telegram-версии)
- ClickHouse трекера — чтение поклик-данных для ранних правил
- Docker compose, несколько сервисов
- Nginx (TLS, заголовки безопасности, блокировка карт исходников)
- Cloudflare DNS/CDN, адрес сервера скрыт
- Vultr VPS, Ubuntu 24.04
- Автоматические сертификаты Let's Encrypt
- Задачи по расписанию на сервере трекера: расход каждые 15 минут, отчёт правил ежедневно
- Python 3 + Tkinter
- Родное меню правки macOS
- SQLite для локальной БД
- py2app для сборки .app
- python-telegram-bot 20 (async)
- Конечный автомат состояний
- Кнопки в сообщениях и обработка нажатий
- Бот аналитики: карточки кампаний, пауза и запуск, вердикты движка правил, монитор состояния
- Keitaro 11.10 API (кампании, лендинги, офферы, расходы)
- Facebook Graph API и Marketing API (посты, комментарии, страницы, кампании)
- Meta Conversions API через собственный сервис-ретранслятор событий
- Unity Ads Statistics API (расход и установки по часам)
- Cutt.ly API (короткие ссылки)
- API партнёрских сетей — сверка продаж
- Приём вебхуков со статусами
- Pytest: 221 тест в 10 файлах, 83 из них добавлены летом 2026
- Проверка движка правил на 90 днях истории без заглядывания в будущее
- Монитор состояния: 22 проверки в 7 группах каждые 30 минут
- Таблица журнала действий в базе
- Единая обработка ошибок
- Структурированное логирование
Что изменилось в работе
8× быстрее, с гарантией отсутствия дубликатов и валидацией всех полей
кампаний за один прогон — каждая настраивается отдельно прямо в таблице
за 10 этапов — от первой рабочей версии до полноценного сервиса
фильтр префиксов fbclid отбрасывал 492 из 672 кликов в сутки, и продажи уходили в Meta без идентификатора клика; проверено на живых журналах: 180/672 → 672/672
кликов из одной ссылки в комментарии размечаются до объявления: 13,5% дописывает Meta, 21,6% — собственный декодер fbclid; четыре одноимённые кампании разложились по разным корзинам
сокращатель отвечал ошибкой на запрос с брендированным доменом, клиент повторял его 14 раз с растущей паузой; теперь сразу переходит на домен по умолчанию
Системный эффект: платформа стала единым источником данных по всем рекламным запускам команды. Telegram-бот для специалистов в дороге, веб-приложение для офисной и совместной работы, десктоп для тех, кто предпочитает приложение на macOS. Все три используют один и тот же код бизнес-логики и одну общую базу кампаний, шаблонов и токенов.
Урок для клиентских проектов: правильная архитектура (разделение ответственности, общая бизнес-логика, несколько интерфейсов поверх неё) позволяет добавить новый интерфейс — мобильное приложение, интеграцию со Slack, голосового помощника — за неделю на той же серверной части.
Лето 2026: расход и сводки. Расход Meta пишется в трекер по часовому поясу каждого рекламного кабинета: кабинеты одного профиля жили на двух поясах, окно суток съезжало на ~10 часов, и часть расхода ложилась на соседний день. Флаг уникальных кликов при записи снял завышение суммы на 10–15%. Запись идёт полной суммой за день, повтор безопасен: 96 прогонов в сутки, вчерашний день досчитывается после полуночи, пока сеть доносит поздние часы. Сводки «регистрация → первая оплата» по кампаниям сети: расход и установки из второй сети, регистрации, оплаты и выручка из трекера, склейка по шестисимвольному идентификатору кампании в её имени; цена установки, доли по шагам воронки, ROI и точка безубыточности. Зрелая доля (регистрации старше 6 часов) показала, что один и тот же оффер конвертирует по-разному в разных приложениях, поэтому приложение смотрят раньше оффера. Оплаты доезжают 24–48 часов, и доля за первые сутки помечена в отчёте как заниженная.
Атрибуция клика до объявления. Фильтр префиксов fbclid в сборщике событий отбрасывал 492 из 672 кликов в сутки: продажа уходила в Conversions API без идентификатора клика, и из 4 продаж за день кабинет видел 2. Проверка семейства префикса подняла долю до 672/672, затем список префиксов убран целиком: такой список устаревает при следующей смене формата. 48 продаж за 7 дней переотправлены с тем же детерминированным идентификатором события, принято 48 из 48. Несколько кампаний крутят один пост с одной ссылкой, и трекер сливал их клики в одну корзину; поле adid внутри fbclid совпало с настоящим идентификатором объявления в 0 из 137 проверенных кликов, поэтому таблица соответствия ведётся своя и засевается из кликов, к которым Meta сама дописывает идентификаторы: 262 пары, 22 объявления, коллизий 0, независимая сверка 361 из 361. Справочник объявление → группа → кампания по 10 кабинетам (912 объявлений, 760 групп, 244 кампании) без нарушений целостности; сборщик идемпотентен по отметке времени — раньше каждый прогон удваивал счётчики. Бот аналитики удваивал показатели трекера на одноимённых кампаниях и складывал продажи из одного потока — 10 при 13 в трекере, что давало ложный сигнал на остановку; теперь суммируются все потоки, и отчёт сходится с трекером до цента. 34 теста на реальных образцах, полностью офлайн.
Движок правил. Пять вердиктов по связкам «кампания трекера × кампании Meta», от ранней остановки до масштабирования. Движок предлагает, решает оператор: в трекер и кабинеты движок не пишет. Три источника: трекер как единственный источник денег и воронки, Meta — ранг, живой расход и состояние кабинета, партнёрская сеть — сверка продаж как предохранитель: если сеть показывает больше продаж, чем трекер, остановка запрещена. Пороги выведены из 92 дней × кампаний и совпали с эвристиками оператора: это точки смены знака ROI по цене уникального клика и цене перехода. Поклик-реконструкция сошлась с отчётом трекера в 1 704 из 1 704 ячеек день × кампания. Проверка на 90 днях истории без заглядывания в будущее: первая версия предлагала остановить флагманскую связку, которая затем принесла 139% прибыли аккаунта. Добавлен предохранитель «связку в плюсе остановить нельзя», минимум продаж для вердикта по CPA поднят с 3 до 8, правило «худшая зона цен» требует минимум 2 продажи — прежде оно выносило 9 из 17 вердиктов при нуле продаж. Эффект правил на 90 днях — 0,8–1,8% расхода, и отчёт говорит об этом прямо. 49 тестов, ежедневный отчёт в Telegram; карточки бота считают вердикт тем же движком и показывают его причину.
Бот аналитики и хранилище. Профили Meta добавляются и переключаются из чата, токен проверяется и сразу удаляется из переписки; пауза и запуск кампаний работают под любым из токенов оператора, при лимитах Meta — повторы с паузами 1, 2 и 5 секунд. Хранилище токенов веб-версии: проверка срока и прав, показ токена после повторного ввода пароля, архив с восстановлением, автоблокировка, журнал устройств входа. Оффер с пустым или заглушечным адресом создать нельзя — после случая, когда 33 оффера вели на заглушку.
Похожие кейсы
Swift/SwiftUI: первая версия за 9 недель — от старта до App Store
Приложение для iOS 17+: расписание и напоминания (24 ч / 1 ч / 10 мин), Speech Framework проверяет…
PWA для фитнес-студии: 1,2 МБ против 47 МБ у обычного приложения
Ставится на телефон как обычное приложение (PWA): работает без сети через Service Worker, уведомления на iOS…
Играбельная реклама для игры: цена установки −38%, установок +73%
Интерактивный мини-уровень на HTML5 через Cocos2d-js. 18 вариаций под 5 рекламных сетей (FB / TikTok /…
Аудит за 9 900 ₽ — с конкретным отчётом и сметой
Расскажу что внедрить в вашем бизнесе в первую очередь, какая будет окупаемость, и нужен ли вообще AI для вашей задачи (иногда — нет).
Или просто напишите свой вопрос — отвечу в течение 2 часов