Search Console の検索パフォーマンス(クリック数・表示回数・CTR・平均掲載順位)を、Search Console API で取得し、運用ダッシュボードのヘッダーに常時表示する構成です。認証にはサービスアカウントを使い、権限は読み取りだけに絞ります。要点は次の 5 つです。
- 取得は Search Console API(`searchanalytics.query`)、認証はサービスアカウント
- 設定は 3 か所: Google Cloud で API を有効化 → サービスアカウントの鍵(JSON)を用意 → Search Console にサービスアカウントを「制限付き」ユーザーとして追加
- 権限はスコープ `webmasters.readonly` と「制限付き」の二重で、読み取りだけ
- データは 2〜3 日遅れて入るため、集計期間は「今日まで」ではなく「データのある最終日までの 28 日」にする
- 平均掲載順位は日ごとの値の単純平均ではなく、表示回数で重み付けして集計する
構成

| 表示 | 内容 |
|---|---|
| CLICKS | 28 日間のクリック数と、前の 28 日間との差(▲▼、改善は緑) |
| IMPR | 28 日間の表示回数と差 |
| CTR | クリック率(クリック ÷ 表示回数)と差 |
| POS | 平均掲載順位と差(値が小さいほど上位。矢印は数値の増減、改善は緑) |
| グラフ | 28 日間の表示回数の日次推移 |
処理の流れは次のとおりです。
1. ダッシュボード(Flask)が取得用の Python スクリプトを呼ぶ(結果は 1 時間保持)2. スクリプトがサービスアカウントの鍵で認証する3. `searchanalytics.query` で日別・ページ別・検索語別の数値を取得する4. 集計した JSON をダッシュボードが表示する
認証の仕組み
サービスアカウントは、人ではなくプログラム用の Google アカウントです。
- メールアドレス(`…@….iam.gserviceaccount.com`)を持ち、Search Console にはこのアドレスをユーザーとして追加する
- パスワードの代わりに秘密鍵(鍵ファイル JSON の `private_key`)を持つ。アドレスは同じファイルの `client_email`
- ライブラリは秘密鍵で署名した JWT を Google のトークンエンドポイントに送り、OAuth 2.0 のアクセストークン(有効期限 1 時間)を受け取る。API はこのトークンで呼ぶ
人のアカウントを使わないため、権限を必要最小限(最小権限の原則)に絞れます。Search Console の権限は「オーナー」「フル」「制限付き」の 3 段階で、データの閲覧だけなら「制限付き」で足ります。
鍵ファイルを持っていれば誰でもそのサービスアカウントとして API を呼べるため、リポジトリや公開フォルダには置かず、認証情報専用のフォルダで管理します。
設定
1. Search Console API を有効にする
Google Cloud コンソールでサービスアカウントのあるプロジェクトを選び、「Google Search Console API」を有効にします。

サービスアカウントは「IAM と管理 → サービスアカウント」で作成し、「鍵 → 鍵を追加 → JSON」で鍵ファイルを発行します。ここでは、Google スプレッドシートの読み取り用に作成済みのサービスアカウントを流用しました。
2. Search Console にユーザーとして追加する
Search Console の「設定 → ユーザーと権限 → ユーザーを追加」で、サービスアカウントのアドレスを権限「制限付き」で追加します。

3. 取得のコード
中心部分です。
from google.oauth2.service_account import Credentials
from googleapiclient.discovery import build
creds = Credentials.from_service_account_file(
"service-account.json",
scopes=["https://www.googleapis.com/auth/webmasters.readonly"], # 読み取りだけ
)
sc = build("searchconsole", "v1", credentials=creds)
rows = sc.searchanalytics().query(
siteUrl="sc-domain:ekplabz.com", # ドメイン プロパティの書き方
body={
"startDate": "2026-10-06",
"endDate": "2026-11-02",
"dimensions": ["date"], # 日別。"page" / "query" でページ別・検索語別
"dataState": "all", # 確定前の新しい日も含める(既定は final)
"rowLimit": 1000, # 1 回の上限は 25,000 行
},
).execute().get("rows", [])
- `siteUrl` はプロパティの種類で書き方が変わる。ドメイン プロパティは `sc-domain:ドメイン`、URL プレフィックスは `https://example.com/`(末尾のスラッシュまで一致させる)
- `dataState: “all”` にすると、確定前の直近のデータも返る。確定値だけなら `final`
- 取得できるのは過去 16 か月分
集計の要点
期間の決め方: 直近 70 日の日別データを取り、データのある最終日を終点にして 28 日をさかのぼります。比較期間はその前の 28 日です。今日を終点にすると、データ未反映の日が 0 として入り、数値が実際より小さく出ます。
合計の式:
| 指標 | 式 |
|---|---|
| クリック数・表示回数 | 日別の値の合計 |
| CTR | 合計クリック数 ÷ 合計表示回数 |
| 平均掲載順位 | Σ(日別の順位 × 日別の表示回数)÷ 合計表示回数 |
平均掲載順位を日別の値の単純平均にすると、表示回数の少ない日の順位が過大に効きます。
証明書エラー: Windows で `CERTIFICATE_VERIFY_FAILED` が出る場合があります。Python の HTTP ライブラリは既定で certifi の証明書を使うため、セキュリティソフトなどが Windows の証明書ストアに入れた証明書を信頼できないことが原因です。`truststore` を使い、OS の証明書ストアで検証させると解消します。
import truststore
truststore.inject_into_ssl()
結果
2026 年 10 月 6 日〜11 月 2 日の実測値と、前の 28 日間の比較です。
| 指標 | 今の 28 日 | 前の 28 日 |
|---|---|---|
| クリック | 42 | 13 |
| 表示回数 | 1,318 | 398 |
| CTR | 3.2% | 3.3% |
| 平均掲載順位 | 7.7 | 9.7 |
クリックと表示回数はおよそ 3 倍、平均掲載順位は 2.0 改善しました。クリックの多いページは、DXF のファイル構造の記事、tools.ekplabz.com の油圧配管の圧力損失ツール、GitHub の Issue の記事などです。数値が日常の作業画面に常に出ているため、確認のために Search Console を開く必要がなくなりました。
制約と次の段階
- インデックス数(ページのインデックス登録レポート)は API で一括取得できない。URL 検査 API は 1 URL ずつで、1 日の上限がある
- 記事の公開日を数値の推移に重ねて表示し、公開の効果を見えるようにする
