Como coletamos dados sobre campanhas publicitárias de sites online (o caminho espinhoso até o produto)

Parece que o campo da publicidade online deveria ser o mais avançado tecnologicamente e automatizado possível. Claro, porque gigantes e especialistas em suas áreas como Yandex, Mail.Ru, Google e Facebook trabalham lá. Mas, como se viu, não há limite para a perfeição e há sempre algo para automatizar.

Como coletamos dados sobre campanhas publicitárias de sites online (o caminho espinhoso até o produto)
Fonte

Grupo de comunicações Rede Dentsu Aegis Rússia é o maior player no mercado de publicidade digital e investe ativamente em tecnologia, buscando otimizar e automatizar seus processos de negócios. Um dos problemas não resolvidos do mercado de publicidade online passou a ser a tarefa de coletar estatísticas sobre campanhas publicitárias de diferentes plataformas da Internet. A solução para este problema resultou finalmente na criação de um produto D1.Digital (leia-se DiVan), sobre o desenvolvimento do qual queremos falar.

Por quê?

1. À data do início do projeto, não existia no mercado um único produto pronto que resolvesse o problema de automatização da recolha de estatísticas sobre campanhas publicitárias. Isso significa que ninguém, exceto nós mesmos, atenderá às nossas necessidades.

Serviços como Improvado, Roistat, Supermetrics, SegmentStream oferecem integração com plataformas, redes sociais e Google Analitycs, além de possibilitarem a construção de dashboards analíticos para análise e controle convenientes de campanhas publicitárias. Antes de começarmos a desenvolver nosso produto, tentamos utilizar alguns desses sistemas para coletar dados de sites, mas, infelizmente, eles não conseguiram resolver nossos problemas.

O principal problema foi que os produtos testados dependiam de fontes de dados, exibindo estatísticas de posicionamento por site, e não forneciam a capacidade de agregar estatísticas sobre campanhas publicitárias. Esta abordagem não nos permitiu ver estatísticas de diferentes sites num só local e analisar o estado da campanha como um todo.

Outro fator foi que nos estágios iniciais os produtos eram voltados para o mercado ocidental e não suportavam integração com sites russos. E para os sites com os quais a integração foi implementada, nem sempre todas as métricas necessárias eram baixadas com detalhes suficientes, e a integração nem sempre era conveniente e transparente, principalmente quando era necessário obter algo que não estava na interface do sistema.
Em geral, decidimos não nos adaptar a produtos de terceiros, mas começamos a desenvolver os nossos próprios...

2. O mercado de publicidade online cresce ano após ano e, em 2018, em termos de orçamentos publicitários, ultrapassou o tradicionalmente maior mercado de publicidade televisiva. Então há uma escala.

3. Ao contrário do mercado de publicidade televisiva, onde a venda de publicidade comercial é monopolizada, existem muitos proprietários individuais de inventário publicitário de vários tamanhos que operam na Internet com as suas próprias contas de publicidade. Como uma campanha publicitária, via de regra, é veiculada em vários sites ao mesmo tempo, para entender o estado da campanha publicitária é necessário coletar relatórios de todos os sites e combiná-los em um grande relatório que mostrará o quadro completo. Isso significa que há potencial para otimização.

4. Pareceu-nos que os proprietários de inventários publicitários na Internet já possuem a infraestrutura para coletar estatísticas e exibi-las em contas publicitárias, e poderão fornecer uma API para esses dados. Isto significa que é tecnicamente possível implementá-lo. Digamos desde já que não foi tão simples.

Em geral, todos os pré-requisitos para a implementação do projeto eram óbvios para nós, e corremos para dar vida ao projeto...

Grande plano

Para começar, formamos uma visão de um sistema ideal:

  • As campanhas publicitárias do sistema corporativo 1C deverão ser carregadas automaticamente nele com seus nomes, períodos, orçamentos e veiculações nas diversas plataformas.
  • Para cada posicionamento dentro de uma campanha publicitária, todas as estatísticas possíveis deverão ser baixadas automaticamente dos sites onde o posicionamento está ocorrendo, como número de impressões, cliques, visualizações, etc.
  • Algumas campanhas publicitárias são rastreadas por meio de monitoramento de terceiros pelos chamados sistemas de publicidade, como Adriver, Weborama, DCM, etc. Há também um medidor industrial de Internet na Rússia - a empresa Mediascope. De acordo com o nosso plano, os dados do monitoramento independente e industrial também deverão ser carregados automaticamente nas campanhas publicitárias correspondentes.
  • A maioria das campanhas publicitárias na Internet visam determinadas ações direcionadas (compra, chamada, inscrição para um test drive, etc.), que são rastreadas através do Google Analytics, e cujas estatísticas também são importantes para compreender o estado da campanha e deve ser carregado em nossa ferramenta.

A primeira panqueca é grumosa

Dado o nosso compromisso com princípios flexíveis de desenvolvimento de software (ágil, todas as coisas), decidimos primeiro desenvolver um MVP e depois avançar iterativamente em direção ao objetivo pretendido.
Decidimos construir MVP com base em nosso produto DANBo (placa de rede Dentsu Aegis), que é uma aplicação web com informações gerais sobre as campanhas publicitárias dos nossos clientes.

Para o MVP, o projeto foi simplificado ao máximo em termos de implementação. Selecionamos uma lista limitada de plataformas para integração. Estas foram as principais plataformas, como Yandex.Direct, Yandex.Display, RB.Mail, MyTarget, Adwords, DBM, VK, FB, e os principais sistemas de publicidade Adriver e Weborama.

Para acessar as estatísticas dos sites via API, utilizamos uma única conta. Um gestor de grupo de clientes que pretendesse utilizar a recolha automática de estatísticas sobre uma campanha publicitária teve primeiro de delegar o acesso às campanhas publicitárias necessárias nos sites à conta da plataforma.

O próximo é o usuário do sistema DANBo teve que fazer upload de um arquivo de determinado formato no sistema Excel, que continha todas as informações sobre o posicionamento (campanha publicitária, plataforma, formato, período de veiculação, indicadores planejados, orçamento, etc.) e identificadores das campanhas publicitárias correspondentes no sites e contadores em sistemas de publicidade.

Parecia, francamente, assustador:

Como coletamos dados sobre campanhas publicitárias de sites online (o caminho espinhoso até o produto)

Os dados baixados foram salvos em um banco de dados e, em seguida, serviços separados coletaram identificadores de campanha em sites deles e baixaram estatísticas sobre eles.

Para cada site, foi escrito um serviço Windows separado, que uma vez por dia acessava uma conta de serviço na API do site e baixava estatísticas para IDs de campanha específicos. A mesma coisa aconteceu com os sistemas de anúncios.

Os dados baixados foram exibidos na interface na forma de um pequeno painel personalizado:

Como coletamos dados sobre campanhas publicitárias de sites online (o caminho espinhoso até o produto)

Inesperadamente para nós, o MVP começou a trabalhar e a baixar estatísticas atuais sobre campanhas publicitárias na Internet. Implementamos o sistema em vários clientes, mas ao tentar escalar, encontramos sérios problemas:

  • O principal problema era a complexidade de preparação dos dados para carregamento no sistema. Além disso, os dados de posicionamento tiveram que ser convertidos para um formato estritamente fixo antes do carregamento. Foi necessário incluir identificadores de entidades de diferentes sites no arquivo de download. Nos deparamos com o fato de que é muito difícil para usuários sem treinamento técnico explicar onde encontrar esses identificadores no site e onde eles precisam ser inseridos no arquivo. Considerando o número de colaboradores dos departamentos que realizam campanhas nos sites e a rotatividade, isso resultou num enorme apoio da nossa parte, com o qual não ficamos nada satisfeitos.
  • Outro problema era que nem todas as plataformas publicitárias possuíam mecanismos para delegar o acesso às campanhas publicitárias a outras contas. Mas mesmo que estivesse disponível um mecanismo de delegação, nem todos os anunciantes estavam dispostos a conceder acesso às suas campanhas a contas de terceiros.
  • Um fator importante foi a indignação que despertou entre os usuários pelo fato de que todos os indicadores planejados e detalhes de posicionamento que eles já inserem em nosso sistema de contabilidade 1C, devem reinserir em DANBo.

Isso nos deu a ideia de que a principal fonte de informações sobre colocação deveria ser nosso sistema 1C, no qual todos os dados são inseridos com precisão e dentro do prazo (o ponto aqui é que as faturas são geradas com base nos dados 1C, portanto, a entrada correta de dados em 1C é uma prioridade para todos (KPI). Foi assim que surgiu um novo conceito de sistema...

Conceito

A primeira coisa que decidimos fazer foi separar o sistema de recolha de estatísticas sobre campanhas publicitárias na Internet num produto separado - D1.Digital.

No novo conceito, decidimos carregar em D1.Digital informações sobre campanhas publicitárias e canais dentro delas de 1C e, em seguida, extrai estatísticas de sites e sistemas AdServing para esses canais. Isso deveria simplificar significativamente a vida dos usuários (e, como sempre, adicionar mais trabalho aos desenvolvedores) e reduzir a quantidade de suporte.

O primeiro problema que encontramos foi de natureza organizacional e estava relacionado com o facto de não termos encontrado uma chave ou sinal pelo qual pudéssemos comparar entidades de diferentes sistemas com campanhas e posicionamentos de 1C. O fato é que o processo em nossa empresa é desenhado de tal forma que as campanhas publicitárias são inseridas em diferentes sistemas por diferentes pessoas (planejadores de mídia, compras, etc.).

Para resolver esse problema, tivemos que inventar uma chave de hash exclusiva, DANBoID, que vinculasse entidades em diferentes sistemas e que pudesse ser identificada de maneira bastante fácil e exclusiva em conjuntos de dados baixados. Este identificador é gerado no sistema interno 1C para cada veiculação individual e é transferido para campanhas, veiculações e contadores em todos os sites e em todos os sistemas AdServing. Implementar a prática de colocar DANBoID em todos os canais demorou um pouco, mas conseguimos :)

Aí descobrimos que nem todos os sites possuem API para coleta automática de estatísticas, e mesmo aqueles que possuem API, ela não retorna todos os dados necessários.

Nesta fase, decidimos reduzir significativamente a lista de plataformas de integração e focar nas principais plataformas que estão envolvidas na grande maioria das campanhas publicitárias. Esta lista inclui todos os maiores players do mercado publicitário (Google, Yandex, Mail.ru), redes sociais (VK, Facebook, Twitter), principais sistemas de AdServing e análise (DCM, Adriver, Weborama, Google Analytics) e outras plataformas.

A maioria dos sites que selecionamos tinha uma API que fornecia as métricas de que precisávamos. Nos casos em que não existia API ou não continha os dados necessários, utilizamos relatórios que eram enviados diariamente para o e-mail do nosso escritório para carregar os dados (em alguns sistemas é possível configurar tais relatórios, em outros combinamos o desenvolvimento de tais relatórios para nós).

Ao analisar dados de diferentes sites, descobrimos que a hierarquia das entidades não é a mesma em sistemas diferentes. Além disso, as informações precisam ser baixadas com detalhes diferentes de sistemas diferentes.

Para resolver este problema, foi desenvolvido o conceito SubDANBoID. A ideia do SubDANBoID é bastante simples, marcamos a entidade principal da campanha no site com o DANBoID gerado, e carregamos todas as entidades aninhadas com identificadores únicos do site e formamos SubDANBoID de acordo com o princípio DANBoID + identificador de primeiro nível entidade aninhada + identificador da entidade aninhada de segundo nível +... Essa abordagem nos permitiu conectar campanhas publicitárias em diferentes sistemas e baixar estatísticas detalhadas sobre elas.

Tivemos também que resolver o problema do acesso às campanhas nas diferentes plataformas. Como escrevemos acima, o mecanismo de delegar o acesso a uma campanha a uma conta técnica separada nem sempre é aplicável. Portanto, tivemos que desenvolver uma infraestrutura para autorização automática via OAuth utilizando tokens e mecanismos de atualização desses tokens.

Posteriormente neste artigo tentaremos descrever com mais detalhes a arquitetura da solução e os detalhes técnicos da implementação.

Arquitetura da solução 1.0

Ao iniciar a implementação de um novo produto, entendemos que precisávamos imediatamente prever a possibilidade de conexão de novos sites, por isso decidimos seguir o caminho da arquitetura de microsserviços.

Ao projetar a arquitetura, separamos os conectores para todos os sistemas externos - 1C, plataformas de publicidade e sistemas de publicidade - em serviços separados.
A ideia principal é que todos os conectores de sites tenham a mesma API e sejam adaptadores que trazem a API do site para uma interface conveniente para nós.

No centro do nosso produto está uma aplicação web, que é um monólito projetado de tal forma que pode ser facilmente desmontado em serviços. Esta aplicação é responsável por processar os dados baixados, coletando estatísticas de diferentes sistemas e apresentando-as aos usuários do sistema.

Para a comunicação entre os conectores e a aplicação web, tivemos que criar um serviço adicional, que chamamos de Connector Proxy. Ele executa as funções de descoberta de serviço e agendador de tarefas. Este serviço executa tarefas de coleta de dados para cada conector todas as noites. Escrever uma camada de serviço foi mais fácil do que conectar um corretor de mensagens, e para nós era importante obter o resultado o mais rápido possível.

Para simplicidade e velocidade de desenvolvimento, também decidimos que todos os serviços serão APIs Web. Isso possibilitou montar rapidamente uma prova de conceito e verificar se todo o projeto funciona.

Como coletamos dados sobre campanhas publicitárias de sites online (o caminho espinhoso até o produto)

Uma tarefa separada e bastante complexa foi configurar o acesso para coletar dados de diferentes contas, o que, conforme decidimos, deveria ser realizado pelos usuários por meio da interface web. Consiste em duas etapas distintas: primeiro, o usuário adiciona um token para acessar a conta via OAuth e, em seguida, configura a coleta de dados para o cliente de uma conta específica. A obtenção de um token via OAuth é necessária porque, como já escrevemos, nem sempre é possível delegar o acesso à conta desejada no site.

Para criar um mecanismo universal para selecionar uma conta em sites, tivemos que adicionar um método à API dos conectores que retorna o esquema JSON, que é renderizado em um formulário usando um componente JSONEditor modificado. Dessa forma, os usuários puderam selecionar as contas das quais desejariam baixar os dados.

Para cumprir os limites de solicitação existentes nos sites, combinamos solicitações de configurações dentro de um token, mas podemos processar tokens diferentes em paralelo.

Escolhemos o MongoDB como armazenamento de dados carregados tanto para a aplicação web quanto para conectores, o que nos permitiu não nos preocupar muito com a estrutura de dados nos estágios iniciais de desenvolvimento, quando o modelo de objeto da aplicação muda a cada dois dias.

Logo descobrimos que nem todos os dados cabem bem no MongoDB e, por exemplo, é mais conveniente armazenar estatísticas diárias em um banco de dados relacional. Portanto, para conectores cuja estrutura de dados é mais adequada para um banco de dados relacional, passamos a utilizar PostgreSQL ou MS SQL Server como armazenamento.

A arquitetura e as tecnologias escolhidas permitiram-nos construir e lançar o produto D1.Digital de forma relativamente rápida. Ao longo de dois anos de desenvolvimento de produtos, desenvolvemos 23 conectores para sites, ganhamos uma experiência inestimável trabalhando com APIs de terceiros, aprendemos a evitar as armadilhas de sites diferentes, cada um com a sua, contribuímos para o desenvolvimento da API de pelo menos 3 sites, baixaram automaticamente informações de quase 15 campanhas e de mais de 000 veiculações, coletaram muito feedback dos usuários sobre o funcionamento do produto e conseguiram alterar diversas vezes o processo principal do produto, com base nesse feedback.

Arquitetura da solução 2.0

Dois anos se passaram desde o início do desenvolvimento D1.Digital. O aumento constante da carga do sistema e o surgimento de cada vez mais novas fontes de dados revelaram gradualmente problemas na arquitetura de solução existente.

O primeiro problema está relacionado à quantidade de dados baixados dos sites. Deparamo-nos com o facto de a recolha e atualização de todos os dados necessários dos maiores sites começar a demorar muito tempo. Por exemplo, a coleta de dados do sistema de publicidade AdRiver, com o qual rastreamos estatísticas para a maioria dos canais, leva cerca de 12 horas.

Para resolver este problema, passamos a utilizar todos os tipos de relatórios para baixar dados de sites, estamos tentando desenvolver sua API junto com os sites para que a velocidade de seu funcionamento atenda às nossas necessidades, e paralelizar ao máximo o download de dados.

Outro problema diz respeito ao processamento dos dados baixados. Agora, quando chegam novas estatísticas de posicionamento, é lançado um processo de vários estágios de recálculo de métricas, que inclui o carregamento de dados brutos, o cálculo de métricas agregadas para cada site, a comparação de dados de diferentes fontes entre si e o cálculo de métricas resumidas para a campanha. Isso causa muita carga na aplicação web que faz todos os cálculos. Várias vezes, durante o processo de recálculo, o aplicativo consumiu toda a memória do servidor, cerca de 10 a 15 GB, o que teve o efeito mais prejudicial no trabalho dos usuários com o sistema.

Os problemas identificados e os planos ambiciosos para o desenvolvimento do produto levaram-nos à necessidade de reconsiderar a arquitetura da aplicação.

Começamos com conectores.
Percebemos que todos os conectores funcionam segundo o mesmo modelo, então construímos um framework de pipeline no qual para criar um conector bastava programar a lógica dos passos, o resto era universal. Se algum conector precisar de melhorias, nós o transferimos imediatamente para uma nova estrutura ao mesmo tempo em que o conector está sendo aprimorado.

Ao mesmo tempo, começamos a implantar conectores para Docker e Kubernetes.
Planejamos há muito tempo a mudança para Kubernetes, experimentamos configurações de CI/CD, mas começamos a mudar apenas quando um conector, por erro, começou a consumir mais de 20 GB de memória do servidor, praticamente matando outros processos . Durante a investigação, o conector foi movido para um cluster Kubernetes, onde permaneceu, mesmo depois que o erro foi corrigido.

Rapidamente percebemos que o Kubernetes era conveniente e, em seis meses, transferimos 7 conectores e Connectors Proxy, que consomem mais recursos, para o cluster de produção.

Seguindo os conectores, decidimos mudar a arquitetura do restante da aplicação.
O principal problema era que os dados vinham dos conectores para os proxies em grandes lotes e, em seguida, chegavam ao DANBoID e eram enviados ao aplicativo web central para processamento. Devido ao grande número de recálculos de métricas, há uma grande carga na aplicação.

Também se revelou bastante difícil monitorar o status de trabalhos individuais de coleta de dados e relatar erros ocorridos nos conectores para um aplicativo Web central, para que os usuários pudessem ver o que estava acontecendo e por que os dados não estavam sendo coletados.

Para resolver esses problemas, desenvolvemos a arquitetura 2.0.

A principal diferença entre a nova versão da arquitetura é que em vez da API Web, utilizamos RabbitMQ e a biblioteca MassTransit para troca de mensagens entre serviços. Para fazer isso, tivemos que reescrever quase completamente o Connectors Proxy, tornando-o Connectors Hub. O nome foi alterado porque a função principal do serviço não é mais encaminhar solicitações aos conectores e de volta, mas gerenciar a coleta de métricas dos conectores.

A partir do aplicativo web central, separamos as informações sobre canais e estatísticas dos sites em serviços separados, o que possibilitou eliminar recálculos desnecessários e armazenar apenas estatísticas já calculadas e agregadas no nível do canal. Também reescrevemos e otimizamos a lógica para calcular estatísticas básicas com base em dados brutos.

Ao mesmo tempo, estamos migrando todos os serviços e aplicações para Docker e Kubernetes para tornar a solução mais fácil de escalar e mais conveniente de gerenciar.

Como coletamos dados sobre campanhas publicitárias de sites online (o caminho espinhoso até o produto)

Onde estamos agora

Produto de arquitetura 2.0 de prova de conceito D1.Digital pronto e funcionando em um ambiente de teste com um conjunto limitado de conectores. Tudo o que resta fazer é reescrever outros 20 conectores para uma nova plataforma, testar se os dados estão carregados corretamente e se todas as métricas estão calculadas corretamente e colocar todo o design em produção.

Na verdade, esse processo acontecerá de forma gradual e teremos que deixar a retrocompatibilidade com APIs antigas para manter tudo funcionando.

Nossos planos imediatos incluem o desenvolvimento de novos conectores, integração com novos sistemas e adição de métricas adicionais ao conjunto de dados baixados de sites conectados e sistemas de publicidade.

Também planejamos transferir todos os aplicativos, incluindo o aplicativo web central, para Docker e Kubernetes. Combinado com a nova arquitetura, isto simplificará significativamente a implantação, monitoramento e controle dos recursos consumidos.

Outra ideia é experimentar a escolha do banco de dados para armazenamento de estatísticas, que atualmente está armazenado no MongoDB. Já transferimos vários novos conectores para bancos de dados SQL, mas aí a diferença é quase imperceptível, e para estatísticas agregadas por dia, que podem ser solicitadas por um período arbitrário, o ganho pode ser bastante sério.

Em geral os planos são grandiosos, vamos em frente :)

Autores do artigo R&D Dentsu Aegis Network Rússia: Georgy Ostapenko (shmiigaa), Mikhail Kotsik (hitexx)

Fonte: habr.com

Adicionar um comentário