こんにちは。小学生向けのニュースサイト、こどもニュースをつくっています。
サイトを公開すると、クローラが来ます。検索エンジンのものだけでなく、AI の学習用や、生成の入力として使うためのものもあります。
このサイトでは、どの用途を許すかを robots.txt に書いています。その設定と、考えたことを書きます。
書いている内容
robots.txt は生成しています。
export const dynamic = 'force-static';
export function GET() {
return new Response(`User-agent: *
Content-Signal: ai-train=yes, search=yes, ai-input=yes
Allow: /
Sitemap: ${absoluteUrl('/sitemap.xml')}
Sitemap: ${absoluteUrl('/news-sitemap.xml')}
`, {
headers: { 'content-type': 'text/plain; charset=utf-8' },
});
}
Content-Signal の行が、用途ごとの意思表示です。3 つとも許可しています。
-
search: 検索インデックスへの利用 -
ai-train: AI モデルの学習への利用 -
ai-input: 生成時の入力(検索して答えるときの参照)としての利用
なぜ全部許可したか
このサイトは、小学生がニュースを読めるようにするために作っています。読まれる経路は多いほうがよい、というのが基本的な立場です。
AI の学習に使われることについても、止める理由が見当たりませんでした。記事は一次情報から書き起こしたもので、独占したい資産ではありません。むしろ、AI が子ども向けの説明を求められたときに、このサイトの書き方が参照されるなら悪くありません。
ai-input も同じです。誰かが AI に質問して、その答えの出典としてこのサイトが挙がるなら、それは目的に合っています。
判断が変わることもあると思いますが、いまは「読まれ方を制限しない」を選んでいます。
拒否したいときに考えること
逆に、拒否する場合に気をつける点も書いておきます。
Content Signals は、あくまで意思表示です。従うかどうかは相手側に委ねられます。技術的に止めるものではありません。
つまり、これを書いたから学習に使われない、とは言えません。本気で止めたいなら、認証を掛けるか、そもそも公開しないことになります。
意思表示に意味が無いわけではなく、従う事業者には効きます。ただ、期待する効果を誤解しないほうがよいと思っています。
静的サイトでの書き方
Next.js で静的書き出しをしている場合、robots.txt もビルド時に生成されます。
export const dynamic = 'force-static';
この指定が要ります。無いと動的なルートとして扱われ、静的書き出しでエラーになります。
sitemap の URL は、絶対 URL のヘルパを通しています。
Sitemap: ${absoluteUrl('/sitemap.xml')}
サイトの起点 URL は環境変数から取っているので、本番とテストで切り替わります。robots.txt に本番の URL が焼かれた状態でテストすると、検証が書けません。
sitemap を 2 つ書いているのは、通常の sitemap と News sitemap を別々に発見してほしいためです。片方だけ書いて、もう片方を通常の sitemap から参照する形にもできますが、それぞれ独立して見つけられるほうが素直でした。
静的ファイルとして置かない理由
public/ に robots.txt を置いても同じものが配信されます。それでもルートとして生成しているのは、URL を組み立てる必要があるからです。
静的なファイルに書くと、サイトの URL が固定されます。プレビュー環境や、ローカルの検証で URL が変わると、そこだけ本番の URL を指したままになります。
「環境によって変わる値が 1 つでもあるなら、生成する」という基準で分けています。
検証しておく
このファイルは、壊れていても誰も気づきません。sitemap の行が抜けていても、サイトは普通に見えます。
なので、E2E で内容を検証しています。ステータスが 200 であること、必要な行が含まれていることです。数行の検査ですが、これが無いと「いつの間にか消えていた」に気づけません。
同じ理由で、生成した XML も検証しています。成果物のうち「人が見ないもの」は、検査を書いておかないと壊れたことが分かりません。
まとめ
- robots.txt の Content Signals で、検索・AI 学習・AI の入力という用途ごとに意思を示せる
- 意思表示であって強制ではない。技術的に止めるものではないと理解しておく
- 静的書き出しでは
force-staticを指定する。URL は絶対 URL のヘルパを通す - 環境によって変わる値があるなら、静的ファイルではなく生成する
- 人が見ない成果物ほど、壊れても気づかない。E2E で数行でも検証しておく