Hvordan vi samlet inn data om reklamekampanjer fra nettsider (den vanskelige veien til produktet)

Det ser ut til at feltet for nettannonsering bør være så teknologisk avansert og automatisert som mulig. Selvfølgelig, fordi slike giganter og eksperter på sitt felt som Yandex, Mail.Ru, Google og Facebook jobber der. Men, som det viste seg, er det ingen grense for perfeksjon, og det er alltid noe å automatisere.

Hvordan vi samlet inn data om reklamekampanjer fra nettsider (den vanskelige veien til produktet)
Kilde

Kommunikasjonsgruppe Dentsu Aegis Network Russland er den største aktøren i det digitale annonsemarkedet og investerer aktivt i teknologi, prøver å optimalisere og automatisere forretningsprosessene. Et av de uløste problemene med nettannonseringsmarkedet er oppgaven med å samle inn statistikk over reklamekampanjer fra forskjellige internettplattformer. Løsningen på dette problemet resulterte til slutt i opprettelsen av et produkt D1.Digital (lest som DiVan), utviklingen som vi ønsker å snakke om.

Hvorfor?

1. På tidspunktet for oppstart av prosjektet var det ikke et eneste ferdig produkt på markedet som løste problemet med å automatisere innsamlingen av statistikk om annonsekampanjer. Dette betyr at ingen unntatt oss selv vil møte våre behov.

Tjenester som Improvado, Roistat, Supermetrics, SegmentStream tilbyr integrasjon med plattformer, sosiale nettverk og Google Analitycs, og gjør det også mulig å bygge analytiske dashboards for praktisk analyse og kontroll av annonsekampanjer. Før vi begynte å utvikle produktet vårt, prøvde vi å bruke noen av disse systemene til å samle inn data fra nettsteder, men de kunne dessverre ikke løse problemene våre.

Hovedproblemet var at de testede produktene var basert på datakilder, viste plasseringsstatistikk etter nettsted, og ga ikke muligheten til å samle statistikk om annonsekampanjer. Denne tilnærmingen tillot oss ikke å se statistikk fra forskjellige nettsteder på ett sted og analysere statusen til kampanjen som helhet.

En annen faktor var at produktene i de innledende stadiene var rettet mot det vestlige markedet og ikke støttet integrasjon med russiske nettsteder. Og for de nettstedene som integrasjon ble implementert med, ble ikke alle nødvendige beregninger alltid lastet ned med tilstrekkelig detaljer, og integrasjonen var ikke alltid praktisk og gjennomsiktig, spesielt når det var nødvendig å få noe som ikke er i systemgrensesnittet.
Generelt bestemte vi oss for ikke å tilpasse oss tredjepartsprodukter, men begynte å utvikle våre egne...

2. Annonsemarkedet på nett vokser fra år til år, og i 2018 passerte det i form av annonsebudsjetter det tradisjonelt største TV-reklamemarkedet. Så det er en skala.

3. I motsetning til TV-reklamemarkedet, hvor salget av kommersiell reklame er monopolisert, er det mange individuelle eiere av annonsebeholdning av ulike størrelser som opererer på Internett med sine egne reklamekontoer. Siden en reklamekampanje som regel kjører på flere nettsteder samtidig, for å forstå statusen til reklamekampanjen, er det nødvendig å samle rapporter fra alle nettsteder og kombinere dem til en stor rapport som viser hele bildet. Dette betyr at det er potensial for optimalisering.

4. Det virket for oss at eierne av annonsebeholdning på Internett allerede har infrastrukturen for å samle inn statistikk og vise dem i reklamekontoer, og de vil kunne gi en API for disse dataene. Dette betyr at det er teknisk mulig å implementere det. La oss si med en gang at det viste seg ikke å være så enkelt.

Generelt var alle forutsetninger for gjennomføringen av prosjektet åpenbare for oss, og vi løp for å bringe prosjektet ut i livet...

Stor plan

Til å begynne med dannet vi en visjon om et ideelt system:

  • Annonsekampanjer fra 1C-bedriftssystemet skal automatisk lastes inn i det med navn, perioder, budsjetter og plasseringer på ulike plattformer.
  • For hver plassering i en reklamekampanje skal all mulig statistikk lastes ned automatisk fra nettstedene der plasseringen finner sted, for eksempel antall visninger, klikk, visninger osv.
  • Noen annonsekampanjer spores ved hjelp av tredjepartsovervåking av såkalte adserving-systemer som Adriver, Weborama, DCM, etc. Det er også en industriell internettmåler i Russland - Mediascope-selskapet. Ifølge planen vår skal data fra uavhengig og industriell overvåking også automatisk lastes inn i de tilsvarende reklamekampanjene.
  • De fleste annonsekampanjer på Internett er rettet mot bestemte målhandlinger (kjøp, ring, registrer deg for en prøvekjøring osv.), som spores ved hjelp av Google Analytics, og statistikk som også er viktig for å forstå statusen til kampanjen og skal lastes inn i verktøyet vårt.

Den første pannekake er klumpete

Gitt vår forpliktelse til fleksible prinsipper for programvareutvikling (smidig, alle ting), bestemte vi oss for først å utvikle en MVP og deretter gå mot det tiltenkte målet iterativt.
Vi bestemte oss for å bygge MVP basert på produktet vårt DANBo (Dentsu Aegis Network Board), som er en nettapplikasjon med generell informasjon om våre kunders annonsekampanjer.

For MVP ble prosjektet forenklet så mye som mulig med tanke på gjennomføring. Vi har valgt en begrenset liste over plattformer for integrering. Dette var hovedplattformene, som Yandex.Direct, Yandex.Display, RB.Mail, MyTarget, Adwords, DBM, VK, FB, og de viktigste annonsesystemene Adriver og Weborama.

For å få tilgang til statistikk på nettsteder via API, brukte vi én enkelt konto. En kundegruppeleder som ønsket å bruke automatisk innsamling av statistikk på en annonsekampanje, måtte først delegere tilgang til nødvendige annonsekampanjer på nettsteder til plattformkontoen.

Neste er systembrukeren DANBo måtte laste opp en fil av et bestemt format til Excel-systemet, som inneholdt all informasjon om plasseringen (reklamekampanje, plattform, format, plasseringsperiode, planlagte indikatorer, budsjett osv.) og identifikatorer for de tilsvarende annonsekampanjene på nettsteder og tellere i annonsesystemer.

Det så ærlig talt skremmende ut:

Hvordan vi samlet inn data om reklamekampanjer fra nettsider (den vanskelige veien til produktet)

De nedlastede dataene ble lagret i en database, og deretter samlet separate tjenester inn kampanjeidentifikatorer på nettsteder fra dem og lastet ned statistikk om dem.

For hvert nettsted ble det skrevet en egen Windows-tjeneste, som én gang om dagen gikk inn under én tjenestekonto i nettstedets API og lastet ned statistikk for spesifiserte kampanje-IDer. Det samme skjedde med annonsesystemer.

De nedlastede dataene ble vist på grensesnittet i form av et lite tilpasset dashbord:

Hvordan vi samlet inn data om reklamekampanjer fra nettsider (den vanskelige veien til produktet)

Uventet for oss begynte MVP å jobbe og begynte å laste ned gjeldende statistikk om reklamekampanjer på Internett. Vi implementerte systemet på flere klienter, men da vi prøvde å skalere, møtte vi alvorlige problemer:

  • Hovedproblemet var kompleksiteten ved å forberede data for lasting inn i systemet. Også plasseringsdataene måtte konverteres til et strengt fast format før lasting. Det var nødvendig å inkludere enhetsidentifikatorer fra forskjellige nettsteder i nedlastingsfilen. Vi står overfor det faktum at det er svært vanskelig for teknisk utrente brukere å forklare hvor man finner disse identifikatorene på siden og hvor i filen de må legges inn. Med tanke på antall ansatte i avdelingene som kjører kampanjer på nettsteder og omsetning, resulterte dette i en enorm støtte fra vår side, som vi absolutt ikke var fornøyd med.
  • Et annet problem var at ikke alle annonseplattformer hadde mekanismer for å delegere tilgang til annonsekampanjer til andre kontoer. Men selv om en delegeringsmekanisme var tilgjengelig, var ikke alle annonsører villige til å gi tilgang til kampanjene sine til tredjepartskontoer.
  • En viktig faktor var indignasjonen som vekket blant brukerne ved at alle de planlagte indikatorene og plasseringsdetaljene som de allerede legger inn i vårt 1C regnskapssystem, må de legge inn på nytt. DANBo.

Dette ga oss ideen om at den primære informasjonskilden om plassering skulle være vårt 1C-system, der alle data legges inn nøyaktig og i tide (poenget her er at fakturaer genereres basert på 1C-data, så korrekt inntasting av data i 1C er en prioritet for alle KPI). Slik oppsto et nytt konsept av systemet...

Konseptet

Det første vi bestemte oss for å gjøre var å skille systemet for innsamling av statistikk om annonsekampanjer på Internett i et eget produkt - D1.Digital.

I det nye konseptet bestemte vi oss for å laste inn D1.Digital informasjon om annonsekampanjer og plasseringer i dem fra 1C, og deretter hente statistikk fra nettsteder og annonseserveringssystemer til disse plasseringene. Dette skulle betydelig forenkle livet for brukere (og, som vanlig, legge til mer arbeid til utviklere) og redusere mengden støtte.

Det første problemet vi møtte var av organisatorisk karakter og var knyttet til at vi ikke kunne finne en nøkkel eller et tegn som vi kunne sammenligne enheter fra ulike systemer med kampanjer og plasseringer fra 1C med. Faktum er at prosessen i vårt selskap er utformet på en slik måte at reklamekampanjer legges inn i forskjellige systemer av forskjellige personer (medieplanleggere, kjøp osv.).

For å løse dette problemet måtte vi finne opp en unik hashed-nøkkel, DANBoID, som kunne koble enheter i forskjellige systemer sammen, og som kunne identifiseres ganske enkelt og unikt i nedlastede datasett. Denne identifikatoren genereres i det interne 1C-systemet for hver enkelt plassering og overføres til kampanjer, plasseringer og tellere på alle nettsteder og i alle AdServing-systemer. Det tok litt tid å implementere praksisen med å sette DANBoID i alle plasseringer, men vi klarte det :)

Så fant vi ut at ikke alle nettsteder har et API for automatisk innsamling av statistikk, og selv de som har et API, returnerer ikke alle nødvendige data.

På dette stadiet bestemte vi oss for å redusere listen over plattformer for integrering betydelig og fokusere på hovedplattformene som er involvert i de aller fleste reklamekampanjer. Denne listen inkluderer alle de største aktørene i annonsemarkedet (Google, Yandex, Mail.ru), sosiale nettverk (VK, Facebook, Twitter), store AdServing og analysesystemer (DCM, Adriver, Weborama, Google Analytics) og andre plattformer.

De fleste nettstedene vi valgte hadde et API som ga beregningene vi trengte. I tilfeller der det ikke var noen API eller det ikke inneholdt nødvendige data, brukte vi rapporter sendt daglig til kontorets e-post for å laste inn data (i noen systemer er det mulig å konfigurere slike rapporter, i andre ble vi enige om utviklingen av slike rapporter for oss).

Når vi analyserte data fra forskjellige nettsteder, fant vi ut at hierarkiet av enheter ikke er det samme i forskjellige systemer. Dessuten må informasjon lastes ned i forskjellige detaljer fra forskjellige systemer.

For å løse dette problemet ble SubDANBoID-konseptet utviklet. Ideen til SubDANBoID er ganske enkel, vi merker hovedenheten til kampanjen på nettstedet med den genererte DANBoID, og ​​vi laster opp alle nestede enheter med unike nettstedidentifikatorer og danner SubDANBoID i henhold til DANBoID-prinsippet + identifikator på første nivå nestet enhet + identifikator for den nestede enheten på andre nivå +... Denne tilnærmingen tillot oss å koble sammen reklamekampanjer i forskjellige systemer og laste ned detaljert statistikk om dem.

Vi måtte også løse problemet med tilgang til kampanjer på forskjellige plattformer. Som vi skrev ovenfor, er mekanismen for å delegere tilgang til en kampanje til en separat teknisk konto ikke alltid aktuelt. Derfor måtte vi utvikle en infrastruktur for automatisk autorisasjon via OAuth ved bruk av tokens og mekanismer for oppdatering av disse tokenene.

Senere i artikkelen vil vi prøve å beskrive mer detaljert arkitekturen til løsningen og de tekniske detaljene for implementeringen.

Løsningsarkitektur 1.0

Da vi startet implementeringen av et nytt produkt, forsto vi at vi umiddelbart måtte sørge for muligheten for å koble til nye nettsteder, så vi bestemte oss for å følge veien til mikrotjenestearkitektur.

Ved utformingen av arkitekturen delte vi koblinger til alle eksterne systemer – 1C, annonseplattformer og annonsesystemer – i separate tjenester.
Hovedideen er at alle koblinger til nettsteder har samme API og er adaptere som bringer nettstedets API til et grensesnitt som er praktisk for oss.

I sentrum av produktet vårt er en webapplikasjon, som er en monolitt som er utformet på en slik måte at den enkelt kan demonteres til tjenester. Denne applikasjonen er ansvarlig for å behandle de nedlastede dataene, samle statistikk fra forskjellige systemer og presentere dem for systembrukere.

For å kommunisere mellom koblingene og nettapplikasjonen, måtte vi opprette en tilleggstjeneste, som vi kalte Connector Proxy. Den utfører funksjonene til Service Discovery og Task Scheduler. Denne tjenesten kjører datainnsamlingsoppgaver for hver kobling hver natt. Å skrive et servicelag var enklere enn å koble til en meldingsmegler, og for oss var det viktig å få resultatet så raskt som mulig.

For enkelhets skyld og utviklingshastighet bestemte vi oss også for at alle tjenester skal være web-APIer. Dette gjorde det mulig å raskt sette sammen et proof-of-concept og verifisere at hele designet fungerer.

Hvordan vi samlet inn data om reklamekampanjer fra nettsider (den vanskelige veien til produktet)

En egen, ganske kompleks oppgave var å sette opp tilgang til å samle inn data fra forskjellige kontoer, som, som vi bestemte, skulle utføres av brukere gjennom webgrensesnittet. Den består av to separate trinn: først legger brukeren til et token for å få tilgang til kontoen via OAuth, og konfigurerer deretter innsamlingen av data for klienten fra en spesifikk konto. Å skaffe et token via OAuth er nødvendig fordi, som vi allerede har skrevet, er det ikke alltid mulig å delegere tilgang til ønsket konto på nettstedet.

For å lage en universell mekanisme for å velge en konto fra nettsteder, måtte vi legge til en metode til connectors API som returnerer JSON Schema, som gjengis til et skjema ved hjelp av en modifisert JSONEditor-komponent. På denne måten kunne brukerne velge kontoene de skulle laste ned data fra.

For å overholde forespørselsgrensene som finnes på nettsteder, kombinerer vi forespørsler om innstillinger innenfor ett token, men vi kan behandle forskjellige tokens parallelt.

Vi valgte MongoDB som lagring for innlastede data for både webapplikasjonen og koblingene, noe som gjorde at vi ikke kunne bekymre oss for mye om datastrukturen i de innledende stadiene av utviklingen, når objektmodellen til applikasjonen endres annenhver dag.

Vi fant fort ut at ikke alle data passer godt i MongoDB, og for eksempel er det mer praktisk å lagre daglig statistikk i en relasjonsdatabase. Derfor, for koblinger hvis datastruktur er mer egnet for en relasjonsdatabase, begynte vi å bruke PostgreSQL eller MS SQL Server som lagring.

Den valgte arkitekturen og teknologiene tillot oss å bygge og lansere D1.Digital-produktet relativt raskt. I løpet av to år med produktutvikling utviklet vi 23 koblinger til nettsteder, fikk uvurderlig erfaring med å jobbe med tredjeparts APIer, lærte å unngå fallgruvene til forskjellige nettsteder, som hver hadde sine egne, bidro til utviklingen av API-en på minst 3 nettsteder, lastet automatisk ned informasjon om nesten 15 000 kampanjer og for mer enn 80 000 plasseringer, samlet inn mange tilbakemeldinger fra brukere om produktets drift og klarte å endre hovedprosessen til produktet flere ganger, basert på denne tilbakemeldingen.

Løsningsarkitektur 2.0

To år har gått siden utviklingen startet D1.Digital. Den konstante økningen i belastningen på systemet og fremveksten av flere og flere nye datakilder avslørte gradvis problemer i den eksisterende løsningsarkitekturen.

Det første problemet er relatert til mengden data som lastes ned fra nettstedene. Vi ble møtt med det faktum at innsamling og oppdatering av all nødvendig data fra de største nettstedene begynte å ta for mye tid. Innsamling av data fra AdRivers annonsesystem, som vi sporer statistikk for de fleste plasseringer med, tar for eksempel ca. 12 timer.

For å løse dette problemet begynte vi å bruke alle slags rapporter for å laste ned data fra nettsteder, vi prøver å utvikle deres API sammen med nettstedene slik at hastigheten på driften oppfyller våre behov, og parallellisere datanedlastingen så mye som mulig.

Et annet problem er knyttet til behandlingen av nedlastede data. Nå, når ny plasseringsstatistikk kommer, lanseres en flertrinns prosess med å beregne beregninger på nytt, som inkluderer innlasting av rådata, beregning av aggregerte beregninger for hvert nettsted, sammenligning av data fra forskjellige kilder med hverandre og beregning av sammendragsberegninger for kampanjen. Dette medfører mye belastning på nettapplikasjonen som gjør alle beregningene. Flere ganger, under omberegningsprosessen, forbrukte applikasjonen alt minnet på serveren, omtrent 10-15 GB, noe som hadde den mest skadelige effekten på brukernes arbeid med systemet.

De identifiserte problemene og ambisiøse planene for videreutvikling av produktet førte til at vi måtte revurdere applikasjonsarkitekturen.

Vi startet med koblinger.
Vi la merke til at alle koblinger fungerer i henhold til samme modell, så vi bygde et pipeline-rammeverk der du bare måtte programmere logikken i trinnene for å lage en kobling, resten var universell. Hvis en kobling krever forbedring, overfører vi den umiddelbart til et nytt rammeverk samtidig som koblingen forbedres.

Samtidig begynte vi å distribuere koblinger til Docker og Kubernetes.
Vi planla flyttingen til Kubernetes i ganske lang tid, eksperimenterte med CI/CD-innstillinger, men begynte å flytte bare da en kobling, på grunn av en feil, begynte å spise opp mer enn 20 GB minne på serveren, og praktisk talt drepte andre prosesser . Under etterforskningen ble koblingen flyttet til en Kubernetes-klynge, hvor den til slutt ble værende, selv etter at feilen ble rettet.

Ganske raskt innså vi at Kubernetes var praktisk, og innen seks måneder overførte vi 7 koblinger og Connectors Proxy, som bruker mest ressurser, til produksjonsklyngen.

Etter koblingene bestemte vi oss for å endre arkitekturen til resten av applikasjonen.
Hovedproblemet var at data kommer fra koblinger til proxyer i store partier, og deretter treffer DANBoID og sendes til den sentrale nettapplikasjonen for behandling. På grunn av det store antallet beregninger av beregninger, er det stor belastning på applikasjonen.

Det viste seg også å være ganske vanskelig å overvåke statusen til individuelle datainnsamlingsjobber og rapportere feil som oppsto i koblinger til en sentral webapplikasjon, slik at brukerne kunne se hva som skjedde og hvorfor data ikke ble samlet inn.

For å løse disse problemene utviklet vi arkitektur 2.0.

Hovedforskjellen mellom den nye versjonen av arkitekturen er at i stedet for Web API, bruker vi RabbitMQ og MassTransit-biblioteket til å utveksle meldinger mellom tjenester. For å gjøre dette måtte vi nesten fullstendig omskrive Connectors Proxy, slik at det ble Connectors Hub. Navnet ble endret fordi hovedrollen til tjenesten ikke lenger er å videresende forespørsler til koblinger og tilbake, men i å administrere innsamlingen av beregninger fra koblinger.

Fra den sentrale nettapplikasjonen skilte vi informasjon om plasseringer og statistikk fra nettsteder til separate tjenester, noe som gjorde det mulig å bli kvitt unødvendige omberegninger og kun lagre allerede beregnet og aggregert statistikk på plasseringsnivå. Vi har også omskrevet og optimalisert logikken for beregning av grunnleggende statistikk basert på rådata.

Samtidig migrerer vi alle tjenester og applikasjoner til Docker og Kubernetes for å gjøre løsningen enklere å skalere og mer praktisk å administrere.

Hvordan vi samlet inn data om reklamekampanjer fra nettsider (den vanskelige veien til produktet)

Hvor er vi nå

Proof-of-concept arkitektur 2.0-produkt D1.Digital klar og arbeider i et testmiljø med et begrenset sett med kontakter. Alt som gjenstår å gjøre er å omskrive ytterligere 20 koblinger til en ny plattform, teste at dataene er lastet inn riktig og alle beregninger er korrekt beregnet, og rulle ut hele designet til produksjon.

Faktisk vil denne prosessen skje gradvis, og vi må forlate bakoverkompatibilitet med gamle API-er for å holde alt fungerende.

Våre umiddelbare planer inkluderer utvikling av nye koblinger, integrasjon med nye systemer og å legge til ytterligere beregninger til settet med data som lastes ned fra tilkoblede nettsteder og annonsesystemer.

Vi planlegger også å overføre alle applikasjoner, inkludert den sentrale nettapplikasjonen, til Docker og Kubernetes. Kombinert med den nye arkitekturen vil dette betydelig forenkle distribusjon, overvåking og kontroll av forbrukte ressurser.

En annen idé er å eksperimentere med valg av database for lagring av statistikk, som for tiden er lagret i MongoDB. Vi har allerede overført flere nye koblinger til SQL-databaser, men der er forskjellen nesten umerkelig, og for aggregert statistikk per dag, som kan etterspørres for en vilkårlig periode, kan gevinsten være ganske alvorlig.

Generelt er planene grandiose, la oss gå videre :)

Forfattere av artikkelen R&D Dentsu Aegis Network Russland: Georgy Ostapenko (shmiigaa), Mikhail Kotsik (hitexx)

Kilde: www.habr.com

Legg til en kommentar