Calcular segmentos de receita para o esquema de valor de conversão da rede SKAd

1. Introdução

Contexto antes de começar

Se você é um desenvolvedor de apps iOS, provavelmente já conhece as atualizações de privacidade do iOS 14.5 ou versões mais recentes. Para medir ações de conversão significativas após a instalação, a Apple disponibiliza a API SKAd Network, que permite medir o sucesso das suas campanhas publicitárias, respeitando a privacidade do usuário. Com base nas necessidades da sua empresa, você pode encontrar a melhor maneira de aproveitar a SKAd Network para coletar insights significativos sobre suas campanhas. Neste codelab, analisamos uma metodologia de exemplo para aproveitar os dados do GAPF no BigQuery e agrupar a receita pós-instalação do app em buckets, que você pode usar para configurar com seu parceiro de atribuição de app. Embora este codelab use uma abordagem baseada em receita, você também pode usar eventos ou abordagens baseadas em funil para medir a SKAN. Confira mais detalhes nesta Central de Ajuda. Este é apenas um exemplo, não é uma recomendação oficial do Google. É possível criar seu próprio esquema com base nas necessidades específicas da sua empresa

O que pretendemos abordar

  • Analisar os dados do GAPF no BigQuery
  • Encontre dados de receita de usuários que fizeram uma conversão entre 0 e 2 dias
  • Agrupar dados de receita em buckets
  • Entender a distribuição de usuários em cada bucket
  • Implemente os buckets no Appsflyer SKAN Conversion Studio

Pré-requisitos

2. Como acessar o BigQuery Export

Acesse Configurações do projeto > Integrações > no BigQuery. A alternância precisa ser ativada primeiro e, depois de ativada, leva cerca de 48 horas para que o conjunto de dados seja disponibilizado. Clique no link mostrado abaixo para acessar o BigQuery

1aa4e20bfd3419d1.png

Executar algumas consultas

Agora que você está no BigQuery, deve ver as tabelas diárias geradas. Na captura de tela de exemplo abaixo, vemos 64 tabelas diárias, então a exportação já está em andamento há 64 dias. Se você estiver acessando pela primeira vez, talvez veja apenas uma tabela diária com os dados do dia anterior. À direita, você vê o esquema da tabela. Consulte mais detalhes sobre os campos aqui.

Para começar a escrever sua consulta, você pode clicar em Consulta > Em uma nova guia

42ba59ec655c5d1b.png

Em seguida, execute a consulta de amostra na nova guia

70ef90d32b7cd7f1.png

3. Analisar dados de receita

Buscando dados de instalação

Agora, para começar a criar os buckets de receita, precisamos analisar primeiro os dados dos usuários que instalaram o app nas últimas 24 a 72 horas. A SKAd Network 4.0 permite visualizar dados em um ou dois dias, enquanto a SKAd Network 3.5 permite 24 horas por padrão. Dependendo das capacidades do seu parceiro de atribuição de app, talvez você possa modificar essa janela de atividade em geral para, no máximo, 72 horas. Quando os usuários instalam e abrem o aplicativo pela primeira vez, o evento first_open é acionado pelo SDK e registrado no BigQuery.

O identificador que pode ser usado para o BigQuery é user_pseudo_id (também chamado de ID da instância do aplicativo). Assim, você pode usar a consulta abaixo para encontrar esses usuários

SELECT
  user_pseudo_id,
  event_name,
  event_date,
  event_timestamp
FROM `project_name.dataset_name.events_2023*`
WHERE
  event_name = 'first_open'
  AND platform = 'IOS'

Alguns pontos a serem observados sobre essa consulta

  • Substitua o nome pela sua tabela exportada do Google Analytics. Você pode usar caracteres curinga para consultar várias tabelas diárias. Por exemplo, 2023* vai consultar todos os dados de 2023
  • Se você tiver muitos usuários, também poderá consultar apenas os últimos 30 dias para agilizar o processamento.
  • Filtramos a plataforma = "IOS". Se você tiver vários apps iOS no seu projeto do Firebase, também poderá adicionar um filtro para app_info.firebase_app_id a fim de receber dados para o aplicativo específico

Como buscar dados de receita

Agora, vamos conferir uma consulta para encontrar a receita dos usuários. Nesse caso, presumimos que seus eventos de receita sejam in_app_purchase e ad_impression. A receita de "in_app_purchase" está disponível em "event_value_usd". Já para "ad_impression", a receita está disponível no parâmetro "value" (valor) dentro dos parâmetros do evento. Se você não conhece os parâmetros de evento no BigQuery, verifique a definição aqui e teste este exemplo de consulta na nossa referência oficial, que também aborda a extração do valor de event_params.

SELECT
  user_pseudo_id,
  event_name,
  EXTRACT(date FROM Parse_datetime('%Y%m%d', event_date)) AS event_date,
  (
    SELECT COALESCE(value.int_value, value.float_value, value.double_value, NULL)
    FROM UNNEST(event_params)
    WHERE
      KEY = 'value'
      AND event_name = 'ad_impression'
  ) AS ad_funded_revenue,
  (
    SELECT value.string_value
    FROM UNNEST(event_params)
    WHERE
      KEY = 'currency'
      AND event_name = 'ad_impression'
  ) AS ad_revenue_currency,
  (
    CASE
      WHEN event_name = 'in_app_purchase' THEN event_value_in_usd
      ELSE 0
      END) AS iap_revenue_usd,
FROM `project_name.dataset_name.events_2023*`
WHERE
  platform = 'IOS'
  AND event_name IN (
    'in_app_purchase',
    'ad_impression')

Vamos entender o que a consulta faz aqui. Estas são as coisas que você notaria

  • Na cláusula WHERE, estamos filtrando os eventos de receita, já que estamos interessados apenas neles e, assim como da última vez, estamos procurando dados do iOS.
  • Na cláusula SELECT, usamos o valor e a moeda do evento de receita de publicidade (ad_impression) e o event_value_in_usd quando o evento é in_app_purchase.
  • Se você estiver enviando várias moedas, primeiro deverá fazer o alinhamento com uma única moeda para esta análise. Para este exemplo, vamos considerar que a moeda da receita financiada pelo anúncio também é USD.

A saída seria algo como o exemplo abaixo (a coluna para user_pseudo_id está encoberta aqui).

1e1e6943e4b3a6d8.png

Combinar esses dados

Até agora, executamos duas consultas, uma para encontrar os dados dos usuários que instalaram e abriram o aplicativo e outra para encontrar a receita desses usuários. Vamos relembrar o que discutimos sobre as limitações da SKAdNetwork. A janela de atribuição só fica disponível entre 0 e 2 dias após a instalação. Por isso, precisamos verificar a instalação e a receita nos carimbos de data/hora dos eventos, além de coletar as informações somente se elas acontecerem dentro desse período. Agora, vamos tentar combinar em uma consulta que forneça a receita total de cada postagem dos dois dias de instalação do app.

#creating the install table
WITH
  install_table AS (
    SELECT
      user_pseudo_id,
      event_name,
      event_date,
      event_timestamp
    FROM `project_name.dataset_name.events_2023*`
    WHERE
      event_name = 'first_open'
      AND platform = 'IOS'
  ),
  #creating the revenue table
  revenue_table AS (
    SELECT
      user_pseudo_id,
      event_name,
      event_timestamp,
      EXTRACT(date FROM Parse_datetime('%Y%m%d', event_date)) AS event_date,
      (
        SELECT COALESCE(value.int_value, value.float_value, value.double_value, NULL)
        FROM UNNEST(event_params)
        WHERE
          KEY = 'value'
          AND event_name = 'ad_impression'
      ) AS ad_funded_revenue,
      (
        SELECT value.string_value
        FROM UNNEST(event_params)
        WHERE
          KEY = 'currency'
          AND event_name = 'ad_impression'
      ) AS ad_revenue_currency,
      (
        CASE
          WHEN event_name = 'in_app_purchase' THEN event_value_in_usd
          ELSE 0
          END) AS iap_revenue_usd,
    FROM `project_name.dataset_name.events_2023*`
    WHERE
      platform = 'IOS'
      AND event_name IN (
        'in_app_purchase',
        'ad_impression')
  )
SELECT
  it.user_pseudo_id AS user_pseudo_id,
  #combine ad revenue and IAP revenue, assuming both are in same currency
  sum(ifnull(rt.iap_revenue_usd,0) + ifnull(rt.ad_funded_revenue,0)) AS total_revenue,
FROM install_table it
INNER JOIN revenue_table rt
  ON it.user_pseudo_id = rt.user_pseudo_id
WHERE
  rt.event_timestamp >= it.event_timestamp
  AND rt.event_timestamp
    <= it.event_timestamp + 86400000000 * 2  #added 86400 000 millisecond as 24 hours, taking for 2 days later
GROUP BY 1

A consulta apenas tenta unir os dados de instalação e de receita no campo user_pseudo_id, e então precisamos garantir que o carimbo de data/hora esteja dentro de dois dias. Se você estiver usando a SKAd Network 3.5, o padrão será 24 horas. Portanto, também será possível alterar a condição para incluir apenas dados de 1 dia.

Agrupar a receita em buckets

Após a consulta anterior, você terá o user_pseudo_id e a receita total

2c1986b93e937d19.png

Agora, precisamos combiná-los em grupos que possam ser usados para nossos intervalos de valor de conversão. Para isso, usaremos a função prox_quantiles do BigQuery, que cria esses intervalos automaticamente. Para este exemplo, vamos supor que queremos criar 5 intervalos, então podemos usar SELECT aproximadamente_quantiles(total_revenue, 5) AS buckets

Com isso, vamos incorporar isso em nossa consulta geral

#creating the install table
WITH
  install_table AS (
    SELECT
      user_pseudo_id,
      event_name,
      event_date,
      event_timestamp
    FROM `project_name.dataset_name.events_2023*`
    WHERE
      event_name = 'first_open'
      AND platform = 'IOS'
  ),
  #creating the revenue table
  revenue_table AS (
    SELECT
      user_pseudo_id,
      event_name,
      event_timestamp,
      EXTRACT(date FROM Parse_datetime('%Y%m%d', event_date)) AS event_date,
      (
        SELECT COALESCE(value.int_value, value.float_value, value.double_value, NULL)
        FROM UNNEST(event_params)
        WHERE
          KEY = 'value'
          AND event_name = 'ad_impression'
      ) AS ad_funded_revenue,
      (
        SELECT value.string_value
        FROM UNNEST(event_params)
        WHERE
          KEY = 'currency'
          AND event_name = 'ad_impression'
      ) AS ad_revenue_currency,
      (
        CASE
          WHEN event_name = 'in_app_purchase' THEN event_value_in_usd
          ELSE 0
          END) AS iap_revenue_usd,
    FROM `project_name.dataset_name.events_2023*`
    WHERE
      platform = 'IOS'
      AND event_name IN (
        'in_app_purchase',
        'ad_impression')
  ),
  total_revenue_table AS (
    SELECT
      it.user_pseudo_id AS user_pseudo_id,
      #combine ad revenue and IAP revenue, assuming both are in same currency
      sum(ifnull(rt.iap_revenue_usd,0) + ifnull(rt.ad_funded_revenue,0)) AS total_revenue,
    FROM install_table it
    INNER JOIN revenue_table rt
      ON it.user_pseudo_id = rt.user_pseudo_id
    WHERE
      rt.event_timestamp >= it.event_timestamp
      AND rt.event_timestamp
        <= it.event_timestamp + 86400000000 * 2  #added 86400 000 millisecond as 24 hours
    GROUP BY 1
  )
SELECT approx_quantiles(total_revenue, 5) AS buckets FROM total_revenue_table

Essa consulta deve dividir a receita em 5 buckets, e o BigQuery tenta manter uma distribuição de percentil consistente

ba46f5d993449948.png

Analise a distribuição de usuários com estes buckets

Esta é uma etapa opcional se você quiser entender a distribuição dos seus usuários em cada bucket. Para nosso exemplo, os intervalos de bucket retornados na consulta anterior são

  • 0,1
  • 0,5
  • 2
  • 2,5
  • 5 [o último valor não deve ser usado na configuração do intervalo]

Nos intervalos finais, vamos ignorar o último bucket 5, já que esse geralmente é o valor máximo e podemos considerar apenas 2, 5 como o último intervalo. Isso ocorre porque os provedores de atribuição de apps tendem a calcular o ROAS usando a média do intervalo. Portanto, o outlier precisa ser excluído para um cálculo mais uniforme.

Agora tentaremos analisar o número de usuários de cada data em todos os períodos para que possamos entender o volume diário de usuários em cada bucket. Podemos fazer isso usando esta consulta de exemplo, em que você pode substituir os valores do bucket pelos seus dados reais, e a consulta ficaria mais ou menos assim.

#creating the install table
WITH
  install_table AS (
    SELECT
      user_pseudo_id,
      event_name,
      event_date,
      event_timestamp
    FROM `project_name.dataset_name.events_2023*`
    WHERE
      event_name = 'first_open'
      AND platform = 'IOS'
  ),
  #creating the revenue table
  revenue_table AS (
    SELECT
      user_pseudo_id,
      event_name,
      event_timestamp,
      EXTRACT(date FROM Parse_datetime('%Y%m%d', event_date)) AS event_date,
      (
        SELECT COALESCE(value.int_value, value.float_value, value.double_value, NULL)
        FROM UNNEST(event_params)
        WHERE
          KEY = 'value'
          AND event_name = 'ad_impression'
      ) AS ad_funded_revenue,
      (
        SELECT value.string_value
        FROM UNNEST(event_params)
        WHERE
          KEY = 'currency'
          AND event_name = 'ad_impression'
      ) AS ad_revenue_currency,
      (
        CASE
          WHEN event_name = 'in_app_purchase' THEN event_value_in_usd
          ELSE 0
          END) AS iap_revenue_usd,
    FROM `project_name.dataset_name.events_2023*`
    WHERE
      platform = 'IOS'
      AND event_name IN (
        'in_app_purchase',
        'ad_impression')
  ),
  total_revenue_table AS (
    SELECT
      it.user_pseudo_id AS user_pseudo_id,
      rt.event_date,
      #combine ad revenue and IAP revenue, assuming both are in same currency
      sum(ifnull(rt.iap_revenue_usd,0) + ifnull(rt.ad_funded_revenue,0)) AS total_revenue,
    FROM install_table it
    INNER JOIN revenue_table rt
      ON it.user_pseudo_id = rt.user_pseudo_id
    WHERE
      rt.event_timestamp >= it.event_timestamp
      AND rt.event_timestamp
        <= it.event_timestamp + 86400000000 * 2  #added 86400 000 millisecond as 24 hours
    GROUP BY 1, 2
  )
SELECT
  event_date,
  sum(CASE WHEN total_revenue BETWEEN 0 AND 0.1 THEN 1 ELSE 0 END) AS Bucket1,
  sum(CASE WHEN total_revenue BETWEEN 0.1 AND 0.5 THEN 1 ELSE 0 END) AS Bucket2,
  sum(CASE WHEN total_revenue BETWEEN 0.5 AND 2 THEN 1 ELSE 0 END) AS Bucket3,
  sum(CASE WHEN total_revenue BETWEEN 2 AND 2.5 THEN 1 ELSE 0 END) AS Bucket4,
  sum(CASE WHEN total_revenue > 2.5 THEN 1 ELSE 0 END) AS Bucket5
FROM total_revenue_table
GROUP BY 1 ORDER BY 1 DESC

Ela retornará os usuários em cada intervalo de receita para cada dia, conforme mostrado abaixo. Se você vir números muito baixos em qualquer bucket ou uma distribuição geralmente desigual, ajuste o número de buckets e execute a consulta novamente.

bf7d73085fe94cb6.png

Um resumo sobre a SKAd Network 4.0

A SKAd Network 4.0 oferece várias janelas de conversão de até 2 dias, 3 a 7 dias e 8 a 35 dias. Na abordagem acima, você também pode alterar facilmente a janela para analisar os dados desses cenários adicionais. Valores de alta granularidade de LOW, MEDIUM e HIGH também estão disponíveis. Se você quiser usar essa abordagem, considere que são três buckets. Então, ao mudar o número de buckets para 3, você consegue os limites BAIXO, MÉDIO e ALTO

4. Implantação com seu provedor de atribuição

Dependendo da plataforma específica, esta orientação pode mudar. Trabalhe com os representantes da plataforma para ter as informações mais atualizadas sobre isso. Para os fins deste exemplo, vamos analisar como fazer a implantação no AppsFlyer.

Na consulta executada anteriormente, os intervalos finais que recebemos como saída foram os seguintes:

ba46f5d993449948.png

  • Intervalo 1 : 0 a 0,1
  • Intervalo 2 : 0,1 a 0,5
  • Intervalo 3 : 0,5 a 2
  • Intervalo 4 : 2 a 2,5

Decidimos ignorar a última faixa de receita, já que isso será um ponto fora da curva e distorce os cálculos médios do provedor de atribuição do app.

A AppsFlyer oferece o SKAN Conversion Studio, onde é bem simples inserir essa informação diretamente na interface. É possível usar a versão 4.0 diretamente ou a opção "Personalizado" se estiver usando a versão 3.5, e adicione "Receita" de medida. Em seguida, você pode apenas adicionar os intervalos de receita que calculou na análise anterior.

f8c56abdf9b405f4.png

Práticas recomendadas e aprendizados no Google Ads

Gostaríamos de fazer algumas recomendações se você está veiculando campanhas no Google Ads e medindo o impacto com um esquema de valor da conversão da rede SKAdNetwork.

  • Verifique se a janela de conversão usada no Google Ads corresponde à janela de atividade especificada na plataforma de atribuição de app. Para a rede SKAd 3.5, isso provavelmente leva de um a três dias. Para fazer os ajustes necessários no Google Ads, siga as etapas listadas aqui.

4fd625aae9d4a43.png

  • Se você usa o Appsflyer, o contador de eventos padrão é 1, o que significa que ele não contabiliza vários eventos por usuário. Se você estiver usando um modelo baseado em eventos para a medição da SKAN e comparar com as campanhas de tCPA no Google Ads, personalize seguindo estas orientações da Appsflyer.

6c7a4d703567700a.png

5. Parabéns

Parabéns! Você configurou seu esquema de valor da conversão da rede da SKAdNetwork. Agora você pode monitorar os dados no Relatório da rede de publicidade do Google Ads para verificar os valores de conversão das suas campanhas quando ele estiver ativo

Você aprendeu

  • Como analisar os dados brutos avançados do GAPF no BigQuery
  • Abordagem analítica para calcular intervalos de receita para sua empresa
  • Implantar o esquema com o AppsFlyer