Calcular os intervalos de receita para o esquema de valor da conversão da SKAdNetwork

1. Introdução

Algumas explicações antes de começar

Se você é um desenvolvedor de apps iOS, provavelmente já ouviu falar das atualizações de privacidade do iOS 14.5 e versões mais recentes. Para medir ações de conversão significativas após a instalação, a Apple oferece a API SKAdNetwork, 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 usar a SKAdNetwork para capturar insights relevantes sobre suas campanhas. Neste codelab, examinamos uma metodologia de exemplo para aproveitar seus dados do GA4F no BigQuery e agrupar a receita após a instalação do app em intervalos, 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 medição da SKAN. Consulte esta Central de Ajuda para orientações mais detalhadas. Este é apenas um exemplo, não uma recomendação oficial do Google. Você pode criar seu próprio esquema com base nas necessidades específicas da sua empresa.

O que vamos abordar

  • Analisar dados do GA4F no BigQuery
  • Encontrar dados de receita de usuários que fizeram conversões em até dois dias
  • Agrupar dados de receita em intervalos
  • Entenda a distribuição de usuários em cada bucket
  • Implementar os intervalos no Appsflyer SKAN Conversion Studio

Pré-requisitos

2. Como acessar o BigQuery Export

Acesse o conjunto de dados no GA4F em Configurações do projeto > Integrações > BigQuery. Primeiro, é preciso ativar a opção. Depois disso, leva cerca de 48 horas para que o conjunto de dados fique disponível. Clique no link abaixo para acessar o BigQuery.

1aa4e20bfd3419d1.png

Executar algumas consultas

Agora que você está no BigQuery, as tabelas diárias geradas vão aparecer. Na captura de tela de exemplo abaixo, vemos 64 tabelas diárias. Portanto, a exportação está sendo executada 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. Confira 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

Como buscar dados de instalação

Para começar a criar os intervalos de receita, primeiro precisamos analisar os dados dos usuários que instalaram o app nas últimas 24 a 72 horas. A SKAdNetwork 4.0 permite visualizar dados em 0 a 2 dias, enquanto a SKAdNetwork 3.5 permite 24 horas por padrão. Dependendo das funcionalidades do seu parceiro de atribuição de app, talvez seja possível modificar essa janela de atividade para não mais de 72 horas. Quando os usuários instalam e abrem o app pela primeira vez, o evento first_open é acionado pelo SDK e registrado no BigQuery.

O identificador que você pode usar para o BigQuery é user_pseudo_id (também chamado de ID da instância do app). Use 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'

Algumas observações sobre essa consulta

  • Substitua o nome da tabela pela sua tabela exportada do Analytics. É possível 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 por 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" e receber dados do app específico.

Como buscar dados de receita

Agora, vamos analisar uma consulta para encontrar a receita dos seus usuários. Nesse caso, vamos presumir 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, enquanto para ad_impression, a receita está disponível no parâmetro value, dentro dos parâmetros do evento. Se você não conhece os parâmetros de evento no BigQuery, confira a definição aqui e teste esta consulta de exemplo 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 só temos interesse neles. 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 precisará alinhar a uma única moeda para essa análise. Para este exemplo, vamos presumir que a moeda da receita financiada por anúncios também seja o dólar americano.

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

1e1e6943e4b3a6d8.png

Como combinar esses dados

Até agora, executamos duas consultas: uma para encontrar os dados dos usuários que instalaram e abriram o app e outra para encontrar a receita desses usuários. Agora, vamos lembrar o que discutimos sobre as limitações da SKAdNetwork. A janela de atribuição só pode estar disponível em um período de 0 a 2 dias após a instalação. Portanto, precisamos verificar os carimbos de data/hora dos eventos de instalação e receita e usar as informações apenas se elas ocorrerem dentro desse período. Agora, vamos tentar combinar em uma consulta que forneça a receita total de cada postagem dois dias após a 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 unir 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 SKAdNetwork 3.5, o padrão é de 24 horas. Portanto, também é possível mudar a condição para incluir apenas os dados de um dia.

Como agrupar a receita em intervalos

Depois da consulta anterior, você terá o user_pseudo_id e a receita total.

2c1986b93e937d19.png

Agora, precisamos combinar isso em intervalos que podem ser usados para nossos intervalos de valores de conversão. Para isso, vamos usar a função approx_quantiles no BigQuery, que cria esses intervalos automaticamente. Vamos supor, para fins deste exemplo, que queremos criar cinco intervalos. Assim, podemos usar SELECT approx_quantiles(total_revenue, 5) AS buckets

Com isso, 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 divide a receita em cinco intervalos, e o BigQuery tenta manter uma distribuição de percentis consistente.

ba46f5d993449948.png

Analisar a distribuição de usuários com esses agrupamentos

Esta etapa é opcional se você quiser entender a distribuição dos usuários em cada bucket. No nosso exemplo, os intervalos de agrupamento 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 de 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 acontece porque os provedores de atribuição de apps tendem a calcular o ROAS usando a média do intervalo. Portanto, o valor discrepante precisa ser excluído para um cálculo mais uniforme.

Agora vamos analisar o número de usuários em cada data em todos os intervalos para entender o volume diário de usuários em cada grupo. Para isso, use esta consulta de exemplo. Nela, você pode substituir os valores de grupo pelos seus dados reais. A consulta vai ficar 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 intervalo de receita para cada dia, como abaixo. Se você encontrar números muito baixos em algum agrupamento ou uma distribuição geralmente desigual, ajuste o número de agrupamentos e execute a consulta novamente.

bf7d73085fe94cb6.png

Uma breve observação sobre a SKAdNetwork 4.0

A SKAdNetwork 4.0 oferece várias janelas de conversão de até 2 dias, de 3 a 7 dias e de 8 a 35 dias. Na abordagem acima, é fácil mudar a janela para analisar dados desses outros cenários também. Valores aproximados de BAIXO, MÉDIO e ALTO também estão disponíveis. Se você quiser usar essa abordagem, pense em três intervalos. Ao mudar o número de intervalos para três, você consegue os limites para BAIXO, MÉDIO e ALTO.

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

Dependendo da plataforma específica, essa orientação pode mudar. Entre em contato com os representantes da plataforma para receber as informações mais atualizadas sobre isso. Para fins deste exemplo, vamos analisar como podemos implantar isso 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, já que ele é um outlier e distorce os cálculos de média do provedor de atribuição do app.

A AppsFlyer oferece o SKAN Conversion Studio, em que é muito simples inserir isso diretamente na interface. Você pode usar a 4.0 diretamente ou o modo "Personalizado" se estiver usando a 3.5 e adicionar a métrica "Receita". Depois, basta adicionar os intervalos de receita que você calculou na análise anterior.

f8c56abdf9b405f4.png

Práticas recomendadas e aprendizados no Google Ads

Confira algumas recomendações se você estiver veiculando campanhas no Google Ads e medindo o impacto com um esquema de valor da conversão da 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 vai acontecer em um a três dias. Portanto, siga as etapas aqui para fazer o ajuste no Google Ads.

4fd625aae9d4a43.png

  • Se você estiver usando o Appsflyer, o contador de eventos padrão será 1, o que significa que ele não considera vários eventos por usuário. Se você estiver usando um modelo baseado em eventos para medição da SKAN e comparando com campanhas de tCPA no Google Ads, siga estas orientações da AppsFlyer para personalizar.

6c7a4d703567700a.png

5. Parabéns

Parabéns, você configurou seu 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 assim que ele estiver disponível.

Você aprendeu

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