SKAd Network コンバージョン値スキーマの収益バケットを計算する

1. はじめに

始める前に

iOS アプリのデベロッパーの方は、iOS 14.5 以降のプライバシーの更新をご存じかもしれません。インストール後の有意なコンバージョン アクションを測定するために、Apple は SKAd Network API を提供しています。この API を使用すると、ユーザーのプライバシーを尊重しながら広告キャンペーンの成果を測定できます。ビジネスニーズに応じて、SKAd Network を活用してキャンペーンに関する有意な分析情報を取得する最適な方法を検討できます。この Codelab では、BigQuery の GA4F データを活用して、アプリのインストール後の収益をバケットにグループ化し、App Attribution Partner とともに設定するためのサンプル手法を確認します。この Codelab では収益ベースのアプローチを使用していますが、SKAN 測定にはイベントベースまたはファネルベースのアプローチも使用できます。詳しくは、こちらのヘルプセンターをご参照ください。これはあくまで一例であり、Google の公式推奨事項ではありません。特定のビジネスニーズに基づいて独自のスキーマを設計できます。

説明する内容

  • BigQuery で GA4F データを探索する
  • 0 ~ 2 日以内にコンバージョンに至ったユーザーの収益データを確認できます
  • 収益データをバケットにグループ化する
  • 各バケット内のユーザー分布を把握する
  • Appsflyer SKAN Conversion Studio でバケットを実装する

前提条件

  • iOS アプリに GA4F SDK が組み込まれており、すべての収益イベント(in_app_purchase または ad funded revenue)が統合されている
  • Firebase から BigQuery へのエクスポートが有効
  • すべての収益イベントも記録している App Attribution Partner

2. BigQuery Export へのアクセス

[プロジェクト設定] > [統合] > [BigQuery] に移動して、GA4F のデータセットに移動します。最初に切り替えを有効にする必要があります。有効にしてからデータセットが使用可能になるまでに 48 時間ほどかかります。以下のリンクをクリックすると、BigQuery に移動します。

1aa4e20bfd3419d1.png

クエリを実行する

BigQuery に移動すると、生成された日次テーブルが表示されます。以下のスクリーンショットの例では、64 個の 1 日ごとのテーブルが表示されているため、エクスポートは 64 日間実行されています。初めてアクセスする場合は、前日のデータの 1 つの日次テーブルのみが表示されることがあります。右側にテーブル スキーマが表示されます。各項目の詳細については、こちらをご覧ください。

クエリの作成を開始するには、[クエリ] > [新しいタブ] をクリックします。

42ba59ec655c5d1b.png

その後、新しいタブでサンプルクエリを実行してみてください

70ef90d32b7cd7f1.png

3. 収益データを分析する

インストール データの取得

収益バケットの構築を始めるには、まず過去 24 ~ 72 時間以内にアプリをインストールしたユーザーのデータを確認する必要があります。SKAd Network 4.0 では 0 ~ 2 日で、SKAd Network 3.5 では 24 時間でデータを表示できます。(アプリ アトリビューション パートナーの機能によっては、このアクティビティ期間を 72 時間以内に変更できる場合があります)。ユーザーがアプリをインストールして初めて開くと、SDK によって first_open イベントが発生し、BigQuery に記録されます。

BigQuery で使用できる識別子は user_pseudo_id(アプリ インスタンス ID とも呼ばれます)であるため、以下のクエリを使用してこれらのユーザーを見つけることができます。

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'

このクエリについて注意すべき点

  • テーブル名を、アナリティクスのエクスポートしたテーブルに置き換えてください。ワイルドカード を使用すると、複数の日次テーブルに対してクエリを実行できます。たとえば、2023* は 2023 年のすべてのデータをクエリします。
  • ユーザー数が多い場合は、過去 30 日間のみクエリを実行して処理を高速化することもできます。
  • プラットフォーム =「IOS」でフィルタします。Firebase プロジェクトに複数の iOS アプリがある場合は、app_info.firebase_app_id のフィルタを追加して、特定のアプリのデータを取得することもできます。

収益データの取得

次に、ユーザーの収益を確認するクエリを見てみましょう。この場合、収益イベントは in_app_purchase と ad_impression であると想定されます。in_app_purchase の収益は event_value_usd で、ad_impression の収益はイベント パラメータの value パラメータで確認できます。BigQuery のイベント パラメータについてよく知らない場合は、こちらで定義を確認することをおすすめします。また、event_params から値を抽出する方法も取り上げている Google の公式リファレンスでこのサンプルクエリを試すこともできます

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')

ここでクエリの内容を理解しましょう。このように

  • WHERE 句では、収益イベントのみを対象とするため、収益イベントをフィルタしています。前回と同様に、iOS データのみを検索しています。
  • SELECT 句では、広告収入イベント(ad_impression)の値と通貨を取得し、イベントが in_app_purchase の場合は event_value_in_usd を取得します。
  • 複数の通貨を送信している場合は、まずこの分析用に単一の通貨に統一する必要があります。この例では、広告収入の通貨も米ドルであると仮定します。

出力は次のようになります(ここでは user_pseudo_id 列は削除されています)。

1e1e6943e4b3a6d8.png

このデータを組み合わせる

ここまでで、2 つのクエリを実行しました。1 つはアプリをインストールして開いたユーザーのデータを調べるクエリ、もう 1 つはそれらのユーザーの収益を確認するクエリです。ここまで、SKAd Network の制限について説明しました。アトリビューション期間は、インストール後 0~2 日間のみ利用できます。そのため、インストールと収益のイベントのタイムスタンプを確認し、その期間内に発生した場合にのみ情報を取得する必要があります。次に、アプリのインストールから 2 日後の各日の合計収益を取得するクエリを作成してみます。

#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

このクエリは、インストール データと収益データを user_pseudo_id フィールドで結合しようとします。このとき、タイムスタンプが 2 日以内であることを確認する必要があります。SKAd Network 3.5 を使用している場合、デフォルトは 24 時間です。1 日分のデータのみが含まれるように条件を変更することもできます

収益をバケットにグループ化

前のクエリを実行すると、user_pseudo_id と合計収益が取得されます。

2c1986b93e937d19.png

これを、コンバージョン値の範囲に使用できる複数のバケットに分ける必要があります。この目的のために、BigQuery の approx_quantiles 関数を使用します。この関数はこれらの範囲を自動的に作成します。この例では、5 つの範囲を作成する必要があるため、SELECT approx_quantiles(total_revenue, 5) AS buckets を使用します。

それでは、これをクエリ全体に組み込みましょう。

#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

このクエリは収益を 5 つのバケットに分割し、BigQuery は一定のパーセンタイル分布を維持しようとします。

ba46f5d993449948.png

これらのバケットでユーザー分布を分析する

各バケットでのユーザーの分布を把握する場合は、この手順は省略できます。この例では、前のクエリで返されたバケット範囲は次のとおりです。

  • 0.1
  • 0.5
  • 2
  • 2.5
  • 5 [最後の値は範囲構成で使用しない]

最後の範囲では、最後のバケット 5 は無視します。これは通常最大値であるため、2.5 を最後の範囲と見なすことができます。これは、アプリ アトリビューションのプロバイダでは広告費用対効果の計算に範囲の平均値を使用する傾向があるため、計算の均一性を高めるために外れ値は除外する必要があるためです。

各バケットの 1 日あたりのユーザー数を把握できるように、すべての範囲の日付ごとにユーザー数を確認します。バケットの値を実際のデータに置き換えると、このクエリは次のようになります。

#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

以下のように、各収益範囲のユーザーが日ごとに返されます。いずれかのバケットで値が非常に低い場合や、全体的に分布が不均一な場合は、バケット数を調整してクエリを再実行することをおすすめします。

bf7d73085fe94cb6.png

SKAd Network 4.0 について

SKAd Network 4.0 の計測期間は、最大 2 日間、3 ~ 7 日間、8 ~ 35 日間です。上記のアプローチでは、期間を簡単に変更して、これらの追加シナリオのデータも分析できます。LOW、MEDIUM、HIGH の大まかな値も使用できます。繰り返しになりますが、このアプローチを使用する場合は 3 つのバケットと考えることができます。つまり、バケット数を 3 に変更すると、LOW、MEDIUM、HIGH のしきい値を取得できます。

4. アトリビューション プロバイダと連携する

プラットフォームによっては、このガイダンスが変更される場合があります。最新情報については、プラットフォームの担当者にお問い合わせください。この例では、現在 AppsFlyer でこの機能をデプロイする方法について説明します。

前に実行したクエリで、出力として受け取った最終的な範囲は以下のようになります。

ba46f5d993449948.png

  • 範囲 1 : 0 から 0.1
  • 範囲 2 : 0.1 ~ 0.5
  • 範囲 3: 0.5~2
  • 範囲 4 : 2 ~ 2.5

最後の収益範囲は無視してください。これは外れ値であり、アプリ アトリビューション プロバイダの平均計算に歪みが生じるためです。

AppsFlyer の SKAN Conversion Studio では、この値を UI に直接入力できます。4.0 を直接使用するか、3.5 を使用している場合は「カスタム」モードを使用して「収益」測定を追加します。そして、以前の分析で計算した収益の範囲を追加するだけです。

f8c56abdf9b405f4.png

Google 広告のベスト プラクティスと教訓

Google 広告でキャンペーンを実施し、SKAd Network コンバージョン値スキーマで影響を測定している場合は、以下の推奨事項を参考にしてください。

  • Google 広告で使用している計測期間が、アプリ アトリビューション プラットフォームで指定したアクティビティ期間と一致していることを確認してください。SKAdNetwork 3.5 では、この期間は 1~3 日以内である可能性が高いため、こちらの手順に沿って Google 広告で調整できます。

4fd625aae9d4a43.png

  • Appsflyer を使用している場合、現在のデフォルトのイベント カウンタは 1 です。つまり、ユーザーごとに複数のイベントを考慮していません。SKAN 測定にイベントベースのモデルを使用し、Google 広告の目標アクション単価キャンペーンと比較している場合は、Appsflyer のこちらのガイダンスに沿ってカスタマイズできます。

6c7a4d703567700a.png

5. 完了

SKAd Network コンバージョン値スキーマのセットアップが完了しました。Google 広告の SKAdNetwork レポートでデータをモニタリングし、Google 広告キャンペーンのコンバージョン値を確認できるようになりました

学習した内容

  • GA4F の豊富な元データを BigQuery で探索する方法
  • ビジネスの収益バケットを計算する分析的アプローチ
  • AppsFlyer を使用してスキーマをデプロイする