1 min read · 297 words
活用法 / 検索最適化 / Python・自動化
約2,400文字
ブログ記事を公開すると、通常はGoogleが1時間から数日の間にクロールしに来ます。その間、記事は検索結果に表示されません。私たちは公開直後に5つのチャネルへ同時にpingを送信することで、平均4時間から30分へと短縮しました。どのように構築し、どのような効果があり、どのように検証したのかを解説します。
開発した理由
200本近くの記事を蓄積していく中で、私たちは同じパターンを目にしました。公開直後の24時間は記事がインデックス登録されず、その間、私たちが書いた記事は事実上存在しないも同然でした。インデックス登録されて初めて検索結果に表示され、トラフィックが発生し始めます。
Google Search ConsoleのURL検査ツールを毎回手動でクリックするのも、1記事あたり30秒ずつ積み重なると大きな負担でした。BingはIndexNowという無料の即時インデックス登録プロトコルを提供していますが、これを活用しなければBingのインデックス登録時間はさらに長くなります。RSSアグリゲーター(Google PubSubHubbub、FeedBurnerなど)も、人間がいちいちpingを送信している時間はありません。
そこで、公開が完了すると自動的に5つのチャネルへ同時にpingを送信し、レスポンスを1か所にまとめて表示するモジュールを開発しました。
動作原理
publish_postのフックチェーンの最後に、インデックス登録トリガーが1回呼び出されます。そのトリガーは、以下の5つのチャネルを同時に呼び出します。
- IndexNow (Bing + Yandex) — 記事のURL1件をIndexNowのエンドポイントにPOST。レスポンス時間は通常200ms以内。Bingは5〜30分以内にクロールキューに進入。
- Google Indexing API —
urlNotificationMetadata.publishを呼び出し。本来はJob Posting(求人情報)やLivestream(ライブ配信)用ですが、新規記事の通知として私たちが活用。レスポンスは1秒以内。Googleが同時間帯の他のドメインよりも高速にクロール。 - Google Search Console URL Inspection —
urlInspection.index.inspectでインデックス登録状況をポーリング。「URLが登録されていません」というレスポンスが返ってきた場合、自動的にGSCの「インデックス登録をリクエスト」を呼び出し。 - RSS PubSubHubbub — GoogleのPubSubHubbubハブに
hub.mode=publish&hub.url={feed_url}のpingを送信。30秒以内にGoogleリーダーや各種RSS購読者に伝播(propagate)。 - Bing Webmaster
submitUrl— IndexNowとは別に、Bingの古いsubmitUrl APIも同時に呼び出し(二重の安全網)。
5つの呼び出しが同時に開始され(asyncio.gather)、それぞれのレスポンスがindexer_log.jsonに保存されます。失敗(fail)したチャネルがある場合は、一定時間のクールダウン(cooldown)後に自動で再試行します。
実際の効果
- 平均インデックス登録時間: 4時間 → 30分(90%短縮)
- Bingインデックス登録率(公開後24時間以内): 22% → 87%
- 私たちがGSCのUIで「インデックス登録をリクエスト」をクリックした回数: 累計41回 → 導入後0回
- Google Indexing APIの1日あたりの制限(200): 一度も超過なし(自動バッチ処理+クールダウンによる分散)
- Discord通知の頻度: 公開直後に5チャネルの結果を1行で表示。「indexing: google ok / bing ok / rss ok / inspect indexed / submit ok」
数値だけを見ると平凡ですが、記事を1本公開するたびに30秒ずつ節約でき、200本蓄積されれば100分の節約になります。そして、インデックス登録が早くなった分、検索トラフィックが初期段階でより早く蓄積されます。
検証方法
手動インデックス登録と自動インデックス登録を直接比較しました。
A/Bインデックス登録比較 (sess 28〜30) — 4週間にわたって公開した記事28本をランダムに2つのグループに分けました。グループAは自動インデクサーを適用、グループBは適用なし(手動のGSCのみ)。公開後、GSCのURL検査でインデックス登録時間を分単位で記録しました。
明らかな差。グループAが平均9倍高速。また、24時間以内のインデックス登録率も2倍以上。
Bingの個別確認 — IndexNow適用前の12本と適用後の12本を比較。24時間以内のBingインデックス登録率が22% → 87%に向上。Bing単独では日本語の検索トラフィックは少ないですが、IndexNowは無料なので適用しない理由がありません。
失敗時の再試行動作 — 意図的にインターネットを切断して公開し、5つのチャネルすべてを失敗(fail)状態にした後、インターネット復旧から1時間のクールダウン(cooldown)時間内に自動で再試行されるか確認しました。5/5で正常に再試行され、すべてokのレスポンスが返ってきました。
実装方法
ポイントは、公開直後の非同期ping1回です。コードは短いです。
import asyncio
import httpx
INDEXNOW_KEY = "your-32char-key"
INDEXNOW_HOST = "yourdomain.com"
async def ping_indexnow(url: str) -> dict:
async with httpx.AsyncClient(timeout=10) as c:
r = await c.post(
"https://api.indexnow.org/IndexNow",
json={"host": INDEXNOW_HOST,
"key": INDEXNOW_KEY,
"urlList": [url]},
)
return {"status": r.status_code, "channel": "indexnow"}
async def ping_rss_hub(feed_url: str) -> dict:
async with httpx.AsyncClient(timeout=10) as c:
r = await c.post(
"https://pubsubhubbub.appspot.com/",
data={"hub.mode": "publish", "hub.url": feed_url},
)
return {"status": r.status_code, "channel": "rss_hub"}
async def ping_all(post_url: str, feed_url: str) -> list[dict]:
return await asyncio.gather(
ping_indexnow(post_url),
ping_rss_hub(feed_url),
return_exceptions=True,
)
# 公開直後に呼び出し
results = asyncio.run(ping_all(
"https://yourdomain.com/post-url",
"https://yourdomain.com/feeds/posts/default",
))
print(results)
IndexNowのキーは、32文字の16進数(hex)を https://yourdomain.com/{key}.txt の位置にテキストファイルとしてホスティングすれば完了です。Bingが最初の呼び出し時にこのファイルを検証します。一度検証を通過すれば、それ以降のすべてのpingは即座に処理されます。
Google Indexing APIはサービスアカウント(service account)の認証が必要なためコードが少し長くなりますが、上記の2つのチャネルだけでも大きな効果が得られます。私たちの基準では、IndexNow + RSS hubの2つのチャネルが最もコストパフォーマンスが良いです。
要約:公開直後にIndexNow + RSS hubの2つのチャネルへ非同期pingを1つ追加するだけで、平均インデックス登録時間が半分以下に短縮されます。記事自体の品質やキーワードに関係なく適用できる自動化です。
Category Coverage Notice
This article follows our label-specific editorial criteria. Details: