Open5

Nuxt3でnoindexじゃないページでnoindexが検出される問題

ytoisytois

概要

Nuxt3でオウンドメディアの開発をしています
記事ページの一部ではSEO上、noindexにしておきたいページがあるため、metaタグにnoindexを指定しているページがあります。
ところが、noindexにしていないページでも、Google Search Console上でnoindexが検出され、ページが正しくインデックスされない問題が発生しました

URL検査を行うと以下のメッセージが表示されました

URL が Google に登録されていません
インデックス登録を許可?: いいえ、'robots' メタタグで 'noindex' が検出されました

ところが、Search Consoleから"公開URLをテスト"するとnoindexは検出されず、"インデックス登録をリクエスト"すると問題なくインデックスされるのです。

ytoisytois

実装

以下は実際のコードとは異なりますが、全体の実装です

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 })
ytoisytois

問題の整理

  • (1) ページ内で条件するページのみで発生
    • 必ずindexしたいページや、必ずnoindexにしたいページでは問題は発生していない
  • (2) ブラウザ上での挙動も正常
    • SSR時のHTMLではそれぞれ正常に反映されている
    • CSR(ページ遷移後)もrobotsメタタグが正常に切り替わっている
  • (3) robotsメタタグ以外の挙動は正常
    • 同じuseMeta内で設定しているtitledescriptionは問題なくインデックスされ検索結果に反映されている
  • (4) "公開URLをテスト"するとnoindexは検出されない
    • "インデックス登録をリクエスト"すると問題なくインデックスされる
  • (5) Bingでは問題なくインデックスされている

(2)(3)(4)から、GoogleBotのサイト回遊中に起こっていそうです。
(5)から、断定できませんがHTMLやJSでの不具合というよりも、Googleのクロールの仕方によるものというような気がします。

ytoisytois

効果がなかったもの

サイトマップの追加

根本原因の解決ではありませんが、"公開URLをテスト"では問題ないので、サイトマップから直接キューに入ればインデックスされるのではと思いましたが、効果ありませんでした。

これは通常のページとは異なり、一度noindexになるとしばらくはBotが訪れなくなるからかもしれません
noindexや404になっても、時間が経つとページが変更されていないか様子を見にくるようなので、しばらく放っておけばインデックスされるかもしれませんが未検証です
また、noindexが検出される前にサイトマップからインデックスキューに入ればインデックスされるかもしれませんが、こちらも未検証です

Metaコンポーネントによる実装

あまり期待はしてませんでしたがuseHeadではなくMetaコンポーネントを使って実装しテストしましたがこちらも効果ありませんでした

<template>
  ...
  <Meta name="robots" :content="indexable ? 'index' : 'noindex'" />
  ...
</template>

しかしながらこれで記事ページ側pages/articles/[id].vueの実装による影響だとあたりを付けました

ytoisytois

解決方法

はっきりした原因は未だ不明ですがとりあえず解決しました
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 }
  }
})