Come abbiamo raccolto i dati sulle campagne pubblicitarie dai siti online (il percorso spinoso verso il prodotto)

Sembra che il campo della pubblicità online debba essere il più tecnologicamente avanzato e automatizzato possibile. Certo, perché lì lavorano giganti ed esperti nel loro campo come Yandex, Mail.Ru, Google e Facebook. Ma, come si è scoperto, non c'è limite alla perfezione e c'è sempre qualcosa da automatizzare.

Come abbiamo raccolto i dati sulle campagne pubblicitarie dai siti online (il percorso spinoso verso il prodotto)
Fonte

Gruppo di comunicazione Dentsu Aegis Network Russia è il più grande attore nel mercato della pubblicità digitale e sta investendo attivamente nella tecnologia, cercando di ottimizzare e automatizzare i propri processi aziendali. Uno dei problemi irrisolti del mercato pubblicitario online è diventato il compito di raccogliere statistiche sulle campagne pubblicitarie da diverse piattaforme Internet. La soluzione a questo problema alla fine ha portato alla creazione di un prodotto D1.Digitale (leggi come DiVan), dello sviluppo di cui vogliamo parlare.

Perché?

1. Al momento dell'inizio del progetto, sul mercato non esisteva un solo prodotto già pronto che risolvesse il problema dell'automazione della raccolta di statistiche sulle campagne pubblicitarie. Ciò significa che nessuno tranne noi stessi soddisferà i nostri bisogni.

Servizi come Improvado, Roistat, Supermetrics, SegmentStream offrono l'integrazione con piattaforme, social network e Google Analitycs e consentono inoltre di creare dashboard analitici per un'analisi e un controllo convenienti delle campagne pubblicitarie. Prima di iniziare a sviluppare il nostro prodotto, abbiamo provato a utilizzare alcuni di questi sistemi per raccogliere dati dai siti, ma sfortunatamente non sono riusciti a risolvere i nostri problemi.

Il problema principale era che i prodotti testati si basavano su fonti di dati, visualizzavano statistiche di posizionamento per sito e non fornivano la possibilità di aggregare statistiche sulle campagne pubblicitarie. Questo approccio non ci ha permesso di vedere le statistiche di diversi siti in un unico posto e di analizzare lo stato della campagna nel suo complesso.

Un altro fattore è che nelle fasi iniziali i prodotti erano destinati al mercato occidentale e non supportavano l'integrazione con i siti russi. E per quei siti con cui è stata implementata l'integrazione, non sempre tutte le metriche necessarie sono state scaricate con sufficiente dettaglio, e l'integrazione non è stata sempre comoda e trasparente, soprattutto quando era necessario ottenere qualcosa che non si trovava nell'interfaccia del sistema.
In generale, abbiamo deciso di non adattarci ai prodotti di terze parti, ma abbiamo iniziato a sviluppare i nostri...

2. Il mercato della pubblicità online cresce di anno in anno e nel 2018, in termini di budget pubblicitari, ha superato il mercato pubblicitario televisivo tradizionalmente più grande. Quindi c'è una scala.

3. A differenza del mercato della pubblicità televisiva, dove la vendita della pubblicità commerciale è monopolizzata, su Internet operano numerosi proprietari individuali di spazi pubblicitari di varie dimensioni con i propri account pubblicitari. Poiché una campagna pubblicitaria, di norma, viene eseguita su più siti contemporaneamente, per comprendere lo stato della campagna pubblicitaria, è necessario raccogliere report da tutti i siti e combinarli in un unico report di grandi dimensioni che mostrerà l'intero quadro. Ciò significa che esiste un potenziale di ottimizzazione.

4. Ci è sembrato che i proprietari di spazi pubblicitari su Internet dispongano già dell'infrastruttura per raccogliere statistiche e visualizzarle negli account pubblicitari e saranno in grado di fornire un'API per questi dati. Ciò significa che è tecnicamente possibile implementarlo. Diciamo subito che non si è rivelato così semplice.

In generale, tutti i prerequisiti per la realizzazione del progetto erano ovvi per noi e abbiamo corso per dargli vita...

Grande piano

Per cominciare, abbiamo formulato una visione di un sistema ideale:

  • Le campagne pubblicitarie del sistema aziendale 1C dovrebbero essere caricate automaticamente al suo interno con i loro nomi, periodi, budget e posizionamenti su varie piattaforme.
  • Per ogni posizionamento all'interno di una campagna pubblicitaria, dai siti in cui avviene il posizionamento dovrebbero essere scaricate automaticamente tutte le statistiche possibili, come il numero di impressioni, clic, visualizzazioni, ecc.
  • Alcune campagne pubblicitarie vengono tracciate utilizzando il monitoraggio di terze parti da parte dei cosiddetti sistemi di adserving come Adriver, Weborama, DCM, ecc. C'è anche un contatore Internet industriale in Russia: la società Mediascope. Secondo il nostro piano, anche i dati del monitoraggio indipendente e industriale dovrebbero essere caricati automaticamente nelle corrispondenti campagne pubblicitarie.
  • La maggior parte delle campagne pubblicitarie su Internet sono mirate a determinate azioni target (acquisto, chiamata, iscrizione a un test drive, ecc.), che vengono monitorate utilizzando Google Analytics, e le cui statistiche sono importanti anche per comprendere lo stato della campagna e dovrebbe essere caricato nel nostro strumento .

La prima frittella è grumosa

Dato il nostro impegno nei confronti dei principi flessibili dello sviluppo software (agile, tutto), abbiamo deciso di sviluppare prima un MVP e poi di muoverci verso l'obiettivo prefissato in modo iterativo.
Abbiamo deciso di creare MVP in base al nostro prodotto DANBo (Consiglio della rete Dentsu Aegis), che è un'applicazione web con informazioni generali sulle campagne pubblicitarie dei nostri clienti.

Per MVP il progetto è stato semplificato il più possibile in termini di implementazione. Abbiamo selezionato un elenco limitato di piattaforme per l'integrazione. Queste erano le piattaforme principali, come Yandex.Direct, Yandex.Display, RB.Mail, MyTarget, Adwords, DBM, VK, FB e i principali sistemi di adserving Adriver e Weborama.

Per accedere alle statistiche sui siti tramite API, abbiamo utilizzato un unico account. Il manager di un gruppo di clienti che desiderava utilizzare la raccolta automatica di statistiche su una campagna pubblicitaria doveva prima delegare all'account della piattaforma l'accesso alle campagne pubblicitarie necessarie sui siti.

Il prossimo è l'utente del sistema DANBo doveva caricare nel sistema Excel un file di un determinato formato, che conteneva tutte le informazioni sul posizionamento (campagna pubblicitaria, piattaforma, formato, periodo di posizionamento, indicatori pianificati, budget, ecc.) e gli identificatori delle corrispondenti campagne pubblicitarie sul siti e contatori nei sistemi pubblicitari.

Sembrava, francamente, terrificante:

Come abbiamo raccolto i dati sulle campagne pubblicitarie dai siti online (il percorso spinoso verso il prodotto)

I dati scaricati venivano salvati in un database e quindi i servizi separati raccoglievano da essi gli identificatori delle campagne sui siti e scaricavano le statistiche su di essi.

Per ciascun sito è stato scritto un servizio Windows separato, che una volta al giorno passava sotto un account di servizio nell'API del sito e scaricava statistiche per gli ID campagna specificati. La stessa cosa è successa con i sistemi pubblicitari.

I dati scaricati venivano visualizzati sull'interfaccia sotto forma di una piccola dashboard personalizzata:

Come abbiamo raccolto i dati sulle campagne pubblicitarie dai siti online (il percorso spinoso verso il prodotto)

Inaspettatamente per noi, MVP ha iniziato a funzionare e ha iniziato a scaricare le statistiche attuali sulle campagne pubblicitarie su Internet. Abbiamo implementato il sistema su diversi client, ma durante il tentativo di scalabilità abbiamo riscontrato seri problemi:

  • Il problema principale era la complessità della preparazione dei dati per il caricamento nel sistema. Inoltre, i dati di posizionamento dovevano essere convertiti in un formato rigorosamente fisso prima del caricamento. Era necessario includere identificatori di entità provenienti da siti diversi nel file di download. Ci troviamo di fronte al fatto che è molto difficile per gli utenti tecnicamente inesperti spiegare dove trovare questi identificatori sul sito e dove devono essere inseriti nel file. Considerando il numero di dipendenti dei dipartimenti che conducono campagne sui siti e il fatturato, ciò si è tradotto in un enorme supporto da parte nostra, di cui non eravamo assolutamente soddisfatti.
  • Un altro problema era che non tutte le piattaforme pubblicitarie disponevano di meccanismi per delegare l’accesso alle campagne pubblicitarie ad altri account. Ma anche se fosse disponibile un meccanismo di delega, non tutti gli inserzionisti sarebbero disposti a concedere l’accesso alle loro campagne ad account di terze parti.
  • Un fattore importante è stata l'indignazione suscitata tra gli utenti per il fatto che tutti gli indicatori pianificati e i dettagli di posizionamento che già inseriscono nel nostro sistema contabile 1C, devono rientrare DANBo.

Questo ci ha dato l'idea che la fonte primaria di informazioni sul posizionamento dovrebbe essere il nostro sistema 1C, in cui tutti i dati vengono inseriti in modo accurato e puntuale (il punto qui è che le fatture vengono generate sulla base dei dati 1C, quindi l'inserimento corretto dei dati in 1C è una priorità per tutti (KPI). È così che è emerso un nuovo concetto di sistema...

Concetto

La prima cosa che abbiamo deciso di fare è stata quella di separare il sistema per la raccolta delle statistiche sulle campagne pubblicitarie su Internet in un prodotto separato: D1.Digitale.

Nel nuovo concetto, abbiamo deciso di caricare in D1.Digitale informazioni sulle campagne pubblicitarie e sui posizionamenti al loro interno da 1C, quindi estrarre statistiche dai siti e dai sistemi di AdServing su questi posizionamenti. Ciò avrebbe dovuto semplificare notevolmente la vita degli utenti (e, come al solito, aggiungere più lavoro agli sviluppatori) e ridurre la quantità di supporto.

Il primo problema che abbiamo riscontrato è stato di natura organizzativa ed era legato al fatto che non riuscivamo a trovare una chiave o un segno con cui confrontare entità di sistemi diversi con campagne e posizionamenti di 1C. Il fatto è che il processo nella nostra azienda è progettato in modo tale che le campagne pubblicitarie vengono inserite in sistemi diversi da persone diverse (media planner, acquirenti, ecc.).

Per risolvere questo problema, abbiamo dovuto inventare una chiave hash univoca, DANBoID, che collegasse insieme entità in diversi sistemi e che potesse essere identificata abbastanza facilmente e in modo univoco nei set di dati scaricati. Questo identificatore viene generato nel sistema 1C interno per ogni singolo posizionamento e viene trasferito a campagne, posizionamenti e contatori su tutti i siti e in tutti i sistemi di AdServing. Implementare la pratica di inserire DANBoID in tutti i posizionamenti ha richiesto del tempo, ma ci siamo riusciti :)

Poi abbiamo scoperto che non tutti i siti hanno un'API per la raccolta automatica delle statistiche, e anche quelli che l'hanno, non restituisce tutti i dati necessari.

In questa fase, abbiamo deciso di ridurre significativamente l'elenco delle piattaforme da integrare e di concentrarci sulle principali piattaforme coinvolte nella stragrande maggioranza delle campagne pubblicitarie. Questo elenco include tutti i maggiori attori nel mercato pubblicitario (Google, Yandex, Mail.ru), social network (VK, Facebook, Twitter), principali sistemi di AdServing e analisi (DCM, Adriver, Weborama, Google Analytics) e altre piattaforme.

La maggior parte dei siti che abbiamo selezionato disponeva di un'API che forniva le metriche di cui avevamo bisogno. Nei casi in cui non esistevano API o non contenevano i dati necessari, per caricare i dati utilizzavamo i report inviati quotidianamente alla posta elettronica del nostro ufficio (in alcuni sistemi è possibile configurare tali report, in altri abbiamo concordato lo sviluppo di tali report per noi).

Analizzando i dati provenienti da siti diversi, abbiamo scoperto che la gerarchia delle entità non è la stessa nei diversi sistemi. Inoltre, le informazioni devono essere scaricate in modo diverso da sistemi diversi.

Per risolvere questo problema è stato sviluppato il concetto SubDANBoID. L'idea di SubDANBoID è abbastanza semplice, contrassegniamo l'entità principale della campagna sul sito con il DANBoID generato, carichiamo tutte le entità nidificate con identificatori univoci del sito e formiamo SubDANBoID secondo il principio DANBoID + identificatore del primo livello entità nidificata + identificatore dell'entità nidificata di secondo livello +... Questo approccio ci ha permesso di collegare campagne pubblicitarie in diversi sistemi e scaricare statistiche dettagliate su di esse.

Abbiamo dovuto risolvere anche il problema dell'accesso alle campagne su diverse piattaforme. Come abbiamo scritto sopra, il meccanismo di delega dell'accesso a una campagna a un account tecnico separato non è sempre applicabile. Pertanto, abbiamo dovuto sviluppare un'infrastruttura per l'autorizzazione automatica tramite OAuth utilizzando token e meccanismi per l'aggiornamento di tali token.

Più avanti nell'articolo cercheremo di descrivere più nel dettaglio l'architettura della soluzione ed i dettagli tecnici dell'implementazione.

Architettura della soluzione 1.0

Avviando l'implementazione di un nuovo prodotto, abbiamo capito che occorreva subito prevedere la possibilità di connettere nuovi siti, quindi abbiamo deciso di seguire la strada dell'architettura a microservizi.

Durante la progettazione dell'architettura, abbiamo separato i connettori a tutti i sistemi esterni - 1C, piattaforme pubblicitarie e sistemi di adserving - in servizi separati.
L'idea principale è che tutti i connettori ai siti abbiano la stessa API e siano adattatori che portano l'API del sito a un'interfaccia per noi conveniente.

Al centro del nostro prodotto c'è un'applicazione web, che è un monolite progettato in modo tale da poter essere facilmente smontato in servizi. Questa applicazione è responsabile dell'elaborazione dei dati scaricati, della raccolta di statistiche da diversi sistemi e della loro presentazione agli utenti del sistema.

Per comunicare tra i connettori e l'applicazione web abbiamo dovuto creare un servizio aggiuntivo, che abbiamo chiamato Connector Proxy. Esegue le funzioni di Service Discovery e Task Scheduler. Questo servizio esegue attività di raccolta dati per ciascun connettore ogni notte. Scrivere un livello di servizio è stato più semplice che connettere un broker di messaggi e per noi era importante ottenere il risultato il più rapidamente possibile.

Per semplicità e velocità di sviluppo, abbiamo anche deciso che tutti i servizi saranno API Web. Ciò ha consentito di assemblare rapidamente una prova di concetto e di verificare che l'intero progetto funzioni.

Come abbiamo raccolto i dati sulle campagne pubblicitarie dai siti online (il percorso spinoso verso il prodotto)

Un compito separato e piuttosto complesso è stato impostare l'accesso per raccogliere dati da diversi account, cosa che, come abbiamo deciso, dovrebbe essere eseguita dagli utenti tramite l'interfaccia web. Consiste in due passaggi separati: in primo luogo, l'utente aggiunge un token per accedere all'account tramite OAuth, quindi configura la raccolta di dati per il client da un account specifico. Ottenere un token tramite OAuth è necessario perché, come abbiamo già scritto, non sempre è possibile delegare l'accesso all'account desiderato sul sito.

Per creare un meccanismo universale per la selezione di un account dai siti, abbiamo dovuto aggiungere un metodo all'API dei connettori che restituisce lo schema JSON, che viene visualizzato in un modulo utilizzando un componente JSONEditor modificato. In questo modo, gli utenti potevano selezionare gli account da cui scaricare i dati.

Per rispettare i limiti di richiesta esistenti sui siti, combiniamo le richieste di impostazioni all'interno di un token, ma possiamo elaborare token diversi in parallelo.

Abbiamo scelto MongoDB come archivio per i dati caricati sia per l'applicazione web che per i connettori, il che ci ha permesso di non preoccuparci troppo della struttura dei dati nelle fasi iniziali dello sviluppo, quando il modello a oggetti dell'applicazione cambia a giorni alterni.

Abbiamo presto scoperto che non tutti i dati si adattano bene a MongoDB e, ad esempio, è più conveniente archiviare le statistiche giornaliere in un database relazionale. Pertanto, per i connettori la cui struttura dati è più adatta a un database relazionale, abbiamo iniziato a utilizzare PostgreSQL o MS SQL Server come storage.

L'architettura e le tecnologie scelte ci hanno permesso di costruire e lanciare il prodotto D1.Digital in tempi relativamente brevi. In due anni di sviluppo del prodotto, abbiamo sviluppato 23 connettori ai siti, acquisito una preziosa esperienza lavorando con API di terze parti, imparato a evitare le trappole di siti diversi, ognuno dei quali aveva il proprio, contribuito allo sviluppo dell'API di almeno 3 siti, hanno scaricato automaticamente informazioni su quasi 15 campagne e per più di 000 posizionamenti, hanno raccolto molti feedback dagli utenti sul funzionamento del prodotto e sono riusciti a modificare più volte il processo principale del prodotto, sulla base di questo feedback.

Architettura della soluzione 2.0

Sono trascorsi due anni dall'inizio dello sviluppo D1.Digitale. Il costante aumento del carico sul sistema e l'emergere di sempre nuove fonti di dati hanno gradualmente rivelato problemi nell'architettura della soluzione esistente.

Il primo problema è legato alla quantità di dati scaricati dai siti. Ci siamo trovati di fronte al fatto che la raccolta e l'aggiornamento di tutti i dati necessari dai siti più grandi hanno iniziato a richiedere troppo tempo. Ad esempio, la raccolta dei dati dal sistema di pubblicità AdRiver, con il quale tracciamo le statistiche per la maggior parte dei posizionamenti, richiede circa 12 ore.

Per risolvere questo problema, abbiamo iniziato a utilizzare tutti i tipi di report per scaricare i dati dai siti, stiamo cercando di sviluppare la loro API insieme ai siti in modo che la velocità del suo funzionamento soddisfi le nostre esigenze e parallelizzare il più possibile il download dei dati.

Un altro problema riguarda il trattamento dei dati scaricati. Ora, quando arrivano le nuove statistiche sui posizionamenti, viene avviato un processo in più fasi di ricalcolo delle metriche, che include il caricamento dei dati grezzi, il calcolo delle metriche aggregate per ciascun sito, il confronto tra dati provenienti da diverse fonti e il calcolo delle metriche di riepilogo per la campagna. Ciò causa molto carico sull'applicazione web che esegue tutti i calcoli. Diverse volte, durante il processo di ricalcolo, l'applicazione ha consumato tutta la memoria del server, circa 10-15 GB, il che ha avuto l'effetto più dannoso sul lavoro degli utenti con il sistema.

I problemi identificati e i piani ambiziosi per l'ulteriore sviluppo del prodotto ci hanno portato alla necessità di riconsiderare l'architettura dell'applicazione.

Abbiamo iniziato con i connettori.
Abbiamo notato che tutti i connettori funzionano secondo lo stesso modello, quindi abbiamo costruito una struttura a pipeline in cui per creare un connettore dovevi solo programmare la logica dei passaggi, il resto era universale. Se qualche connettore richiede miglioramenti, lo trasferiamo immediatamente in un nuovo framework mentre il connettore viene migliorato.

Allo stesso tempo, abbiamo iniziato a implementare connettori su Docker e Kubernetes.
Avevamo pianificato il passaggio a Kubernetes da molto tempo, sperimentato le impostazioni CI/CD, ma abbiamo iniziato a spostarci solo quando un connettore, a causa di un errore, ha iniziato a consumare più di 20 GB di memoria sul server, praticamente uccidendo altri processi . Durante l'indagine, il connettore è stato spostato in un cluster Kubernetes, dove alla fine è rimasto anche dopo la correzione dell'errore.

Ci siamo resi conto abbastanza rapidamente che Kubernetes era conveniente e nel giro di sei mesi abbiamo trasferito 7 connettori e Connectors Proxy, che consumano più risorse, al cluster di produzione.

Seguendo i connettori, abbiamo deciso di modificare l'architettura del resto dell'applicazione.
Il problema principale era che i dati provenivano dai connettori ai proxy in grandi batch, quindi colpivano il DANBoID e venivano inviati all'applicazione web centrale per l'elaborazione. A causa dell'elevato numero di ricalcoli delle metriche, il carico sull'applicazione è elevato.

Si è rivelato inoltre piuttosto difficile monitorare lo stato dei singoli lavori di raccolta dati e segnalare gli errori che si verificavano all'interno dei connettori a un'applicazione web centrale in modo che gli utenti potessero vedere cosa stava succedendo e perché i dati non venivano raccolti.

Per risolvere questi problemi, abbiamo sviluppato l'architettura 2.0.

La differenza principale tra la nuova versione dell'architettura è che invece della Web API utilizziamo RabbitMQ e la libreria MassTransit per scambiare messaggi tra servizi. Per fare questo abbiamo dovuto riscrivere quasi completamente Connectors Proxy, rendendolo Connectors Hub. Il nome è stato cambiato perché il ruolo principale del servizio non è più quello di inoltrare richieste ai connettori e viceversa, ma di gestire la raccolta di metriche dai connettori.

Dall'applicazione web centrale, abbiamo separato le informazioni sui posizionamenti e le statistiche dai siti in servizi separati, il che ha permesso di eliminare ricalcoli non necessari e memorizzare solo statistiche già calcolate e aggregate a livello di posizionamento. Abbiamo anche riscritto e ottimizzato la logica per il calcolo delle statistiche di base basate su dati grezzi.

Allo stesso tempo, stiamo migrando tutti i servizi e le applicazioni su Docker e Kubernetes per rendere la soluzione più facile da scalare e più comoda da gestire.

Come abbiamo raccolto i dati sulle campagne pubblicitarie dai siti online (il percorso spinoso verso il prodotto)

Dove siamo adesso

Prodotto con architettura proof-of-concept 2.0 D1.Digitale pronto e funzionante in un ambiente di test con un set limitato di connettori. Tutto ciò che resta da fare è riscrivere altri 20 connettori su una nuova piattaforma, verificare che i dati siano caricati correttamente e che tutti i parametri siano calcolati correttamente e mettere in produzione l'intero progetto.

Questo processo, infatti, avverrà gradualmente e dovremo lasciare la retrocompatibilità con le vecchie API per far sì che tutto funzioni.

I nostri piani immediati includono lo sviluppo di nuovi connettori, l'integrazione con nuovi sistemi e l'aggiunta di ulteriori metriche all'insieme di dati scaricati dai siti collegati e dai sistemi di pubblicità.

Prevediamo inoltre di trasferire tutte le applicazioni, inclusa l'applicazione web centrale, su Docker e Kubernetes. In combinazione con la nuova architettura, ciò semplificherà notevolmente l’implementazione, il monitoraggio e il controllo delle risorse consumate.

Un'altra idea è sperimentare la scelta del database per l'archiviazione delle statistiche, che attualmente è archiviato in MongoDB. Abbiamo già trasferito diversi nuovi connettori ai database SQL, ma lì la differenza è quasi impercettibile e per le statistiche aggregate giornaliere, che possono essere richieste per un periodo arbitrario, il guadagno può essere piuttosto notevole.

In generale, i piani sono grandiosi, andiamo avanti :)

Autori dell'articolo R&D Dentsu Aegis Network Russia: Georgy Ostapenko (shmiigaa), Michail Kotsik (hitexx)

Fonte: habr.com

Aggiungi un commento