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

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

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 にわざわざ入りに行かなくても、自動でクロールされると思うとかなり楽になる。

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

관련 글

Next.js フルスタックブログ開発記
Next.js フルスタックブログ開発記
Web開発に初めて触れてから1年ほど経った頃、自分だけのブログを持ちたいと思うようになった。そこで、およそ6か月これだけにかかりきりになって作ってみることにした。フロントエンド側の機能については、下記のキム・ドヒョンさんのブログを参考にするだけで十分だと思う。自分も mdx を使ってブログを作るだけ...
Caddyを利用した Next.js 無停止デプロイ(ローカルサーバー)
Caddyを利用した Next.js 無停止デプロイ(ローカルサーバー)
ホームページに何かをちょこちょこ載せたくなるたびにビルドしていたら、そのタイミング에 가끔 접속하는人がいるようだった。そうしているうちに、サーチコンソールでスコアがどんどん下がる現象が起きた。このままではまずいと思い、無停止デプロイをする方法を考えてみることにした。1. プロジェクトフォルダ2つ+...
Google検索インデックスの自動化 - Web Search Indexing API
Google検索インデックスの自動化 - Web Search Indexing API
前回の IndexNow に続いて、Google でも自動化してみることにした。調べてみると、Google は API として Web Search Indexing というものを提供していた。1. 対象範囲公式にこの API がサポートしている範囲は、求人情報とストリーミング動画サービスである。リ...
Nextjs、React サーバーがハッキングされた経験
Nextjs、React サーバーがハッキングされた経験
最初にセキュリティ問題に気づいたのは、12月5日の未明だった。React で認証なしにリモートコード実行が可能だということ。そのニュースを見て他の人には共有したものの、自分は大丈夫だろうと思って特に気にも留めなかった。1. ハッキングの痕跡を発見ところが、ブログのコードを更新しようとアクセスしてみる...
ブログに多言語機能を追加する(NextJS・next-intl・Vercel AI SDK)
ブログに多言語機能を追加する(NextJS・next-intl・Vercel AI SDK)
最近、ブログに多言語対応機能が必要だと感じた。そこで next-intl を使って多言語サービスを実装してみることにした。1.i18nまず多言語サービスを行うときには、守るべき原則がある。これを internationalization と呼ぶが、かなり長いので、先頭の i と末尾の n、そしてその...
Nextjsで多言語設定をする方法
Nextjsで多言語設定をする方法
私のブログへのアクセスを増やすためにどうすればいいか考えて、多言語設定を試してみることにしました。さまざまな方法を探しましたが、まずは言語ごとに異なるルーティングをすることから始めることに。next-intlを使って試してみました。1. インストールyarn add next-intl2. 適用適用は少し面倒ですが、次のような手順で進めれば大丈夫です。

댓글을 불러오는 중...