Nuxt3でnoindexじゃないページでnoindexが検出される問題
概要
Nuxt3でオウンドメディアの開発をしています
記事ページの一部ではSEO上、noindexにしておきたいページがあるため、metaタグにnoindexを指定しているページがあります。
ところが、noindexにしていないページでも、Google Search Console上でnoindexが検出され、ページが正しくインデックスされない問題が発生しました
URL検査を行うと以下のメッセージが表示されました
URL が Google に登録されていません
インデックス登録を許可?: いいえ、'robots' メタタグで 'noindex' が検出されました
ところが、Search Consoleから"公開URLをテスト"するとnoindexは検出されず、"インデックス登録をリクエスト"すると問題なくインデックスされるのです。
実装
以下は実際のコードとは異なりますが、全体の実装です
composable関数でmeta周りの取り扱いを共通化し、各ページで呼び出して利用していました
// composables/use-meta.ts
export default (metaOptions: { index: boolean }) => {
useHead({
meta: [
{ meta: 'robots', content: metaOptions.index ? 'index' : 'noindex' }
]
}
}
// pages/articles/[id].vue
const { data: article } = await useFetch(`/api/articles/${articleId}`)
const indexable = computed(() => {
// 下書きの場合はインデックスしない
if (article.value?.is_draft) return false
// その他の条件
...
return true
})
useMeta({ index: indexable.value })
問題の整理
- (1) ページ内で条件するページのみで発生
- 必ずindexしたいページや、必ずnoindexにしたいページでは問題は発生していない
- (2) ブラウザ上での挙動も正常
- SSR時のHTMLではそれぞれ正常に反映されている
- CSR(ページ遷移後)もrobotsメタタグが正常に切り替わっている
- (3) robotsメタタグ以外の挙動は正常
- 同じ
useMeta
内で設定しているtitle
やdescription
は問題なくインデックスされ検索結果に反映されている
- 同じ
- (4) "公開URLをテスト"するとnoindexは検出されない
- "インデックス登録をリクエスト"すると問題なくインデックスされる
- (5) Bingでは問題なくインデックスされている
(2)(3)(4)から、GoogleBotのサイト回遊中に起こっていそうです。
(5)から、断定できませんがHTMLやJSでの不具合というよりも、Googleのクロールの仕方によるものというような気がします。
効果がなかったもの
サイトマップの追加
根本原因の解決ではありませんが、"公開URLをテスト"では問題ないので、サイトマップから直接キューに入ればインデックスされるのではと思いましたが、効果ありませんでした。
これは通常のページとは異なり、一度noindexになるとしばらくはBotが訪れなくなるからかもしれません
noindexや404になっても、時間が経つとページが変更されていないか様子を見にくるようなので、しばらく放っておけばインデックスされるかもしれませんが未検証です
また、noindexが検出される前にサイトマップからインデックスキューに入ればインデックスされるかもしれませんが、こちらも未検証です
Metaコンポーネントによる実装
あまり期待はしてませんでしたがuseHead
ではなくMetaコンポーネントを使って実装しテストしましたがこちらも効果ありませんでした
<template>
...
<Meta name="robots" :content="indexable ? 'index' : 'noindex'" />
...
</template>
しかしながらこれで記事ページ側pages/articles/[id].vue
の実装による影響だとあたりを付けました
解決方法
はっきりした原因は未だ不明ですがとりあえず解決しました
3.1から追加されたuseSeoMeta
を使っていますが、これはuseHead
のラップのようなので特に関係ないはず
リアクティブな値(computed
)を使うと発生するのかもしれません
// pages/articles/[id].vue
const { data: article } = await useFetch(`/api/articles/${articleId}`)
useSeoMeta({
robots: () => {
// 下書きの場合はインデックスしない
if (article.value?.is_draft) {
return { noindex: true }
}
return { index: true }
}
})