Skip to content
This repository has been archived by the owner on Jun 1, 2023. It is now read-only.

SEO対策のため、hreflangタグ、sitemapを追加する #5001

Closed
NEKOYASAN opened this issue Jul 11, 2020 · 50 comments · Fixed by #5056
Closed

SEO対策のため、hreflangタグ、sitemapを追加する #5001

NEKOYASAN opened this issue Jul 11, 2020 · 50 comments · Fixed by #5056
Labels
help-wanted 特に助けを必要としているもの improvement 改善や新機能の要望

Comments

@NEKOYASAN
Copy link
Contributor

改善詳細 / Details of Improvement

  • 現在、検索画面でタイトルが英語で表示されてしまっている。

スクリーンショット / Screenshot

image

期待する見せ方・挙動 / Expected behavior

  • SEO対策のため、hreflangタグ、sitemapを追加する

動作環境・ブラウザ / Environment

  • macOS / Windows / Linux / iOS / Android
  • Chrome / Safari / Firefox / Edge / Internet Explorer
@kaizumaki
Copy link
Collaborator

実装については、 こちら #4991 (comment)@MaySoMusician さんが提案してくれた内容でいけるのではと思うのですが、いかがでしょう?

@kaizumaki kaizumaki added the help-wanted 特に助けを必要としているもの label Jul 11, 2020
@NEKOYASAN
Copy link
Contributor Author

これへの対応としては良いと思います!

SEO的な話をするのであれば(前にも出したかもしれませんが)下記の構造化データへの対応をしても良いかもしれません。
https://developers.google.com/search/docs/data-types/special-announcements?hl=ja

@harmo-snipe
Copy link

@Nekoya3さん
こんにちは。
構造化データが実装できるなら、とても有益な検索結果になりますので、もし可能であれば(何をマークアップするかによりますが)実装してみてはどうでしょうか。
SpecialAnnouncementのプロパティ
・diseaseSpreadStatistics
・newsUpdatesAndGuidelines
・quarantineGuidelines
などが該当しそうです。

ただ本件は、検索結果が英語で表示される原因と解決に全く関係無いので、別で議論した方が良いかと思います。

@harmo-snipe
Copy link

harmo-snipe commented Jul 14, 2020

PRとかできないので、自分のできることをやってみます。

hreflangを実装後のサイトは、次の様になっています。
例えばトップページに
https://stopcovid19.metro.tokyo.lg.jp/
の例です。

<link rel="alternate" hreflang="ja" href="https://stopcovid19.metro.tokyo.lg.jp/" />
<link rel="alternate" hreflang="en-US" href="https://stopcovid19.metro.tokyo.lg.jp/en/" />
<link rel="alternate" hreflang="zh-CN" href="https://stopcovid19.metro.tokyo.lg.jp/zh-cn/" />
<link rel="alternate" hreflang="zh-TW" href="https://stopcovid19.metro.tokyo.lg.jp/zh-tw/" />
<link rel="alternate" hreflang="ko-KR" href="https://stopcovid19.metro.tokyo.lg.jp/ko/" />
<link rel="alternate" hreflang="x-default" href="https://stopcovid19.metro.tokyo.lg.jp/en/" />

このように、すべてのページを記載します。
さらに言語の中のページ例えば、
https://stopcovid19.metro.tokyo.lg.jp/en/
英語のページであれば、次をマークアップします。
<link rel="alternate" hreflang="ja" href="https://stopcovid19.metro.tokyo.lg.jp/" />
<link rel="alternate" hreflang="en-US" href="https://stopcovid19.metro.tokyo.lg.jp/en/" />
<link rel="alternate" hreflang="zh-CN" href="https://stopcovid19.metro.tokyo.lg.jp/zh-cn/" />
<link rel="alternate" hreflang="zh-TW" href="https://stopcovid19.metro.tokyo.lg.jp/zh-tw/" />
<link rel="alternate" hreflang="ko-KR" href="https://stopcovid19.metro.tokyo.lg.jp/ko/" />
<link rel="alternate" hreflang="x-default" href="https://stopcovid19.metro.tokyo.lg.jp/en/" />

このように、すべての言語ページにすべての代替言語へジャンプできるようにします。
サーチコンソールがあれば、ループになっているかどうか調べてくれます。

なおx-defaultというのは、何か?という点ですが、ここはGoogleが言語判断できない時の地域に対して
デフォルトでどの言語を表示するかです。

ということで、修正結果のみ掲載しました。
トップを含んだすべての言語ページの~の中に入れるだけです。
ページに応じてタグを変化させたりする必要はないので、機械的に可能です。

@goki90210
Copy link
Contributor

@harmo-snipe さん

ja-basicは要らないのでしょうか?

@harmo-snipe
Copy link

harmo-snipe commented Jul 14, 2020

@goki90210 さん、こんにちは。
basicもうまく認識できれば良いのですが、
「ISO_639-1」には登録が無いようです。
hreflangは、検索エンジンにキーワードを入れたとき、どの言語で検索結果を表示するか選択するアルゴリズムに
ヒントを与えるのものです。なので、実装されているISO言語と、ISOの地域を指定する必要があります。
Queryで「コロナたいさく かんせんしょう」と入れても、Googleはjaかja-basicかを判断するのは難しいと思います。

@goki90210
Copy link
Contributor

goki90210 commented Jul 14, 2020

https://nuxt-community.github.io/nuxt-i18n/seo.html#improving-performance
を見る限り、修正箇所は
https://github.com/tokyo-metropolitan-gov/covid19/blob/a7a56fbeb9290552abd76119478d7a8c718bac01/nuxt.config.ts#L91-L102

https://github.com/tokyo-metropolitan-gov/covid19/blob/a7a56fbeb9290552abd76119478d7a8c718bac01/layouts/default.vue#L89-L110
だと思われますが、すでに他の設定があるのでどう修正したらうまくいくかはわからないです。
Nuxt/Vue/TypeScriptに詳しい方お願いします。

p.s.
@harmo-snipe さん ありがとうございます。

@ghost
Copy link

ghost commented Jul 14, 2020

毎度言うだけで申し訳ないです。

hreflangタグについて、例えば、以下の考え方でen/ja/ja-Hira/ko/zh-CN/zh-TWはいかがでしょうか。
ここでの表記順に意図はなくnumericにしただけです。
テクニカルに広く知られた常識のようなものがあるのであればそちらを優先して考慮いただければと思います。

  • 言語のみを指定して地域を指定しない(リージョンを指定しないのはサイトの特性からの個人的思いつきで全くテクニカルな根拠はありません)
  • 言語に複数の文字体系がある場合はISO15924を用いる(ISO15924)
  • 中国語の場合はISO15924を用いるとzh-Hant(繁体)/zh-Hans(簡体)になりますがURLに寄せてzh-CN/zh-TWとする(Hiraとbasicの違いは本件の対応を優先して見なかった事にする)

@goki90210
Copy link
Contributor

covid19/nuxt.config.ts
は修正せず、
covid19/layouts/default.vue

  head(): MetaInfo {
    const i18nSeo = this.$nuxtI18nSeo()
    const ogLocale =
      i18nSeo.meta && i18nSeo.meta.length > 0
        ? i18nSeo.meta[0]
        : {
            hid: 'og:locale',
            name: 'og:locale',
            content: this.$i18n.locale
          }
    return {
      htmlAttrs : i18nSeo.htmlAttrs,
      link: [
        {
          rel: 'canonical',
          href: `https://stopcovid19.metro.tokyo.lg.jp${this.$route.path}`
        },
        {
          rel: 'stylesheet',
          href: 'https://api.mapbox.com/mapbox-gl-js/v1.8.1/mapbox-gl.css'
        },
        ...i18nSeo.link!
      ],

と修正することで

<link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico">
<link data-n-head="ssr" rel="apple-touch-icon" href="/apple-touch-icon-precomposed.png">
<link data-n-head="ssr" rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900&amp;display=swap">
<link data-n-head="ssr" rel="manifest" href="/_nuxt/manifest.7fb87607.json">
<link data-n-head="ssr" rel="shortcut icon" href="/_nuxt/icons/icon_64.bc00b8.png">
<link data-n-head="ssr" rel="canonical" href="https://stopcovid19.metro.tokyo.lg.jp/">
<link data-n-head="ssr" rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/v1.8.1/mapbox-gl.css">
<link data-n-head="ssr" data-hid="alternate-hreflang-ja" rel="alternate" href="/" hreflang="ja">
<link data-n-head="ssr" data-hid="alternate-hreflang-ja-JP" rel="alternate" href="/ja-basic" hreflang="ja-JP">
<link data-n-head="ssr" data-hid="alternate-hreflang-en" rel="alternate" href="/en" hreflang="en">
<link data-n-head="ssr" data-hid="alternate-hreflang-en-US" rel="alternate" href="/en" hreflang="en-US">
<link data-n-head="ssr" data-hid="alternate-hreflang-zh" rel="alternate" href="/zh-cn" hreflang="zh">
<link data-n-head="ssr" data-hid="alternate-hreflang-zh-CN" rel="alternate" href="/zh-cn" hreflang="zh-CN">
<link data-n-head="ssr" data-hid="alternate-hreflang-zh-TW" rel="alternate" href="/zh-tw" hreflang="zh-TW">
<link data-n-head="ssr" data-hid="alternate-hreflang-ko" rel="alternate" href="/ko" hreflang="ko">
<link data-n-head="ssr" data-hid="alternate-hreflang-ko-KR" rel="alternate" href="/ko" hreflang="ko-KR">

が出力されるところまでは確認しました。
これだと日本語が「やさしいにほんご」で表示される可能性がありますね。

PRは私のポリシーに合わない(i18nSeo.link!とNon-null Assertion Operatorがあるため)のと
このあと、しばらく時間が取れないのでしません。

@MaySoMusician
Copy link
Contributor

hreflang="x-default" については、日本語を原文として翻訳作業を行なっているので日本語ページを x-default にした方が良いのではないでしょうか?

@harmo-snipe
Copy link

harmo-snipe commented Jul 14, 2020

hreflang="x-default" は、私の説明の通りGoogleで地域と言語が理解できないときに何を表示するかです。
イギリスで「Corona tokyo」とかで検索すると、該当する地区ではないが、近接言語のenがあるとして、恐らく英語を返却します。
しかし、エジプトで検索するとどの言語を表示して良いのかGoogle側では判断できません。
そのときx-defaultがマークアップされていれば、その言語で表示しようとします。

この例から考えて、defaultは英語が妥当だと判断しました。

@goki90210 さん
誤動作の原因にもなりますし、日本語はjaだけで良いと思います。

@MaySoMusician
Copy link
Contributor

@kaizumaki x-default の設定値に関して、仕様としてはharmo-snipeさんに上記で説明いただいている通りですが、「サイトで翻訳していない言語のユーザーには何語を表示してほしいか」という部分に関して東京都側の意見も確認したいところだと思います。

harmo-snipeさんが指摘する通り、英語を表示すると多くのユーザーをカバーできると思いますが、本サイトでは英語が必ずしも最新の情報ではない点、日本語以外はあくまでも仮の訳であるという点を考慮すると、 x-default は日本語でも良いのではないかと私は思います。
nuxt-i18nの仕様としても、英語・中国語(簡体字・繁体字)・韓国語以外のユーザーは初回読み込み時に(どの言語のURLを踏んだとしても)自動で日本語ページにリダイレクトされてしまうはずです。

@kaizumaki
Copy link
Collaborator

@MaySoMusician

「サイトで翻訳していない言語のユーザーには何語を表示してほしいか」という部分に関して東京都側の意見も確認したいところだと思います。

そうですね。東京都に確認してみましょう。
英語にするか日本語にするか、一長一短ですね。それも伝えておきます。

@harmo-snipe
Copy link

@MaySoMusician さん
なるほど、そうであればちゃんと判断してもらった方が良いですね。

nuxt-i18nの仕様としても、英語・中国語(簡体字・繁体字)・韓国語以外のユーザーは初回読み込み時に(どの言語のURLを踏んだとしても)自動で日本語ページにリダイレクトされてしまうはずです。

うわコレは、初めて知りました。(nuxt-i18nというのを全く知らずに書くのは良くないと思いながら)
何か色々まずい気がします。
もう少し教えてくれませんか?

まず、Googlebotの仕様としてクッキーは保存しないし、クリックもしません。(そういう仕様です)
つまり、初回は必ず日本語にリダイレクトされる仕様なら、
Googlebotのクロールの度に日本語サイトになるはずです。
しかし、現状はご覧の通り英語版になります。
もしかしたら、少し近づきましたかね。

@NEKOYASAN
Copy link
Contributor Author

nuxt-i18nモジュールのissueにも似た感じのissueが立ってますね…

nuxt-modules/i18n#761 (comment)

@harmo-snipe
Copy link

@Nekoya3 さん
情報、ありがとうございます。
搭載言語が無ければ(英語がなければ)このリダイレクトが機能して、Googlebotは日本語ページをクロールしていたのですね。
なるほど、一連の原因が分かった感じです。

つまり、あるとき英語版を搭載したら、以降検索結果が英語版になった

という感じですね。
でも、解決法はこのissue #5001 が一番綺麗だと思います。

コアなリダイレクト部分がいじれる人がいるなら、暫定的に
・クッキーが記録されてない
・HTTPリクエストの Accept-Language: ja 以外
・現在同じ日本語ページではない(リダイレクトループ回避判断)

これらの条件の時に、必ず日本語ページへリダイレクトする様に変更したら、
検索結果が日本語に戻ることになると思います。
(しかし汚いですし、他どんな影響があるか想定出来ない)

ということで、原因らしきものが分かっても
hreflangの勇者待ちになります。

@NEKOYASAN
Copy link
Contributor Author

x-defaultを日本語にした状態で実装試しますね

@MaySoMusician
Copy link
Contributor

MaySoMusician commented Jul 14, 2020

つまり、あるとき英語版を搭載したら、以降検索結果が英語版になった

本サイトの英語は数か月から存在しており、 #4991 で報告される前までは検索結果には特に問題無く日本語で表示されていたように思うのですが...

多言語化周りの目立った変更は #4991 で出ていたnuxt関連ライブラリの更新以外では意図的には行なっていないはずなので、

  • コードで意図しない変更が起きている
  • googlebotの仕様が変わって、クローラが言語設定として英語を要求するようになった & hreflang を正確に記述しないと日本語ページに辿り着かなくなった
    • googlebotはCookieを読まないということなので、英語が表示されていることは navigator.languages の値か Accept-Language で英語の優先順位が高い(nuxt-i18nが正常に動作していれば)
  • googlebotが誤って /en を読みに行っていて、今まではnuxt-i18nがリダイレクトを行なっていたが、逆にnuxt-i18nが誤作動でリダイレクトを行なわなくなった?

あたりが要因なのではないかなぁと個人的には推測しています。

@NEKOYASAN
Copy link
Contributor Author

NEKOYASAN commented Jul 14, 2020

image

Speed Insightでもリダイレクトしちゃってますね
この感じだとnuxtのバージョンアップ周りが怪しい感じがしています...

もしくはGoogle Botの仕様変更が行われたかですね(他地域版で発生していないためこの可能性は低い)

@NEKOYASAN
Copy link
Contributor Author

#4898 でnuxt-i18nのアップデート入ってますが、DeployPreview的にはそれ以前のものでも/enの内容が表示されているため比較ができません...

@harmo-snipe
Copy link

@MaySoMusician さん
私は本問題が発生してから、googlebotの振る舞いを確認していますが、
一連の流れでgoogle側の仕様変更や問題で、本件が発生しているとは考えにくいです。
何度も書きますが、現状のhtmlの振る舞いなら、必ずこうなります。

そのライブラリ?の更新あとという事であれば、それが原因かもしれないです。
まず、私が調べた大前提です。

a)htmlの言語の出し分け方法
 1.ブラウザ側のHTTPリクエストヘッダAccept-Language を見ている
 2.Accept-Language でリクエストされた言語が存在すればそのページへリダイレクトする。
 3.Accept-Language でリクエストされた言語が無ければ日本語にリダイレクトされる。(未確認)
 4.Accept-Languageを搭載せずリクエストすれば英語ページにリダイレクトされる(Googlebotの挙動)

今までnuxtが、ちゃんと機能していなかったのか、何かの修正タイミングでデフォルトが日本語から英語に変更されたのか、このあたりの仕様は私にはわかりません。
ただSEOの識者としては、上記の動作をしており、Googlebotに対して英語版をリダイレクトしていれば、現在の動きになり矛盾はありません。

これから3の実験をしますが、根拠無しの想定ですが、デフォルトが英語に変わったとかだったら
3が日本語ではなく英語になりますねw

@harmo-snipe
Copy link

上記3は日本語にならないですね。
第二言語を選んだ可能性はありますが、英語にリダイレクトされました。

image

@NEKOYASAN
Copy link
Contributor Author

@harmo-snipe Cookie持ったままになってませんか?

@harmo-snipe
Copy link

念のため上記2の実験結果をアップしておきます。
という事が分かっても、結局、enバージョン(全言語)にhreflangを搭載するのが一番綺麗な修正方法だと思います。

image

@harmo-snipe
Copy link

見ての通りprivate browsingです。

@MaySoMusician
Copy link
Contributor

上記3は日本語にならないですね。
第二言語を選んだ可能性はありますが、英語にリダイレクトされました。

image

こちらは第二言語が選ばれています。
#4991 でもコメントしましたがnuxt-i18nの言語判定はここにあるdoDetectBrowserLanguageで行なわれており、内部的に呼ばれているmatchBrowserLocaleでは与えられた言語設定文字列の配列をループしています
(というよりそのように直してもらいました cf: nuxt-modules/i18n#654, nuxt-modules/i18n#655

こちらの環境では

  • 言語設定をdeのみにすると日本語ページが
  • 言語設定をdeとen( navigator.languages = ["de", "en"] )では英語ページが

表示されました。(それぞれCookieとキャッシュを毎回全削除しています)

@harmo-snipe
Copy link

@MaySoMusician さん。
Firefoxは、第二言語を削除できなかったので、Chromeで試しましたが、おっしゃるとおり日本語になりました。
優先順位テーブルをみて実装している言語があればそれにリダイレクトするのですね。
問題は、Accept-LanguageがNULLまたは無し等の場合、何にリダイレクトするかです。
それはコードから、逆に想定出来るものですか?
分かれば教えて欲しいです。

GooglebotはAccept-Languageをリクエストしないので
「何か」を見て「en_US」にリダイレクトしているのは事実なのですが。
その当たりの処理が、核心だと思います。

いずれにしても、リダイレクトで強制的に日本語にしない場合は、hreflangの実装が必要です。

Chromeのテスト記録を添付します。
image

@harmo-snipe
Copy link

harmo-snipe commented Jul 15, 2020

1日経過しましたが
#5001 (comment)
の4の処理の部分を、内容を理解し適切に修正できる方はいらっしゃいませんか。

現在GooglebotのHTTPリクエストに対して英語版のページをリダイレクトしています。
クッキーが無いのにリダイレクト処理をするのはいまいち理解できませんが、
リダイレクトするなら日本語にするべきです。

Googleがどのようなリクエストをこのサーバーに行っているのか、
ログなどで確認出来れば、条件の確定ができると思います。
(条件が確定しようが英語版にリダイレクトしてい現状を修正しないと英語版のママです)

英語版にリダイレクトする処理が意図的なのか、バグなのか、
コードの分かる方は解析をお願いできませんか。

本改修を行わない限り、検索結果のタイトル/他は、当面英語で表示されることになります。
何度も訴えておりますが #4991 の原因はメタタグ云々は関係無く、本問題により発生しているのは確実です。

改修案1
・現在何らかの原因でgooglebotのリクエストに対して英語版にリダイレクトしているのを、日本語版にリダイレクトするように修正する。

改修案2
・現在何らかの原因でgooglebotのリクエストに対して英語にリダイレクトしているのをやめる。
・リダイレクトはクッキーが保存されている場合に限定する。
・hreflangの実装を行う。

以上となります。
そのほか別の案がある場合、効果が期待できるか否かコメントします。

余談ですが私の環境では最初の東京都のマークが出て読み込み中みたいな表示の時はgooglebotに日本語ページを返しており、そのあとのページ表示レンダリング時に、enにリダイレクトします。
以前は、全画面インタースティシャルの読み込み中画面なんて無かったのですが。
あと細かくGooglebotの動きをみているとリダイレクトエラーも検出しています。
これはリダイレクトループが発生している場合に検出される事が多いです。
私はコードは読めないので、全然分かりませんがAccept-languagesを判定する当たりでこのヘッダーが無い時の処理でリダイレクトループなどしてないでしょうか。

@kaizumaki
Copy link
Collaborator

「サイトで翻訳していない言語のユーザーには何語を表示してほしいか」という部分に関して東京都側の意見も確認したいところだと思います。

東京都に確認したところ、defaultは日本語にしてほしいとのことでした。

@Nekoya3

x-defaultを日本語にした状態で実装試しますね

その方向で実装を試してもらってもいいでしょうか?

@MaySoMusician
Copy link
Contributor

ブラウザの言語設定(HTTPリクエストのAccept-Languages ではなく navigator.languages )をページ上部に表示させるように改造したページを作りました: https://determined-spence-36c612.netlify.app/

image

ブラウザのコンソールで navigator.languages を打った時と同じ結果が表示されていると思います。

image

このページをGoogleのモバイルフレンドリーテストにかけると下図のようになります

image

https://search.google.com/test/mobile-friendly?id=vPANO0N28jbY5xajDHlF0Q

これはGoogleが「言語設定を明示的に英語」にした状態でアクセスしてきたことを意味します。googlebotが全く同じ仕様でクロールしているのであれば、検索結果に英語で表示されているのは、現在のソースコードとしては期待通りの動作結果だといえます。仮にhreflangを記述してもgooglebotが日本語ページに到達できない場合は、googlebotのみ特別なリダイレクト措置を取らねばならないかもしれません。

@goki90210
Copy link
Contributor

goki90210 commented Jul 15, 2020

ということはNuxtJS, nuxt-i18nのアップグレードは関係ない可能性が高そうということですね。(※訂正します。)

ちなみに、JMeterなどでクライアント側のJavaScriptを実行しない状態でリクエストを送ると
パスで指定した言語で出力されています(当たり前ですが…)。

仮にhreflangを記述してもgooglebotが日本語ページに到達できない場合は、googlebotのみ特別なリダイレクト措置を取らねばならないかもしれません。

もしそうならかなり厄介ですね…。

@harmo-snipe
Copy link

誤解があるようなので補足しますが、hreflang使用の大前提にリダイレクトは不要です。
en版がgooglebotに読まれ、そのen版にhreflangがあれば「代替の言語が存在する」と判断します。
そこに日本語があれば、日本語のページをクロールしインデックスします。

なので「何か」を見て変なリダイレクトを実装するとhreflangは機能しません。
例えば、HTTPリクエストの「何か」です。

#5001 (comment)
の改善案2が最善だと私の発言を残しておきます。

@harmo-snipe
Copy link

今回のissueとは、まったく関係無く言語設定の本来あるべき仕様は次の通りです。
1)日本語ドメインなので、リクエストがなんであれ日本語のコンテンツを返却する。
2)外国語を実装したい場合は、hreflangで「日本語の」代替ページを検索エンジンに指示する。
3)言語のリダイレクトは使用しない。
4)3の例外として利用者が明示的にクッキーを保存し言語設定を保存した場合はリダイレクトする。

現在1が英語版のため、日本語を実装しても英語ページの代替に日本語があるという意味になります。
まあこのサイトの大きさと影響力からして不利になる事は無いと思いますが、私ならやらないです。
image

@goki90210
Copy link
Contributor

@harmo-snipe さん
今後は、元ネタのリンクを貼っていただけますでしょうか。
https://support.google.com/webmasters/answer/182192?hl=ja
ですよね。(画像だけだと何を根拠に言ってるのかわかりません。)

https://github.com/tokyo-metropolitan-gov/covid19/blob/3744e68343b19cd66cf8025d6d63483be55bd24e/nuxt-i18n.config.ts#L28
のオプションを変えればよいのでリダイレクトを止めるのは難しくはないはずです。

hreflangは「やさしいにほんご」を外さないといけないので要カスタマイズですね。

@harmo-snipe
Copy link

@goki90210 さん
リンク張り忘れ、失礼しました。
オプション設定で、簡単にリダイレクトを外せるなら、
hreflangの実装の時、あわせて実施すると効果があると思います。

関係無い話かもですが、 Nuxtの識者から
・ブラウザの言語コードを返却するタグ自体が無い場合、どのような振る舞いになるのか
・何故英語版にリダイレクトするのか
・何故リダイレクトエラーになっているのか(ループしているのでは?)
の回答をもらっていないのですが、何かわかりますか?
なお、Googlebotは「言語を指定しない」ので、何かしら判断を行い英語版にリダイレクトしていると考えられます。

@harmo-snipe
Copy link

Googlebotが明示的に英語を指定してリクエストをしているという情報があるので、調べてみました。
自分のサイトにgooglebotのHTTPリクエストヘッダを取得するログを吐き出してみました。

内容は
[Host] => www.harukas.org
[Connection] => keep-alive
[Accept] => text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
[From] => googlebot(at)googlebot.com
[User-Agent] => Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
[Accept-Encoding] => gzip,deflate,br
です。
見ての通り、どこにも言語の指定はありません。
ましてやenの文字すらどこにもありません。
google側が言語を一切要求してないにも関わらず、
サーバ側が意図的にen_USとなり英語ページにリダイレクトし、英語を出力しているのは明白です。

googlebotの種類は複数有り、これはほんの一つなのでもう少し監視を続けてみます。
https://support.google.com/webmasters/answer/6144055?hl=ja

@MaySoMusician
Copy link
Contributor

@harmo-snipe 調査いただきありがとうございます。
navigator.languages についても調査いただけますか?
本サイトで使用しているnuxt-i18nはHTTPリクエストのAccept-Language より navigator.languages の値を優先して 言語判定をしています。

#4991 (comment)

「ブラウザの言語設定」「HTTPリクエストヘッダーのaccept-language」の順に設定を参照

と申し上げた部分です)

私が調査したところではgooglebotは navigator.languages'en_US' をセットした状態でサイトにアクセスしています。
これはnuxt-i18nにとっては「ブラウザのWebサイトを表示する言語設定(ブラウザのUIの言語ではない)が英語のユーザーがアクセスしてきた」と同じ状況になります(通常のユーザーとgooglebotの区別はつかない)。
「ブラウザのWebサイトを表示する言語設定」で「英語」と判定された時点で英語ページに誘導されることが決定するので、Accept-Languageの値は無視されます。

現在は、Cookieによる設定が無ければ、上記のようにユーザーの言語を判定して該当する言語のページにリダイレクト(HTTP 3xx系のリダイレクトではなく、単にそのページにroutingすることをnuxt-i18nでは"redirect"と呼んでいます)する設定になっていますので、結果的にgooglebotは英語のページに誘導されます。
(googlebotの navigator.languages が最近変更されていないならば、現在の挙動こそソースコード通りのものであり、逆に日本語の検索結果が表示されていた今までの挙動が不可解ということになります。)


いずれにせよ https://support.google.com/webmasters/answer/182192?hl=ja にあるとおり、Googleはユーザーの言語設定を参照して自動リダイレクトすることは避けよ( Avoid automatic redirection based on the user’s perceived language.)としているので、Cookieが無い場合の自動リダイレクトの設定を解除するのが良いと思われます。

(実装当初は、SNSでURLが共有されたときに、他の言語のユーザーが共有したリンクを踏んでも自分の言語で表示されるように、という目的で「Cookieが無い場合の自動リダイレクト」が設定されました)

@shgtkshruch
Copy link
Contributor

shgtkshruch commented Jul 15, 2020

googlebotの navigator.languages が最近変更されていないならば、現在の挙動こそソースコード通りのものであり、逆に日本語の検索結果が表示されていた今までの挙動が不可解ということになります。

こちらに関して調査したので、まとめてみます。

TLDR

  • 挙動が変わったのは nuxt-i18n のバージョンアップによって、初回レンダリングの処理が変わったため
  • 依存しているライブラリのバージョンアップはやったほうが良いと思っているので、この対応自体を否定するものではありません

クロール結果の推移

こちらにあるように、6/16 の時点では日本語でクロールされています。
#4808 (comment)

また個人的にも Google で検索した際に日本語で表示していることを確認しているので、英語版ができてからしばらくたっても、日本語でクロールされていたと考えらます。

Googlebot の仕様が変わったことも考えにくいので、6/16 以降に行われた本リポジトリの何らかの変更によって英語でクロールされるようになったと考えられます。

このリポジトリ上の変更点

これ以降の動作確認は、こちらの設定で行っています。

  • ブラウザの言語設定を英語に設定
  • Cookie を削除
  • プライベートモード

こちらの PR で Nuxt.js や nuxt-i18n をバージョンアップしています。

Netlify の Deploy Preview で確認すると、日本語ページを表示してから CSR で英語ページにコンテンツを差し替えています。
この段階では body 内は翻訳されていますが、head 要素内にある titledescription は翻訳されていません。
(この挙動に関して nuxt-i18n で issue が上がっています。後述)

スクリーンショット 2020-07-15 20 35 00

次に Nuxt.js や nuxt-i18n をバージョンアップした PR では、head 要素内にある titledescription も翻訳されています。
動作的には CSR で書き換えるのでなく、301 で日本語 -> 英語へリダイレクトしています。

スクリーンショット 2020-07-15 17 12 31

#4933 の変更が Production にも取り込まれていて、Production でも head 内が英語で返ってきます。
(皆さんもおっしゃっていますが、この状態で Google がクロールすれば、英語ページが Index されるのは自然な挙動だと思います。)

これらの経緯を見ると、package のアップデートによってリダイレクトの挙動が変わった可能性があります。
以下、リダイレクトに関係ありそうな nuxt-i18n の変更点を見ていきます。

nuxt-i18n の変更点

#4898 から #4933 の差分として、nuxt-i18n が 6.12.2 -> 6.13.0 へ上がっています。
nuxt-18n の v6.13.0 の CHANGELOG を見ると、先程書いた head 内の要素が翻訳できないバグに関する修正がマージされています。

・ initial redirect breaks reactivity in static mode (54b8186), closes #737

issue: nuxt-modules/i18n#737
PR: nuxt-modules/i18n#753

この PR では、head 内の書き換えをするために location.assign を使ってリダイレクトするようになっています。
https://github.com/nuxt-community/nuxt-i18n/pull/753/files#diff-83b3cb859f692745926fd4e46f138d21

それ以前は nuxt-i18n の setLocale で SPA 的な意味での「リダイレクト」をしていましたが、上記修正を取り込んだ #4933 以降のアプリケーションは、日本語ページの HTML を取得して JavaScript で言語判定がされたあとに、(ユーザーの言語設定が英語であれば)HTTP 的な意味での「リダイレクト」をして英語ページの HTML を取得しています。

リダイレクトでページを再取得しているので、SSG で生成された head 内も多言語化された HTML が返ってきます。
こちらが Googlebot にクロールされて、検索結果が英語に変わったと考えられます。

今までは head 内が翻訳されていなかったために、(navigator.languageen-US の)Googlebot にも日本語の titledescription が返っていたので問題が顕在化しなかったのではないでしょうか?

@harmo-snipe
Copy link

@shgtkshruch さん

動作的には CSR で書き換えるのでなく、301 で日本語 -> 英語へリダイレクトしています。

なるほど、私が確認した以下の現象と完全に一致しました。

余談ですが私の環境では最初の東京都のマークが出て読み込み中みたいな表示の時はgooglebotに日本語ページを返しており、そのあとのページ表示レンダリング時に、enにリダイレクトします。
以前は、全画面インタースティシャルの読み込み中画面なんて無かったのですが。
あと細かくGooglebotの動きをみているとリダイレクトエラーも検出しています。

今までは head 内が翻訳されていなかったために、(navigator.language が en-US の)Googlebot にも日本語の title や description が返っていたので問題が顕在化しなかったのではないでしょうか?

完全同意です。

結論は、nuxt-i18nのバージョン問題ということで原因はほぼ解明できたのかなと思いました。
コードで書いた事が実際にそうなっていなく、偶然うまく動いていた感じですね。

言語選択を実装するのは非常に良いことだと思いますが、各所挙動の影響を考えずリダイレクトするのは
さまざまな問題が発生しますし、やはり慎重に行った方が良いかと思います。
またサーバ側なのだからHTTPレスポンスが取得できるはずなのに、JS発行をして言語取得するのも、仕組み上仕方ないのかなとも思いますが、何かパフォーマンスの無駄な気がします。
googlebotは私が引用したリンクのように「言語設定を持たないbot」です。おそらくnavigator.language の挙動もgooglebotのフレームワークであるChromeシリーズの流用で偶然そうなっているだけで、また別の言語に変更するか、ある日なくなるかもしれません。
そういうことに影響しないようなサイト構成でお願いします。

修正方法は提示しましたし、後はお任せします。
なお、私はクッキーで保存された情報があるときは、該当言語にリダイレクトしても良いというスタンスですが、Google側は「リダイレクトを使用するな」です。ここの違いははっきり申し上げておきます。
なお、Googlebotはクッキーの保持はしませんしクリックもしません。この仕様が突然変わることは、当面ないと思います。

@MaySoMusician
Copy link
Contributor

@shgtkshruch @harmo-snipe お二方、ありがとうございます。
nuxt-i18nの挙動がバージョンアップによってかなり変更されていたのですね。

またサーバ側なのだからHTTPレスポンスが取得できるはずなのに、JS発行をして言語取得するのも、仕組み上仕方ないのかなとも思いますが、何かパフォーマンスの無駄な気がします。
googlebotは私が引用したリンクのように「言語設定を持たないbot」です。おそらくnavigator.language の挙動もgooglebotのフレームワークであるChromeシリーズの流用で偶然そうなっているだけで、また別の言語に変更するか、ある日なくなるかもしれません。
そういうことに影響しないようなサイト構成でお願いします。

サーバー側をPHPで制御しているわけではないので、navigator.languagesreq.headers['accept-language'] のパフォーマンスの差異はあまり無いとは思いますが、

The Accept-Language HTTP header in every HTTP request from the user's browser uses the same value for the navigator.languages property except for the extra qvalues (quality values) field (e.g. en-US;q=0.8).

(https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/languages)

とは異なるクローラーの挙動があることを考えると、どちらを見るかはある程度重要な問題になってきますね。
とはいえ、この部分はnuxt-i18nに変更してもらうか、もしくは独自実装になってきますが...。

@NEKOYASAN
Copy link
Contributor Author

@MaySoMusician 最終的な対応としてはどうしましょうか?

でいきましょうか?

@goki90210
Copy link
Contributor

goki90210 commented Jul 16, 2020

動作的には CSR で書き換えるのでなく、301 で日本語 -> 英語へリダイレクトしています。

正確にはHTTP 301ではなく、JavaScript上のlocation.assignで転送するんですよね?
単に301と書いてしまうとサーバーサイドでHTTP 301を返しているように誤解してしまいます。
(リダイレクトという意味で301と書かれたのだと思いますが…。)

#5001 (comment)
でJMeter云々と(開発している人にとっては当たり前と思っていることですが)書いたのはそういう理由です。

@ghost
Copy link

ghost commented Jul 16, 2020

オフトピックですいません。

hreflangタグについて、例えば、以下の考え方でen/ja/ja-Hira/ko/zh-CN/zh-TWはいかがでしょうか。
ここでの表記順に意図はなくnumericにしただけです。
テクニカルに広く知られた常識のようなものがあるのであればそちらを優先して考慮いただければと思います。

ja-basicについてnuxt-i18n.config.tslocalesをいじればいいと思ったのは私の考えが浅かったようです。
以下のようにhreflangog:localeで仕様が合わないのと、クロールに悪影響がある可能性があるので、@goki90210 さんがおっしゃるようにhreflangについてja-basicに関する除外処理が必要なのですね。

@kaizumaki
Copy link
Collaborator

みなさんご検討いただきありがとうございます!

@Nekoya3 @MaySoMusician そろそろ実装したいところですが、どのような方向性でいきますか?

@MaySoMusician
Copy link
Contributor

MaySoMusician commented Jul 19, 2020

とりあえず私のほうで、nuxt-i18nによる自動リダイレクトの停止と、hreflangの設定までやりたいと思います。

  • sitemapはどうするか: hreflangがあれば一応sitemapは必須ではない
    • 引き続き本issueで議論 or 別issue or 即時対応(sitemapもつける)
  • 言語判定のリダイレクトに関して: 「Cookieがあるときのみ、その言語にする」はnuxt-i18nでは実現が厳しそうなので、独自実装になると思いますが、Googleはこれを非推奨としているので、やるかやらないか含めて別issueを立てようと思います

@kaizumaki
Copy link
Collaborator

@MaySoMusician

とりあえず私のほうで、nuxt-i18nによる自動リダイレクトの停止と、hreflangの設定までやりたいと思います。

OKです!よろしくお願いします 🙏
残りは様子をみながら別issueで良いと思います。

@harmo-snipe
Copy link

harmo-snipe commented Jul 19, 2020

@kaizumaki さん
ちょっと気が早いかもですが、hreflangが実装されるとその状態の確からしさをサーチコンソールで確認する事ができます。
image

インターナショナルターゲティングという項目です。
恐らく実装終了してから3日程度あとに内容が徐々に表示されてくるはずです。
このあたり、アクセスしてデータをいただける準備など、お願いできるなら
いまのうちに実施しておいたほうがよいかもです。
(hreflang搭載後、3日経過後にデータ下さいみたいな)
https://support.google.com/webmasters/answer/6059209?hl=ja

hreflangはとても面倒なタグで
■トップページ(日本語)
このページに日本語①、英語③、中国語(繁)、韓国語・・・
■トップページ(英語)
このページに日本語、英語②、中国語(繁)、韓国語・・・
■新規患者に関する報告件数の推移 ④(英語)
このページに日本語、英語、中国語(繁)、韓国語・・・

①日本語の実装ページにも日本語の実装されたlinkを指示する必要があります。
②英語版でも同様
③日本語ページに代替として実装する言語をすべて指定
④新規患者に関する報告件数の推移みたいなサブページにもすべて実装が必要

基本どれかが欠けたり、抜けたら「リターンがありません」になります。
また言語指定コードを間違うと「不明な言語コード」になります、
これらの情報がインターナショナルターゲティングレポートに表示されれますので、
開発者にフィードバックをしてくれるとありがたいです。

※国のタブは恐らく日本語ドメインなのでjaに固定されていると思われます。
これはgTLDのとき母国語を何するか設定するものですからhreflangには関係ありません。

@kaizumaki
Copy link
Collaborator

@harmo-snipe

これらの情報がインターナショナルターゲティングレポートに表示されれますので、
開発者にフィードバックをしてくれるとありがたいです。

情報ありがとうございます!東京都の担当の方に伝えておきます。

@harmo-snipe
Copy link

harmo-snipe commented Jul 20, 2020

・リダイレクトの停止
・hreflangの実装
を外部から確認しました。
また、本不具合であるキーワードで検索しても、Googleは日本語で返却している事を確認しました。

@MaySoMusician さんお疲れ様でした。

image

多言語例も入れておきます。
中国語繁体字
image

英語
image

韓国語
image

@kaizumaki
Copy link
Collaborator

東京都の担当の方から、Google Search Consoleのインターナショナルターゲティングレポートの画面が送られてきました。
無事に反映されたようです。みなさんありがとうございました!

0721インターナショナルターゲティングレポート

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
help-wanted 特に助けを必要としているもの improvement 改善や新機能の要望
Projects
None yet
6 participants