Як ми збирали дані щодо рекламних кампаній з інтернет-майданчиків (тернистий шлях до продукту)

Здається, що сфера інтернет-реклами має бути максимально технологічною та автоматизованою. Ще б пак, адже там працюють такі гіганти та експерти у своїй справі, як Яндекс, Mail.Ru, Google і Facebook. Але, як виявилося, немає межі досконалості і завжди є що автоматизувати.

Як ми збирали дані щодо рекламних кампаній з інтернет-майданчиків (тернистий шлях до продукту)
Джерело

Комунікаційна група Dentsu Aegis Network Ukrainian - Найбільший гравець на рекламному digital ринку і активно інвестує в технології, намагаючись оптимізувати і автоматизувати свої бізнес-процеси. Одним із невирішених завдань ринку інтернет-реклами стало завдання збору статистики з рекламних кампаній з різних інтернет-майданчиків. Вирішення цього завдання в результаті вилилося у виробництво продукту D1.Digital (Читати як ДіВан), про розробку якого ми і хочемо розповісти.

Навіщо?

1. На момент старту проекту на ринку не було жодного готового продукту, що вирішує завдання автоматизації збору статистики з рекламних кампаній. Значить, ніхто, крім нас самих, не закриє наші потреби.

Такі сервіси, як Improvado, Roistat, Supermetrics, SegmentStream пропонують інтеграцію з майданчиками, соціальними мережами та Google Analitycs, а також дають можливість будувати аналітичні дашборди для зручного аналізу та контролю рекламних кампаній. Перед тим, як почати розвивати свій продукт, ми спробували використати деякі з цих систем для збору даних з майданчиків, але, на жаль, вони не змогли вирішити наших завдань.

Головною проблемою стало те, що продукти, що тестуються, відштовхувалися від джерел даних, відображаючи статистику розміщень у розрізах по майданчиках, і не давали можливості агрегувати статистику з рекламних кампаній. Такий підхід не дозволяв побачити статистику з різних майданчиків в одному місці та проаналізувати стан кампанії цілком.

Іншим фактором стало те, що на початкових етапах продукти були спрямовані на західний ринок і не підтримували інтеграцію з російськими майданчиками. А за тими майданчиками, з якими було реалізовано інтеграцію, не завжди вивантажувалися всі необхідні метрики з достатньою деталізацією, а інтеграція не завжди була зручною та прозорою, особливо коли потрібно було отримати щось, чого немає в інтерфейсі системи.
Загалом ми вирішили не підлаштовуватися під сторонні продукти, а зайнялися розробкою свого…

2. Ринок інтернет-реклами зростає рік у рік, і в 2018 році за обсягом рекламних бюджетів він випередив традиційно найбільший ринок ТБ-реклами. Отже, є масштаб.

3. На відміну від ринку ТБ-реклами, де продаж комерційної реклами монополізовано, в Інтернеті працює безліч окремих власників рекламного інвентарю різної величини зі своїми рекламними кабінетами. Так як рекламна кампанія, як правило, йде відразу на декількох майданчиках, то для розуміння стану рекламної кампанії треба зібрати звіти з усіх майданчиків і звести їх в один великий звіт, який покаже картинку цілком. Отже, є потенціал оптимізації.

4. Нам здавалося, що власники рекламного інвентарю в інтернеті вже мають інфраструктуру для збору статистики та її відображення в рекламних кабінетах, і вони зможуть надати API до цих даних. Отже, є технічна можливість реалізації. Скажімо одразу, що виявилося не все так просто.

Загалом, всі передумови для реалізації проекту були для нас очевидні, і ми побігли втілювати проект у життя.

Грандіозний план

Для початку ми сформували бачення ідеальної системи:

  • У неї повинні автоматично завантажуватись рекламні кампанії з корпоративної системи 1С з їх назвами, періодами, бюджетами та розміщеннями по різноманітних майданчиках.
  • Для кожного розміщення всередині рекламної кампанії повинна автоматично завантажуватись вся можлива статистика з майданчиків, на яких йде розміщення, така як кількість показів, кліків, переглядів та інше.
  • Деякі рекламні кампанії відстежуються за допомогою стороннього моніторингу так званими системами adserving, такими як Adriver, Weborama, DCM і т.д. Також є індустріальний вимірник Інтернету в Росії – компанія Mediascope. Дані незалежного та індустріального моніторингу за нашим задумом також повинні автоматично підвантажуватись до відповідних рекламних кампаній.
  • Більшість рекламних кампаній в Інтернет націлені на певні цільові дії (купівля, дзвінок, запис на тест-драйв і т.д.), які відстежуються за допомогою Google Analytics, і статистика за якими також важлива для розуміння стану кампанії та має завантажуватись у наш інструмент .

Перший млинець грудкою

Враховуючи нашу прихильність до гнучких принципів розробки ПЗ (agile, усі справи), ми вирішили спочатку розробити MVP і далі рухатися до наміченої мети ітеративно.
MVP ми вирішили будувати на основі нашого продукту DANBo (Dentsu Aegis Network Board), що представляє собою web додаток із загальною інформацією щодо рекламних кампаній наших клієнтів.

Для MVP проект було максимально спрощено з погляду реалізації. Ми вибрали обмежений список інтеграційних майданчиків. Це були основні майданчики, такі як Яндекс.Директ, Яндекс.Дисплей, RB.Mail, MyTarget, Adwords, DBM, VK, FB, та основні adserving системи Adriver та Weborama.

Для доступу до статистики на майданчиках через API ми використовували єдиний обліковий запис. Менеджер клієнтської групи, який хотів використати автоматичний збір статистики з рекламної кампанії, мав спочатку делегувати доступ до потрібних рекламних кампаній на майданчиках на обліковий запис платформи.

Далі користувач системи DANBo повинен був завантажити в систему Excel файл певного формату, в якому була прописана вся інформація про розміщення (рекламна кампанія, майданчик, формат, період розміщення, планові показники, бюджет і т.д.) та ідентифікатори відповідних рекламних кампаній на майданчиках та лічильників adserving системах.

Виглядало це, чесно кажучи, жахливо:

Як ми збирали дані щодо рекламних кампаній з інтернет-майданчиків (тернистий шлях до продукту)

Завантажені дані зберігалися до бази даних, та був окремі сервіси збирали їх ідентифікатори кампаній на майданчиках і завантажували за ними статистику.

Для кожного майданчика було написано окремий windows сервіс, який раз на добу ходив під одним службовим обліковим записом в API майданчики та вивантажував статистику за заданими ідентифікаторами кампаній. Аналогічно відбувалося і з adserving системами.

Завантажені дані відображалися на інтерфейсі у вигляді невеликого самописного дашборду:

Як ми збирали дані щодо рекламних кампаній з інтернет-майданчиків (тернистий шлях до продукту)

Несподівано для нас самих MVP заробив і почав завантажувати актуальну статистику рекламних кампаній в Інтернеті. Ми впровадили систему на кількох клієнтах, але при спробі масштабування натрапили на серйозні проблеми:

  • Головна проблема була у трудомісткості підготовки даних для завантаження у систему. Також дані розміщення треба було приводити до строго фіксованого формату перед завантаженням. У файл для завантаження потрібно було прописувати ідентифікатори сутностей із різних майданчиків. Ми зіткнулися з тим, що технічно непідготовленим користувачам дуже важко пояснити, де знайти ці ідентифікатори на майданчику і куди їх потрібно проставити. Враховуючи кількість співробітників у підрозділах, що ведуть кампанії на майданчиках, та плинність, це вилилося у величезний обсяг підтримки на нашому боці, що нас категорично не влаштовувало.
  • Іншою проблемою було те, що не на всіх рекламних майданчиках були механізми делегування доступу до рекламних кампаній на інші облікові записи. Але навіть якщо механізм делегування був доступний, не всі рекламодавці були готові надавати доступ до своїх кампаній стороннім обліковим записам.
  • Немаловажним став фактор обурення, яке у користувачів викликало те, що всі планові показники та деталі розміщення, які вони вже вносять до нашої облікової системи 1С, вони повинні повторно вносити і в DANBo.

Це наштовхнуло нас на думку, що першоджерелом інформації про розміщення повинна служити наша 1С система, в яку всі дані вносяться акуратно і в строк (тут справа в тому, що на підставі даних 1С формуються рахунки, тому коректне внесення даних до 1С стоїть у всіх KPI). Так з'явилася нова концепція системи.

Концепція

Перше, що ми вирішили зробити, це виділити систему збору статистики з рекламних кампаній в Інтернет в окремий продукт. D1.Digital.

У новій концепції ми вирішили завантажувати в D1.Digital інформацію щодо рекламних кампаній та розміщень усередині них з 1С, а потім підтягувати до цих розміщень статистику з майданчиків та з AdServing систем. Це мало значно спростити життя користувачам (і, як водиться, додати роботи розробникам) і зменшити обсяг підтримки.

Перша проблема, з якою ми зіткнулися, була організаційного характеру і пов'язана з тим, що ми не змогли знайти ключ або ознаку, за якою можна було б зіставити сутності з різних систем з кампаніями та розміщеннями з 1С. Справа в тому, що процес у нашій компанії влаштований так, що рекламні кампанії в різні системи заносяться різними людьми (медіапленери, баінг та ін.).

Щоб вирішити цю проблему, нам довелося винайти унікальний хешований ключ, DANBoID, який би пов'язував сутності в різних системах воєдино, і який можна було б досить легко і однозначно ідентифікувати в наборах даних, що завантажуються. Цей ідентифікатор генерується у внутрішній 1С системі для кожного окремого розміщення та прокидається в кампанії, розміщення та лічильники на всіх майданчиках та у всіх AdServing системах. Впровадження практики проставлення DANBoID у всі розміщення зайняло певний час, але ми впоралися з цим 🙂

Далі ми з'ясували, що далеко не всі майданчики мають API для автоматичного збору статистики, і навіть у тих, у яких API є, він повертає не всі потрібні дані.

На цьому етапі ми вирішили значно скоротити список майданчиків для інтеграції та зосередитись на основних майданчиках, які задіяні у переважній більшості рекламних кампаній. До цього списку потрапили всі найбільші гравці рекламного ринку (Google, Яндекс, Mail.ru), соціальні мережі (VK, Facebook, Twitter), основні системи AdServing та аналітики (DCM, Adriver, Weborama, Google Analytics) та інші майданчики.

У більшості обраних нами майданчиків був API, який віддавав необхідні нам метрики. У тих випадках, коли API не було, або в ньому не було потрібних даних, для завантаження даних ми використовували звіти, які щодня надходять на службову пошту (в одних системах є можливість налаштування таких звітів, в інших погодили розробку таких звітів для нас).

При аналізі даних із різних майданчиків ми з'ясували, що ієрархія сутностей не однакова у різних системах. Більше того, із різних систем інформацію необхідно завантажувати у різній деталізації.

Для вирішення цієї проблеми було розроблено концепцію SubDANBoID. Ідея SubDANBoID досить проста, ми помічаємо основну сутність кампанії на майданчику згенерованим DANBoID, а всі вкладені сутності ми вивантажуємо з унікальними ідентифікаторами майданчика і формуємо SubDANBoID за принципом DANBoID + ідентифікатор вкладеної сутності першого рівня в'язати рекламні кампанії у різних системах та вивантажити деталізовану статистику за ними.

Також довелося вирішувати проблему доступу до кампаній на різних майданчиках. Як ми вже писали вище, механізм делегування доступу до кампанії на окремий технічний обліковий запис не завжди застосовується. Тому нам довелося розробити інфраструктуру для автоматичної авторизації через OAuth із використанням токенів та механізми оновлення цих токенів.

Далі у статті спробуємо докладніше описати архітектуру рішення та технічні деталі реалізації.

Архітектура рішення 1.0

Починаючи реалізацію нового продукту, ми розуміли, що одразу потрібно передбачити можливість підключення нових майданчиків, тому вирішили піти шляхом мікросервісної архітектури.

При проектуванні архітектури ми виділили в окремі послуги конектори до всіх зовнішніх систем - 1С, рекламних майданчиків і adserving систем.
Основна ідея полягає в тому, що всі конектори до майданчиків мають однакове API і є адаптерами, що приводять API майданчиків до зручного для нас інтерфейсу.

У центрі нашого продукту — веб-додаток, який є монолітом, який спроектований таким чином, щоб його можна було легко розібрати на сервіси. Ця програма відповідає за обробку завантажених даних, зіставлення статистики з різних систем та подання її користувачам системи.

Для спілкування конекторів з веб-програмою довелося створити додатковий сервіс, який ми назвали Connector Proxy. Він виконує функції Service Discovery та Task Scheduler. Цей сервіс щоночі запускає завдання збору даних для кожного конектора. Написати сервіс-прошарку було простіше, ніж підключати брокер повідомлень, а для нас було важливо отримати результат якнайшвидше.

Для простоти та швидкості розробки ми також вирішили, що всі сервіси будуть Web API. Це дозволило швидко зібрати proof-of-concept та перевірити, що вся конструкція працює.

Як ми збирали дані щодо рекламних кампаній з інтернет-майданчиків (тернистий шлях до продукту)

Окремим, досить складним завданням виявилося налаштування доступів для збору даних з різних кабінетів, яке, як ми вирішили, має здійснюватися користувачами через веб-інтерфейс. Вона складається з двох окремих кроків: спочатку користувач через OAuth додає токен для доступу до облікового запису, а потім налаштовує збір даних для клієнта з певного кабінету. Отримання токена через OAuth необхідно, тому що, як ми вже писали, не завжди можна делегувати доступ до потрібного кабінету на майданчику.

Щоб створити універсальний механізм вибору кабінету з майданчиків, нам довелося додати в API конекторів метод, що віддає JSON Schema, яка рендерується у форму за допомогою модифікованого компонента JSONEditor. Так користувачі змогли вибирати облікові записи, з яких необхідно завантажувати дані.

Щоб дотримуватись лімітів запитів, що існують на майданчиках, ми об'єднуємо запити щодо налаштувань в рамках одного токена, але різні токени можемо обробляти паралельно.

Як сховища для завантажених даних як для веб-додатки, так і для конекторів ми вибрали MongoDB, що дозволило не сильно морочитися щодо структури даних на початкових етапах розробки, коли об'єктна модель програми змінюється через день.

Незабаром ми з'ясували, що не всі дані добре лягають у MongoDB і, наприклад, статистику щодня зручніше зберігати в реляційній базі. Тому для конекторів, структура даних яких більше підходить під реляційну базу даних, як сховища ми почали використовувати PostgreSQL або MS SQL Server.

Вибрана архітектура та технології дозволили нам відносно швидко побудувати та запустити продукт D1.Digital. За два роки розвитку продукту ми розробили 23 конектори до майданчиків, отримали безцінний досвід роботи зі сторонніми API, навчилися обходити підводні камені різних майданчиків, які у кожного виявилися свої, сприяли розвитку API як мінімум 3 майданчиків, автоматично завантажили інформацію майже по 15 000 кампаній і більш ніж 80 000 розміщень, зібрали багато зворотний зв'язок від користувачів по роботі продукту і встигли кілька разів поміняти основний процес роботи продукту, ґрунтуючись на цьому зворотному зв'язку.

Архітектура рішення 2.0

Минуло два роки після старту розробки D1.Digital. Постійне зростання навантаження на систему і поява нових джерел даних поступово розкрили проблеми в існуючій архітектурі рішення.

Перша проблема пов'язана з обсягом даних, які завантажуються з майданчиків. Ми зіткнулися з тим, що збирання та оновлення всіх необхідних даних із найбільших майданчиків стало займати занадто багато часу. Наприклад, збір даних по adserving системі AdRiver, за допомогою якої ми відстежуємо статистику здебільшого розміщень, займає близько 12 годин.

Щоб вирішити цю проблему, ми почали використовувати всілякі звіти для завантаження даних із майданчиків, намагаємось розвивати разом із майданчиками їх API, щоб швидкість його роботи задовольняла нашим потребам, та паралелити завантаження даних, наскільки це можливо.

Інша проблема пов'язана з обробкою завантажених даних. Зараз при надходженні нової статистики з розміщення, запускається багатоступеневий процес перерахунку метрик, який включає завантаження сирих даних, прорахунок агрегованих метрик по кожному майданчику, зіставлення даних з різних джерел між собою і розрахунок зведених метрик по кампанії. Це викликає велике навантаження на веб-додаток, який здійснює всі розрахунки. Кілька разів програма в процесі перерахунку з'їдала всю пам'ять на сервері, близько 10-15 Гб, що згубно позначалося на роботі користувачів з системою.

Зазначені проблеми та грандіозні плани на подальший розвиток продукту привели нас до необхідності переглянути архітектуру програми.

Почали ми з конекторів.
Ми помітили, що всі конектори працюють за однією моделлю, тому побудували фреймворк-конвеєр, в якому для створення конектора потрібно було лише запрограмувати логіку кроків, решта була універсальною. Якщо якийсь конектор вимагає доопрацювання, то одночасно з доопрацюванням конектора відразу переводимо його на новий фреймворк.

Паралельно ми почали розміщувати конектори у докер та Kubernetes.
Переїзд в Kubernetes планували досить довго, експериментували з налаштуваннями CI/CD, але почали переїжджати тільки тоді, коли один конектор через помилку став від'їдати більше 20 Гб пам'яті на сервері, практично вбиваючи інші процеси. На час розслідування конектор переселили в кластер Kubernetes, де він у результаті залишився, навіть коли помилку було виправлено.

Досить швидко ми зрозуміли, що Kubernetes це зручно, і за півроку перенесли в кластер продакшена 7 конекторів та Connectors Proxy, які споживають найбільше ресурсів.

Слідом за конекторами ми вирішили змінювати архітектуру іншої програми.
Основною проблемою було те, що дані приходять з конекторів у проксі великими пачками, а потім б'ються по DANBoID і віддаються до центрального веб-додатку для обробки. Через велику кількість перерахунків метрик виникає велике навантаження на додаток.

Також виявилося досить складно моніторити статуси окремих завдань на збір даних і передавати помилки, що відбуваються всередині конекторів, до центрального web-додатку, щоб користувачі могли бачити, що відбувається, і через що не збираються дані.

Для вирішення цих проблем ми розробили архітектуру 2.0.

Головна відмінність нової версії архітектури полягає в тому, що замість Web API ми використовуємо RabbitMQ та бібліотеку MassTransit для обміну повідомленнями між сервісами. Для цього довелося практично повністю переписати Connectors Proxy, зробивши з нього Connectors Hub. Назва змінили тому, що основна роль сервісу тепер не в прокиданні запитів у конектори і назад, а в управлінні збором метрик з конекторів.

З центрального web програми ми виділили в окремі послуги інформацію про розміщення та статистику з майданчиків, що дало можливість позбутися зайвих перерахунків і на рівні розміщень зберігати тільки вже розраховану та агреговану статистику. Також ми переписали та оптимізували логіку розрахунку основних статистик на основі сирих даних.

Паралельно ми переносимо всі сервіси та додатки в докер і Kubernetes, щоб рішення простіше масштабувалося і ним було зручно керувати.

Як ми збирали дані щодо рекламних кампаній з інтернет-майданчиків (тернистий шлях до продукту)

Де ми зараз

Proof-of-concept архітектури 2.0 продукту D1.Digital готовий та працює в тестовому оточенні з обмеженим набором конекторів. Справа за малим - переписати ще 20 конекторів на нову платформу, протестувати, що дані коректно завантажуються, а всі метрики правильно вважаються, і викотити всю конструкцію в продакшн.

Насправді цей процес відбуватиметься поступово і нам доведеться залишити зворотну сумісність зі старими API, щоб усе продовжувало працювати.

У найближчих наших планах стоїть розробка нових конекторів, інтеграція з новими системами та додавання додаткових метрик у набір даних, що вивантажуються із підключених майданчиків та adserving систем.

Також плануємо перенести всі додатки, у тому числі і центральний web додаток, докер і Kubernetes. У поєднанні з новою архітектурою це дозволить помітно спростити розгортання, моніторинг та контроль споживаних ресурсів.

Ще є ідея поекспериментувати з вибором БД для зберігання статистики, яка зараз зберігається у MongoDB. Декілька нових конекторів ми вже перевели на SQL-бази, але там різниця майже непомітна, а для агрегованої статистики днями, яку можна вимагати за довільний період, виграш може бути досить серйозним.

Загалом плани грандіозні, рухаємося далі 🙂

Автори статті R&D Dentsu Aegis Network Russia: Георгій Остапенко (shmiigaa), Михайло Коцик (hitexx)

Джерело: habr.com

Додати коментар або відгук