ETL витрат Meta Ads
src/stack/components/meta/ — щоденна викачка витрат з Facebook рекламних кабінетів у ClickHouse
Щодня вночі викачуємо з Meta Graph API скільки коштів витратив кожен рекламний оголошення за попередній день і зберігає це у ClickHouse-таблицю ad_spend. Мета — зіставляти рекламні витрати з воронкою кандидатів у дашборді аналітики.
Інтервал
Щодня о 08:00 за Києвом (Europe/Kiev) worker.
Запускається лише у production.
Таблиця ad_spend (ClickHouse)
ReplacingMergeTree — дедуплікація по ключу (date, platform, utm_source, utm_campaign, campaign_id). Усі аналітичні запити використовують FINAL для того щоб злиті дублі не потрапляли у результат. TTL — 3 роки.
| Поле | Тип | Опис |
|---|---|---|
date | Date | дата рекламного показу (YYYY-MM-DD) |
platform | LowCardinality | зараз завжди facebook |
utm_source / medium / campaign / content / manager / account | String/LowCardinality | розібрані з url_tags рекламного креативу |
campaign_id / campaign_name | String | ідентифікатор і назва кампанії з Meta API |
ad_id | String | ідентифікатор оголошення (ad) |
spend | Float64 | витрати за день у валюті рекламного акаунту |
currency | LowCardinality | валюта кабінету (напр. USD, UAH) |
Поточна структура реклами Facebook
Менеджер, Портфоліо компанії (BeSocial Studio)
└─ Рекламний акаунт Target #1 ← єдиний активний кабінет
└─ Campaigns (кілька)
└─ Ads (~5 оголошень)
Pixel: ...956 ← прив'язаний на рівні менеджера, портфоліо компанії
Зараз використовується одне портфоліо і один рекламний кабінет. Код розрахований на кілька кабінетів (ітерація по всіх adaccounts), але фактично API повертає один.
ETL-послідовність
Крок 1 — визначення пропущених дат
дивиться на максимальну дату в таблиці:
- Якщо таблиця порожня → завантажує останні 30 днів.
- Якщо дані є → викачуємо до вчора включно (тобто сьогоднішній день не чіпаємо — дані ще неповні).
Крок 2 — активні рекламні акаунти
Рекламні акаунти, підгружаємо список акаунтів до яких у BACKEND_USER є доступ. Наприклад, Target #1
Крок 3 — insights по оголошеннях за день
Підгружаємо трати за цей день по конкретним рекламам:
GET /{accountId}/insights — level ad, fields campaign_id, campaign_name, ad_id, ad_name, spend, time_range = один конкретний день. Ліміт: 1000 рядків на кабінет.
Після отримання — фільтр spend > 0: оголошення без витрат за день не зберігаються.
Крок 4 — UTM з рекламних креативів
Проходимось по кожній рекламі, дістаємо UTM мітки.
Нюанси
-
Дата у київському часовому поясі, арифметика по UTC. При зсуві на N днів спочатку формується поточна дата за Europe/Kiev, потім арифметика виконується в UTC-midnight щоб уникнути стрибків при переході на літній/зимовий час.
-
Валюта не нормалізується. Якщо різні кабінети мають різні валюти (USD і UAH одночасно) — рядки в
ad_spendматимуть різніcurrency. Агрегаціяsum(spend)по всіх рядках без фільтра поcurrencyдаватиме математично некоректну суму. Зараз всі кабінети — USD.