Зерно строки: ID, канал, неделя

Зерно строки для размещений у меня одно: ID вакансии, канал и неделя. Пока этих трёх полей нет, витрина данных — переименованный xlsx. Дашборд на следующей неделе собирают заново.

Оркестратор я выбираю потом. Сначала строка, которую можно повторить в понедельник.

Предметная область — размещения на hh и Авито и вилки рынка. Как это стыкуется с должностью, а не со словарём HR, разобрано в статье про дашборды, BI и ETL. Здесь только слой базы.

Демо Свода собрано на синтетике. Механика экрана как в проде. Абсолютные бюджеты клиентов не публикую: NDA. Цифры ниже либо методика, либо уже округлённый порядок величины.

Что лежит в строке

Витрина отвечает на один вопрос. Что произошло с этим объявлением на этом канале за эту неделю. «Как поживает кабинет» в эту ячейку не влезает.

ПолеЗачем оно в зернеЧто будет, если его выкинуть
ID вакансииБюджет и отклики одного объявленияСреднее кабинета прячет мёртвые ID
Каналhh и Авито считаются отдельноОдин CPL на два прайса
НеделяПилот и фон не смешиваютсяМесяц выглядит «нормально»
ПрофильКассир не склеивается с кадровикомСвод сравнивает разные роли
ГородПилот в одном городе не размазывается на сеть«В целом по стране»

Формула стоимости отклика живёт этажом выше. Целиком дробь здесь не повторяю. Разбор — CPL отклик. Витрина нужна, чтобы у дроби был знаменатель из той же строки. Соседний лист для этого уже поздно.

Если бюджет больше нуля, а откликов нет, строка остаётся. Это дыра. Нулевым CPL её не называю. Прятать агрегированием «по профилю за месяц» не даю. Сначала строка. Потом свёртка.

Откуда берётся неделя

Кабинеты Avito и hh.ru забираю раз в неделю, xlsx из личного кабинета. Имя файла уже несёт период. Форматов несколько: «с DD по DD.MM.YY» и «с DD.MM по DD.MM.YY». Даты внутри файла — второй источник боли. У одного клиента ISO YYYY-MM-DD. У другого день стоит первым.

Реальный баг из прода. ISO без явного формата прочиталась как dayfirst. 9 июня стало 6 сентября. Флаг «новая публикация» ушёл в ноль по всем строкам канала. Витрина загрузилась. Отчёт открылся. Неделя была чужая.

После этого парсер даты на угадывание библиотеки не оставляю.

Месяц в зерно не кладу. Месяц удобен для слайда и вреден для решения. За четыре недели внутри месяца успевают случиться переиздание, смена менеджера, вход в рекламную кампанию и двухнедельное списание. Списание выглядит как «бюджет упал», хотя рычаг никто не трогал. Медиаплан на следующую неделю собирается из выходов и лимита. Из этого среднего его не собираю. Как устроен сам план — медиаплан вакансий.

Атрибуция кампании к неделе у меня календарная. Подпись из кабинета тут ни при чём. Период кампании в таймзоне Москвы сравниваю с неделей выгрузки по максимальному числу общих дней. Если пересечение одинаковое, беру более раннюю неделю. На домашней неделе вакансии — не больше одной подписи кампании. Иначе одна строка получает два бюджета.

Канал общим не бывает

hh и Авито — разные кабинеты, разные прайсы, разные файлы. В базе это разные таблицы на пару «клиент × канал». Они создаются при первой загрузке, без ручной миграции под нового клиента. В витрине канал — поле зерна. Фильтр «на потом» из него не делаю.

Сложить отклики двух площадок до деления на бюджет — получить цену, которой нет ни в одном кабинете. На планёрке её защищать нечем. Сначала две строки. Потом, если нужно, сравнение рядом. Сумму не рисую.

Профиль — четвёртое поле. В зерно вместо ID его не ставлю. Названия в выгрузке пляшут: регистр, дефис, «УБОРЩИК / ЦА», стажировка в скобках. Классификация правилами: ключевое слово, стоп-слово, порядок проверки, дефолт «Без профиля». На контрольной партии за 4 недели точность была 99,7%, 638 из 640 строк. Проверка прод-правил. Бенчмарк рынка из неё не следует. Две ошибки обычно на пограничном заголовке. Такие строки остаются в хвосте на разбор.

К строке джойнится флаг: объявление уже в автоматизации продвижения или это ещё витрина без рычага. Без флага нельзя отличить «платим за то, что уже крутится» от «платим за карточку».

Какого размера это бывает

Точные объёмы клиентов не публикую. Порядок величины, уже округлённый из-за NDA и уже названный в статье про CPL: порядка 150–200 тысяч строк на канал у крупного клиента. Это не «у всех» и не маркетинговый объём продукта. Маленький кабинет живёт в той же схеме зерна. Меняется число строк. Определение недели то же.

На таком объёме недельный пересчёт «на лету по сырым фактам» не оставляю. Держу недельные агрегаты заранее. Иначе свод двух панелей, где недели стоят столбцами, ждёт сырой скан. Дашборд, который открывается дольше планёрки, в работу не берётся. Экран этого свода — демо. На демо данные синтетические.

Планёрка не ждёт скан. Она ждёт строку.

Если свод открывается дольше, чем люди готовы сидеть молча, его уже не смотрят. Смотрят тот файл, который успели собрать руками в воскресенье. Витрина нужна, чтобы этот файл больше не собирать.

Чего витрина не знает

Витрина размещений не знает, вышел ли человек на работу и остался ли он на 90-й день. Она знает вход: бюджет, отклики, показы, просмотры, контакты, город, профиль, флаг продвижения. Качество найма и знаменатель текучести — другие таблицы. Склеивать их в одну строку «CPL с удержанием» без общего ключа источника не буду. Получится отчёт ни о чём.

Резюме в эту таблицу не кладу. В строке размещения карточки кандидата нет, и тащить её туда не из чего.

Медиаплан она тоже не заменяет. Медиаплан смотрит вперёд, от нужных выходов к слотам. Витрина смотрит назад, на неделю, которую уже закрыл файл кабинета. Путать их значит защищать план цифрой, которая ещё не наступила, или защищать факт пожеланием «давайте ещё десять вакансий».

Что остаётся в сырье

Сырой xlsx не выкидываю. Он нужен, когда строка витрины спорит с кабинетным итогом и надо увидеть исходную ячейку. Дашборд сырьё не читает. Иначе каждая планёрка заново выбирает, какой столбец считать откликом, а какой — контактом.

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

Порядок загрузки держу скучным. Сначала период из имени файла. Потом даты внутри с явным форматом, без угадывания. Потом классификация профиля. Потом джойн флага автоматизации по ID. Потом проверка суммы бюджета против итога кабинета. Только после этого недельный агрегат можно открывать в BI.

Если сумма не сошлась, витрину коэффициентом не подгоняю. Расхождение — баг парсера или другой состав ID. Его видно до экрана. Подгонка сделала бы дашборд красивым и неверным. Такой экран хуже пустого.

Отдельные таблицы на пару клиент × канал нужны не для красоты схемы. У клиентов разные форматы дат и разные имена колонок. Общая таблица «все кабинеты мира» заставляет молча приводить их к одному смыслу. Лучше вторая таблица и явный маппинг, чем одна колонка, в которой у одного клиента отклик, а у другого контакт.

Четыре проверки перед BI

Перед тем как дашборд считается готовым, смотрю на загрузку. Красота графика подождёт.

  1. Число строк недели не упало в ноль из-за даты, которая уехала в другой месяц.
  2. Доля профиля «Без профиля» не прыгнула без нового словаря. Прыжок значит, что заголовки сменили шаблон, а правила остались старыми.
  3. Сумма бюджета по ID сходится с итогом кабинета этой недели. Если не сходится, дыра в парсере. В маркетинге её искать рано.
  4. ID с бюджетом и нулём откликов на месте. Их отсутствие значит, что фильтр «где есть отклики» уже соврал.

Если все четыре сходятся, витрину можно отдавать в BI. Если нет, дашборд лучше не открывать. Он уверенно покажет чужую неделю.

Смежные тексты: CPL и дробь, кто собирает эти дашборды, медиаплан, который начинается с выходов.

Ещё из цикла