InfraGuard

訪問者・検索インサイト

サイトごとに保存したサービスアカウントとプロパティ紐付けを使い、GA4 のビジター分析と Search Console の検索トラフィックを Web サイトカードから直接参照します。

概要 — 何をする画面か

サービス ▸ Web の各カードでは ユニークビジター 数の横に2つのアイコンが並び、それぞれモーダルを開きます。

アイコン モーダル データ元
人物 ビジター分析 Google Analytics 4(Analytics Data API)
虫めがね 検索トラフィック Google Search Console(Search Analytics API)

カードの nginx_meta_ct アクセスインテルが 自サーバーが受け取ったもの を教えるのに対し、この2つのモーダルは 訪問者がどこから来たのか、どの検索語が連れてきたのか を教えます — サーバーログにはそもそも含まれていない情報です。

WordPress で Site Kit が行っていることは、突き詰めれば レポートのリクエストを代わりに組み立てること です。Laravel では自分で組み立てれば同じ数値が得られるため、プラグインも google/apiclient も使いません — 作業の全体は「秘密鍵で JWT に署名し、アクセストークンと交換する」だけであり、サーバーはそれをネイティブに署名できます。REST エンドポイント2つのために巨大な依存ツリーを抱えるのは割に合いません。

こんなときに使う

画面構成

どちらのモーダルも 概要 / キーワード / トラフィック のタブに分かれており(キーワードタブは検索モーダルにのみ存在します)、スクロールではなくタブ切り替えで見ます。期間セレクターは 7 / 28 / 90 日 を提供します — サーバー側でホワイトリスト化されているものと同じ集合です。

ビジター分析(GA4)

チャネルとソースは同じものではありません。 チャネルはまとめられた答え(Organic Search)、ソースは具体的な答え(google・naver・github.com)です。とくに韓国のサイトでは、naver か google かで、流入の物語がまったく別のものになります。

検索トラフィック(Search Console)

平均掲載順位はインプレッション加重です。 単純平均では、掲載順位1位のインプレッション1件が40位の1万件を相殺してしまい、数値を実態よりはるかに良く見せてしまいます。

設定手順

1. サービスアカウントを作成する(Google Cloud)

  1. Google Cloud Console → プロジェクトを選択または作成 → IAM と管理 ▸ サービス アカウント → サービス アカウントを作成。プロジェクトレベルのロールは不要です。
  2. 作成したアカウントを開く → キー → 鍵を追加 ▸ 新しい鍵を作成 ▸ JSON → ファイルをダウンロードします。
  3. API とサービス ▸ ライブラリ で Google Analytics Data API と Google Search Console API を有効化します。

2. InfraGuard に登録する

サービス ▸ Web ▸ Web サイト管理 ▸ 対象サイトの編集タブ、Google 連携 の下で設定します。

項目 値 入手先
GA4 プロパティ ID 数字のみ(例 550688232) GA4 の管理 ▸ プロパティの詳細、または URL #/a<account>p<property>/ の p の後ろ
Search Console プロパティ sc-domain:example.com または https://example.com/ Search Console のプロパティ選択に表示される文字列そのまま
サービスアカウント JSON ダウンロードしたファイル 全体 を貼り付け —

GA4 のプロパティ ID はアカウント ID ではありません。 #/a405285491p550688232/ では、a の後ろがアカウント、p の後ろがプロパティ です。Google は「そのようなプロパティは存在しない」と「権限がない」を意図的に区別しません(プロパティの存在自体が情報だからです)。そのため番号を間違えると、権限の問題とまったく同じに見えます。まずプロパティ ID を確認してください。

Search Console のプロパティをドメインから推測してはいけません。 それがドメインプロパティ(sc-domain:)なのか URL プレフィックス(https://…/)なのかは、所有権を確認した本人しか知りません。選択を誤ると エラーではなく空の結果 が返ります。

3. 各プロパティにサービスアカウントを招待する

JSON はあくまで身元にすぎず、アクセス権は プロパティごと に付与します。保存後に表示される client_email をコピーして、次を行います。

プロパティ 場所 ロール
GA4 管理 ▸ プロパティ のアクセス管理 ▸ + 閲覧者
Search Console 設定 ▸ ユーザーと権限 ▸ ユーザーを追加 フル

GA4 ではこれは プロパティ のアクセス管理であり、アカウント のアクセス管理ではありません(左の列がアカウント、真ん中がプロパティです)。Search Console は制限付きではなく フル にしてください — Search Analytics API は制限付きユーザーを拒否します。サービスアカウントには受信箱がないため、「メールで通知」のチェックは外してください。

4. 接続をテストする

管理モーダルの [接続テスト] は、保存済みの認証情報で両方の API を1回ずつ(直近7日)呼び出し、それぞれの結果を個別に報告します。

状態 意味
ok Google が応答しました。0件でも成功です — 新しいサイトや GSC の遅延はエラーではありません
fail Google 自身の文言と、招待すべき client_email
skip プロパティが未設定のためスキップしました(失敗ではありません)

認証情報がまったくない場合は何も呼び出しません(外部リクエストはゼロ)。未保存の編集内容はテストされません — 先に保存してください。

正しさのルール — なぜ数値をこのように組み立てるのか

以下は Site Kit がすでに実証した落とし穴に倣ったもので、いずれも根拠のあるものです。

ルール 理由
期間は 昨日で終わる 当日は集計途中のため、含めると右端が必ず落ち込んで見えます
GA4 は metricAggregations:['TOTAL'] の totals[0] を読む limit の掛かった行を合計すると、見出しの数値が過少になります
すべての GA4 リクエストに hostName の in-list フィルター 1つのプロパティが複数ホストにまたがることは多く、これがないとカードにプロパティ全体のトラフィックが出ます。カードの vts 集計と正確に一致させるため、そのサービスが保有するすべてのドメイン(主ドメイン・追加ドメイン・www)を渡します
ランキングは keepEmptyRows:false + notExpression{emptyFilter} を使う GA4 の (not set) は実在の都市やソースを日常的に上回ってしまいます
時系列は keepEmptyRows:true を使う トラフィックが0の日が軸から消えてはいけません
GSC は dataState:'all' と約2日の遅延を用いる これがないと直近数日が0として読め、トラフィックの急落に見えます
ドメインプロパティは page contains でスコープを絞る sc-domain: は全サブドメインにまたがるため、兄弟サイトのキーワードが混入します

データソース

対象 接続 / 場所 役割
infr_web_service.ga4_property_id · gsc_site_url default(000771) サイトごとのプロパティ紐付け
infr_web_service.google_cred_enc · google_cred_email default(000772) サイトごとのサービスアカウント(Crypt、書き込み専用)
Analytics Data API properties/{id}:runReport 外部 ビジターレポート
Search Console searchAnalytics/query 外部 検索トラフィックレポート

サービス: Services\Google\{GoogleTokenService, GoogleReportService, SiteInsightService}、エンドポイントは Service\WebController@insight{Visitors,Search,Test}。

キャッシュ: レポートのレスポンスはキャッシュされ、キャッシュキーには実行主体(client_email)が含まれます。同じ URL・同じ本文でも別アカウントからのリクエストは別の認可であり、キーを共有すると、あるサイトに別のサイトのキャッシュ応答を返してしまいます。

認証情報がサイトごとである理由

グローバルな .env キー1つでは 成り立ちません。 登録されたサイトはそれぞれ別のオーナー、したがって別の Google アカウントに属し、1つのサービスアカウントは招待されたプロパティしか読めません — 顧客が2社になった瞬間、どちらかが必ず失敗します。だからこそサイトごとに貼り付ける欄があります。

認証情報の欄は 触れたときにだけ送信されます。フォームが秘密鍵を受け取り直すことはないため、「送られてこない=消去」と解釈すると、メモだけを編集したときにも認証情報が消えてしまいます。明示的に空にすることだけが削除の方法です。

アクセス権限

対象は 登録済みサイトの id でのみ 指定します — プロパティ ID をパラメーターで渡すことはできません。呼び出し側がプロパティを指定できるなら、当方のサービスアカウント権限が 他人の GA4/Search Console プロパティを読む経路になってしまいます(カタログのライブテスト と同じ SSRF 回避の規律です)。期間も同様にサーバー側で 7/28/90 にホワイトリスト化されています。

トラブルシューティング・FAQ

関連項目

순 방문자 옆의 방문자 · 검색 아이콘
순 방문자 옆의 방문자 · 검색 아이콘