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

1. Introdução

Um pouco de contexto antes de começar

Se você é um desenvolvedor de apps iOS, deve ter ouvido falar das 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 SKAdNetwork para coletar insights importantes sobre suas campanhas. Neste codelab, analisamos uma metodologia de exemplo para aproveitar os dados do GAPF no BigQuery e agrupar a receita após a 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. Você pode projetar seu próprio esquema com base nas necessidades específicas do seu negócio

O que pretendemos abordar

  • Analisar dados do GA4F 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 está no BigQuery, você deve ver as tabelas diárias geradas. Na captura de tela de exemplo abaixo, há 64 tabelas diárias, então a exportação está em execução há 64 dias. Se você estiver acessando pela primeira vez, talvez só apareça 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, clique em Consulta > Em uma nova guia.

42ba59ec655c5d1b.png

Em seguida, tente executar a consulta de exemplo 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 da tabela pela 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 um processamento mais rápido.
  • Filtramos em platform = "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 analisar uma consulta para encontrar a receita dos seus usuários. Nesse caso, presumimos que seus eventos de receita são 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. 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 está fazendo 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.
  • Agora, na cláusula SELECT, estamos usando 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 fins deste exemplo, vamos supor que a moeda da receita proveniente de anúncios também é USD.

A saída será semelhante à abaixo (a coluna para user_pseudo_id está editada 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. Portanto, precisamos verificar os carimbos de data/hora do evento para instalação e receita e coletar as informações somente se elas ocorrerem nesse 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 tenta mesclar os dados de instalação e de receita no campo user_pseudo_id. Depois, 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, vamos usar a função prox_quantiles do BigQuery, que cria esses intervalos automaticamente. Vamos supor que, para fins deste exemplo, queremos criar cinco intervalos. Portanto, podemos usar SELECT approx_quantiles(total_revenue, 5) AS buckets

Vamos incorporar isso à 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. No nosso exemplo, os intervalos de balde 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]

Para os intervalos finais, vamos ignorar o último bucket 5, já que esse é geralmente o valor máximo, e podemos considerar 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

Ele vai retornar os usuários em cada faixa de receita para cada dia, como abaixo. Se você encontrar 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 SKAdNetwork 4.0 oferece várias janelas de conversão de até dois, três a sete e oito a 35 dias. Na abordagem acima, você pode mudar facilmente a janela para analisar os dados desses outros cenários. 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. Entre em contato com os representantes da plataforma para receber as informações mais atualizadas sobre o assunto. Para os fins deste exemplo, vamos analisar como fazer a implantação no AppsFlyer.

Na consulta que executamos 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 o último intervalo de receita, porque ele é um valor fora da curva e distorce os cálculos médios do seu provedor de atribuição de apps.

A AppsFlyer oferece o SKAN Conversion Studio, onde é muito simples inserir esse código diretamente na interface. Você pode usar a versão 4.0 diretamente ou o modo "Personalizado" se estiver usando a versão 3.5 e adicionar a métrica "Receita". Em seguida, adicione os intervalos de receita que você 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 que você está usando no Google Ads corresponde à janela de atividade especificada na plataforma de atribuição de apps. 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ê estiver usando o Appsflyer, o contador de eventos padrão é 1, o que significa que não considera vários eventos por usuário. Se você estiver usando um modelo baseado em eventos para a medição da SKAN e comparando com campanhas de tCPA no Google Ads, poderá personalizar seguindo estas orientações do Appsflyer.

6c7a4d703567700a.png

5. Parabéns

Parabéns, você configurou o esquema de valor da conversão da SKAdNetwork. Agora você pode monitorar os dados no Relatório da SKAdNetwork do Google Ads para verificar os valores de conversão das suas campanhas do Google Ads quando elas estiverem ativas.

Você aprendeu

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