# Facebook Ads: как работает коннектор

В этой статье вы узнаете, как коннектор Facebook Ads выгружает данные в хранилище ROMI center: с какой периодичностью, как устроена таблица и откуда берутся UTM-метки. Полный список полей — в статье [Facebook Ads: описание выгружаемых полей](https://help-ru.romi.center/facebook-ads-opisanie-vygruzhaemyh-polej).

## Периодичность

Выгрузка идёт раз в сутки. Окно по умолчанию — от «сегодня минус 7 дней» до вчера включительно, по одному заданию на день. Текущий день не выгружается.

> **Примечание**
> Facebook создаёт задания отдельным ночным прогоном в 02:30, тогда как остальные коннекторы серии — общим в 02:00: так сделано после инцидента, когда тяжёлая выгрузка в общей очереди задач съела несколько часов и до Facebook очередь в тот день не дошла.

Гранулярность данных: строка = объявление × день. Уровни группы и кампании попадают в ту же строку идентификаторами и названиями, поля креатива — колонками с префиксом `ad_creative_`.

> **Важно**
> При крупных аккаунтах Facebook отвечает ошибкой «уменьшите объём данных». В этом случае коннектор сам перестраивает стратегию: сначала запрашивает список кампаний за день, затем идёт по каждой кампании отдельным запросом. Прогон становится медленнее, но доходит до конца.

## Как сохраняет данные

*   **Куда:** хранилище ROMI center на движке ClickHouse.
*   **Имя таблицы:** `facebook_<идентификатор профиля>_<id подключения>`.
*   **Структура таблицы:** движок `MergeTree`, сортировка по `stats_day`, разбиение на партиции по дню статистики.
*   **Порядок колонок:** общие поля (`stats_day`, `utm_*`, `cost`) → колонки конвертации валют → выбранные поля статистики → выбранные поля креатива → служебные `rc_import_id`, `rc_created_at`.
*   **Структура догоняется, а не пересоздаётся.** Недостающие колонки добавляются при очередной выгрузке, существующие не удаляются.

> **Примечание**
> Пустых значений в таблице не бывает: все поля статистики и креатива объявлены типом, не допускающим пустое значение, поэтому там, где данных нет, окажется ноль или пустая строка. Многие метрики Facebook отдаёт массивами (действия, конверсии, ROAS, просмотры видео) — они записываются JSON-строкой в одну колонку, разбирать их нужно на стороне отчёта.

## Перезапись за 7 дней

Facebook уточняет статистику задним числом (доучёт конверсий, пересчёт расхода), поэтому каждую ночь перезагружаются последние 7 завершённых дней. Каждый день — отдельное задание: если строк нет, день пропускается и прежние данные сохраняются; если строки есть, весь день удаляется и записывается заново.

Ручная перезагрузка за произвольный период доступна в кабинете и ставит такие же посуточные задания. При включённой опции «удалить данные» таблица сносится целиком и создаётся заново первой же выгрузкой.

## Дополнительные настройки

| Настройка | Что делает |
| --- | --- |
| Профиль | Рекламный аккаунт Facebook, из которого берётся статистика. Его идентификатор входит в имя таблицы. |
| Выбор полей | Задаёт набор колонок таблицы — отдельно по статистике и по креативам. Клики и показы выгружаются всегда. |
| НДС | Расходы приходят из Facebook без НДС; при включённой настройке ROMI center добавляет его по указанной ставке. |
| Конвертация валют | На каждую выбранную валюту добавляется колонка `cost_converted_<валюта>` — расход, пересчитанный по курсу на дату строки. Исходная валюта — валюта рекламного аккаунта. |
| UTM-метки для всех кампаний | Подменяет `utm_source`, `utm_medium`, `utm_campaign` заданными значениями во всех строках. |
| UTM-метки для выбранных кампаний | То же, но покампанийно; индивидуальное значение приоритетнее общего. |
| Пауза коннектора | Останавливает создание новых заданий. |

> **Примечание**
> Настройка «Фильтр кампаний» осталась от старого интерфейса: новый визард её не задаёт и при каждом сохранении обнуляет — режима «все, кроме выбранных» у Facebook нет вовсе.

Перед каждой выгрузкой проверяются две вещи: жив ли токен и есть ли доступ к выбранному рекламному аккаунту. Истёкший или отозванный токен и потеря доступа к аккаунту переводят подключение в состояние ошибки; до починки выгрузка не идёт. Временные ответы Facebook («сервис недоступен», «запрос занял слишком долго») ошибкой авторизации не считаются.

## Откуда берутся UTM-метки

Единственный источник разметки — поле `url_tags` креатива объявления: строка параметров вида `utm_source=fb&utm_medium=cpc&...`. Ссылка объявления при этом не разбирается.

Порядок сборки:

1.  **Значения по умолчанию:** `rc-facebook` (`utm_source`), `rc-cpm` (`utm_medium`), `(not set)` для `utm_campaign`, `utm_term`, `utm_content`. Если у креатива есть публикация Instagram, источник по умолчанию — `rc-instagram`.
2.  **Параметры из `url_tags`** — перекрывают значения по умолчанию.
3.  **Пользовательские метки** из настроек подключения — общие или покампанийные.
4.  **Подстановка макросов Facebook** (`{{ad.id}}`, `{{ad.name}}`, `{{adset.id}}`, `{{adset.name}}`, `{{campaign.id}}`, `{{campaign.name}}`) в получившихся значениях.
5.  **`utm_id`**: если метки в разметке нет — подставляется идентификатор кампании.

Разметка запоминается на объявление: метки считаются один раз при первой встрече объявления в прогоне, и у всех его строк они одинаковые.

> **Важно**
> `url_tags` разбирается собственным парсером, а не стандартным разбором адреса: из строки удаляются все пробелы, значение обрезается по второму знаку «=» (из `utm_content=a=b` в таблицу попадёт `a`), а escape-последовательности вроде `%20` не декодируются.

> **Примечание**
> Признак «метки собрались не полностью» у Facebook не показателен — он взводится практически всегда, даже при полной разметке. Ориентироваться нужно на сами значения меток в таблице.

## Технические поля

| Поле | Тип | Что означает |
| --- | --- | --- |
| `rc_import_id` | Целое число | Идентификатор прогона выгрузки, которым записана строка. |
| `rc_created_at` | Дата и время | Момент записи строки в хранилище (не время события). При перезаписи дня обновляется у всех строк дня. |

В таблицах Facebook нет `rc_updated_at` и `rc_datasource`.
