Google 広告のコンバージョンと GA4 のキーイベントが合わないとき|管理画面で分けられる差を先に引き、月の数字は計測期間のあとに確定させる

Google 広告の[コンバージョン]と GA4 の購入のキーイベントの差には、管理画面だけで分けられる分(クリックの日と購入の日の違い、月末のあとに増える分、広告以外の購入)と、データの担当者に頼まないと分けられない分があります。管理画面での控え方、月の数字を暫定と確定に分ける決め方、原因の表、頼むときの突き合わせの表と SQL 5本を載せています。

この記事をシェア:
目次 クリックで開く

Google 広告の管理画面から先月のコンバージョンを書き写し、GA4 の購入の数と並べたら、合わなかった。月の半ばに管理画面を開き直すと、先月の数そのものも増えている。報告に書くのは、いつの、どの数なのか。

2つの数の差には、管理画面だけで分けられる分と、データの担当者に頼まないと分けられない分があります。クリックの日と購入の日の違い、月末のあとに増える分、広告以外の購入は前者です。毎月この2つの数を報告しているマーケティングの担当者向けに、管理画面での手順と、後者の頼み方をまとめました。

数字と図の出どころは、架空の通販サイトのクリックと購入のデータです。広告とデータの分析を手がける当社が、確かめ方を説明するために組み立てました。

2つの列は数える日が違う。どちらが多くなるかは、月の境目をまたぐ購入しだい

Google 広告のキャンペーンの表でいつも見る[コンバージョン]列は、購入が起きた日ではなく、広告がクリックされた日で数えます。ヘルプには「コンバージョンの日時ではなくクリックの日時に基づいて計算されます」とあります。広告費もクリックの日で計算されるので、コンバージョン単価や広告費用対効果は、この列で見ると正確です。

購入が起きた日で数える列も別にあり、名前は[コンバージョン(コンバージョンの日時別)]です。Google アナリティクスなどの数と比べるときに使う列です。GA4 で成果として数えるイベントは、2024年3月の変更から「キーイベント」と呼ばれています。キーイベントを読み込んで作ったコンバージョンも、Google 広告の中ではクリックの日で数えます。7月19日にクリックして20日に買った人は、Google 広告では19日、アナリティクスでは20日の購入です。

報告に使うのは、使い道で分けて両方です。費用と並べる単価や費用対効果は[コンバージョン]で、GA4 や自社の注文の記録と比べる数は[コンバージョン(コンバージョンの日時別)]で見ます。

7月から9月の、同じ購入を購入の日とクリックの日で数えた月の数。7月は250件と258件、8月は243件と233件、9月は225件と233件
同じ購入でも、購入の日で数えるか、クリックの日で数えるかで、月の数が変わる

図は、同じ購入を2つの日付で数え分けたものです。購入の日で数えた月の数から、前の月にクリックしてこの月に買った分を引きます。そこに、この月にクリックして翌月以降に買った分を足すと、クリックの日で数えた月の数になります。

どちらの列が多くなるかは、この2つの分の大小で決まります。例のデータでも、7月は購入の日で250件・クリックの日で258件、8月は243件・233件でした。

管理画面で分けられる差は3つ。2つの列と google / cpc に絞った GA4 の購入を控える

先に、計測期間を押さえておきます。計測期間(クリックスルー コンバージョンの計測期間)は、クリックのあと何日までの購入を Google 広告に記録するかの設定で、既定は30日です。GA4 のキーイベントの数は、この期間に関係なく購入を数えます。

3つの差を分けるために、月ごとにすることは次の4つです。

  1. Google 広告のキャンペーンの表で、[表示項目の変更]から[コンバージョン(コンバージョンの日時別)]を足し、[コンバージョン]と並べます。月ごとに2つの数を書き写し、書き写した日(以下、控えた日)を横に書きます。
  2. GA4 は[レポート]で、購入のキーイベントを[セッションの参照元 / メディア]が google / cpc の行に絞り、同じ月の数を書き写します。GA4 の[広告]の[コンバージョン パフォーマンス]に出るのは、キーイベントではなく Google 広告と共有したコンバージョンなので、ここでは使いません。
  3. Google 広告の表の[分類]から[コンバージョン]→[コンバージョンまでの日数]を開き、購入がクリックの何日後に起きているかを見ます。見るのは、ヘルプの条件どおり、30日以上前(計測期間がより長ければ、それよりも前)に終わった月です。
  4. 設定を控えます。同じ購入でも、設定が違えば数が変わるからです。Google 広告は、コンバージョン アクションの計測期間・カウント方法・メイン/サブ、アトリビューション モデルと、アカウントのタイムゾーンです。GA4 は、プロパティのタイムゾーンと、アトリビューション設定のレポート用のアトリビューション モデル、「貢献度が割り当てられるチャネル」です。
管理画面で控える数の図。GA4 の購入のキーイベント444件を google / cpc に絞った数を A とし、[コンバージョン(コンバージョンの日時別)]225件、[コンバージョン]233件。管理画面で分けられない差は A から225を引いた数。データの担当者に頼むと分かれる内訳として、広告のクリックから来た人の購入263件と、うち計測期間の外38件
画面で控えた2つの数の引き算(A − 225)が、管理画面で分けられない差になる

9月で見ると、GA4 の購入のキーイベントは444件、[コンバージョン]に当たる数は、月末から計測期間がたったあとで233件でした。この2つを並べて「広告の成果が少なく出ている」と読むのは、引ける差を引いてからにします。

まず、GA4 を google / cpc に絞ると、自然検索やメールなど広告のクリックから来ていない購入が外れます。Google 広告は、そのアカウントの広告へのクリックなどから起きた成果しか数えないからです。次に、比べる相手を[コンバージョン]から[コンバージョン(コンバージョンの日時別)](例のデータで当たる数は225件)に替えます。233件との差は月の境目の分で、2つの列を並べれば分かります。

そのうえで、google / cpc に絞った GA4 の数から[コンバージョン(コンバージョンの日時別)]を引いた差が、管理画面で分けられない差です。図の A に当たる数は、例のデータでは作っていません。データの担当者に頼むと、この差のうち、計測期間の外(と2回目以降)の分が分かれます。例のデータでは、広告のクリックから来た人の購入が263件で、225件との差の38件は、クリックの日から30日間の外で起きた購入でした。ただし263件は購入1件ずつにクリックを結び付けた数で、画面で絞った A と同じになるとは限りません。A と263件の差は表には出ないので、原因の表の GCLID やアトリビューションの行で確かめます。

カウント方法が「初回のみ」なら、同じクリックからの2回目以降の購入も、管理画面で分けられない差に入ります。GA4 のキーイベントにもカウント方法(「イベントごとに 1 回」「セッションごとに 1 回」)があります。こちらはセッションの中で何回数えるかの設定で、単位が違います。

なお、貢献度が割り当てられるチャネルが[有料チャネルとオーガニック チャネル]なら、読み込んだコンバージョンの計測期間とカウント方法は GA4 側で決まります。「キーイベントのルックバック ウィンドウ」も効くので、GA4 の設定も控えます。どの計測期間・カウント方法にするか自体を見直すなら、広告のコンバージョンの定義を社内で持つ記事が役に立ちます。

クリックの日で数えた月は、月末から計測期間の日数がたつまでは増えうる

控えた数を比べるときに効くのは、いつ控えたかです。9月の数を、月末から何日後までのデータで数えたかで並べました。

9月の数を、月末から60日後までのデータで数えた線グラフ。クリックの日で数えた数は月末に191件、7日後までで213件、14日後までで223件、27日後までで233件。購入の日で数えた数は225件。10月1日に控えた9月191件を、もう増えない8月233件と並べると9月が減ったように見える
クリックの日で数えた9月は27日後までに233件になった。29日後より後には増えようがない

クリックの日で数えた数は、月末の時点で191件、7日後までのデータで213件、14日後までで223件でした。27日後までのデータで233件になり、そのあとは増えていません。9月30日のクリックは、計測期間30日なら10月29日(月末の29日後)まで数えるので、29日後より後には増えようがありません。27日後に届いたのは、例のデータの購入の起き方によるものです。

月末の時点の191件は、購入の日の225件から、前の月のクリックの分(34件)を引いた数です。翌月以降に買う分が、まだ1件も入っていません。当社が控える日を変えて数え直すと、動いたのはクリックの日で数えた数で、購入の日で数えた数は225件のままでした(処理の遅れを入れていないデータです。実際の管理画面では[コンバージョン(コンバージョンの日時別)]も数日は動きます)。

計測期間を7日にすると、クリックの日で数えた数は月末に163件、6日後までのデータで168件になり、それより後は増えませんでした。増えうる日数の上限は、計測期間の日数で決まります。

図の下の箱は、この増え方を知らずに並べた例です。10月1日に控えた9月の191件を、もう増えない8月の233件と並べると、9月が大きく減ったように見えます。10月30日以降に控え直すと、9月も233件でした。

確定日は計測期間のあとが基本。早めるなら、増え方が小さいことを確かめてから

月の数字を確定させる日の基本は、月末から計測期間の日数がたった日以降です。計測期間30日なら、9月分は10月30日以降に控え直した数です。計測期間が30日以上なら、手順3で書いた、[コンバージョンまでの日数]を見る前にヘルプが求めている条件とも合います。

そのうえで、処理の遅れを見込みます。Google 広告と GA4 の間の同期と処理に24〜48時間、大きな変更やアカウントのリンクのあとは最大7日かかることがあります。推定コンバージョンが安定するまでは最長5日、GA4 のキーイベントの貢献度は記録から最長12日、変わることがあります。何日に確定させるかの推奨はヘルプに見当たらなかったので、当社は計測期間に数日を足した日を、自社の確定日として1つ決めておく形をすすめています。計測期間30日なら、たとえば月末から35日後以降の最初の営業日(9月分なら11月4日)です。

この35日は、同期の24〜48時間と推定の最長5日を見込んだ日数です。大きな変更やアカウントのリンクのあとの最大7日は、まかなえない場合があるので、そうした変更をした月は確定日を遅らせます。GA4 の貢献度が変わる最長12日も、貢献度が割り当てられるチャネルを[有料チャネルとオーガニック チャネル]にしているなら、確定日を遅らせることを考えます。

それより早く、たとえば翌月7日に確定させたいなら、その日のあとの増え方が小さいことを先に確かめます。手順3の条件を満たす過去の月で、[コンバージョンまでの日数]を開き、クリックから7日をこえて起きる購入がどれくらいあるかを見ます。過去の月を、翌月7日と計測期間のあとの2回控えて比べてもかまいません。広告の月次レポートを判定の表から作る記事で翌月7日に取り直して確定にしている例は、自社の増え方を見て早めに締める運用です。ここでは、計測期間を待つ運用を基本にしています。

確定日より前に報告するときは、クリックの日の数に「暫定」と書き、[コンバージョン(コンバージョンの日時別)]を並べます。この列は月末のあとに起きた購入では増えないので、暫定の月の様子をつかむのに使えます。

月次の報告の表の例。10月8日に控えた、7月から9月の[コンバージョン]と[コンバージョン(コンバージョンの日時別)]、2つの列の差、状態。9月はクリックの日213件、購入の日225件で、暫定・11月4日に控え直す。7月と8月は確定。表の下に定義の1行
9月だけが暫定。クリックの日の数は、確定日に控え直すまで増えうる

報告の表の例です。見る場所は2つで、①は2つの列の差、②は月ごとの暫定・確定の印と、控え直す日です。この例は10月8日に控えたので、9月のクリックの日の213件はまだ途中の数です。

表の下には定義を1行で書きます。たとえば「コンバージョン=Google 広告の[コンバージョン](クリックの日、計測期間30日、全件)。9月分は10月8日に控えた暫定で、11月4日に控え直して確定」です。何の列を、どの設定で、いつ控えたかが書いてあれば、翌月に数が変わっても説明がつきます。

管理画面で分けられない差は、原因の表で確かめて理由を書き添える

差を出す前に、3つを見直します。google / cpc に絞った GA4 の数と[コンバージョン(コンバージョンの日時別)]を同じ日に控えたか、GA4 を google / cpc に絞ったか、確定日を過ぎているかです。確定日の前なら、確定日に控え直してから差を出します(それまでは暫定)。

それでも残る差は、次の表の原因から来ています。上から確かめます。

原因確かめる場所どうするか
計測期間の外、同じクリックからの2回目以降(カウント方法)コンバージョン アクションの計測期間・カウント方法([有料チャネルとオーガニック チャネル]なら GA4 の設定)理由を書き添えて確定。分けたいならデータの担当者に頼む
タイムゾーンの違いGoogle 広告のアカウントと GA4 のプロパティのタイムゾーン理由を書き添えて確定。分けたいならデータの担当者に頼む
GCLID(Google クリック ID)が届いていない自動タグ設定。ランディング ページのリダイレクト(?gclid=test を付けて開き、URL に残るかを見る)設定を直す。直す前の月は理由を書き添えて確定
別の Google 広告アカウントのクリック同じサイトに広告を出しているアカウント比べる範囲をそろえる
メイン/サブ、[すべてのコンバージョン]、ビュースルー コンバージョンコンバージョン アクションのメイン/サブ、比べている列比べる列をそろえる
アトリビューションの違い控えたアトリビューション モデルと、貢献度が割り当てられるチャネル理由を書き添えて確定
推定コンバージョン(クロスデバイス・同意)[クロスデバイス コンバージョン]列。すべてのコンバージョン アクションの合計なので、差からそのまま引けない。同意による推定を分けて見る列はヘルプに見当たらない理由を書き添えて確定
無効なクリック[無効なクリック数][無効なインタラクション回数]列。クリックの数で、削除されたコンバージョンの数は出ない理由を書き添えて確定
処理の遅れ控えた日と、直前の設定の変更やアカウントのリンク確定日を遅らせる

どうするかは、大きく分けて3つです。そろえて比べ直すか、理由を書き添えて確定するか、確定日を遅らせるかです。差が何%までなら問題ないという線は引きません。差の大きさではなく、行を1つずつ確かめて片づけます。

報告には、定義の1行の下に、この差の1行を添えます。たとえば「管理画面で分けられない差 ◯件:計測期間の外の購入、推定とアトリビューションによる。計測期間・カウント方法・タイムゾーンの設定は控えてある」です。GA4 の中で数が合わないとき(ユーザー数の推定や同意モードなど)は、GA4 の数値不整合の原因を確かめる記事で扱っています。

データの担当者に頼むのは、購入1件ずつにクリックの日を付けた突き合わせの表

計測期間の外や2回目以降の購入まで分けたいときは、データの担当者に突き合わせの表を頼みます。GA4 の購入から、Google 広告が数えない分を順に引いていく表です。

9月の突き合わせの表。GA4 の購入のキーイベント444件から、広告以外の購入181件、計測期間の外38件を引くと、購入の日で数えた数225件。前の月のクリックからの購入34件を引き、翌月以降に買った分42件を足すと、クリックの日で数えた数233件。カウント方法が初回のみなら、2回目以降の購入12件も引いて213件と212件
GA4 の購入444件から順に引き、管理画面の2つの列と比べる数(225件と233件)を出す

9月なら、444件から広告以外の購入(181件)と計測期間の外(38件)を引いた225件が、[コンバージョン(コンバージョンの日時別)]と比べる数です。そこから月の境目の分を直した233件が、[コンバージョン]と比べる数です。カウント方法が「初回のみ」なら、同じクリックからの2回目以降(12件)も引きます。表の終わりでは、順に引いて出した数とクリックの日で直接数えた数が同じになるかを見て、表の数え方を確かめます。

返ってくれば足りるのは、月ごとの各行の数と、比べる2つの数、それに数えた時点・計測期間・カウント方法の3つの条件です。数えた時点は、管理画面の数を控えた日の0時にそろえてもらいます。ずれると、クリックの日の数に、まだ数えていない購入の分が混ざります。表の数と管理画面の数がそれでも合わなければ、前の節の表の下の行(GCLID・アトリビューション・推定など)を確かめます。

表の作り方と、この記事の数字で言えないこと

例の数字は、6〜9月のクリック26,834件と11月末までの購入2,195件を BigQuery(東京)に入れ、下の5本の SQL で数えました。GA4 の BigQuery エクスポートと、Google 広告のクリックの表(ClickStats。BigQuery Data Transfer Service で転送)をつなぎます。キーイベントに基づく Google 広告のコンバージョンは BigQuery に出せるようになる予定が無い(GA4 のヘルプのよくある質問)ので、数え方は表の中で指定します。エクスポートの始め方はGA4 と BigQuery の連携の記事にあります。

つなぐ鍵は collected_traffic_source.gclid です。どのイベントに入るかを書いた公式の説明は見当たらなかったので、同じ人の購入前90日以内で、この列が入っていた最後のイベントに結び付けました。当社が試したとき、GA4 の公開サンプル(2021年1月の表)にはこの列がありませんでした。クリックの表の元の ClickView は90日前までしか取れないので、突き合わせたい月の90日前から転送をためます。日付の基準のそろえ方はGA4 の BigQuery で日付が1日ずれるときの記事にあります。

同じ注文 ID の購入は1件にまとめます。GA4 が同じ ID の重複を除くのはウェブ ストリームのデータだけなので、アプリ ストリームの購入があれば、まとめるかどうかを分けて決めます。注文 ID が空の文字列・NULL・(not set) の購入をどう数えるかは、先に決めておきます(GA4 の購入を BigQuery で数え直す記事でも決めておく項目です)。GA4 のヘルプは空の文字列の購入を「すべて重複として除去」すると書いていますが、全部を除くのか1件を残すのかは、この文からは決めきれません。1. の SQL は先頭の設定で選べます(「1件にまとめる」は、読む期間全体で1件にします。決まった3つ以外の値を書くと、エラーで止まります)。例のデータにこうした購入を12件入れて比べると、注文の数は書き方によって2,186件から2,195件まで変わりました。

波かっこの所は、自社の表の名前・計測期間・カウント方法・数えた時点に置き換えます。計測期間の内か外かは、クリックの日と購入の日の差が計測期間の日数より小さいかで決めました(ヘルプの、3月1日のクリックを30日間なら3月30日まで数える例に合わせた)。時刻の単位での切り方は、ヘルプに見当たりませんでした。

0. 日付の基準を確かめる(kit_00_date_check.sql)
-- 0. 日付の基準が同じかを確かめる
-- GA4 の event_date は、プロパティのタイムゾーンの日付。event_timestamp は UTC のマイクロ秒。
-- 購入のイベントで、event_date が日本時間の日付と UTC の日付のどちらと一致するかを数える。
-- 日本時間と全件一致すれば、Google 広告のアカウントのタイムゾーン(日本時間)と同じ基準で突き合わせられる。
-- Google 広告のアカウントのタイムゾーンが日本時間でなければ、下の 'Asia/Tokyo' もそのタイムゾーンに書き換える。
-- 差し替える所:{EVENTS}・{SUFFIX_FILTER} は kit_01 と同じ(例:`プロジェクト.analytics_123456789.events_*` と _TABLE_SUFFIX BETWEEN '20260501' AND '20261130')
WITH events AS (
  SELECT * FROM {EVENTS} WHERE {SUFFIX_FILTER}
)
SELECT
  COUNT(*) AS purchase_events,
  COUNTIF(event_date = FORMAT_DATE('%Y%m%d', DATE(TIMESTAMP_MICROS(event_timestamp), 'Asia/Tokyo'))) AS same_as_tokyo,
  COUNTIF(event_date = FORMAT_DATE('%Y%m%d', DATE(TIMESTAMP_MICROS(event_timestamp)))) AS same_as_utc
FROM events
WHERE event_name = 'purchase';
1. 購入1件ずつに、結び付くクリックとクリックの日を付ける(kit_01_purchase_click.sql)
-- 1. 購入1件ずつに、結び付く広告のクリック(gclid)とクリックの日を付けた表を作る
-- 差し替える所:
--   {EVENTS}:GA4 の BigQuery エクスポート(例:`プロジェクト.analytics_123456789.events_*`)
--   {SUFFIX_FILTER}:読む日の範囲(例:_TABLE_SUFFIX BETWEEN '20260501' AND '20261130')。突き合わせる月の 90 日前から読む
--   {CLICKS}:Google 広告の ClickStats 表(BigQuery Data Transfer Service。例:`プロジェクト.google_ads.p_ads_ClickStats_1234567890`。表の名前は自社の転送で確かめる)
--   {OUT}:作る表(例:`プロジェクト.データセット.purchase_click`)
-- collected_traffic_source.gclid は、そのイベントと一緒に収集された Google クリック ID。
-- 購入(purchase)のイベントに入っているとは限らないので、同じ人(user_pseudo_id)の、購入の前 90 日以内に
-- gclid が入っていたイベントのうち最後のものに結び付ける。
-- これは Google 広告の実際の割り当て(アトリビューション モデル)の再現ではない。突き合わせのための決めごと。
--
-- 注文 ID(ecommerce.transaction_id)の扱い:
--   同じ注文 ID の購入は1件にまとめる(GA4 のヘルプ:同じトランザクション ID の購入イベントは重複が除去される。ウェブ ストリームのみ)。アプリ ストリームの購入があれば、stream_id で分けてから決める。
--   注文 ID が空の文字列(''。空白だけのものも含める)の購入:GA4 のヘルプに「transaction_id="" である購入イベントはすべて重複として除去されます」とあるので、既定は「除く」。
--   注文 ID が NULL か '(not set)' の購入:GA4 のヘルプに扱いの記載が見当たらないので、下の設定で選ぶ。
--   既定の「1件ずつ」は、重複除去は同じ注文 ID の購入どうしに働くので、注文 ID の無い購入は画面でもまとめられずに数えられると読んだため(当社の読み)。
--   除いた購入も表には残し、excluded_by_rule = TRUE を付ける(突き合わせの表で「除いた購入」の行に出す)。
--   「1件にまとめる」は、{SUFFIX_FILTER} で読む期間全体で1件になる(月ごとではない。まとめた中で最初の時刻の購入の月に入る)。
DECLARE empty_id_rule STRING DEFAULT '除く';        -- 注文 ID が '':'除く'(既定。ヘルプの記載どおり)/'1件にまとめる'/'1件ずつ'
DECLARE missing_id_rule STRING DEFAULT '1件ずつ';   -- 注文 ID が NULL・'(not set)':'1件ずつ'(既定)/'1件にまとめる'/'除く'
-- 設定の値が上の3つのどれでもなければ、ここで止める(書き違えたまま数えないため)
-- NULL も止める(NULL は NOT IN の比べで真にならず、止まらないまま数えてしまうため)
IF IFNULL(empty_id_rule, '') NOT IN ('除く', '1件にまとめる', '1件ずつ') OR IFNULL(missing_id_rule, '') NOT IN ('除く', '1件にまとめる', '1件ずつ') THEN
  SELECT ERROR(CONCAT('kit_01 の設定の値が違います:empty_id_rule=', IFNULL(empty_id_rule, 'NULL'), '、missing_id_rule=', IFNULL(missing_id_rule, 'NULL')));
END IF;

CREATE OR REPLACE TABLE {OUT} AS
WITH events AS (
  SELECT * FROM {EVENTS} WHERE {SUFFIX_FILTER}
),
ad_visits AS (   -- gclid が入っていたイベント(人と gclid ごとに、最初の時刻)
  SELECT user_pseudo_id, collected_traffic_source.gclid AS gclid, MIN(event_timestamp) AS visit_ts
  FROM events
  WHERE collected_traffic_source.gclid IS NOT NULL
  GROUP BY user_pseudo_id, gclid
),
purchase_events AS (   -- 購入のイベント。注文 ID の種類を分け、1件ずつ数えるときの鍵(人ごとの通し番号)を付ける
  SELECT
    user_pseudo_id,
    ecommerce.transaction_id AS transaction_id,
    event_timestamp AS conv_ts,
    PARSE_DATE('%Y%m%d', event_date) AS conv_date,
    CASE
      WHEN ecommerce.transaction_id IS NULL OR TRIM(ecommerce.transaction_id) = '(not set)' THEN 'missing'
      WHEN TRIM(ecommerce.transaction_id) = '' THEN 'empty'   -- 空白だけの注文 ID も空の文字列と同じに扱う(ヘルプの記載は "" だけで、空白だけの扱いは見当たらない)
      ELSE 'id'
    END AS id_kind,
    CONCAT('row:', IFNULL(user_pseudo_id, ''), ':',
           CAST(ROW_NUMBER() OVER (PARTITION BY user_pseudo_id ORDER BY event_timestamp) AS STRING)) AS row_key
  FROM events
  WHERE event_name = 'purchase'
),
keyed AS (       -- まとめる鍵と、除くかどうかを、上の2つの設定から決める
  SELECT
    * EXCEPT (row_key),
    CASE
      WHEN id_kind = 'id' THEN CONCAT('id:', transaction_id)
      WHEN id_kind = 'empty' AND empty_id_rule = '1件にまとめる' THEN 'empty'
      WHEN id_kind = 'missing' AND missing_id_rule = '1件にまとめる' THEN CONCAT('missing:', IFNULL(transaction_id, 'NULL'))
      ELSE row_key
    END AS order_key,
    (id_kind = 'empty' AND empty_id_rule = '除く') OR (id_kind = 'missing' AND missing_id_rule = '除く') AS excluded_by_rule
  FROM purchase_events
),
purchases AS (   -- 同じ鍵は最初の1件にまとめ、何件あったかを残す
  SELECT
    *,
    COUNT(*) OVER (PARTITION BY order_key) AS events_same_id
  FROM keyed
  WHERE TRUE
  QUALIFY ROW_NUMBER() OVER (PARTITION BY order_key ORDER BY conv_ts) = 1
),
linked AS (      -- 購入の前 90 日以内にあった、同じ人の最後の gclid
  SELECT p.*, v.gclid, v.visit_ts
  FROM purchases AS p
  LEFT JOIN ad_visits AS v
    ON v.user_pseudo_id = p.user_pseudo_id
   AND v.visit_ts <= p.conv_ts
   AND v.visit_ts >= p.conv_ts - 90 * 86400 * 1000000
  WHERE TRUE
  QUALIFY ROW_NUMBER() OVER (PARTITION BY p.order_key ORDER BY v.visit_ts DESC) = 1
),
clicks AS (      -- クリックの日とキャンペーン(gclid ごとに1行)
  SELECT click_view_gclid, ANY_VALUE(segments_date) AS click_date, ANY_VALUE(campaign_id) AS campaign_id
  FROM {CLICKS}
  GROUP BY click_view_gclid
)
SELECT
  l.order_key, l.transaction_id, l.id_kind, l.excluded_by_rule, l.user_pseudo_id, l.conv_ts, l.conv_date, l.events_same_id, l.gclid,
  c.click_date, c.campaign_id,
  DATE_DIFF(l.conv_date, c.click_date, DAY) AS days_from_click,           -- クリックの日から購入の日までの日数
  IF(l.gclid IS NULL OR l.excluded_by_rule, NULL,
     ROW_NUMBER() OVER (PARTITION BY l.gclid, l.excluded_by_rule ORDER BY l.conv_ts)) AS nth_for_click   -- 同じクリックからの何回目の購入か(除いた購入は数えない)
FROM linked AS l
LEFT JOIN clicks AS c ON c.click_view_gclid = l.gclid;
2. 突き合わせの表を作る(kit_02_bridge.sql)
-- 2. 突き合わせの表:GA4 の購入から、Google 広告が数えない分を順に引き、管理画面の2つの列と比べる数を出す
--    d_by_conv_date は[コンバージョン(コンバージョンの日時別)]と比べる数(購入の日で数えた数)、
--    h_by_click_date は[コンバージョン]と比べる数(クリックの日で数えた数)。check_diff は表の数え方の検算の差(0なら合っている)
-- 差し替える所:
--   {PC}:kit_01 で作った表(例:`プロジェクト.データセット.purchase_click`)
--   {AS_OF}:数えた時点。日本時間の 'YYYY-MM-DD HH:MM:SS'。この時刻より前の購入だけを使う
--            例:'2026-10-01 00:00:00'=9月末までのデータ。管理画面の数と比べるときは、管理画面の数を控えた日の 0 時にする
--            Google 広告のアカウントのタイムゾーンが日本時間でなければ、下の 'Asia/Tokyo' もそのタイムゾーンに書き換える
--   {WINDOW}:計測期間(クリックスルー コンバージョンの計測期間)の日数。例:30
--   {COUNT_MODE}:カウント方法。'全件' か '初回のみ'(Google 広告のコンバージョン アクションの設定と同じにする)
-- 結果を表に保存するとき(kit_03 の {BRIDGE} に使う):
--   1) 下の「WITH p AS (」の行の前に、次の1行を足す
--        CREATE OR REPLACE TABLE `プロジェクト.データセット.bridge_20261001` AS
--      (表の名前には {AS_OF} の日付を入れておくと、どの時点の表か分かる)
--   2) いちばん最後の「ORDER BY month;」を「;」にする
--   3) 3行の DECLARE はそのまま残して、全体を1回で実行する
DECLARE as_of TIMESTAMP DEFAULT TIMESTAMP('{AS_OF}', 'Asia/Tokyo');  -- 数えた時点(この時刻より前の購入だけを使う)
DECLARE window_days INT64 DEFAULT {WINDOW};                           -- 計測期間の日数
DECLARE count_mode STRING DEFAULT '{COUNT_MODE}';                     -- カウント方法:'全件' か '初回のみ'

WITH p AS (
  SELECT
    *,
    NOT excluded_by_rule AND gclid IS NOT NULL AS from_ad,                    -- 広告のクリックからの訪問が前にある購入
    NOT excluded_by_rule AND click_date IS NOT NULL
      AND days_from_click < window_days AS in_window,                          -- 計測期間の内(3月1日のクリック・30日間→3月30日までに合わせた)
    (count_mode = '全件' OR nth_for_click = 1) AS counted                      -- カウント方法を当てたとき数えるか
  FROM {PC}
  WHERE conv_ts < UNIX_MICROS(as_of)
),
by_conv AS (     -- 購入の日の月で数える
  SELECT
    DATE_TRUNC(conv_date, MONTH) AS m,
    SUM(events_same_id) AS a0_purchase_events,                                 -- GA4 の purchase のイベント数
    SUM(IF(excluded_by_rule, events_same_id, 0)) AS a_excluded,                -- kit_01 の設定で除いた購入(注文 ID が '' など)
    COUNTIF(NOT excluded_by_rule) AS a_orders,                                 -- 注文 ID ごとに1件にした数
    COUNTIF(NOT excluded_by_rule AND id_kind <> 'id') AS a_no_order_id,        -- うち注文 ID の無い購入(NULL・'(not set)' など)
    COUNTIF(from_ad) AS b_from_ad,
    COUNTIF(from_ad AND click_date IS NULL) AS b_click_not_found,              -- gclid がクリックの表に無い
    COUNTIF(from_ad AND click_date IS NOT NULL AND NOT in_window) AS b_outside_window,
    COUNTIF(in_window) AS c_in_window,
    COUNTIF(in_window AND counted) AS d_by_conv_date,                         -- 購入の日で数えた数([コンバージョン(コンバージョンの日時別)]と比べる)
    COUNTIF(in_window AND counted AND DATE_TRUNC(click_date, MONTH) < DATE_TRUNC(conv_date, MONTH)) AS e_clicked_in_earlier_month
  FROM p
  GROUP BY m
),
by_click AS (    -- クリックの日の月で数える
  SELECT
    DATE_TRUNC(click_date, MONTH) AS m,
    COUNTIF(in_window AND counted) AS h_by_click_date,                        -- クリックの日で数えた数([コンバージョン]と比べる)
    COUNTIF(in_window AND counted AND DATE_TRUNC(conv_date, MONTH) > DATE_TRUNC(click_date, MONTH)) AS f_bought_in_later_month
  FROM p
  WHERE click_date IS NOT NULL
  GROUP BY m
)
SELECT
  m AS month,
  IFNULL(a0_purchase_events, 0) AS a0_purchase_events,
  IFNULL(a0_purchase_events, 0) - IFNULL(a_excluded, 0) - IFNULL(a_orders, 0) AS same_order_id_dup,
  IFNULL(a_excluded, 0) AS excluded_by_rule,
  IFNULL(a_orders, 0) AS a_orders,
  IFNULL(a_no_order_id, 0) AS no_order_id,
  IFNULL(a_orders, 0) - IFNULL(b_from_ad, 0) AS not_from_ad,
  IFNULL(b_from_ad, 0) AS b_from_ad,
  IFNULL(b_click_not_found, 0) AS click_not_found,
  IFNULL(b_outside_window, 0) AS outside_window,
  IFNULL(c_in_window, 0) AS c_in_window,
  IFNULL(c_in_window, 0) - IFNULL(d_by_conv_date, 0) AS second_or_later,
  IFNULL(d_by_conv_date, 0) AS d_by_conv_date,
  IFNULL(e_clicked_in_earlier_month, 0) AS e_clicked_in_earlier_month,
  IFNULL(f_bought_in_later_month, 0) AS f_bought_in_later_month,
  IFNULL(d_by_conv_date, 0) - IFNULL(e_clicked_in_earlier_month, 0) + IFNULL(f_bought_in_later_month, 0) AS g_bridge,
  IFNULL(h_by_click_date, 0) AS h_by_click_date,
  IFNULL(d_by_conv_date, 0) - IFNULL(e_clicked_in_earlier_month, 0) + IFNULL(f_bought_in_later_month, 0) - IFNULL(h_by_click_date, 0) AS check_diff   -- 検算の差(0なら表の数え方は合っている)
FROM by_conv
FULL JOIN by_click USING (m)
ORDER BY month;
3. 管理画面から控えた数と並べて、差を出す(kit_03_reconcile_ui.sql)
-- 3. Google 広告の管理画面の数と並べ、数え方で説明のつかない差を出す
--    unexplained_diff_* は説明のつかない差。0になるとは限らない(推定・アトリビューションなど、数え方の外の理由で出る)
--    kit_02 の check_diff(表の数え方の検算の差。0なら合っている)とは別のもの
-- 差し替える所:
--   {UI}:管理画面の数を月ごとに書き写した表。列は month DATE(月の1日)、conversions FLOAT64([コンバージョン]列)、
--         conversions_by_conv_time FLOAT64([コンバージョン(コンバージョンの日時別)]列)、taken_on DATE(控えた日=書き写した日)
--         作り方の例(数字は控えた値に替える):
--           CREATE OR REPLACE TABLE `プロジェクト.データセット.ads_ui_20261001`
--             (month DATE, conversions FLOAT64, conversions_by_conv_time FLOAT64, taken_on DATE);
--           INSERT INTO `プロジェクト.データセット.ads_ui_20261001` VALUES
--             (DATE '2026-09-01', 191, 225, DATE '2026-10-01');
--   {BRIDGE}:kit_02 の結果を保存した表(kit_02 の先頭のコメントの手順)。
--             kit_02 の {AS_OF} は、控えた日(taken_on)の 0 時にそろえる。ずれると、クリックの日の差に「まだ数えていない購入の分」が混ざる
SELECT
  u.month,
  u.taken_on,
  u.conversions_by_conv_time,
  b.d_by_conv_date,
  ROUND(u.conversions_by_conv_time - b.d_by_conv_date, 2) AS unexplained_diff_by_conv_time,   -- 購入の日どうしの説明のつかない差(調べる分)
  u.conversions,
  b.h_by_click_date,
  ROUND(u.conversions - b.h_by_click_date, 2) AS unexplained_diff_by_click_date               -- クリックの日どうしの説明のつかない差
FROM {UI} AS u
LEFT JOIN {BRIDGE} AS b USING (month)
ORDER BY u.month;
4. 月末から何日後までのデータで数えたかを並べる(kit_04_close_day.sql)
-- 4. 月の数字を確定させる日を決める表:月末から n 日後までのデータで数えると、その月の数字はどう変わるか
-- 購入の日で数えた数(by_conv_date、[コンバージョン(コンバージョンの日時別)]と比べる数)と、
-- クリックの日で数えた数(by_click_date、[コンバージョン]と比べる数)を、同じ n で並べる。
-- 差し替える所:{PC}=kit_01 で作った表、{WINDOW}・{COUNT_MODE}=kit_02 と同じ、
--   {M0}・{M1}=見る月の最初と最後(月の1日。例:2026-06-01 と 2026-09-01)、{NMAX}=月末から何日後まで見るか(例:60)
--   Google 広告のアカウントのタイムゾーンが日本時間でなければ、下の 'Asia/Tokyo' もそのタイムゾーンに書き換える
-- 読み方:クリックの日の数が、ある n から先で変わらなくなる。計測期間が W 日なら、増えうるのは n=W−1 まで(月の最後の日のクリックの計測期間の最後の日)
DECLARE window_days INT64 DEFAULT {WINDOW};
DECLARE count_mode STRING DEFAULT '{COUNT_MODE}';

WITH p AS (
  SELECT
    *,
    NOT excluded_by_rule AND click_date IS NOT NULL AND days_from_click < window_days AS in_window,   -- kit_01 の設定で除いた購入は数えない
    (count_mode = '全件' OR nth_for_click = 1) AS counted
  FROM {PC}
),
grid AS (
  SELECT m, n, UNIX_MICROS(TIMESTAMP(DATE_ADD(LAST_DAY(m), INTERVAL n + 1 DAY), 'Asia/Tokyo')) AS as_of_micros
  FROM UNNEST(GENERATE_DATE_ARRAY(DATE '{M0}', DATE '{M1}', INTERVAL 1 MONTH)) AS m,
       UNNEST(GENERATE_ARRAY(0, {NMAX})) AS n                -- n=月末から何日後までのデータか(0=月末まで)
)
SELECT
  g.m AS month,
  g.n AS days_after_month_end,
  COUNTIF(p.in_window AND p.counted AND DATE_TRUNC(p.conv_date, MONTH) = g.m AND p.conv_ts < g.as_of_micros) AS by_conv_date,
  COUNTIF(p.in_window AND p.counted AND DATE_TRUNC(p.click_date, MONTH) = g.m AND p.conv_ts < g.as_of_micros) AS by_click_date
FROM grid AS g
CROSS JOIN p
GROUP BY month, days_after_month_end
ORDER BY month, days_after_month_end;
突き合わせの表の行と SQL の列名(9月の値)
表の行SQL の列9月
GA4 の購入のキーイベントa0_purchase_events444
同じ注文 ID の重複same_order_id_dup0
決めに従って除いた購入excluded_by_rule0
注文の数a_orders444
うち注文 ID の無い購入no_order_id0
広告以外の購入not_from_ad181
広告からの購入b_from_ad263
クリックの表に無い GCLIDclick_not_found0
計測期間の外outside_window38
計測期間の内c_in_window225
2回目以降の購入(初回のみのとき)second_or_later0(初回のみなら12)
購入の日で数えた数([コンバージョン(コンバージョンの日時別)]と比べる)d_by_conv_date225
前の月のクリックからの購入e_clicked_in_earlier_month34
翌月以降に買った分f_bought_in_later_month42
順に引いて出した数(検算用)g_bridge233
クリックの日で数えた数([コンバージョン]と比べる)h_by_click_date233
検算の差(0なら表の数え方は合っている)check_diff0

3. の SQL の unexplained_diff_by_conv_time・unexplained_diff_by_click_date は、表の数と管理画面の数の差で、0になるとは限りません。

この記事の数字で言えないこともあります。例のデータに入れたのは数え方の違いだけで、処理の遅れ、推定、無効なクリックによる削除、アトリビューションやタイムゾーンの違いは入れていません。Google 広告の数も、管理画面ではなく、その数え方で SQL で数え直したものです。クリックの表には無効なクリックも入ります。GA4 から読み込んだコンバージョンの[コンバージョン(コンバージョンの日時別)]の日付が、イベントの時刻か読み込んだ時刻かは、ヘルプで確かめられませんでした。

ヘルプの内容は2026年10月23日と24日に確かめたものです。突き合わせが合っても、広告が無くても起きた購入を除いた、広告で増えた分は分かりません。その測り方は広告で増えた分だけを測る記事にあります。

先月分の2つの列を、今日と計測期間のあとの2回控える

まず今日、先月分の[コンバージョン]と[コンバージョン(コンバージョンの日時別)]を、GA4 の google / cpc の数と一緒に控えます。計測期間の日数がたった日にもう一度控えれば、自社の数が月末のあとにどれだけ増えるかが分かり、確定日を早められるかも判断できます。

この2回の控えと突き合わせの表を、月次の報告の決まった作業にするところまでを、当社の広告運用の支援とデータ集計の仕組みづくりの中で、一緒に組み立てられます。

広告運用支援

Google広告・Meta広告・LINE広告・Yahoo!広告の運用を、GA4やCRMとのデータ連携を土台に立て直します。コンバージョン計測の整備から媒体をまたいだ改善まで、社内で判断できる形で伴走します。

AT
aurant technologies 編集

上場企業からスタートアップまで、数多くのデータ分析基盤構築・AI導入プロジェクトを主導。単なる技術提供にとどまらず、MA/CRM(Salesforce, Hubspot, kintone, LINE)導入によるマーケティング最適化やバックオフィス業務の自動化など、常に「事業数値(売上・利益)」に直結する改善実績多数。

この記事が役に立ったらシェア:

広告運用の資料

「Meta CAPI / 広告計測高度化ガイド」

広告運用支援の内容を見る