検索インデックス生成の自動化 - IndexNow

힘센캥거루
2025년 12월 11일(수정됨)
4
nextjs

Bingにサイト登録をしている途中で知ったのだが、Bingでは IndexNow という機能を提供している。

ポイントは、APIキーを使って、記事を書いた直後にすぐインデックス作成リクエストを飛ばせるということ。

検索インデックス生成の自動化 - IndexNow-1

下のようなリクエストを fetch で作り、投稿機能に連動させておけば、記事をDBに保存すると同時にインデックス生成のリクエストが可能になる。

POST /IndexNow HTTP/1.1
Content-Type: application/json; charset=utf-8
Host: api.indexnow.org
{
  "host": "www.example.org",
  "key": "f9ee84af58564dacb6bfe55d808a252c",
  "keyLocation": "https://www.example.org/f9ee84af58564dacb6bfe55d808a252c.txt",
  "urlList": [
      "https://www.example.org/url1",
      "https://www.example.org/folder/url2",
      "https://www.example.org/url3"
      ]
}

そこで他のサイトのAPIも調べてみたところ、ネイバーとGoogleにもAPIがあった。

ネイバーはウェブマスターが IndexNow をサポートしていた。

host だけが違うだけで、他の要素はすべて同じだった。

ということで、IndexNow を使ってみることにした。

検索インデックス生成の自動化 - IndexNow-2

1. IndexNow とは?

検索インデックス生成の自動化 - IndexNow-3

従来の検索方式では、検索エンジンが自動で自分のサイトをクロールし、更新を確認してインデックス処理を進める。

クロールが行われなければ、ひたすら待つしかない。

この問題を解決するために登場した技術が、まさにIndexNowだ。

検索インデックス生成の自動化 - IndexNow-4

サイトのコンテンツを作成・削除・修正するたびに、サーバーに push を送るという仕組みである。

ウェブサイト側から直接リクエストを送ると、検索エンジンはその URL をインデックスするよう予約を入れる。

2. 検索エンジンの対応状況

現在、以下のような検索エンジンが IndexNow をサポートしている。

なお、サイトごとに API のホストが少しずつ異なる。

検索インデックス生成の自動化 - IndexNow-5

ネイバーが案内している内容は、下記リンクを確認してみよう。

3. 実装方法

1) Key ファイルの作成

サイトルートに <key>.txt ファイルを置いて、サイト所有者であることを認証する。

このメモ帳の中には key 文字列だけが入っていなければならない。

https://example.com/1234567890ABCDEF.txt

2) URL 変更を検索エンジンに送信

POST で次のような JSON を送る。

検索エンジンはリクエストを受け取ると、該当 URL を素早く再クロールするよう予約する。

{
  "host": "example.com",
  "key": "1234567890ABCDEF",
  "keyLocation": "https://example.com/1234567890ABCDEF.txt",
  "urlList": [
    "https://example.com/post/123",
    "https://example.com/about"
  ]
}

4. Nextjs での利用

IndexNow 用の npm ライブラリもあるが、コード自体がシンプルなので、関数をひとつ作るだけにしておこう。

自分で書いてもいいが、gpt や claude 兄貴に書かせるとかなり良いものが出てくる。

そこまで重要な部分でもないので、適当に「作って」と頼んで、じっくり読むくらいでよい。

type IndexNowPayload = {
  host: string;
  key: string;
  keyLocation: string;
  urlList: string[];
};

const INDEXNOW_ENDPOINT = "https://api.indexnow.org/indexnow"; // Bing/共用向け

export async function submitToIndexNow(
  urls: string[],
  options?: {
    host?: string;
    key?: string;
    keyLocation?: string;
    endpoint?: string; // 必要であればネイバー用 endpoint などに差し替え
  }
): Promise<void> {
  if (!urls.length) return;

  const host =
    options?.host ??
    process.env.INDEXNOW_HOST ?? // 例: "earthscience.kr"
    new URL(urls[0]).host;

  const key = options?.key ?? process.env.INDEXNOW_KEY;
  const keyLocation =
    options?.keyLocation ??
    process.env.INDEXNOW_KEY_LOCATION ?? // 例: "https://earthscience.kr/1234567890ABCDEF.txt"
    `https://${host}/${key}.txt`;

  const endpoint = options?.endpoint ?? INDEXNOW_ENDPOINT;

  if (!key) {
    throw new Error("IndexNow keyが設定されていません。環境変数 INDEXNOW_KEY を確認してください。");
  }

  const payload: IndexNowPayload = {
    host,
    key,
    keyLocation,
    urlList: urls,
  };

  const res = await fetch(endpoint, {
    method: "POST",
    headers: {
      "Content-Type": "application/json; charset=utf-8",
    },
    body: JSON.stringify(payload),
  });

  if (!res.ok) {
    const text = await res.text().catch(() => "");
    throw new Error(
      `IndexNow リクエスト失敗: ${res.status} ${res.statusText} ${text ? `- ${text}` : ""}`
    );
  }
}

ちなみにネイバーはエンドポイントが異なるので、ネイバーにも送るなら 2 回 fetch する必要がある。

あとはこれを、記事作成・記事更新・記事削除 API にそっと載せてあげればよい。

export async function Post(request: NextRequest){
    
	...

    const post = await createPost({
      title,
      excerpt: excerpt || "",
      content,
      category: category || "その他",
      categoryId: categoryId || null,
      thumbnail: thumbnail || null,
      published: published || false,
    });

    // IndexNow へ新規記事を通知(published の場合のみ)
    if (post.published && post.slug) {
      try {
        const postUrl = `${process.env.NEXT_PUBLIC_URL}/post/${post.slug}`;
        await submitToIndexNow([postUrl]);
        console.log('IndexNow 送信成功:', postUrl);
      } catch (indexError) {
        console.error('IndexNow 送信失敗:', indexError);
        // IndexNow が失敗しても記事公開自体は成功扱い
      }
    }
	
	...

}

5. トラブルシューティング

Bing には問題なく登録されるのに、ネイバーにはうまく登録されない現象が起きた。

調べてみると、ネイバーでは host を指定する際に https:// を除いておく必要があるとのこと。

以下のような手順で、実際のホスト名だけを取り出す必要がある。

options?.origin ??
process.env.NEXT_PUBLIC_URL ?? // 通常は https://ドメイン
new URL(urls[0]).origin;

const originUrl = new URL(origin);
const host = options?.host ?? originUrl.host; // ✅ ドメイン部分だけ

例えば、以下のように変更しなければならない。

{
  "host": "https://earthscience.kr"  // 422 エラー発生!
  "host": "earthscience.kr"		 // これは通る
}

6. まとめ

検索インデックス生成の自動化 - IndexNow-6

いま書いているこの記事をテスト用に一度公開・編集してみたところ、うまく動いているようだ。

これからは Bing や Naver にわざわざ入りに行かなくても、自動でクロールされると思うとかなり楽になる。

しばらくは、どのように動作するか様子を見ようと思う。

댓글을 불러오는 중...