PR
AIで記事作成を効率化したいなら → 高品質SEO記事生成AIツール【Value AI Writer byGMO】
※本記事は、2026年10月に実際に構築・運用している内容の記録です。Google APIの仕様や管理画面の場所は変更される可能性があります。
こんにちは!Conomacです。
「今週もAnalyticsの管理画面を開いて、CSVを落として、前回の数字と見比べて…」。ブログを複数運営していると、分析そのものより「データを集める作業」に時間を持っていかれることはありませんか。
当ブログでは3つのサイトを運営していて、Search Console(GSC)とGA4のデータを毎回手作業でエクスポートしていました。GA4はプロパティの切り替え、GSCはプロパティ選択、そして落としたCSVを日付フォルダに整理して…と、地味に手数が多い作業です。
そこで今回は、Google APIとサービスアカウントでGSC・GA4のデータを自動取得する仕組みを作りました。いまは毎週決まった時間にデータが落ちてきて、前回比較のレポートまで自動で作られる状態です。この記事では、方式の選び方、セットアップ手順、そして「APIの数字は本当に画面のエクスポートと一致するのか」の検証結果までまとめます。
この記事でわかること
- GSC・GA4をAPIで自動取得する全体構成と役割分担
- OAuthではなくサービスアカウントを選ぶべき理由(7日でトークンが切れる罠)
- 外部ライブラリなしでサービスアカウント認証を書く方法
- 取得した数字が画面エクスポートとバイト単位で一致することの検証手順
- 「数値が合わない」と誤解しやすい書式の罠(丸め・改行コード・%表記)
手作業のどこが辛いのか
自動化の前に、実際に手作業のどこが負担だったのかを整理します。意外と「API化しても同じ手間では?」と思われがちなので、ここを明確にしておくのが大事です。
- サイト数だけ手数が増える:3サイトあれば、GSCのエクスポートを3回、GA4のプロパティ切り替えを3回
- GA4はプロパティ切り替えを忘れると別サイトの数字を落とす:実際に「中身が同一のCSVが2枚」という事故がありました
- 窓がずれる:GSCの書き出しは取得日までの28日分なので、前回と今回で期間がズレて単純比較できない
- やらないと数字が止まる:手作業は忙しいと後回しになり、気づけば1か月空く
つまり、自動化で消したいのは「分析」ではなく「収集と整形」と「実行の忘れ」です。ここを分けて考えると、作るべきものが見えてきます。
方式の選択:OAuthではなくサービスアカウント
Google APIを使う方法は大きく2つあります。結論から言うと、定期実行するならサービスアカウント一択です。
| 方式 | 有効期限 | 定期実行との相性 |
|---|---|---|
| OAuth(ブラウザで同意) | アプリが「テスト」状態だとリフレッシュトークンが7日で失効 | 毎週必ず止まる。7日ごとに再同意が必要 |
| サービスアカウント(採用) | なし(鍵を消すまで有効) | そのまま動き続ける |
OAuthの「7日失効」は、個人開発で非常によくハマる罠です。テスト用アプリのままだとリフレッシュトークンが1週間で無効になり、週次で回したい自動化がちょうど1回動いたあとに死にます。
サービスアカウントなら鍵ファイルを1回作るだけで済み、しかも読み取り専用のスコープしか要求しないので、原理的にデータを書き換えられません。「見るだけ」の自動化には適した方式です。
全体構成:判断と実行を分ける
今回の構成はシンプルです。認証とデータ取得をスクリプトが担当し、分析はAIエージェント(OpenClaw)が担当します。
| 工程 | 担当 |
|---|---|
| Google APIの認証(JWT署名→トークン交換) | Node.jsスクリプト |
| GSC・GA4からのデータ取得とCSV整形 | Node.jsスクリプト |
| 前回との比較・改善候補の抽出 | AIエージェント |
| 定期実行(毎週決まった時間) | スケジューラ |
ポイントは「数値の取得と整形はコード、解釈はLLM」という分担です。数字をLLMに作らせると検算できないので、取得と整形は機械的に、意味づけだけをAIに任せます。
セットアップ手順
1. Google CloudでAPIを有効化する
Google Cloud Consoleでプロジェクトを作り、「APIとサービス」→「ライブラリ」から次のAPIを有効化します。
- Google Search Console API
- Google Analytics Data API
- Google Analytics Admin API(プロパティ一覧を自動で引くため。任意)
2. サービスアカウントを作り、鍵(JSON)を落とす
「認証情報」→「認証情報を作成」→「サービスアカウント」で作成し、ロールは付与しません(権限は次の手順でGSC・GA4側から与えます)。作成後に「キー」タブからJSON形式の鍵をダウンロードします。
この鍵ファイルは、Gitリポジトリの外(例:ホームディレクトリ配下の設定フォルダ)にパーミッション600で置きます。クラウドにアップロードしたり、チャットに貼ったりは絶対にしません。
3. Search Consoleにサービスアカウントを追加する
GSCの各プロパティで「設定」→「ユーザーと権限」→「ユーザーを追加」を開き、サービスアカウントのメールアドレス(xxxx@プロジェクトID.iam.gserviceaccount.com形式)を権限「フル」で追加します。読み取りしかしないので実害はありません。
4. GA4にサービスアカウントを追加する
GA4の「管理」→「プロパティのアクセス管理」で、同じメールアドレスをロール「閲覧者」で追加します。
5. 外部ライブラリなしで認証を書く
意外と知られていませんが、サービスアカウント認証はNode.jsの標準モジュールだけで書けます。googleapisパッケージは不要です。やることは「JWT(RS256)を自分で署名して、トークンエンドポイントに交換してもらう」だけです。
import crypto from 'node:crypto';
const b64url = (input) => Buffer.from(input).toString('base64')
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
const now = Math.floor(Date.now() / 1000);
const header = b64url(JSON.stringify({ alg: 'RS256', typ: 'JWT' }));
const claims = b64url(JSON.stringify({
iss: serviceAccount.client_email,
scope: 'https://www.googleapis.com/auth/webmasters.readonly',
aud: 'https://oauth2.googleapis.com/token',
iat: now,
exp: now + 3600,
}));
const signer = crypto.createSign('RSA-SHA256');
signer.update(header + '.' + claims);
const assertion = header + '.' + claims + '.' + b64url(signer.sign(serviceAccount.private_key));
// この assertion を grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer でPOSTするとアクセストークンが返る
依存パッケージがゼロなので、壊れる要因が少ないのが気に入っています。鍵の置き場所さえ守れば、数年動き続けます。
つまずき①:権限を追加したつもりで403
最初の実行でいきなりHTTP 403が出ました。原因は単純で、GSCへのユーザー追加が済んでいなかっただけです。GA4側だけ追加して満足していました。
切り分けは「GSCは403/GA4は通る」ならGSCの権限、逆ならGA4のアクセス管理、とどちらのAPIで落ちたかを見るのが最短です。エラー本文のURLに searchconsole が入っているか analyticsdata が入っているかで、ほぼ確定できます。
つまずき②:プロパティ文字列は「URLプレフィックス」と「ドメイン」で別物
2つ目の罠はHTTP 404です。GSCのプロパティは、登録の仕方で文字列そのものが変わります。
- URLプレフィックス プロパティ →
https://example.com/(末尾のスラッシュまで含めて完全一致) - ドメイン プロパティ →
sc-domain:example.com(プロトコルなし・スラッシュなし)
私の場合、同じサイトでも1つはURLプレフィックス、もう1つはドメインプロパティで登録されていて、推測で書いた設定が404になりました。ここは推測せず、sites.list(GSCのプロパティ一覧を返すAPI)を叩いて実際にAPIから見える文字列をそのまま使うのが確実です。一覧を出すスクリプトを1本作っておくと、設定ミスが激減します。
つまずき③:APIと画面で数字が合わない、と思ったら書式の違いだった
これが今回いちばん面白かった発見です。取得したCSVを、管理画面から手で落としたCSVと突き合わせると、合計値は完全一致しているのに、ファイルの中身はけっこう違いました。
原因は数値ではなく書式でした。APIは生の値を返し、管理画面は表示用に加工してから書き出すためです。
| 項目 | 管理画面のエクスポート | APIの生値 |
|---|---|---|
| 平均掲載順位 | 列によって小数1桁(6.5) |
6.54 |
| ちょうど0.5の丸め | 銀行丸め(5.625→5.62) |
加工なし |
| CTR | 1.1%(末尾ゼロを削る) |
0.011 |
| 改行コード | GSCはLF/GA4はCRLF | (自分で決める) |
| ページURL | パスは日本語、アンカーはエンコードのまま | 全体がパーセントエンコード |
| 国名 | 日本語(イギリス、スイス連邦) |
ISOコード(gbr、che) |
特に銀行丸めは盲点でした。「ちょうど0.5は偶数側に丸める」という規則なので、一般的な四捨五入(0.5は切り上げ)で実装すると5.625が5.63になり、1行だけ一致しません。JavaScriptのtoFixedは切り上げるので、そこだけ自前の丸め関数に置き換えて一致させました。
大事なのは「数字が違う」と「書式が違う」を切り分けることです。合計値を先に突き合わせて一致を確認してから、行単位で差分を見る——この順番で調べると、焦ってロジックを疑う前に原因が絞れます。
検証:画面エクスポートとAPIの突き合わせ結果
同じ期間・同じプロパティで両方を取得し、ファイル単位で比較した結果がこちらです。合計値はすべて一致しました。
| ファイル | 判定 |
|---|---|
| GSC 日付別 | バイト単位で完全一致 |
| GSC デバイス別 | バイト単位で完全一致 |
| GSC ページ別 | 中身完全一致(0クリック同士の並び順のみ差) |
| GSC クエリ別 | 中身完全一致(同上) |
| GSC 国別 | 中身完全一致(同上) |
| GA4 ページ別 | バイト単位で完全一致 |
残った差は「0クリック(表示だけ)の行同士の並び順」で、これはGoogleの内部順序なので再現できません。データとしては同一なので、分析には一切影響しません。
この検証をやった意味は大きいです。「自動化に置き換えても、これまで見ていた数字と同じものを見ている」と確信を持って言えるようになりました。自動化で一番こわいのは「静かに間違った数字を見続ける」ことなので、移行時は必ず新旧を突き合わせるべきだと思います。
定期実行に載せて、手作業をゼロにする
取得スクリプトができたら、あとはスケジューラに載せるだけです。出力先は手作業で使っていたフォルダとまったく同じ構成にしてあるので、既存の分析手順を一切書き換えずに移行できました。
| 以前(手作業) | 現在(自動) |
|---|---|
| 3サイト分のCSVを手でエクスポート | 毎週月曜の朝に自動取得 |
| プロパティ切り替えの事故 | 設定ファイルに固定なので事故ゼロ |
| 忙しいと後回しになる | 忘れようがない |
| 前回比較は手で集計 | レポートまで自動生成 |
実際、毎回20〜30分かかっていた収集作業が完全にゼロになりました。浮いた時間を「数字の解釈」に使えるのが、いちばん大きい変化です。
まとめ
GSC・GA4の自動取得は、思ったよりずっと小さな構成で作れます。ポイントをまとめます。
- 定期実行するならサービスアカウント。OAuthは7日で切れるため向かない
- 認証はNode.js標準モジュールだけで書ける(依存ゼロ)
- GSCのプロパティ文字列はAPIで実測する。推測すると404
- 移行時は新旧の数値を突き合わせる。「書式の違い」と「値の違い」を切り分ける
- 出力先を手作業と同じ形にすると、既存の分析手順を壊さず移行できる
アクセス解析は「集める→見る→直す」の3段階です。まず最初の「集める」を自動化すると、後の2段階が毎週必ず回り始めます。
当ブログでは、今後もOpenClaw×APIによるブログ運営の自動化ノウハウを発信していきます!
関連記事
🔗 あわせて読みたい: ブログ画像からYouTubeショートを全自動で作る方法
🔗 あわせて読みたい: WordPress REST APIをPythonで操作|記事を一括更新する方法
Dify×ローカルLLMでAIブログを自動化|無料で始めて1記事1円
OpenClawに「1行指示」するだけで旅行ブログ記事が完成!DeepSeek×Fal.aiの実コストを公開
OpenClawでブログ運営を自動化!Google API・OpenAI API・DeepSeek APIを徹底比較
Pinterest APIでブログ記事を90件まとめて自動ピン化してみた!OpenClaw×Pinterest連携のセットアップ手順