はじめに:国と言語が混ざると分析が崩れる
越境ECを始めると、アクセス解析が一気に複雑になります。日本国内向けのECなら「日本のユーザーが日本語で買う」という前提で済みますが、海外に売り始めた瞬間、その前提は崩れます。
たとえば、こんな状況が同時に起こります。
- 台湾からのアクセスだが、ブラウザの言語設定は英語
- アメリカ在住の日本人が日本語でサイトを閲覧している
- 香港のユーザーが繁体字と簡体字のどちらでも閲覧できてしまう
- VPN経由で本来とは違う国としてカウントされる
このとき、GA4の標準レポートで「国」だけ、あるいは「言語」だけを見て判断すると、施策の優先順位を間違えます。「英語圏が伸びている」と思って英語の広告に投資したら、実は英語設定のまま日本語で買っている在外日本人だった、というのはよくある話です。
越境ECで本当に知りたいのは「どの国の市場が売上を生んでいるか」であり、それを正しく出すには国と言語を分けて扱う必要があります。GA4の管理画面だけでは限界があるので、この記事ではBigQueryエクスポートを使って国別に正確に集計する方法を解説します。
GA4エクスポートの geo.country と device.language
GA4をBigQueryにエクスポートすると、events_* テーブルに国と言語の情報が含まれます。越境ECで主に使うのは次の2つです。
geo.country:イベント発生時の推定国
geo.country は、GoogleがIPアドレスなどから推定したユーザーの所在国です。値は「Japan」「United States」「Taiwan」のような英語の国名文字列で入ります。ISOコードではない点に注意してください。
関連するフィールドとして、geo.region(地域・州)、geo.city(都市)、geo.continent(大陸)もあります。国単位で粗すぎる場合は地域まで掘り下げられます。
注意点として、geo.country は「市場としての国」を表すのに最も近い指標ですが、あくまで推定です。後述するように、VPNやモバイル回線で実際の所在地とずれることがあります。
device.language:ブラウザ/端末の言語設定
device.language は、ユーザーの端末やブラウザの言語設定です。「ja-jp」「en-us」「zh-tw」のような小文字のロケール文字列で入ります。
ここで重要なのは、device.language は「サイトをどの言語で表示したか」ではなく「ユーザーの端末がどの言語に設定されているか」だという点です。多言語サイトで実際に表示した言語を知りたい場合は、page_location のパス(例:/en/)や、自前で送信するカスタムパラメータを使う必要があります。
つまり、geo.country が「どこの市場か」、device.language が「ユーザーがどの言語を好むか」を表していて、この2つを掛け合わせて初めて越境ECの実態が見えてきます。
国別の売上・CVを集計するSQL
それでは、purchase イベントから国別の売上とコンバージョン数を集計してみます。GA4のeコマースでは、購入金額は ecommerce.purchase_revenue または event_params の value に入ります。ここでは標準的な ecommerce.purchase_revenue_in_usd を例にします。
SELECT
geo.country AS country,
COUNT(DISTINCT
(SELECT ep.value.string_value
FROM UNNEST(event_params) ep
WHERE ep.key = 'transaction_id')
) AS purchases,
COUNT(DISTINCT user_pseudo_id) AS buyers,
ROUND(SUM(ecommerce.purchase_revenue_in_usd), 2) AS revenue_usd
FROM `your_project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260701' AND '20260731'
AND event_name = 'purchase'
GROUP BY country
ORDER BY revenue_usd DESC;
transaction_id を COUNT(DISTINCT ...) で数えているのは、同じ購入が複数回送信される重複を排除するためです。GA4の購入イベントは稀に二重計上されるので、件数を正確に出したい場合は注文IDで一意にカウントするのが安全です。
さらに、国と言語を掛け合わせて見ると、先ほど述べた「在外日本人」のような層が浮かび上がります。
SELECT
geo.country AS country,
device.language AS language,
COUNT(DISTINCT
(SELECT ep.value.string_value
FROM UNNEST(event_params) ep
WHERE ep.key = 'transaction_id')
) AS purchases,
ROUND(SUM(ecommerce.purchase_revenue_in_usd), 2) AS revenue_usd
FROM `your_project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260701' AND '20260731'
AND event_name = 'purchase'
GROUP BY country, language
ORDER BY revenue_usd DESC
LIMIT 50;
このクエリで「United States × ja-jp」のように、英語圏なのに日本語設定の組み合わせがまとまった売上を持っていたら、それは在外日本人の市場です。英語の広告ではなく、日本語のまま海外配送の訴求をした方が効く可能性が高い、と判断できます。
国を主語にした集計をベースに、言語はあくまで補助線として使うのがコツです。
通貨換算・タイムゾーンの扱い
越境ECで国別集計をするとき、つまずきやすいのが通貨とタイムゾーンです。
通貨
GA4には2系統の金額フィールドがあります。
ecommerce.purchase_revenue:イベント送信時の通貨(event_paramsのcurrencyで単位が分かる)での金額ecommerce.purchase_revenue_in_usd:GoogleがUSDに換算した金額
複数通貨で販売している場合、purchase_revenue をそのまま合計すると、円とドルとユーロを足し算してしまい無意味な数字になります。国別の合計を出すなら、いったんUSD換算済みの purchase_revenue_in_usd で揃えるのが手堅い方法です。
ただし、Googleの換算レートはイベント発生時点のもので、自社の会計上のレートとは一致しません。経理の数字と突き合わせる用途では、currency 別に元通貨のまま集計し、自社で定めた固定レートを掛け直す方が、説明可能性が高くなります。
SELECT
geo.country AS country,
(SELECT ep.value.string_value
FROM UNNEST(event_params) ep WHERE ep.key = 'currency') AS currency,
ROUND(SUM(ecommerce.purchase_revenue), 2) AS revenue_original
FROM `your_project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260701' AND '20260731'
AND event_name = 'purchase'
GROUP BY country, currency
ORDER BY country;
タイムゾーン
GA4の event_timestamp はUTCのマイクロ秒です。日付で区切るとき、どのタイムゾーンで「1日」を切るかで集計結果が変わります。
日本のEC事業者が日本時間で運用しているなら、日付の境界を日本時間に揃えるのが自然です。
SELECT
DATE(TIMESTAMP_MICROS(event_timestamp), 'Asia/Tokyo') AS jst_date,
geo.country AS country,
COUNT(*) AS purchases
FROM `your_project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260701' AND '20260801'
AND event_name = 'purchase'
GROUP BY jst_date, country
ORDER BY jst_date;
ここで注意したいのは、海外の購入は現地では別の日付かもしれないということです。日本時間の深夜は、アメリカでは前日の昼です。セール期間を「現地時間で何日まで」と区切っている場合、集計のタイムゾーンと販売ルールのタイムゾーンを一致させないと、境界の前後で件数がずれます。どのタイムゾーンを基準にするかは、最初に決めて記録しておくのが大切です。
_TABLE_SUFFIX の範囲は日付シャードに対するものなので、JSTで切りたいときは前後1日を余分に含めてからフィルタすると取りこぼしを防げます。
⚠️ 地域判定の限界
ここまで国別集計の方法を説明してきましたが、geo.country には構造的な限界があります。これを理解せずに数字を鵜呑みにすると、誤った市場判断につながります。
主な限界は次のとおりです。
- VPN・プロキシ:実際とは違う国として記録されます。プライバシー意識の高い地域ほど影響が出ます。
- モバイルキャリアのIP集約:通信事業者によっては、別の地域のIPが割り当てられ、所在国がずれることがあります。
- 同意がない場合のデータ欠損:Consent Modeで計測同意が得られないと、イベント自体が送られなかったり推定で補完されたりします。地域によって同意率が違うため、国別の比率に偏りが出ます。
(not set)の存在:IPから国を推定できないアクセスはgeo.countryが(not set)になります。これを除外するか別枠で扱うかで、合計が変わります。- 推定の粒度:都市レベルになるほど精度は落ちます。
geo.city単位の判断は慎重にすべきです。
実務上の対処としては、第一に geo.country を「絶対値」ではなく「相対的な傾向」として読むことです。「Aの国がBの国の約2倍」という大小関係は信頼できても、「ちょうど何件」という精緻さは期待しすぎないのが安全です。
第二に、配送先住所のような確定情報がある場合は、受注システム側の国情報を正とし、GA4は流入や行動の分析に使う、と役割を分けることです。GA4の地域判定はあくまでマーケティング判断のための推定であり、請求や配送の根拠データではありません。
このあたりの「GA4の数字と受注システムの数字が合わない」問題への向き合い方は、BigQueryでEC受注データとGA4を結合して売上帰属を出す方法でも詳しく扱っています。
まとめ
越境ECの分析では、国と言語を混同せず分けて扱うことが出発点になります。この記事の要点を整理します。
geo.countryは市場としての国、device.languageはユーザーの言語の好みを表す- 国を主語に集計し、言語は在外層などを見抜く補助線として使う
- 金額はUSD換算で揃えるか、元通貨+自社レートで揃えるかを目的別に選ぶ
- 日付の境界はタイムゾーンを最初に決めて統一する
geo.countryは推定であり、VPNや同意状況で偏る。絶対値ではなく傾向として読む
GA4の標準レポートだけでは、こうした掛け合わせや通貨・タイムゾーンの調整は難しいですが、BigQueryエクスポートを使えば自社の運用に合わせた正確な集計ができます。
国別の流入が出せるようになったら、次はその流入の「質」を見る段階です。チャネルごとの流入品質を比較する考え方は、GA4×BigQueryでSNS流入の質を測定して比較した記事が参考になります。まずは小さく、自社の主要な数か国だけでも国別集計を回してみることをおすすめします。