madpwa Docs · без логина Keitaro В кабинет
Публичная инструкция

Логин не нужен. Пошаговая настройка Keitaro — раздел 3 ↓. В кабинете то же: Потоки → «Хвосты и трекинг».

https://madpwa.com/postback?subid={external_id}&status={status}

Хвосты, трекинг и интеграции

Практическая документация для кабинета madpwa.com: хвосты, Keitaro, postback и пиксели.


Коротко: как устроена цепочка

1
Реклама FB / TikTok

Ссылка «С хвостом» из карточки потока

https://madpwa.com/n/{naming_key}?fbp=…&sub1=…&sub3={{campaign.name}}…
2
Кабинет /n/…
  • сохраняем click_id + fbp/fbc/fbclid
  • раскрываем макросы, дописываем хвост (если append_query = Да)
  • редирект 302 на Campaign URL трекера
3
Трекер Keitaro

В Campaign URL обязательно:

external_id={clickId}
Юзер → PWA
  • открывает /a/{slug}
  • браузерный пиксель + POST /api/pwas/{slug}/event
  • CAPI (FB / Twitter)
Конверсия → нам
  • S2S Postback:
https://madpwa.com/postback?subid={external_id}&status=lead|sale
  • счётчики leads/deps + CAPI + Web Push

Три ссылки в карточке потока:

СсылкаЧто это
ПотокЧистый /n/{key} без параметров
С хвостомТот же URL + шаблон query для рекламы
PostbackURL для S2S в трекере

1. Хвосты

Что такое хвост

Хвост — query-строка на ссылке запуска. В неё кладут параметры рекламной сети и свои sub*, чтобы они доехали до трекера и в макросы оффера.

Пример (как в кабинете):

https://madpwa.com/n/nk_xxxxxxxx?fbp=PIXEL&ttp=TTP&sub1=SUB1&sub2=SUB2&sub3={{campaign.name}}&sub4={{adset.name}}&sub5={{ad.name}}

В Facebook/TikTok макросы {{…}} подставляет сама рекламная сеть. На выходе получается обычная строка ?sub3=MyCampaign&….

Куда попадает хвост

  1. Реклама ведёт на лендинг PWA: GET /a/{slug}?… (преленд → стор → /go). Прямой оффер без воронки: /n/{key} или /a/{slug}/go.
  2. На /go (или /n/…) кабинет создаёт click_id, пишет клик в БД (вместе с fbp / fbc / fbclid, если они были в query).
  3. Выбирается URL оффера по правилам потока (GEO / платформа / вес).
  4. Макросы {clickId}, {sub1}, {campaignName}… раскрываются.
  5. Редирект 302 на трекер.

«Добавлять параметры с потока / ссылки запуска» (append_query)

РежимПоведение
Да (по умолчанию)К офферу дописываются параметры потока и весь хвост со ссылки запуска. При конфликте ключей побеждает поток / params правила.
НетХвост не дописывается целиком. В трекер уходят только макросы, которые явно прописаны в URL оффера ({sub1}, {clickId}…).

Всегда добавляются служебные: click_id, nk (ключ потока). Params конкретного URL-правила применяются всегда.

Макросы в URL оффера

Пишутся в фигурных скобках:

МакросОткуда берётся
{clickId}Наш id клика (для Keitaro → external_id)
{campaignName}, {adsetName}, {adName}Из хвоста / UTM-алиасов
{campaignId}, {adsetId}, {adId}, {accountId}То же
{networkSource}, {networkChannel}utm_source / utm_medium и синонимы
{country}, {language}GEO / язык
{deviceBrand}, {deviceModel}, {osName}, {osVer}Из UA или хвоста
{sn_SUBNAME}Любой ключ хвоста: {sn_sub1} ← sub1=…
{fd:af_siteid}AppsFlyer-style: af_siteid / site_id

Алиасы хвоста (часть списка): utm_campaign → campaignName, utm_source → networkSource, ad_id → adId и т.д. Полный набор — в namings.py (NAMING_MACROS, _INCOMING_ALIASES).

Правила URL в потоке

Типичный оффер для Keitaro:

https://tracker.example/XXXXX?external_id={clickId}&sub1={sub1}&sub2={sub2}&sub3={sub3}

Без external_id={clickId} постбек не склеит конверсию с кликом.

Код

ФайлРоль
namings.pyСхема, макросы, build_redirect, GEO-роутинг
app.pyGET /n/{key}, GET /a/{slug}/go
static/cabinet.jsКарточка потока, копирование хвоста / postback

2. Трекинг

2.1 Клик и атрибуция

ЭндпоинтНазначение
GET /n/{key}Редирект по потоку
GET /a/{slug}/goТо же через PWA (если привязан поток)

В таблице clicks сохраняются: click_id, slug, IP, UA, fbp, fbc, fbclid, naming_key.

Этот click_id и есть то, что трекер должен вернуть в постбеке как subid (через external_id в Campaign URL).

2.2 S2S Postback

Формат как у Skak (полный) или минимальный:

GET /postback?subid={external_id}&tid={tid}&status={status}&payout={conversion_revenue:usd}&sale_status=sale,dep,ftd,deposit,approved&lead_status=lead,reg&currency=usd
GET /postback?subid={external_id}&status={status}&payout=…|sum=…|amount=…
status (или через sale/lead_status)Что делаем
lead, reg, registration+1 lead, событие reg, CAPI reg
sale, dep, deposit, purchase, ftd, approved+1 dep, событие dep, CAPI dep

Дополнительно: Web Push по slug PWA, запись в stats_events, CAPI с сохранёнными fbp/fbc/fbclid клика.

В Keitaro → Source → S2S Postback — та же схема, что Skak, хост madpwa.com. Подробный копипаст: §3.

{external_id} в Keitaro — это наш click_id.

2.3 Пиксели в браузере + клиентские события

На store / preland / white (по настройкам) в <head> попадает HTML из metrics.head_html().

КаналБраузерСервер (CAPI)
Facebookfbevents.js или 1×1 img (pixel_as_img)Graph /{pixel_id}/events
Twitter/Xuwt.jsAds API measurement/conversions
TikTokНет своего Pixel SDKТолько прокидывание ttclid/ttp на оффер при tiktok_source

Клиентский скрипт (landings.install_script):

Карта событий по умолчанию (настраивается на PWA):

Этап воронкиFB-событие по умолчанию
InstallLead
RegCompleteRegistration
DepPurchase

Пиксели задаются в карточке PWA: fb_pixels (pixel_id + access token), tw_pixels (Track ID + API key). Без токена — только браузер; с токеном — ещё и CAPI.

2.4 Лог «События Ads»

2.5 Статистика воронки

stats.py — виды: visit, open, install, reg, dep, push_*. На install списывается CPI (CPI_CENTS, по умолчанию 2 цента = $0.02).

2.6 Клоака

cloak.py: боты / VPN / hosting → white-страница. Страна: заголовок Cloudflare CF-IPCountry или ip-api.com. Настройки PWA: bot_hosting, bot_proxy, tiktok_source, pixel_on_white, white_url и др.


3. Как настроить Keitaro (как у Skak)

Схема та же, что у Skakapp: реклама → наш `/n/…` → Keitaro → оффер → S2S postback → нам. Мы не шлём конверсии в Keitaro — Keitaro шлёт их нам на /postback.

madpwa ≈ Skak: что совпадает

Skakmadpwa
Клик в Adsих launch / naminghttps://madpwa.com/n/{key}?… («С хвостом»)
В Keitaro External IDparam external_id = {clickId}то же
S2S Postbackhttps://uclient.skakapp.com/postback?subid={external_id}&…https://madpwa.com/postback?subid={external_id}&…
Склейкаsubid ← {external_id} ← наш click_idто же
Lead / Salelead_status / sale_status спискиподдерживаем те же списки

Отличия: другой домен postback; у Skak ещё from=client_ID_SKAK (у нас не нужен). Остальное можно копировать 1-в-1.


Готовые ссылки (копипаст)

1) Keitaro → Edit Source → S2S postback

Как у Skak, только хост наш:

https://madpwa.com/postback?subid={external_id}&tid={tid}&status={status}&payout={conversion_revenue:usd}&sale_status=sale,dep,ftd,deposit,approved&lead_status=lead,reg&currency=usd

Минимальный вариант:

https://madpwa.com/postback?subid={external_id}&status={status}

Send only statuses: Lead + Sale (как на скрине Skak).

QueryКто подставляетЗачем
subid={external_id}Keitaroнаш click_id (обязательно)
status={status}Keitarolead / sale / …
payout={conversion_revenue:usd}Keitaroсумма → FB Purchase CAPI
tid={tid}Keitaroпишется в лог postbacks (опционально)
sale_status=…константакакие status считать депозитом
lead_status=…константакакие status считать регистрацией
currency=usdконстантавалюта CAPI

2) Keitaro → Edit Source → Parameters (шаблон как Skak)

В колонке Parameter / Placeholder — то, что Keitaro допишет к Campaign URL. Справа — макросы madpwa (их раскроет наш /n/… при редиректе на трекер).

NameParameterPlaceholder or value
External IDexternal_id{clickId}
Ad Campaign IDad_campaign_id{campaignId}
Sitesource{networkSource}
Sub 1sub1{sn_sub1}
Sub 2sub2{sn_sub2} или свой BUYER_ID
Sub 3sub3{sn_sub3}
Sub 4sub4{sn_sub4}
Sub 5sub5{sn_sub5}
Campaign namecampaign_name{campaignName}
App numberapp_num{appNum}
App bundleapp_bundle{appBundle}
Adset IDadset_id{adsetId}
Adset nameadset_name{adsetName}
Ad IDad_id{adId}
Ad namead_name{adName}
Network channelnetwork_channel{networkChannel}
Organicis_organic{isOrganic}
GAIDgaid{gaid}
Back UrlisBackUrl0
Pixel Facebookfbp{sn_fbp}
Pixel TikTokttp{sn_ttp}
OS nameos_name{osName}
OS veros_ver{osVer}
Languagelanguage{language}
Countrycountry{country}
FB clickfbclid{sn_fbclid}

Критично: строка External ID = external_id / {clickId} — без неё postback не склеится.

3) Кабинет → поток → URL оффера

Вставьте Campaign URL из Keitaro (после сохранения Source параметры уже в шаблоне). Должно получиться примерно так:

https://ВАШ-ТРЕКЕР/XXXXX?external_id={clickId}&source={networkSource}&ad_campaign_id={campaignId}&sub1={sn_sub1}&sub2={sn_sub2}&sub3={sn_sub3}&sub4={sn_sub4}&sub5={sn_sub5}&campaign_name={campaignName}&fbp={sn_fbp}&fbclid={sn_fbclid}&country={country}&os_name={osName}

«Добавлять параметры» = Да.

4) Реклама — только «С хвостом»

https://madpwa.com/n/nk_xxxxxxxx?fbp=PIXEL_ID&ttp=TTP&sub1=SUB1&sub2=BUYER&sub3={{campaign.name}}&sub4={{adset.name}}&sub5={{ad.name}}

{{…}} — макросы FB/TikTok. Нельзя кидать в Ads сырой Campaign URL Keitaro.


Что куда (кратко)

ГдеЧто
Keitaro Source → S2Spostback madpwa (блок выше)
Keitaro Source → Parametersтаблица External ID + subs (как Skak)
Кабинет → поток → офферCampaign URL с external_id={clickId}
Ads«С хвостом» /n/…
PWAпривязать поток + Pixel + Access Token

Шаг за шагом

  1. Keitaro → Sources → New / Edit

- S2S postback = ссылка madpwa из блока «Готовые ссылки». - Send only: Lead + Sale. - Parameters: External ID → external_id = {clickId} (+ остальные по таблице).

  1. Кампания Keitaro на этом Source → скопировать Campaign URL.
  2. Кабинет → Потоки → в оффер вставить Campaign URL; append_query = Да; сохранить.
  3. PWA → выбрать поток; Метрики → pixel + token.
  4. В Ads — «С хвостом».
  5. Прогон теста (ниже).

Как прогнать тест (когда всё добавили)

A. Ручной тест postback (30 секунд)

  1. Открой ссылку «С хвостом» из карточки потока (или чистый /n/ключ) в браузере.
  2. DevTools → Network → найди 302 на трекер. В URL скопируй значение external_id= (это наш click_id).
  3. В новой вкладке открой (подставь свой id):
https://madpwa.com/postback?subid=СКОПИРОВАННЫЙ_EXTERNAL_ID&status=lead

Должно вернуть {"ok":"1"}.

  1. Для депозита:
https://madpwa.com/postback?subid=СКОПИРОВАННЫЙ_EXTERNAL_ID&status=sale&payout=10&currency=usd
  1. Проверь в кабинете:

- у PWA вырос leads / deps; - раздел События Ads — строка CAPI (если есть Access Token у пикселя).

Без живого клика (external_id из шага 2) postback придёт, но не привяжется к PWA — счётчики не вырастут.

B. Тест из Keitaro

  1. Сделай тестовый клик по «С хвостом» → клик появится в Keitaro с External ID.
  2. В Keitaro на этом клике / конверсии отправь тестовый Lead (или Conversion → Lead).
  3. Keitaro дернет наш S2S URL сам.
  4. Снова проверь счётчики + «События Ads».

C. Тест пикселя без Keitaro

В карточке PWA → Метрики → кнопка Тест (install / reg / dep) — шлёт CAPI напрямую. Это проверка token/pixel, не склейки с трекером.


Маппинг status → события

status (или из sale/lead_status)КабинетFB по умолчанию
lead, reg, registrationlead / regCompleteRegistration
sale, dep, deposit, purchase, ftd, approveddepPurchase

Если в postback заданы sale_status=… и lead_status=… — кабинет смотрит на эти списки (как Skak).


Частые ошибки

ОшибкаСимптом
Нет external_id={clickId} в Parameters / оффереPostback есть, клик не находится
В postback subid={subid} вместо {external_id}Пустой/чужой subid
В Ads — Campaign URL KeitaroКабинет не создал click_id
Пиксель без Access TokenCAPI с postback молчит
Sub6 с параметром sub5 (дубль как на части скринов Skak)Затирает sub5 — лучше sub6 / {sn_sub6}

Короткий чеклист

  1. Source S2S = madpwa postback (Skak-формат).
  2. Parameters: external_id = {clickId}.
  3. Поток: Campaign URL + append_query Да.
  4. Ads: только «С хвостом».
  5. Тест postback status=lead.

4. Интеграции

Реклама и атрибуция

ИнтеграцияНазначениеКак подключенаЧто настроить
KeitaroТрекер (основной сценарий)Campaign URL в оффере + S2S /postbackexternal_id={clickId} в URL; postback с {external_id} → subid
Facebook Pixel + CAPIPageView, install/reg/depБраузерный скрипт + Graph APIВ PWA: fb_pixels (id + token), события, Domain Verify; env PWA_FB_GRAPH
Twitter/X Pixel + CAPIБраузер + Conversions APIuwt.js + Bearer APIВ PWA: tw_pixels; env PWA_TW_CAPI
TikTokПараметры клика + фильтр ботовttclid/ttp на оффер; tiktok_source в клоакеТогл в настройках PWA. Отдельного TikTok Pixel/CAPI нет
UTM / макросы FBИмена кампаний/адсетов в хвостеАлиасы в namings.pyКлючи в ссылке запуска
AppsFlyer-style{fd:af_siteid}Алиас queryaf_siteid / site_id в хвосте

Любой трекер с S2S и external_id работает по той же схеме, что Keitaro. Отдельной интеграции Binom в коде нет.

Пуши и мессенджеры

ИнтеграцияНазначениеКакНастройка
Web Push (VAPID)Нативные пуши PWApywebpush + Service Workerdata/vapid.json, env VAPID_MAILTO
OneSignalОпциональный SDKCDN в <head>onesignal_on, onesignal_app
Push.expressОпциональный пушcdn.push.express/auto.jspush_express_on, push_express_app (+ поле key в настройках)
ExtendyPartner pushcdn.extendy.net/partner.jsextendy_on, extendy_id
Telegram LoginВход в кабинетPOST /api/auth/telegramTELEGRAM_BOT_TOKEN, TELEGRAM_BOT_NAME

Домены и инфраструктура

ИнтеграцияНазначениеКакНастройка
CloudflareЗоны, A-записи, custom hostnamescloudflare_cf.pyCF_API_TOKEN, CF_ACCOUNT_ID, опционально CF_SAAS_ZONE_ID, PWA_PUBLIC_IPS
NamecheapПроверка/покупка доменовXML API (registrar.py)REGISTRAR_PROVIDER=namecheap, NAMECHEAP_*
PorkbunТо жеJSON APIREGISTRAR_PROVIDER=porkbun, PORKBUN_*
RDAPДоступность без ключей регистратораHTTP—
ip-api.comСтрана / proxy / hosting для клоакиcloak.lookup_ipПубличный API
Bypass URLОбход клоаки (bypass-ключ)HMAC _bypassKeyPWA_BYPASS_SECRET, PWA_BYPASS_TTL

Прочее

ЧтоПримечание
Шаблоны Google Play / App StoreТолько UI лендинга, не API консолей
custom_jsПроизвольный JS на store-странице
CRM wteam.appОтдельный продукт — не делить nginx/БД/CF с PWA

5. Переменные окружения

ПеременнаяОбласть
CPI_CENTS, ADMIN_USER, ADMIN_PASSWORDБиллинг / вход
CABINET_HOSTS, PWA_PUBLIC_ORIGIN, PWA_PUBLIC_IPS, PWA_SKIP_DNS, PORTХостинг
TELEGRAM_BOT_TOKEN, TELEGRAM_BOT_NAMETelegram
VAPID_MAILTOWeb Push
CF_API_TOKEN, CF_ACCOUNT_ID, CF_SAAS_ZONE_IDCloudflare
REGISTRAR_PROVIDER, NAMECHEAP_*, PORKBUN_*Домены
PWA_FB_GRAPH, PWA_TW_CAPI, PWA_METRICS_LOG, PWA_METRICS_SINKМетрики
PWA_BYPASS_SECRET, PWA_BYPASS_TTLBypass клоаки

На проде секреты: /etc/pwa-cabinet.env (см. deploy/pwa-cabinet.service). Пиксели, потоки, токены CAPI — в SQLite (pwas, namings), не в env.


6. Словарь RU ↔ код

В кабинетеВ коде
хвост / С хвостомlaunch tail, query pass-through
потокnamings, naming_key, /n/…
Добавлять параметры…append_query
Замыкающая ссылкаclosing_url
оффер / трекерoffer_url / Campaign URL
постбек/postback
пиксель / CAPIpixel / Conversions API
События Adsads-events log
клоака / whitecloak.py / white page
метрикиmetrics.py

7. Ключевые файлы

ФайлТема
namings.pyХвосты, макросы, редирект
metrics.pyПиксели, CAPI, лог
landings.pyКлиентский трекинг, шаблоны
cloak.pyФильтры трафика
stats.pyВоронка
settings.pyТоглы PWA (TikTok, пуши, пиксель на white…)
cloudflare_cf.pyCloudflare
registrar.pyNamecheap / Porkbun
bypass.pyОбход клоаки
app.py/n/…, /postback, /event, API
static/cabinet.jsUI потоков и метрик

https://madpwa.com/docs/tracking · алиас /docs/keitaro