# Яндекс Директ: как работает коннектор

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

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

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

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

*   **Куда:** хранилище ROMI center на движке ClickHouse.
*   **Имя таблицы:** `yd_<логин>_<id подключения>` (например `yd_client_276`).
*   **Структура таблицы:** движок `MergeTree`, сортировка по `stats_day`, разбиение на партиции по дню статистики (`PARTITION BY toYYYYMMDD(stats_day)`). Именно посуточные партиции делают перезапись дня дешёвой.
*   **Порядок колонок:** 10 обязательных (`stats_day`, пять `utm_*` + `utm_id`, `cost`, `clicks`, `impressions`) → выбранные пользователем поля → колонки конвертации валют → служебные `rc_import_id`, `rc_created_at` в самом конце.
*   **Структура догоняется, а не пересоздаётся.** При каждой выгрузке недостающие колонки добавляются `ALTER TABLE … ADD COLUMN`. Колонки никогда не удаляются: если поле выключить в настройках, колонка останется в таблице со старыми значениями, новые строки будут писаться в неё пустыми.

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

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

Перезапись — это замена дня целиком, а не обновление отдельных строк и не дедупликация: если статистика за день пришла, весь день сначала удаляется (`DROP PARTITION`, при неудаче — `DELETE` по `stats_day`), а затем записывается заново.

> **Важно**
> Пустой ответ API не очищает день. Если Яндекс Директ за дату ничего не вернул, старые данные остаются на месте.

*   Удаление дня выполняется один раз за прогон, перед записью первой порции строк.
*   Строки за пределами окна 7 дней штатная выгрузка не трогает — их меняет только ручная перезагрузка.

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

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

| Настройка | Что делает |
| --- | --- |
| НДС | Две схемы, зависящие от возраста подключения. Новые подключения запрашивают расход у Яндекс Директа без НДС и добавляют его по указанной ставке. Старые (созданные до перехода на новый визард) запрашивают расход с НДС и вычитают его по ставке. То есть при ненулевой ставке в колонке `cost` у новых подключений сумма с НДС, у старых — без НДС. Схема подключения не меняется при сохранении настроек — перейти на новую можно только пересоздав подключение (в визарде показывается предупреждение). |
| Конвертация валют | На каждую выбранную валюту добавляется колонка `cost_converted_<валюта>` — расход, пересчитанный по курсу на дату строки. Исходная валюта берётся из кабинета Яндекс Директа. Курсы кэшируются в справочнике; при отсутствии запрашиваются по очереди у openexchangerates, OANDA и ЦБ РФ. |
| UTM-метки для всех кампаний | Подменяет `utm_source`, `utm_medium`, `utm_campaign` заданными значениями во всех строках. |
| UTM-метки для выбранных кампаний | То же, но для конкретных кампаний; индивидуальное значение приоритетнее общего. |

Заблокированный аккаунт или несуществующий клиентский логин переводят подключение в состояние ошибки авторизации с письмом пользователю; до починки задания не создаются.

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

В таблице хранилища создаются два служебных поля:

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

Служебные поля всегда стоят последними в структуре — новое пользовательское поле добавляется перед ними.
