Pipeline обработки клика
GET /click/{slug} → build_click_context() (GeoIP, device, bot) → resolve_stream() (фильтры + лимиты + привязка) → record_click() → placeholders.substitute() → 302 redirect. Каждый шаг логируется в traffic_log.
Открытый CPA-трекер на Python/FastAPI: потоки трафика, 25+ фильтров, S2S-постбэки, идемпотентные конверсии, аналитика CR/EPC/CPC/ROI, Click API v3, Admin REST API. Без SPA — серверный рендеринг с Alpine.js, HTMX и Chart.js.
Рынок CPA-трекеров представлен закрытыми платными решениями (Keitaro, Binom, BeMob). Командам, которые работают с платным трафиком, нужен инструмент, где клик принимается за миллисекунды, маршрутизируется по правилам, конверсия атрибутируется и возвращается в источник — и всё это на собственном сервере.
Архитектурно нужно было решить: спроектировать pipeline обработки клика с GeoIP и device detection; реализовать систему фильтров из 25+ критериев с AND/OR логикой; обеспечить идемпотентность постбэков; построить аналитику CR/EPC/CPC/ROI поверх миллионов кликов без OLAP; поддержать интеграции с источниками трафика (Facebook, ExoClick, PropellerAds) через шаблоны и outgoing S2S.
Open Tracker — это открытый self-hosted CPA-трекер, который я спроектировал и разработал с нуля. Серверный рендеринг на FastAPI + Jinja2, интерактив через HTMX, Alpine.js и Chart.js.
Проект построен вокруг конвейера обработки клика: GeoIP и device detection, система фильтров из 25+ критериев, маршрутизация по потокам (forced / regular / default), идемпотентные постбэки и аналитика с CR, EPC, CPC и ROI.
Система написана на Python (FastAPI + SQLAlchemy 2.0 Core + Jinja2), работает на SQLite для быстрого старта и поддерживает PostgreSQL. 200+ тестов, ruff clean.
Проект с открытым исходным кодом под AGPL-3.0. Исходники доступны на GitHub.
Монолит с фабрикой FastAPI: бизнес-логика в core/, веб-слой в web/. SQLAlchemy 2.0 Core без ORM — 24+ таблиц через _table(conn, name). ClickIngestor Protocol как точка расширения для очередей и ClickHouse.
GET /click/{slug} → build_click_context() (GeoIP, device, bot) → resolve_stream() (фильтры + лимиты + привязка) → record_click() → placeholders.substitute() → 302 redirect. Каждый шаг логируется в traffic_log.
Forced — перехватывают весь трафик по приоритету. Regular — маршрутизация по весу или A/B-сплит с user binding. Default — catch-all fallback. Лимиты (caps) на клики/день/месяц и бан-листы.
GET|POST /postback принимает конверсии (sale/lead/reject/rebill). Связка (click_id, transaction_id) защищает от дубликатов. Outgoing S2S postback возвращает конверсию в источник трафика. Image-pixel fallback для нетипичных сценариев.
Гео (country, region, city, ISP, ASN), устройство (тип, OS, браузер), VPN/прокси, параметры кампании (source, keyword, creative, sub_id_1..30), время (hour, day of week), уникальность. Filter logic: and/or. Поддержка @empty.
build_chart_payload(): sparse SQL GROUP BY + Python zero-fill для временных рядов. KPI: CR, EPC, CPC, ROI, RPC. Drill-down: campaign → stream → offer. Режим даты: по клику или по конверсии. Экспорт CSV/XLSX.
Click API v3 — server-side ingest для PHP/WordPress без 302. LP API — интеграция лендингов. Admin REST API (/api/v1/*) с Bearer-токеном: кампании, потоки, офферы, клики, конверсии, отчёты.
Полноценный CPA-трекер с открытым кодом: от приёма клика до аналитики ROI.
технологический стек
SQLAlchemy 2.0 Core, Jinja2, Alpine.js, HTMX, Chart.js, Tailwind CDN. SQLite для старта, PostgreSQL для продакшена.
схема данных
Кампании, потоки, офферы, источники, клики, посетители, конверсии, daily-агрегаты, интеграции, хелс-чеки — всё через SQLAlchemy Core.
критериев маршрутизации
Гео, устройство, OS, браузер, VPN, sub_id_1..30, время, уникальность — с AND/OR логикой и @empty.
покрытие
pytest: ingest, постбэки, фильтры, потоки, binding, conversion cap, drill-down, traffic log, hardening. ruff clean.