技術スタック

Google Search ConsoleのインデックスリクエストをAPI通じて行う方法

2023.12.31

実装をさっさとみたい方はAPIを使用してプログラム的にリクエストするへ移動してください。

ページがGoogleに乗らない状態に

個人開発で作成したwebサービス RouteShareのユーザーインプレッション数を伸ばすため、Crowdワークスでライターを募集して記事をたくさん作成したが一向にOrganig Searchが伸びない現象に悩んでいました。

おもむろにSearch Consoleを調べている時に「インデックスの登録」というものを見つけました。すると

未登録の部分が200件となっていました。この未登録とはGoogle上で配信されていないという意味になります。つまり記事を書いたのにもかかわらず、記事が検索結果にでてこないというやばい状態です。

もう少し下に移動するとその未登録の理由がわかります。

自分の場合はこの「検出」というとこが200件ありました。この検出というのは公式いわく

ページは Google により検出されましたが、まだクロールされていません。これは通常、Google が URL をクロールしようとしたものの、サイトへの過負荷が予想されたため、クロールの再スケジュールが必要となった場合です。そのため、レポート上で最終クロール日が空欄になっています。

という意味であり、サイトマップ上で新規のページが認識されているがサイト負荷が予想されたためクロール(インデックス登録)が見送られたということです。

この未登録状態を人力で解消するためには以下のようにします。

1: 「検証」の行をクリックして表示される未登録のページ一覧のURLを確認

2: URLを検査(一覧の虫眼鏡マーク)

3: 「インデックス登録をリクエスト」をクリック

リクエストを送ることでインデックス登録を再度行ってくれ、問題なければ登録されます。

一件ずつやってもいいのですが、検査やインデックスリクエストの時にローディングがかかるので200件あると結構時間がかかります。何かプログラム的にやる方法がないかを探したところ、Google Indexing APIというものがありました。

APIを使用してプログラム的にリクエストする

Google Indexing APIでおおまかな内容が書いてありますが、要約すると

  1. Google Cloud Platoform にてサービスアカウントを作成し、キーを取得する。(GCPのアカウントが必要です)
  2. 登録したアカウントのアドレスをSearch Consoleのユーザーに登録し、所有者と同じ権限を持たせる。
  3. キーを用いたOauthでトークンを取得した後、対象のURLを更新するAPIリクエストを投げる。

上記の通りです。

サービスアカウントの作成とキーの取得

GCPのアカウントがない場合はその作成から行ってください。(今回は省略)

「IAMと管理」から「サービスアカウント」に移動します。「サービスアカウントを作成」をクリックします。

アカウント名、IDを入力します。2と3は何も入力しなくて大丈夫です。

作成後に一覧に戻るので、作成したアカウントを詳細表示します。「キー」のタブに移動して「鍵を追加」から「新しい鍵を作成」をクリックします。

タイプでは「JSON」を選択し、作成をクリックします。JSONがダウンロードされますので、APIリクエストを行うディレクトリに保存しておいてください。まずはキーの取得が完了しました。

サービスアカウントをserach consoleに登録する

サービスアカウントがserach consoleを触れるようにユーザーとして登録しておきます。

公式のドキュメントが旧UIを参照した形で書かれていますので注意してください。このページでは2024年1月現在のUIで説明します。

まずは権限を付与したいサイト(プロパティー)を選択し、「設定」をクリックします。表示されたらユーザーと権限をクリックします。

ユーザーと権限で「ユーザーを追加」をクリックして、サービスアカウントのアドレスとコピペして権限を「オーナー(委任された所有者)」を選択します。

サービスアカウントのアドレスはサービスアカウント一覧または、キーJSONのclient_emailから取得できます。権限を付与してアドレスを登録すればこのアカウントからAPIアクセスができるようになります。(アドレス、所有者の確認は不要)

APIリクエストの実装

私はnode.jsで実装しました。google apiライブラリを使用して簡単に実装ができ、公式にもいくつかの言語でサンプルコードがあります。

サンプルコードは1件しかできないので、ダウンロードした未登録のURLCSVファイルを読み込んで必要分をAPIリクエストするようなコードにしました。(本来であればBatchリクエストがいいですが、難しかったので今回は1件ずつリクエストを送ります。機会があればBatchリクエストの解説もします)

またIndexing APIは200件ほど(多分)のレートリミットがあるのでリクエスト間と送信数は時間を明けた方がいいです。とりあえずコードは以下の通りです。

var fs = require('fs');
var axios = require('axios');
var { google } = require('googleapis');
var key = require('./key.json');
var {parse} = require('csv-parse/sync');
var {stringify} = require('csv-stringify/sync');

const jwtClient = new google.auth.JWT(
  key.client_email,
  null,
  key.private_key,
  ['https://www.googleapis.com/auth/indexing'],
  null
);

jwtClient.authorize(function(err,token) {
  if (err) {
    console.log(err);
    return;
  }

  // CSVファイルからURLを読み込む
  var urls = parse(fs.readFileSync('./data.csv'), {
    columns: false,
    trim: true
  });

  var requestedUrls = [];

  // 各URLに対してリクエストを送信
  let stop = false;
  (async () => {
    for (let i = 0; i < urls.length; i++) {
      if(stop) break;
      let url = urls[i][0];
      await new Promise(resolve => setTimeout(resolve, 1000)); // 1秒の遅延

      await axios.post("https://indexing.googleapis.com/v3/urlNotifications:publish",{
        'url': url,
        'type': 'URL_UPDATED'
      },{
        headers: {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer '+token.access_token
        },
      })
      .then(res=>{
        requestedUrls.push([url]);
      })
      .catch(err=>{
        console.error(err)
        stop = true;
      })
    }

    // 成功したURLを requested.csv に書き込む
    fs.writeFileSync('requested.csv', stringify(requestedUrls));
  })();
});

更新が行われたかを確認したいときは、対象のURLをserach consoleで検査したときに「ページのインデックス登録」のタブでクロールされたか、インデックス登録を許可が「はい」になっているかで確認できます。

もし上記の方法でインデックスされない場合はページの品質が悪いか、URLで変なリダイレクトが起きていたり、正常に表示できていない可能性がありますのでサーバの設定などを見直してみてください。

私の方でもなんとか200件のインデックスが行われました。(右側の緑が急激に増えている)

Copyright © 2021 jun. All rights reserved.