【無料】Google Indexing APIでWordPressの全記事を一括インデックス申請する方法|パーマリンク変更後にも有効

IT
この記事は約8分で読めます。

WordPressのパーマリンク設定を変更しました。日付+ID形式(/2021-09-04/183/)から、スラッグ形式(/rakuraku-iphone-1/)へ。変更後、Search Consoleからこんな通知が届きました。

Search Consoleのインプレッション減少通知

旧URLをGoogleが引き続きクロールしようとするものの、ページ構成が変わったことで混乱が生じている状態です。301リダイレクトは設定済みなのでユーザーは正しいページに飛べますが、Googleが新URLへの切り替えを完了するまでに時間がかかります。

「全記事を早く新URLで再インデックスさせたい」——そこで調べたのがGoogle Indexing APIです。

この記事でわかること

  • Google Indexing APIを使ってWordPressの全記事を一括でインデックス申請する方法
  • GCPサービスアカウントの作成〜Search Console連携までのセットアップ手順
  • Pythonスクリプトで記事公開のたびに自動申請する仕組みの作り方

サイトマップpingは2024年に廃止されていた

以前はこのコマンドでGoogleにサイトマップの更新を通知できました。

curl "https://www.google.com/ping?sitemap=https://example.com/sitemap.xml"

しかしGoogleはこのpingエンドポイントを2024年に廃止しています。Bingも同様です。

方法状況
サイトマップping(Google)❌ 2024年廃止
サイトマップping(Bing)❌ 廃止
Search Console手動申請✅ ただし1件ずつ手動
Google Indexing API✅ プログラムから一括申請可能

Google Indexing APIとは

Google Indexing APIは、URLをGoogleに通知してクロール・インデックスを促すAPIです。

注意点:公式には「JobPosting(求人情報)」や「BroadcastEvent(ライブ動画)」の構造化データを持つページ向けとされています。一般のブログ記事は対象外ですが、実際には通常のページでも申請でき、多くのSEO担当者が活用しています。

費用:無料。Google Cloud Platformの無料枠内で十分に収まります(1日200URLまで)。

セットアップ手順

Step 1:GCPプロジェクトの作成とAPI有効化

  1. Google Cloud Console にアクセス
  2. 上部「プロジェクト選択」→「新しいプロジェクト」→ 名前を入力して作成
  3. 左メニュー「APIとサービス」→「ライブラリ」→「Web Search Indexing API」で検索 → 有効化

Step 2:サービスアカウントとJSONキーの作成

  1. 「APIとサービス」→「認証情報」→「認証情報を作成」→「サービスアカウント」
  2. 名前(例:blog-indexing)を入力 →「作成して続行」→「完了」
  3. 作成したサービスアカウントをクリック →「キー」タブ →「鍵を追加」→「新しい鍵を作成」→「JSON」
  4. ダウンロードされたJSONファイルを安全な場所に保存

認証情報を作成する際、「アクセスするデータの種類」は「アプリケーションデータ」を選択します。

GCP認証情報の作成画面

Step 3:Search ConsoleにサービスアカウントをオーナーとしてP追加

  1. Search Console を開く
  2. 左下「設定」→「ユーザーと権限」→「ユーザーを追加」
  3. サービスアカウントのメールアドレス(xxxx@yyyy.iam.gserviceaccount.com)をオーナーとして追加

メールアドレスはダウンロードしたJSONファイルの client_email フィールドに記載されています。権限は必ず「オーナー」にしてください。「フルユーザー」では申請が弾かれます。

Search Consoleへのユーザー追加画面

Pythonスクリプト

必要なライブラリをインストールします。

pip3 install PyJWT cryptography
import json, time
import urllib.request, urllib.error, base64
from pathlib import Path

KEY_FILE     = Path("サービスアカウント.json")
SITE         = "https://example.com"
WP_USER      = "WordPressユーザー名"
WP_PASS      = "WordPressアプリパスワード"
INDEXING_URL = "https://indexing.googleapis.com/v3/urlNotifications:publish"

def get_access_token():
    import jwt, time
    with open(KEY_FILE) as f:
        key = json.load(f)
    now = int(time.time())
    payload = {
        "iss": key["client_email"],
        "scope": "https://www.googleapis.com/auth/indexing",
        "aud": "https://oauth2.googleapis.com/token",
        "iat": now, "exp": now + 3600,
    }
    signed = jwt.encode(payload, key["private_key"], algorithm="RS256")
    data = (f"grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion={signed}").encode()
    req = urllib.request.Request("https://oauth2.googleapis.com/token", data=data,
        headers={"Content-Type": "application/x-www-form-urlencoded"})
    with urllib.request.urlopen(req) as r:
        return json.load(r)["access_token"]

def fetch_all_post_urls():
    token = base64.b64encode(f"{WP_USER}:{WP_PASS}".encode()).decode()
    urls, page = [], 1
    while True:
        req = urllib.request.Request(
            f"{SITE}/wp-json/wp/v2/posts?per_page=100&page={page}&status=publish",
            headers={"Authorization": f"Basic {token}"})
        with urllib.request.urlopen(req) as r:
            posts = json.load(r)
        if not posts: break
        urls.extend(p["link"] for p in posts)
        if len(posts) < 100: break
        page += 1
    return urls

def submit_url(url, access_token):
    payload = json.dumps({"url": url, "type": "URL_UPDATED"}).encode()
    req = urllib.request.Request(INDEXING_URL, data=payload,
        headers={"Authorization": f"Bearer {access_token}", "Content-Type": "application/json"})
    try:
        with urllib.request.urlopen(req) as r:
            return True, json.load(r)
    except urllib.error.HTTPError as e:
        return False, json.load(e)

token = get_access_token()
urls  = fetch_all_post_urls()
for i, url in enumerate(urls, 1):
    ok, _ = submit_url(url, token)
    print(f"{'✅' if ok else '❌'} [{i:2d}] {url}")
    time.sleep(0.5)

実行結果

インデックス申請スクリプトの実行ログ

18件全件、エラーなしで申請完了しました。申請後、数日〜1週間ほどでSearch Consoleに新URLが反映され始めます。

月次チェックに組み込む

記事を公開するたびに手動で実行するのは面倒なので、月次のブログメンテナンスチェックに組み込んでいます。

# 月次チェック
python3 _meta/blog_check.py

# インデックス申請(記事公開後・パーマリンク変更後)
python3 _meta/indexing_api.py

まとめ

  • WordPressのパーマリンク変更後はSearch Consoleのインプレッションが一時的に落ちる
  • サイトマップpingは2024年に廃止済み——Google Indexing APIが現在唯一の自動化手段
  • GCPサービスアカウントの設定は15分ほどで完了、費用は無料
  • Pythonスクリプトで全記事を一括申請でき、以降は記事公開のたびに実行するだけ

パーマリンクを変更した方、新しく記事を公開した方はぜひ試してみてください。

コメント

タイトルとURLをコピーしました