meta-ad-spend

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 роки.

ПолеТипОпис
dateDateдата рекламного показу (YYYY-MM-DD)
platformLowCardinalityзараз завжди facebook
utm_source / medium / campaign / content / manager / accountString/LowCardinalityрозібрані з url_tags рекламного креативу
campaign_id / campaign_nameStringідентифікатор і назва кампанії з Meta API
ad_idStringідентифікатор оголошення (ad)
spendFloat64витрати за день у валюті рекламного акаунту
currencyLowCardinalityвалюта кабінету (напр. 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.