Data

22 ago, 2018

Maximizando o desempenho do processo com Maze, a plataforma de visualização de funil da Uber

Publicidade

Na Uber, gastamos uma quantidade considerável de recursos tornando a experiência de inscrição do motorista a mais fácil possível. Na escala da Uber, até um aumento de 1% na taxa de inscrições para as primeiras viagens (a taxa de conversão do motorista) carrega um impacto monumental.

Em dezembro de 2016, o cientista de dados da Uber, Andrey Liscovich, levantou a hipótese de que as ferramentas tradicionais de análise de funil não eram adequadas para estudar a real experiência de inscrição do motorista porque a tratavam como uma sequência fixa de etapas, enquanto que, na prática, o caminho da inscrição até a primeira viagem é um labirinto complexo, que quaisquer dois motoristas podem atravessar de forma diferente.

Para obter uma compreensão mais realista de como os usuários interagem com a tecnologia de inscrição, ele iniciou um esforço multifuncional para desenvolver uma nova plataforma de visualização de funil chamada Maze, que reconheceu a complexidade subjacente do funil.

Ao aplicar o Maze nos logs capturados durante a inscrição do motorista, podemos visualizar os caminhos reais que os motoristas fazem ao se inscreverem na Uber e identificar os gargalos que ocorrem no processo. O aplicativo do Maze na Uber expandiu-se desde então para além do caso de uso de inscrição, e agora é usado para visualizar muitos processos, desde pegar e deixar um cliente em seu destino até interações do usuário com o nosso site.

Continue lendo para saber como a equipe Uber Visualization desenvolveu o Maze e por que essa nova solução oferece uma visão incomparável da experiência do usuário da Uber.

Navegando pelo Maze: por que construímos uma nova ferramenta

Antes de 2016, visualizamos a experiência de inscrição do motorista como uma simples série de etapas cronológicas em uma ordem fixa. Em qualquer etapa do processo, uma determinada porcentagem de motoristas aspirantes desistiria ou “churn”.

Figura 1. Essa visão simplista de um funil destaca onde um usuário pode ser deixado.

Nesse modelo, a taxa de conversão é o produto da porcentagem de conversões em cada etapa. Então, para melhorar nossa taxa de conversão, precisávamos reduzir a rotatividade. Essa abordagem, embora valiosa, era limitada porque não levava em conta a ordem na qual os eventos de inscrição do motorista ocorreriam ou se eles aconteciam.

Há muitos pontos de entrada para o fluxo de inscrição do motorista (páginas da web, e-mail e aplicativo, para citar alguns), variando por região. Nem todos os candidatos a motorista passam pelo mesmo processo de inscrição. E mesmo para aqueles que o fazem:

  • O que acontece se eles iniciarem o processo no telefone e optarem por continuar em um computador desktop?
  • E se eles pausarem sua inscrição e a retomarem dois meses depois?
  • E se eles voltarem um passo e trocarem informações inócuas (por exemplo, tipo de carro, cor do carro etc.) que já haviam enviado?

As respostas para essas perguntas têm um impacto notável em nossa taxa de conversão.

O longo caminho para a conversão

Quando começamos a medir o número de etapas, desde a inscrição até a ativação, ou seja, todos os eventos que pudemos detectar, descobrimos uma enorme variação no número de etapas realmente realizadas pelos motoristas.

Em alguns casos, foram necessárias algumas dezenas de etapas para ir da inscrição à primeira viagem, mas em outros isso demorou muito mais tempo. Em alguns casos, os candidatos a motorista podem passar por centenas de eventos antes de abandonarem o funil.

Ao contrário do que assumimos há muito tempo, não existe um caminho mais eficaz para a conversão, mas sim milhares – alguns curtos, outros longos, alguns lineares, alguns desonestos. De fato, a jornada para a conversão é um verdadeiro labirinto.

Entrando no Maze

Para entender melhor o processo de inscrição, criamos o Maze, uma ferramenta para visualizar sequências agregadas de eventos, permitindo-nos responder perguntas, como:

  • Quantos motoristas passaram pelo evento A?
  • Quantos passaram pelo evento A e depois pelo evento B?
  • Quantos passaram pelo evento A e depois pelo evento C?
  • Quantos passaram pelo evento A, depois B, depois D?
  • Quantos passaram pelo evento A, depois B, depois D, mas não C?

Responder a essas perguntas por meios tradicionais (por exemplo, uma consulta SQL) é trabalhoso e propenso a erros. Em vez disso, nossa ferramenta encontra o tamanho de cada sequência de eventos e representa todo o funil visualmente.

Apresentação

Figura 2. O Maze Sunburst visualiza como a ferramenta rastreia e organiza os dados das sessões de inscrição do motorista.

Quando um usuário abre o aplicativo do motorista e inicia a inscrição, o app registra todas as ações que ele realiza, permitindo que o Maze transforme cada sessão do aplicativo em uma série de eventos.

Para explorar essas sessões como um todo unificado, usamos uma visualização sunburst, uma representação visual do funil feita de anéis concêntricos. Os anéis centrais do sunburst são compostos de múltiplos arcos, representando os primeiros eventos de todas as sequências, e podem terminar em um anel se todas as sequências começarem no mesmo evento.

Então, para cada passo extra, desenhamos um anel feito de um ou vários segmentos de arco, com cada segmento correspondendo a um evento específico e dimensionado proporcionalmente às sequências que correspondem a esse evento.

Na interface de usuário do Maze, podemos destacar um determinado caminho com nosso cursor, e ele representará as sequências de eventos nessa ordem exata, permitindo-nos ver facilmente a proporção do total de sessões que eles representam nesse nó.

Como as sequências podem ficar bastante longas e há apenas muitas camadas que podemos mostrar na tela, também permitimos que os usuários aumentem o zoom em um determinado arco e refaçam o sunburst a partir desse momento, oferecendo uma visualização mais precisa e detalhada dos dados.

Figura 3. Nessa visualização, procuramos eventos cujos nomes terminam com START, SUCCESS ou FAILURE. Quando adicionamos esse filtro, a forma do sunburst se torna muito diferente

A partir daí, podemos usar a interface do usuário para refinar os resultados de que precisamos. Por exemplo, como mostrado na Figura 3, podemos filtrar os eventos que queremos representados na tela.

Figura 4. Usando uma sequência de filtros, podemos ver sequências de inscrição específicas, como eventos de falha que seguem eventos bem-sucedidos.

Na verdade, nossa interface do usuário nos permite fazer todos os tipos de filtragem e exploração. Por exemplo, podemos aplicar “sequência de filtros” para manter apenas sequências que tenham determinados eventos em uma determinada ordem.

Também podemos restringir nosso sunburst às sessões do usuário durante as quais uma consulta de dados bem-sucedida é seguida por um erro na mesma consulta. Esse tipo de especificação nos permite explorar possíveis pontos problemáticos durante a experiência de inscrição do motorista, o que nos permite entender o que deu errado e determinar como podemos corrigi-lo para futuros usuários.

Alcançando o centro do labirinto: o primeiro ganha

Figura 5. Uma torre de nós roxos na parte superior da nossa visualização representa cliques no botão Voltar de um navegador para uma determinada página da web envolvida no processo de inscrição do motorista, permitindo diagnosticar armadilhas de conversão.

Na Uber, nossos cientistas de dados usam o Maze para testar certas hipóteses e avaliar sua validade.

Na Figura 5, por exemplo, observamos uma torre de nós roxos na parte superior de nossa visualização, representando cliques no botão Voltar do navegador para uma determinada página da web durante o processo de inscrição do motorista.

A espiral roxa indica que os indivíduos não puderam retornar às etapas anteriores, sugerindo que o botão Voltar do navegador era o bloqueador. Nesse cenário, podemos dizer que os candidatos a motorista nessa etapa continuariam clicando nesse botão até desistirem completamente do processo ou decidirem continuar progredindo cronologicamente.

Figura 6. O Maze ilumina partes específicas do funil de inscrição do motorista.

Arquitetura do Maze

Criamos o front-end do Maze usando a pilha de tecnologia web da Uber, com base no React 16 e no Redux. Nossa arquitetura web também incorpora um cliente React e um servidor Node como um proxy RPC, além de métricas de desempenho integradas, monitoramento de tráfego e relatórios de cobertura.

Figura 7. A arquitetura do app Maze incorpora um cliente React, um servidor Node e um painel de monitoramento.

Para apresentar valiosas visualizações de dados em escala, o Maze atinge um equilíbrio bem definido entre interações de usuário responsivas e alto desempenho. Além do framework Redux, o cache em camadas é aplicado ao nosso sistema, conforme detalhado abaixo:

  • React Layer Cache: a primeira camada de cache acima do React Store inclui cache in-state e React Selectors, evitando cálculos pesados e nova renderização.
  • Web Worker: como parte do cache do navegador, o Web Worker armazena backup de dados para cálculos instantâneos em ações que não precisam acessar o banco de dados de back-end. SharedWorkers permitem uma experiência de usuário tranquila para ações que regeneram toda a visualização.
  • Cache de memória do lado do nó: cada solicitação para cada evento de inscrição de todos os motoristas em São Francisco, por exemplo, resultaria em milhões de peças de dados sendo coletadas. Essa camada de cache garante que a primeira visualização dos dados tenha um baixo custo.

Processamento de dados de visualização

A visualização de dados em escala pode ser um processo desafiador. O Maze resolve esse problema, permitindo-nos visualizar árvores de dados muito grandes. A visualização de grandes sequências de eventos pode resultar em árvores de até 100 camadas em profundidade e potencialmente em centenas de ramificações em cada folha, correlacionando-se a milhões de nós e centenas de megabytes de dados que devem ser baixados em uma única solicitação.

Usar o React e o Redux em uma escala tão grande pode ser arriscado, pois não queremos que um cálculo infinito seja aplicado a cada envio de ação individual. Quando a resposta do back-end utiliza centenas de megabytes, a manutenção de estados de renderização de redutores para containers e componentes acaba sendo um luxo para recursos limitados do navegador.

Usamos a biblioteca D3 para renderização de dados importantes no Maze. O uso de ações do modelo de objeto de documento real (DOM) disparadas pelo D3 pode ser relativamente complicado se animações ou transições forem necessárias, já que o React espera que toda a estrutura do DOM seja regenerada para atualizações de estado. A solução que aplicamos no Maze é usar estados in-component, bem como caches para cada novo conjunto de dados e apenas despachar uma atualização de dados global quando novas agregações forem necessárias.

Há muitos insights que podemos extrair dos dados brutos usando a estratégia certa para casos de uso reais. Por exemplo, “filtrar certo tipo de evento fora da vista”, pode se tornar uma questão de algoritmo, “remover nós com um determinado tipo de evento da árvore”. Essa situação pode ser separada nas seguintes etapas:

  • Salve o conjunto de dados original
  • Aplique novos acessórios aos dados atuais
  • Renderize a exibição mais recente para todas as regras

A partir daí, os Web Workers executam o ajuste de dados e entregam os resultados de cada cálculo para que possamos atender às interações do usuário em tempo real sem precisar consultar o back-end, enquanto os conjuntos de dados originais são compartilhados no cache do navegador.

Armazenamento e agregação

Em termos práticos, o Maze é uma ferramenta de análise de sequências que fornece insights sobre sessões, onde uma “sessão” pode ser uma viagem de passageiro, uma visita ao website, um procedimento de inscrição para um novo motorista ou qualquer uma das muitas interações reais do usuário com a nossa plataforma. Em outras palavras, o Maze coleta uma lista de eventos para milhares de sessões e as agrega em uma única exibição em árvore.

Figura 8. A arquitetura de serviço do Maze aproveita várias fontes de dados diferentes para agregar e filtrar para uma determinada consulta.

O back-end do Maze lida principalmente com agregação de dados. O back-end é responsável pela inscrição de dados, backup/backfilling/caching, agregação, coleta de sessões, validação e garantia de qualidade, além de servir dados bem estruturados em nosso banco de dados OLAP para análise de dados.

Para cada fonte de dados integrada, o back-end do Maze recebe dados executando tarefas Spark programadas diariamente em tabelas Hive predefinidas e dados em tempo real da nossa plataforma de análise de streaming open source, AthenaX.

Como a fonte de dados bruta é muito barulhenta e até mesmo uma única solicitação de consulta requer uma quantidade significativa de tempo para processar, a “pré-agregação” de dados ocorre antes de gravar no banco de dados.

Essa etapa garante que os dados salvos possam estar o mais próximo possível da definição de esquema de leitura especificada. Além disso, ter esse esquema nos permite criar filtros personalizados nos metadados, permitindo assim uma consulta mais dinâmica.

O processo de agregação atende diretamente ao front-end do Maze com dois resultados principais: dados agregados para visualização e registros detalhados da sessão. Durante uma interação típica, um usuário do Maze primeiro verifica a visualização em busca de funis inesperados e mergulha em cada sessão individual para obter mais informações.

Esse padrão permite que o back-end do Maze otimize o desempenho usando o Redis como cache de memória. Como esses dois resultados (com estruturas muito diferentes) são criados a partir do mesmo conjunto de dados, economizamos recursos por não precisar consultar os dois resultados com milhões de eventos cada.

Aproveitando essas propriedades, o back-end do Maze agrega, armazena e percorre dados com precisão e eficiência.

Desafios e melhorias

O Maze foi desenvolvido inicialmente a partir de um protótipo de hackathon Uber. Nossos engenheiros precisaram de muito esforço para produzir o Maze e fornecer uma qualidade de dados relativamente estável e uma interface de usuário tranquila. Abaixo, descrevemos alguns dos desafios que enfrentamos ao desenvolver a próxima geração dessa nova e poderosa ferramenta de visualização:

  • Ajuste de consulta de back-end: “Determinar o status de todos os motoristas em São Francisco até o último minuto” não é uma pergunta simples de responder. Agora estamos trabalhando com a quarta geração da lógica de agregação do Maze e melhorando ativamente o processo de inscrição de dados.
  • Escalabilidade de dados: Ao criar o Maze, perguntamos a nós mesmos qual é a melhor abordagem de armazenamento para nosso banco de dados de processamento analítico online (OLAP)? Havia muitas opções disponíveis na Uber, e todas elas foram criadas para diferentes propósitos. Foi preciso muito esforço de engenharia tentando encontrar soluções alternativas para a escala de dados e os requisitos em tempo real, e reconhecemos que esse sempre seria um processo contínuo. Mesmo com nossas soluções usando o MemSql, ainda há espaço para crescimento.
  • Renderização dinâmica e manutenção de estado interno: Renderizar milhões de nós em um navegador web usando D3 não é realista. Com a renderização dinâmica, a manutenção de estado interno e os caches no navegador, podemos exibir dados muito pequenos para renderizar e ocultar todo o iceberg de nossos usuários.
  • Limpeza do tempo de execução do JavaScript: Foi uma decisão difícil, porém razoável, remover o Immutable.js e outros pacotes sofisticados de nossa solução. No front-end, nos preocupamos com cada milissegundo de desempenho e eliminamos possíveis bloqueadores para acelerar a experiência do usuário.
  • E mais: Outras melhorias em que estamos trabalhando incluem testes completos de cobertura e integração de testes, simulação de dados offline, melhoria contínua de monitoramento e alertas, visualização mais eficiente, maior escala de grupos de usuários e conjunto de problemas e resolução de problemas sem fim.

Outras oportunidades

Ainda temos um longo caminho a percorrer para otimizar o Maze. Também reconhecemos que os esforços para tornar um produto quase perfeito nunca terminam. No entanto, migrando o Uber Web tech stack do Bedrock para o Fusion.js usando o webpack em vez do gulp.js, desenvolvendo um novo procedimento de transação de dados para reduzir a latência de rede, atualizando os componentes de UI seguindo o último projeto BaseUI, integrando testes A/B e simplesmente experimentando com mais visualizações seriam potencialmente beneficiar o próprio produto e os engenheiros.

No entanto, voltando aos objetivos originais do Maze, estávamos em um local onde o produto é bem definido, a estrutura de dados é estável e o desempenho é alto mesmo quando usamos quantidades massivas de dados em tempo real.

Analisando essas qualidades, surgiu uma nova pergunta: como podemos ampliar o que temos agora para atender mais usuários com insights sobre as perguntas relacionadas a funil e conversão? Em outras palavras, como podemos servir dados mais úteis para que nossos usuários possam determinar com eficiência a causa raiz dos problemas em um funil?

Tudo na Uber é um funil

Como resultado do Maze e de outros esforços de larga escala para resolver problemas conhecidos no processo de inscrição, a taxa de conversão de inscrições em cidades dos EUA aumentou em mais de 50% desde 2016. Graças ao Maze, podemos detectar melhor e explicar anomalias de inscrição que, de outra forma, voariam sob o radar e permaneceriam quebradas.

Existem muitos outros processos similares ao registro de motorista na Uber que envolvem uma população que passa por vários eventos, terminando com um resultado bem-sucedido ou menos desejável. Poucos meses depois de entregarmos a primeira versão do Maze, começamos a abrir a ferramenta para mais de 20 outros casos de uso, como sessões de aplicativos de passageiro, Uber Eats, captações no aeroporto e o aplicativo de cartão Uber Visa.

Agora, qualquer pessoa na Uber que é responsável por um processo pode incorporar seus dados ao Maze e diagnosticar conversões.

Como registramos os eventos de todas as nossas ferramentas internas, também podemos usar o Maze para entender como essas ferramentas são usadas (na verdade, usar o Maze para analisar o uso do Maze é uma das primeiras coisas que fizemos!).

E funis são tudo

Originalmente, o Maze apenas propunha visualizações em sunburst. O sunburst introduz alguns vieses, já que os anéis voltados para o exterior ocupam mais espaço na tela do que os anéis mais próximos do centro que representam a mesma proporção.

Figura 9. Arcos do mesmo ângulo ocupam mais espaço na visualização sunburst, à medida que o raio do círculo aumenta.

Essa distorção realmente funciona bem para o Maze, pois os arcos externos geralmente são muito pequenos e, como tal, as camadas externas tendem a ser escassas.

No entanto, criamos muitas variações do sunburst e muitas outras formas de olhar para esse conjunto de dados, incluindo sunbursts invertidos, sunbursts de largura variável, sunbursts animados, icicles, diagramas de link de nós e sequências agrupadas. Continuamos adicionando novos itens à nossa caixa de ferramentas, pois diferentes maneiras de visualizar nossos dados podem gerar novos insights e criar um valor tremendo para nossos usuários.

Visualização Markov

Animação sunpulse entre dois sunbursts

Sunburst de largura variável/Modos de coloração diferentes

Figura 10: Esse conjunto de visualizações experimentais que desenvolvemos no Maze mostra percepções de dados de várias perspectivas diferentes.

Visualização de sequências individuais, agrupadas por similaridade

Além do Maze

O Maze não é um fim em si mesmo. O objetivo do projeto é desempenhar um papel em uma iniciativa de visualização maior: a Funnel Health. Com a Funnel Health, os usuários podem definir seu próprio funil a partir de eventos selecionados e receber alertas inteligentes quando certas características do funil indicam que é necessária uma ação.

Por exemplo, o Maze pode nos ajudar a determinar quais ações tomar se observarmos uma queda enorme na taxa de coleta de sessões de viagem do passageiro ou encontrar pontos de atrito do usuário após a implementação de uma nova versão do aplicativo.

Quando bem integrada com outras ferramentas centradas em funil, como Flow, IFTTT Engine e Maze, a Funil Health da Uber dará às nossas equipes uma visão melhor sobre essas situações.

Você quer nos ajudar a construir a próxima geração de ferramentas de funil? Estamos à procura de engenheiros de back-end, front-end e visualização para se juntarem a nós! O Maze também conta com o trabalho open source da equipe de visualização. Estamos sempre procurando por colaboradores. Envie-nos um e-mail aqui para mais detalhes!

Assine nossa newsletter para acompanhar as mais recentes inovações da Uber Engineering.

***

Este artigo é do Uber Engineering. Ele foi escrito por Yujia Luo e Jerome Cukier. A tradução foi feita pela Redação iMasters com autorização. Você pode conferir o original em: