Jak zbieraliśmy dane o kampaniach reklamowych ze stron internetowych (ciernna droga do produktu)

Wydaje się, że dziedzina reklamy internetowej powinna być jak najbardziej zaawansowana technologicznie i zautomatyzowana. Oczywiście, ponieważ pracują tam tacy giganci i eksperci w swojej dziedzinie, jak Yandex, Mail.Ru, Google i Facebook. Ale jak się okazało, perfekcja nie ma granic i zawsze można coś zautomatyzować.

Jak zbieraliśmy dane o kampaniach reklamowych ze stron internetowych (ciernna droga do produktu)
źródło

Grupa komunikacyjna Dentsu Aegis Network Rosja jest największym graczem na rynku reklamy cyfrowej i aktywnie inwestuje w technologię, starając się optymalizować i automatyzować swoje procesy biznesowe. Jednym z nierozwiązanych problemów rynku reklamy internetowej jest zadanie gromadzenia statystyk dotyczących kampanii reklamowych z różnych platform internetowych. Rozwiązanie tego problemu ostatecznie zaowocowało stworzeniem produktu D1.Cyfrowy (czytaj jako DiVan), o rozwoju którego chcemy porozmawiać.

Dlaczego?

1. W momencie rozpoczęcia projektu na rynku nie było ani jednego gotowego produktu, który rozwiązywałby problem automatyzacji zbierania statystyk dotyczących kampanii reklamowych. Oznacza to, że nikt poza nami nie będzie zaspokajał naszych potrzeb.

Usługi takie jak Improvado, Roistat, Supermetrics, SegmentStream oferują integrację z platformami, sieciami społecznościowymi i Google Analitycs, a także umożliwiają budowanie dashboardów analitycznych w celu wygodnej analizy i kontroli kampanii reklamowych. Zanim zaczęliśmy rozwijać nasz produkt, próbowaliśmy wykorzystać niektóre z tych systemów do zbierania danych z witryn, ale niestety nie były one w stanie rozwiązać naszych problemów.

Głównym problemem było to, że testowane produkty bazowały na źródłach danych, wyświetlały statystyki miejsc docelowych według witryn i nie zapewniały możliwości agregowania statystyk dotyczących kampanii reklamowych. Takie podejście nie pozwoliło nam zobaczyć statystyk z różnych serwisów w jednym miejscu i przeanalizować stanu kampanii jako całości.

Kolejnym czynnikiem było to, że na początkowych etapach produkty były skierowane na rynek zachodni i nie wspierały integracji z rosyjskimi zakładami. A w przypadku tych witryn, z którymi wdrożono integrację, nie zawsze wszystkie niezbędne metryki były pobierane z wystarczającą szczegółowością, a integracja nie zawsze była wygodna i przejrzysta, szczególnie gdy trzeba było uzyskać coś, czego nie ma w interfejsie systemu.
Ogólnie rzecz biorąc, postanowiliśmy nie dostosowywać się do produktów innych firm, ale zaczęliśmy opracowywać własne...

2. Rynek reklamy internetowej rośnie z roku na rok i w 2018 roku pod względem budżetów reklamowych wyprzedził tradycyjnie największy rynek reklamy telewizyjnej. Zatem istnieje skala.

3. W odróżnieniu od rynku reklamy telewizyjnej, gdzie sprzedaż reklamy komercyjnej jest zmonopolizowana, w Internecie działa wielu indywidualnych właścicieli zasobów reklamowych różnej wielkości, posiadających własne konta reklamowe. Ponieważ kampania reklamowa z reguły odbywa się w kilku witrynach jednocześnie, aby zrozumieć stan kampanii reklamowej, konieczne jest zebranie raportów ze wszystkich witryn i połączenie ich w jeden duży raport, który pokaże cały obraz. Oznacza to, że istnieje potencjał optymalizacji.

4. Wydawało nam się, że właściciele zasobów reklamowych w Internecie posiadają już infrastrukturę do gromadzenia statystyk i wyświetlania ich na kontach reklamowych oraz będą mogli udostępnić API dla tych danych. Oznacza to, że technicznie możliwe jest jego wdrożenie. Od razu powiedzmy, że okazało się, że nie jest to takie proste.

Generalnie wszystkie przesłanki do realizacji projektu były dla nas oczywiste i pobiegliśmy powołać projekt do życia...

Wielki Plan

Na początek stworzyliśmy wizję idealnego systemu:

  • Kampanie reklamowe z systemu korporacyjnego 1C powinny być do niego automatycznie ładowane wraz z ich nazwami, okresami, budżetami i miejscami docelowymi na różnych platformach.
  • Dla każdego miejsca docelowego w ramach kampanii reklamowej powinny zostać automatycznie pobrane wszystkie możliwe statystyki ze stron, w których odbywa się umiejscowienie, takie jak liczba wyświetleń, kliknięć, wyświetleń itp.
  • Niektóre kampanie reklamowe są śledzone za pomocą monitoringu stron trzecich przez tak zwane systemy reklamowe, takie jak Adriver, Weborama, DCM itp. W Rosji istnieje również przemysłowy licznik internetowy - firma Mediascope. Zgodnie z naszym planem dane z niezależnego i przemysłowego monitoringu powinny być automatycznie ładowane również do odpowiednich kampanii reklamowych.
  • Większość kampanii reklamowych w Internecie nakierowana jest na określone działania docelowe (zakup, połączenie, zapisanie się na jazdę próbną itp.), które są śledzone za pomocą Google Analytics, a statystyki dla których są również ważne dla zrozumienia statusu kampanii i powinien zostać załadowany do naszego narzędzia.

Pierwszy naleśnik jest nierówny

Biorąc pod uwagę nasze przywiązanie do elastycznych zasad tworzenia oprogramowania (agile, wszystko), zdecydowaliśmy się najpierw opracować MVP, a następnie iteracyjnie zmierzać do zamierzonego celu.
Postanowiliśmy zbudować MVP w oparciu o nasz produkt DANBo (karta sieciowa Dentsu Aegis), czyli aplikacja internetowa zawierająca ogólne informacje na temat kampanii reklamowych naszych klientów.

Dla MVP projekt został maksymalnie uproszczony pod względem wykonawczym. Wybraliśmy ograniczoną listę platform do integracji. Były to główne platformy, takie jak Yandex.Direct, Yandex.Display, RB.Mail, MyTarget, Adwords, DBM, VK, FB oraz główne systemy reklamowe Adriver i Weborama.

Aby uzyskać dostęp do statystyk na stronach poprzez API, korzystaliśmy z jednego konta. Menedżer grupy klientów, który chciał skorzystać z automatycznego zbierania statystyk dotyczących kampanii reklamowej, musiał najpierw delegować dostęp do niezbędnych kampanii reklamowych w serwisach do konta platformy.

Następny jest użytkownik systemu DANBo musiał załadować plik w określonym formacie do systemu Excel, który zawierał wszystkie informacje na temat miejsca docelowego (kampania reklamowa, platforma, format, okres umieszczenia, planowane wskaźniki, budżet itp.) oraz identyfikatory odpowiednich kampanii reklamowych na stronie witryny i liczniki w systemach reklamowych.

Szczerze mówiąc, wyglądało to przerażająco:

Jak zbieraliśmy dane o kampaniach reklamowych ze stron internetowych (ciernna droga do produktu)

Pobrane dane zostały zapisane w bazie danych, a następnie osobne serwisy pobrały z nich identyfikatory kampanii w witrynach i pobrały na ich temat statystyki.

Dla każdej witryny napisano osobną usługę Windows, która raz dziennie trafiała pod jedno konto usługi w API serwisu i pobierała statystyki dla określonych identyfikatorów kampanii. To samo stało się z systemami reklamowymi.

Pobrane dane zostały wyświetlone na interfejsie w formie małego, niestandardowego dashboardu:

Jak zbieraliśmy dane o kampaniach reklamowych ze stron internetowych (ciernna droga do produktu)

Niespodziewanie dla nas MVP zabrał się do pracy i zaczął pobierać aktualne statystyki dotyczące kampanii reklamowych w Internecie. Wdrożyliśmy system u kilku klientów, jednak przy próbie skalowania napotkaliśmy poważne problemy:

  • Głównym problemem była złożoność przygotowania danych do załadowania do systemu. Ponadto przed załadowaniem dane dotyczące miejsc docelowych musiały zostać przekonwertowane do ściśle określonego formatu. W pobieranym pliku konieczne było uwzględnienie identyfikatorów podmiotów z różnych serwisów. Mamy do czynienia z faktem, że nieprzeszkolonym technicznie użytkownikom bardzo trudno jest wyjaśnić, gdzie w serwisie znaleźć te identyfikatory i gdzie w pliku należy je wprowadzić. Biorąc pod uwagę liczbę pracowników działów prowadzących kampanie na stronach oraz obroty, przełożyło się to na ogromne wsparcie z naszej strony, z czego absolutnie nie byliśmy zadowoleni.
  • Kolejnym problemem było to, że nie wszystkie platformy reklamowe posiadały mechanizmy delegowania dostępu do kampanii reklamowych na inne konta. Jednak nawet gdyby dostępny był mechanizm delegowania uprawnień, nie wszyscy reklamodawcy byliby skłonni przyznać dostęp do swoich kampanii kontom osób trzecich.
  • Ważnym czynnikiem było oburzenie, które wzbudziło wśród użytkowników fakt, że wszystkie planowane wskaźniki i szczegóły rozmieszczenia, które już wprowadzają do naszego systemu księgowego 1C, muszą ponownie wejść DANBo.

To nasunęło nam pomysł, że podstawowym źródłem informacji o umiejscowieniu powinien być nasz system 1C, do którego wszystkie dane są wprowadzane dokładnie i na czas (chodzi o to, że faktury generowane są na podstawie danych 1C, więc prawidłowe wprowadzanie danych do 1C jest priorytetem dla wszystkich KPI). Tak powstała nowa koncepcja systemu...

Koncepcja

Pierwszą rzeczą, na którą zdecydowaliśmy się, było wydzielenie systemu zbierania statystyk dotyczących kampanii reklamowych w Internecie do osobnego produktu - D1.Cyfrowy.

W nowej koncepcji postanowiliśmy załadować do D1.Cyfrowy informacje o kampaniach reklamowych i miejscach docelowych w nich z 1C, a następnie pobierają statystyki z witryn i systemów AdServing dla tych miejsc docelowych. Miało to znacząco ułatwić życie użytkownikom (i jak zwykle przysporzyć więcej pracy programistom) oraz zmniejszyć wysokość wsparcia.

Pierwszy problem, jaki napotkaliśmy, miał charakter organizacyjny i wiązał się z tym, że nie mogliśmy znaleźć klucza ani znaku, za pomocą którego moglibyśmy porównać podmioty z różnych systemów z kampaniami i miejscami docelowymi z 1C. Faktem jest, że proces w naszej firmie jest zaprojektowany w taki sposób, że kampanie reklamowe wprowadzane są do różnych systemów przez różne osoby (media planiści, kupcy itp.).

Aby rozwiązać ten problem, musieliśmy wymyślić unikalny klucz skrótu, DANBoID, który łączyłby ze sobą podmioty w różnych systemach i który można by dość łatwo i jednoznacznie zidentyfikować w pobranych zbiorach danych. Identyfikator ten jest generowany w wewnętrznym systemie 1C dla każdego pojedynczego miejsca docelowego i przesyłany do kampanii, miejsc docelowych i liczników we wszystkich witrynach i we wszystkich systemach AdServing. Wdrożenie praktyki umieszczania DANBoID we wszystkich lokalizacjach zajęło trochę czasu, ale udało się :)

Następnie dowiedzieliśmy się, że nie wszystkie strony posiadają API do automatycznego zbierania statystyk, a nawet te, które posiadają API, nie zwracają one wszystkich niezbędnych danych.

Na tym etapie postanowiliśmy znacząco zawęzić listę platform do integracji i skupić się na głównych platformach, które biorą udział w zdecydowanej większości kampanii reklamowych. Ta lista obejmuje wszystkich największych graczy na rynku reklamowym (Google, Yandex, Mail.ru), sieci społecznościowych (VK, Facebook, Twitter), głównych systemów AdServing i analitycznych (DCM, Adriver, Weborama, Google Analytics) i innych platform.

Większość wybranych przez nas witryn posiadała interfejs API zapewniający potrzebne dane. W przypadkach, gdy nie było API lub nie zawierało ono niezbędnych danych, w celu wczytania danych korzystaliśmy z raportów przesyłanych codziennie na nasz biurowy adres e-mail (w niektórych systemach istnieje możliwość konfiguracji takich raportów, w innych uzgodniliśmy opracowanie takich raportów) dla nas).

Analizując dane z różnych serwisów odkryliśmy, że hierarchia podmiotów nie jest taka sama w różnych systemach. Co więcej, informacje muszą być pobierane z różną szczegółowością z różnych systemów.

Aby rozwiązać ten problem, opracowano koncepcję SubDANBoID. Idea SubDANBoID jest dość prosta, oznaczamy na stronie główną encję kampanii wygenerowanym DANBoID, a wszystkie zagnieżdżone encje wgrywamy z unikalnymi identyfikatorami strony i tworzymy SubDANBoID zgodnie z zasadą DANBoID + identyfikator pierwszego poziomu jednostka zagnieżdżona + identyfikator jednostki zagnieżdżonej drugiego poziomu +... Takie podejście pozwoliło nam połączyć kampanie reklamowe w różnych systemach i pobrać szczegółowe statystyki na ich temat.

Musieliśmy także rozwiązać problem dostępu do kampanii na różnych platformach. Jak pisaliśmy powyżej, nie zawsze można zastosować mechanizm delegowania dostępu do kampanii na osobne konto techniczne. W związku z tym musieliśmy opracować infrastrukturę do automatycznej autoryzacji poprzez OAuth z wykorzystaniem tokenów oraz mechanizmy aktualizacji tych tokenów.

W dalszej części artykułu postaramy się opisać bardziej szczegółowo architekturę rozwiązania oraz szczegóły techniczne wdrożenia.

Architektura rozwiązania 1.0

Rozpoczynając wdrożenie nowego produktu, zrozumieliśmy, że od razu musimy zapewnić możliwość łączenia nowych witryn, dlatego zdecydowaliśmy się podążać ścieżką architektury mikroserwisowej.

Projektując architekturę, rozdzieliliśmy złącza do wszystkich systemów zewnętrznych - 1C, platform reklamowych i systemów reklamowych - na osobne usługi.
Główną ideą jest to, że wszystkie konektory do witryn mają ten sam interfejs API i są adapterami, które przenoszą interfejs API witryny do wygodnego dla nas interfejsu.

Sercem naszego produktu jest aplikacja internetowa, która stanowi monolit zaprojektowany w taki sposób, aby można go było łatwo rozłożyć na usługi. Aplikacja ta odpowiada za przetwarzanie pobranych danych, zestawianie statystyk z różnych systemów i prezentowanie ich użytkownikom systemu.

Aby komunikować się pomiędzy konektorami a aplikacją webową, musieliśmy stworzyć dodatkową usługę, którą nazwaliśmy Connector Proxy. Realizuje funkcje Service Discovery i Task Scheduler. Ta usługa uruchamia zadania gromadzenia danych dla każdego łącznika każdej nocy. Napisanie warstwy usług było prostsze niż podłączenie brokera komunikatów, a dla nas ważne było, aby wynik uzyskać jak najszybciej.

Dla prostoty i szybkości rozwoju zdecydowaliśmy również, że wszystkie usługi będą Web API. Umożliwiło to szybkie zmontowanie proof-of-concept i sprawdzenie, czy cały projekt działa.

Jak zbieraliśmy dane o kampaniach reklamowych ze stron internetowych (ciernna droga do produktu)

Osobnym, dość złożonym zadaniem było ustawienie dostępu umożliwiającego zbieranie danych z różnych kont, co – jak uznaliśmy – powinno być realizowane przez użytkowników poprzez interfejs WWW. Składa się z dwóch odrębnych kroków: najpierw użytkownik dodaje token umożliwiający dostęp do konta poprzez OAuth, a następnie konfiguruje zbieranie danych dla klienta z konkretnego konta. Uzyskanie tokena poprzez OAuth jest konieczne, gdyż jak już pisaliśmy, nie zawsze da się delegować dostęp do wybranego konta w serwisie.

Aby stworzyć uniwersalny mechanizm wybierania konta z serwisów, musieliśmy dodać do API konektorów metodę zwracającą JSON Schema, która jest renderowana do postaci przy użyciu zmodyfikowanego komponentu JSONEditor. W ten sposób użytkownicy mogli wybrać konta, z których będą pobierać dane.

Aby zachować zgodność z limitami żądań obowiązującymi na stronach, łączymy żądania ustawień w ramach jednego tokena, ale możemy przetwarzać różne tokeny równolegle.

Wybraliśmy MongoDB jako magazyn załadowanych danych zarówno dla aplikacji webowej, jak i konektorów, co pozwoliło nam nie martwić się zbytnio strukturą danych na początkowych etapach rozwoju, kiedy model obiektowy aplikacji zmienia się co drugi dzień.

Szybko przekonaliśmy się, że nie wszystkie dane dobrze mieszczą się w MongoDB i np. wygodniej jest przechowywać dzienne statystyki w relacyjnej bazie danych. Dlatego w przypadku konektorów, których struktura danych jest bardziej odpowiednia dla relacyjnej bazy danych, zaczęliśmy używać PostgreSQL lub MS SQL Server jako magazynu.

Wybrana architektura i technologie pozwoliły nam stosunkowo szybko zbudować i uruchomić produkt D1.Digital. W ciągu dwóch lat rozwoju produktu opracowaliśmy 23 konektory do stron, zdobyliśmy bezcenne doświadczenie w pracy z API stron trzecich, nauczyliśmy się unikać pułapek różnych stron, z których każda miała swoją, przyczyniliśmy się do rozwoju API co najmniej 3 witryn, automatycznie pobrał informacje na temat prawie 15 000 kampanii i ponad 80 000 miejsc docelowych, zebrał wiele informacji zwrotnych od użytkowników na temat działania produktu i na podstawie tych informacji udało mu się kilkukrotnie zmienić główny proces produktu.

Architektura rozwiązania 2.0

Od rozpoczęcia prac minęły dwa lata D1.Cyfrowy. Stały wzrost obciążenia systemu i pojawianie się coraz większej liczby nowych źródeł danych stopniowo ukazywały problemy w istniejącej architekturze rozwiązania.

Pierwszy problem związany jest z ilością danych pobieranych ze stron. Stanęliśmy przed faktem, że zbieranie i aktualizacja wszystkich niezbędnych danych z największych serwisów zaczęło zajmować zbyt dużo czasu. Przykładowo zebranie danych z systemu reklamowego AdRiver, za pomocą którego śledzimy statystyki dla większości miejsc docelowych, zajmuje około 12 godzin.

Aby rozwiązać ten problem zaczęliśmy wykorzystywać wszelkiego rodzaju raporty do pobierania danych z serwisów, staramy się wspólnie z serwisami rozwijać ich API tak, aby szybkość jego działania odpowiadała naszym potrzebom, a pobieranie danych było jak najbardziej zrównoleglone.

Kolejny problem dotyczy przetwarzania pobranych danych. Teraz, gdy pojawią się nowe statystyki dotyczące miejsc docelowych, rozpoczyna się wieloetapowy proces ponownego obliczania wskaźników, który obejmuje ładowanie surowych danych, obliczanie zagregowanych wskaźników dla każdej witryny, porównywanie ze sobą danych z różnych źródeł i obliczanie podsumowujących wskaźników dla kampanii. Powoduje to duże obciążenie aplikacji internetowej, która wykonuje wszystkie obliczenia. Kilkukrotnie podczas procesu przeliczania aplikacja zużywała całą pamięć serwera, około 10-15 GB, co najbardziej negatywnie wpływało na pracę użytkowników z systemem.

Zidentyfikowane problemy i ambitne plany dalszego rozwoju produktu skłoniły nas do konieczności ponownego przemyślenia architektury aplikacji.

Zaczęliśmy od złączy.
Zauważyliśmy, że wszystkie konektory działają według tego samego modelu, dlatego zbudowaliśmy framework potokowy, w którym aby stworzyć konektor wystarczyło zaprogramować logikę kroków, reszta była uniwersalna. Jeśli konektor wymaga ulepszenia, to natychmiast przenosimy go na nowy framework w tym samym czasie, gdy konektor jest udoskonalany.

W tym samym czasie rozpoczęliśmy wdrażanie konektorów do Dockera i Kubernetesa.
Przeprowadzkę na Kubernetes planowaliśmy dość długo, eksperymentowaliśmy z ustawieniami CI/CD, ale ruszyliśmy dopiero, gdy jedno złącze przez błąd zaczęło zjadać ponad 20 GB pamięci na serwerze, praktycznie zabijając inne procesy . W trakcie dochodzenia łącznik został przeniesiony do klastra Kubernetes, gdzie ostatecznie pozostał, nawet po naprawieniu błędu.

Dość szybko zdaliśmy sobie sprawę, że Kubernetes jest wygodny i w ciągu sześciu miesięcy przenieśliśmy do klastra produkcyjnego 7 konektorów i Connectors Proxy, które zużywają najwięcej zasobów.

Idąc za złączami, postanowiliśmy zmienić architekturę reszty aplikacji.
Główny problem polegał na tym, że dane docierają ze złączy do serwerów proxy w dużych partiach, a następnie trafiają do DANBoID i są wysyłane do centralnej aplikacji internetowej w celu przetworzenia. Ze względu na dużą liczbę przeliczeń metryk, aplikacja jest bardzo obciążona.

Dość trudne okazało się także monitorowanie statusu poszczególnych zadań gromadzenia danych i raportowanie błędów występujących w konektorach do centralnej aplikacji internetowej, aby użytkownicy mogli zobaczyć, co się dzieje i dlaczego dane nie są zbierane.

Aby rozwiązać te problemy, opracowaliśmy architekturę 2.0.

Główna różnica pomiędzy nową wersją architektury polega na tym, że zamiast Web API do wymiany komunikatów pomiędzy usługami wykorzystujemy RabbitMQ oraz bibliotekę MassTransit. Aby to zrobić, musieliśmy prawie całkowicie przepisać Connectors Proxy, tworząc z niego Connectors Hub. Nazwa została zmieniona, ponieważ główna rola usługi nie polega już na przekazywaniu żądań do konektorów i z powrotem, ale na zarządzaniu zbieraniem metryk z konektorów.

Z centralnej aplikacji webowej wydzieliliśmy informacje o miejscach docelowych i statystyki z serwisów na osobne usługi, co pozwoliło pozbyć się niepotrzebnych przeliczeń i przechowywać na poziomie miejsca docelowego jedynie już wyliczone i zagregowane statystyki. Przepisaliśmy także i zoptymalizowaliśmy logikę obliczania podstawowych statystyk na podstawie surowych danych.

Jednocześnie migrujemy wszystkie usługi i aplikacje do Dockera i Kubernetesa, aby rozwiązanie było łatwiejsze w skalowaniu i wygodniejsze w zarządzaniu.

Jak zbieraliśmy dane o kampaniach reklamowych ze stron internetowych (ciernna droga do produktu)

Gdzie teraz jesteśmy

Produkt oparty na architekturze 2.0 stanowiącej dowód koncepcji D1.Cyfrowy gotowy i działający w środowisku testowym z ograniczonym zestawem złączy. Wszystko, co pozostało do zrobienia, to przepisać kolejnych 20 konektorów na nową platformę, sprawdzić, czy dane są poprawnie załadowane i czy wszystkie metryki są poprawnie obliczone, a następnie wdrożyć cały projekt do produkcji.

W rzeczywistości proces ten będzie przebiegał stopniowo i będziemy musieli porzucić kompatybilność wsteczną ze starymi interfejsami API, aby wszystko działało.

Nasze najbliższe plany obejmują rozwój nowych konektorów, integrację z nowymi systemami oraz dodanie dodatkowych metryk do zbioru danych pobieranych z podłączonych witryn i systemów reklamowych.

Planujemy także przeniesienie wszystkich aplikacji, w tym centralnej aplikacji webowej, do Dockera i Kubernetesa. W połączeniu z nową architekturą znacznie uprości to wdrażanie, monitorowanie i kontrolę zużywanych zasobów.

Innym pomysłem jest poeksperymentowanie z wyborem bazy danych do przechowywania statystyk, która obecnie przechowywana jest w MongoDB. Przenieśliśmy już kilka nowych konektorów do baz SQL, ale tam różnica jest prawie niezauważalna, a w przypadku statystyk zagregowanych w dzień, których można żądać za dowolny okres, zysk może być całkiem poważny.

Ogólnie plany są imponujące, przejdźmy dalej :)

Autorzy artykułu R&D Dentsu Aegis Network Rosja: Georgy Ostapenko (shmiigaa), Michaił Kotsik (hitex)

Źródło: www.habr.com

Dodaj komentarz