Calcula los buckets de ingresos para el esquema de valor de conversión de SKAdNetwork

1. Introducción

Un poco de contexto antes de comenzar

Si eres desarrollador de apps para iOS, seguramente ya conoces las actualizaciones de privacidad de iOS 14.5 y versiones posteriores. Para medir las acciones de conversión significativas posteriores a la instalación, Apple proporciona la API de SKAdNetwork, que te permite medir el éxito de tus campañas publicitarias y, al mismo tiempo, respetar la privacidad del usuario. Según las necesidades de tu empresa, puedes encontrar la forma más óptima de aprovechar SKAdNetwork para captar estadísticas significativas sobre tus campañas. En este codelab, analizamos una metodología de ejemplo para aprovechar tus datos de GA4F en BigQuery y agrupar los ingresos posteriores a la instalación de la app en segmentos, que luego puedes usar para configurar con tu socio de atribución de aplicaciones. Si bien este codelab usa un enfoque basado en los ingresos, también puedes usar enfoques basados en eventos o embudos para la medición de SKAN. Consulta este Centro de ayuda para obtener información más detallada. Este es solo un ejemplo, no una recomendación oficial de Google. Puedes diseñar tu propio esquema según las necesidades específicas de tu empresa.

Temas que abordaremos

  • Explora los datos de GA4F en BigQuery
  • Busca los datos de ingresos de los usuarios que generaron conversiones en un plazo de 0 a 2 días
  • Agrupa los datos de ingresos en intervalos
  • Comprende la distribución de usuarios en cada bucket
  • Implementa los discretizaciones en Appsflyer SKAN Conversion Studio

Requisitos previos

2. Cómo acceder a BigQuery Export

Para navegar al conjunto de datos en GA4F, visita Configuración del proyecto > Integraciones > BigQuery. Primero, debes habilitar el botón de activación y, una vez que lo hagas, el conjunto de datos tardará alrededor de 48 horas en estar disponible. Puedes hacer clic en el vínculo que se muestra a continuación para ir a BigQuery.

1aa4e20bfd3419d1.png

Ejecuta algunas consultas

Ahora que estás en BigQuery, deberías ver las tablas diarias generadas. En la siguiente captura de pantalla de ejemplo, vemos 64 tablas diarias, por lo que la exportación se ha ejecutado durante 64 días. Si accedes a ella por primera vez, es posible que solo veas 1 tabla diaria con los datos del día anterior. A la derecha, verás el esquema de la tabla. Puedes consultar más detalles sobre los campos aquí.

Para comenzar a escribir tu consulta, puedes hacer clic en Consulta > En una pestaña nueva.

42ba59ec655c5d1b.png

Luego, puedes intentar ejecutar la consulta de muestra en la pestaña nueva.

70ef90d32b7cd7f1.png

3. Analiza los datos de ingresos

Recuperación de datos de instalación

Ahora, para comenzar a crear los segmentos de ingresos, primero debemos analizar los datos de los usuarios que instalaron la app en las últimas 24 a 72 horas. La versión 4.0 de SKAdNetwork te permite ver los datos en un plazo de 0 a 2 días, mientras que la versión 3.5 permite 24 horas de forma predeterminada. (Según las capacidades de tu socio de atribución de aplicaciones, es posible que puedas modificar esta ventana de actividad de forma general a no más de 72 horas). Cuando los usuarios instalan la app y la abren por primera vez, el SDK activa el evento first_open y se registra en BigQuery.

El identificador que puedes usar para BigQuery es user_pseudo_id (también llamado ID de instancia de la app), por lo que puedes usar la siguiente consulta para encontrar a estos usuarios.

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'

Algunos aspectos que debes tener en cuenta sobre esta búsqueda

  • Reemplaza el nombre de la tabla por la tabla exportada de Analytics. Puedes usar comodines para consultar varias tablas diarias. Por ejemplo, 2023* realizará la búsqueda en todos los datos de 2023.
  • Si tienes muchos usuarios, también puedes consultar solo los últimos 30 días para un procesamiento más rápido.
  • Aplicamos un filtro en platform = "IOS". En caso de que tengas varias apps para iOS en tu proyecto de Firebase, también puedes agregar un filtro para app_info.firebase_app_id y obtener datos de la app específica.

Recuperación de datos de ingresos

Ahora veamos una consulta para encontrar los ingresos de tus usuarios. En este caso, supondríamos que tus eventos de ingresos son in_app_purchase y ad_impression. Los ingresos provenientes de in_app_purchase están disponibles en event_value_usd, mientras que, para ad_impression, los ingresos están disponibles en el parámetro value, dentro de los parámetros del evento. Si no conoces los parámetros de eventos en BigQuery, te recomendamos que consultes la definición aquí y que pruebes esta consulta de ejemplo en nuestra referencia oficial, que también abarca la extracción del 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')

Veamos qué hace la consulta. Estas son las cosas que notarías

  • En la cláusula WHERE, filtramos los eventos de ingresos, ya que solo nos interesan esos, y, como la última vez, buscamos datos de iOS.
  • Ahora, en la cláusula SELECT, tomamos el valor y la moneda del evento de ingresos publicitarios (ad_impression), y tomamos el event_value_in_usd cuando el evento es in_app_purchase.
  • Si envías datos en varias monedas, primero deberás alinearlos en una sola moneda para este análisis. Para los fines de este ejemplo, supondremos que la moneda de los ingresos financiados por publicidad también es el USD.

El resultado sería similar al siguiente (aquí se oculta la columna de user_pseudo_id).

1e1e6943e4b3a6d8.png

Cómo combinar estos datos

Hasta ahora, ejecutamos dos consultas: una para encontrar los datos de los usuarios que instalaron y abrieron la app, y otra para encontrar los ingresos de esos usuarios. Ahora, recordemos lo que analizamos sobre las limitaciones de SKAdNetwork. La ventana de atribución solo puede estar disponible entre 0 y 2 días después de la instalación. Por lo tanto, deberemos verificar las marcas de tiempo de los eventos de instalación y de ingresos, y solo tomaremos la información si se produce dentro de ese período. Ahora, intentemos combinarlo en una consulta que proporcione los ingresos totales de cada publicación dos días después de la instalación de la 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

La consulta solo intenta unir los datos de instalación y los datos de ingresos en el campo user_pseudo_id, y luego debemos asegurarnos de que la marca de tiempo esté dentro de los 2 días. Si usas SKAdNetwork 3.5, el valor predeterminado es de 24 horas, por lo que también puedes cambiar la condición para incluir solo los datos de 1 día.

Agrupa los ingresos en categorías

Después de la consulta anterior, tendrás el user_pseudo_id y los ingresos totales.

2c1986b93e937d19.png

Ahora, debemos combinar esto en discretizaciones que podamos usar para nuestros rangos de valores de conversión. Para ello, usaremos la función approx_quantiles en BigQuery, que crea automáticamente estos rangos. Para los fines de este ejemplo, supongamos que queremos crear 5 rangos, por lo que podemos usar SELECT approx_quantiles(total_revenue, 5) AS buckets.

Con eso, incorporemos esto a nuestra consulta general.

#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

Esta consulta dividirá los ingresos en 5 discretizaciones, y BigQuery intentará mantener una distribución de percentiles coherente.

ba46f5d993449948.png

Analiza la distribución de usuarios con estos intervalos

Este es un paso opcional si deseas comprender la distribución de tus usuarios en cada bucket. En nuestro ejemplo, los rangos de discretización que se devolvieron en la consulta anterior son los siguientes:

  • 0.1
  • 0.5
  • 2
  • 2.5
  • 5 [el último valor no se debe usar en la configuración del rango]

Para los rangos finales, ignoraremos el último bucket 5, ya que, por lo general, ese es el valor máximo, y podemos considerar que 2.5 es el último rango. Esto se debe a que los proveedores de atribución de aplicaciones suelen calcular el ROAS con la media del rango, por lo que se debe excluir el valor atípico para obtener un cálculo más uniforme.

Ahora intentaremos observar la cantidad de usuarios para cada fecha en todos los rangos, de modo que podamos comprender el volumen diario de usuarios en cada bucket. Podemos hacerlo con esta consulta de ejemplo, en la que puedes reemplazar los valores de los buckets por tus datos reales. La consulta se verá de la siguiente manera:

#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

Devolverá los usuarios en cada rango de ingresos para cada día, como se muestra a continuación. Si ves números muy bajos en algún bucket o una distribución generalmente desigual, es posible que desees ajustar la cantidad de buckets y volver a ejecutar la consulta.

bf7d73085fe94cb6.png

Información breve sobre SKAdNetwork 4.0

SKAdNetwork 4.0 proporciona varias ventanas de conversión de hasta 2 días, de 3 a 7 días y de 8 a 35 días. En el enfoque anterior, también puedes cambiar fácilmente la ventana para analizar los datos de estos casos adicionales. También están disponibles los valores generales de LOW, MEDIUM y HIGH. Nuevamente, si deseas usar este enfoque, puedes pensar en 3 discretizaciones. Por lo tanto, si cambias la cantidad de discretizaciones a 3, puedes obtener los umbrales para BAJO, MEDIO y ALTO.

4. Implementación con tu proveedor de atribución

Según la plataforma específica, es posible que esta orientación cambie. Para obtener la información más actualizada sobre este tema, trabaja con los representantes de la plataforma. Para los fines de este ejemplo, veremos cómo podemos implementar esta función en AppsFlyer

En la consulta que ejecutamos anteriormente, los rangos finales que recibimos como resultado fueron los siguientes:

ba46f5d993449948.png

  • Rango 1 : De 0 a 0.1
  • Rango 2 : 0.1 a 0.5
  • Rango 3 : De 0.5 a 2
  • Rango 4 : De 2 a 2.5

Recuerda que decidimos ignorar el último rango de ingresos, ya que será un valor atípico y sesgará los cálculos promedio de tu proveedor de atribución de aplicaciones.

AppsFlyer ofrece SKAN Conversion Studio, donde es muy sencillo ingresar esta información directamente en la IU. Puedes usar la versión 4.0 directamente o el modo "Personalizado" si usas la versión 3.5 y agregar la medición de "Ingresos". Luego, puedes agregar los rangos de ingresos que calculaste en el análisis anterior.

f8c56abdf9b405f4.png

Prácticas recomendadas y aprendizajes sobre Google Ads

Si ejecutas campañas en Google Ads y mides el impacto a través de un esquema de valores de conversión de SKAdNetwork, te dejamos algunas recomendaciones

  • Asegúrate de que la ventana de conversión que usas en Google Ads coincida con la ventana de actividad que especificaste en tu plataforma de atribución de aplicaciones. En el caso de la versión 3.5 de SKAdNetwork, es probable que esto ocurra en un plazo de 1 a 3 días, por lo que puedes ajustarlo según corresponda en Google Ads siguiendo los pasos que se indican aquí.

4fd625aae9d4a43.png

  • Si usas Appsflyer, actualmente el contador de eventos predeterminado es 1, lo que significa que no tiene en cuenta varios eventos por usuario. Si utilizas un modelo basado en eventos para la medición de SKAN y lo comparas con las campañas de CPA objetivo en Google Ads, puedes personalizarlo siguiendo esta guía de AppsFlyer.

6c7a4d703567700a.png

5. Felicitaciones

Felicitaciones, configuraste correctamente tu esquema de valores de conversión de SKAdNetwork. Ahora puedes supervisar los datos en tu informe de SKAdNetwork de Google Ads para verificar los valores de conversión de tus campañas de Google Ads una vez que se publiquen.

Aprendiste lo siguiente:

  • Cómo explorar los datos sin procesar enriquecidos de GA4F en BigQuery
  • Enfoque analítico para calcular los segmentos de ingresos de tu empresa
  • Implementa el esquema con AppsFlyer