Node.jsでGoogle Search Console APIをローカルで実行して特定キーワードの検索順位データをCSV化する

はじめに

Google Search Console API はGoogle Search Consoleの多くの機能にプログラムでアクセスしてさまざまなデータの取得が可能です。

今回は特定のキーワードに対する検索順位とインプレッション数を日毎の数を取得して、CSVファイルに保存する処理を行うプログラムをNode.jsで作成しました。

作成するプログラムについて

  • Google Search Consoleから特定のキーワードに対する検索順位とインプレッション数を取得
  • 取得するのは1週間前から3日前まで
  • すでに取得済みの日付はCSVには書き込まない
  • CSVファイルは初回は新規作成を行い、2回目以降は追記を行う
  • CSVファイルの最終行は空行にしない

Google Search Console API の準備

  1. Google Cloud Platform ( https://console.cloud.google.com/ ) にプロジェクトを追加します。
  2. 「APIとサービス」に移動し、「Google Search Console API」を有効にします。
    Search Console API
  3. 認証情報の作成を行います。
    creation-of-authentication-information
  4. 作成したサービスアカウント
    service-account

Google Search Console の準備

Search ConsoleのユーザーにGoogle Cloud のサービスアカウントを追加します。
権限は「制限付き」にします。
users-and-permissions

Node.js の準備

Node.js のインストールに関してはここでは詳しく記述しません。必要な方は以下を参照してください。

https://nodejs.org/en/learn/getting-started/how-to-install-nodejs

標準以外で追加で導入する必要のあるモジュールはdotenvとGoogle APIs Node.js Clientになります。インストールは以下のコマンドになります。

npm install dotenv
npm install googleapis

サービスアカウントの認証情報はプログラムと同じディレクトリに「.env」というファイルを作成してそこにプライベートキー情報JSONファイルのパスを記述します。

=./Quickstart-xxxxxxxxxx.json

Node.js の準備

app.js として作成しました。

require('dotenv').config(); // .envファイルを環境変数として読み込み
const fs = require('fs');
// Google APIs Node.js Client 読み込み
const { google } = require('googleapis');

// 保存ファイル名
const fileName = 'position.csv';
// 対象サイトのURL
const siteUrl = 'https://www.example.com/';
// 検索キーワード
const query = 'example';

async function runPosition() {
  // Google認証の初期化
  const auth = new google.auth.GoogleAuth({
    keyFile: process.env.GOOGLE_APPLICATION_CREDENTIALS,
    scopes: ['https://www.googleapis.com/auth/webmasters.readonly'],
  });
  const authClient = await auth.getClient();
  google.options({ auth: authClient });
  // Search Consoleライブラリの読み込み
  const searchConsole = google.searchconsole('v1');

  // 3日前までしか取れないので、終了日は3日前に設定する
  // 文字列化する際にtoISOStringを使用するため、JSTのタイムゾーンオフセット分ずらす
  const endDateDate = new Date(Date.now() + 9 * 60 * 60 * 1000 - 3 * 24 * 60 * 60 * 1000);
  const endDate = endDateDate.toISOString().substring(0, 10);
  // 開始日は7日前に設定しておく(終了日の4日前)
  const startDate = new Date(endDateDate - 4 * 24 * 60 * 60 * 1000).toISOString().substring(0, 10);

  // データ取得
  const response = await searchConsole.searchanalytics
    .query({
      siteUrl,
      requestBody: {
        startDate,
        endDate,
        dimensions: ['date'],
        dimensionFilterGroups: [
          {
            groupType: 'and',
            filters: [
              {
                dimension: 'query',
                operator: 'contains',
                expression: query,
              },
            ],
          },
        ],
        metrics: ['position'],
        rowLimit: 25000,
      },
    });

  const positionData = [];
  // ステータスチェック
  if (response.statusText == 'OK' && response.data.rows.length) {
    for (const row of response.data.rows) {
      const date = row.keys[0];
      positionData.push({
        date,
        position: row.position,
        impressions: row.impressions,
      });
    }
  } else {
    // 失敗時
    console.log('error', response.statusText, response);
    return;
  }

  // 保存済みのファイルがあれば読み込む
  const text = fs.existsSync(fileName) ? fs.readFileSync(fileName).toString() : '';
  // 保存済みの最新日の取得
  let lastDate = '0000-00-00';
  if (text) {
    const lastLine = text.trim().split('\r\n').pop();
    const dateStr = lastLine.split(',')[0];
    if (!isNaN(dateStr.replace(/-/g, ''))) {
      lastDate = dateStr;
    }
  }
  if (!text) {
    // 保存済みファイルがない場合はヘッダーを書き込み
    const header = Object.keys(positionData[0]).join(',');
    fs.writeFileSync(fileName, header);
  }
  // 書き込み用データ
  const appendLines = /\n$/.test(text) ? [] : [''];
  for (const data of positionData) {
    const dateValue = data.date;
    // 保存済みの最新日より新しい日付のみ追記する
    if (dateValue > lastDate) {
      appendLines.push(Object.values(data).join(','));
    }
  }
  const appendText = appendLines.join('\r\n');
  if (appendText) {
    fs.appendFileSync(fileName, appendText);
  }
}

runPosition();

ファイル構成

.env
Quickstart-xxxxxxxxxx.json
app.js

プログラム実行

node app.js

生成されたcsvファイルの例

date,position,impressions
2024-09-06,31.431818181818183,176
2024-09-07,39.402877697841724,139
2024-09-08,26.38118811881188,202
2024-09-09,23.186046511627907,258
2024-09-10,23.760135135135137,296

まとめ

簡単なプログラムを作成しまてみました。

もっと複雑なディメンジョンやメトリックスの組み合わせをプログラムを使用して解析することや別のツールなどと連携することも可能です。

紹介したプログラムが何かの参考になれば幸いです。

ご興味がありましたらお問い合わせください

この記事をシェアする :