ボタンやJavaScriptのリンクがクロールされない原因と直し方
「商品一覧」ボタンを押せば、ページはちゃんと切り替わる。ユーザーは誰も困っていない。それなのに、遷移先のページだけが検索結果に出てこない――。この症状に気づいたとき、まず疑いたいのがリンクの「作り方」です。Googleの公式ドキュメント「リンクをクロール可能にする」は、リンクをクロール可能(=Googleの巡回ロボットがたどれる状態)にするには、href属性を持つaタグ(a要素) を使うよう案内しています。buttonタグやJavaScriptのクリックイベントだけで作った「見た目だけのリンク」は、この公式の形から外れます。まずここを疑ってください。
Googleが「クロール可能」と案内するリンクの形
Googleはリンクを、ページ同士の関連性の把握と、新しいページの発見に使っています。つまりリンクはユーザーの導線であると同時に、Googlebot(Googleの巡回ロボット)がサイトを知る入口でもあります。入口の形が想定外だと、その先を見つけてもらえない場合があります。
公式ドキュメントには、推奨される書き方と推奨されない書き方が例つきで載っています。整理すると次のとおりです。
| 書き方 | 例 | 公式ドキュメント上の扱い |
|---|---|---|
| href属性に相対URL | <a href="/products"> | 推奨例として掲載 |
| href属性に絶対URL | <a href="https://example.com/stuff"> | 推奨例として掲載 |
| href属性にパラメータ付きURL | <a href="/products.php?id=123"> | 推奨例として掲載 |
hrefに javascript: を書く | <a href="javascript:goTo('products')"> | 推奨されない(ただしGoogleは解決を試みる場合がある) |
| hrefの無いaタグ/button・spanタグ+クリックイベント | <button onclick="goTo('/products')"> | 公式の「クロール可能な形」に当てはまらない |
推奨例はすべて「hrefに普通のURLが入ったaタグ」です。相対URLでも、パラメータ付きでも構いません。一方、javascript: で始まるhrefは、公式の例示で「推奨されない。ただしGoogleは解決を試みる場合がある」という扱いです。拾われる可能性はゼロではない、けれど当てにはできない。そういう位置づけです。そして表の最後の行、buttonやspanにクリックイベントを付けた擬似リンクは、公式が示す「クロール可能な形」そのものに当てはまりません。Googlebotに発見されないままになる場合があります。
リンクの見える文字(アンカーテキスト)にも同じドキュメントが触れています。説明的で、簡潔で、リンク先に関連した文言が良いとされ、altも空・リンクテキストも空の画像リンクは悪い例として挙げられています。形を直すついでに、文言も一緒に見直すと一石二鳥です。
なぜ「押せば動くのに」見つからないのか
ブラウザ上では、buttonのクリックイベントでも問題なく画面は遷移します。人間には区別がつきません。では、Googleは何が違うのか。
公式ドキュメントによると、GoogleはJavaScriptを「クロール→レンダリング→インデックス登録」という流れで処理します。レンダリングとは、HTMLやJavaScriptを実際に実行して画面を組み立てる処理のことです。Googlebotはページをクロール用とレンダリング用のキュー(順番待ちの列)に入れて処理を進め、キューから取り出したURLへHTTPリクエストを送る前には、まずrobots.txt(巡回の許可・拒否を書くファイル)を読んで、クロールが許可されているかを確認します。
ここで押さえたいのは、Googlebotが自らクリックイベントを実行して遷移先を探してくれることは、期待しないほうが安全だという点です。レンダリング後のHTML(DOM=ブラウザ上に組み立てられたページ構造)にhref付きのaタグとして現れていれば拾われる余地はあります。しかし「クリックして初めてURLが決まる」作りでは、たどる手がかりがHTMLの中にそもそも存在しません。押せば動く。でもたどれない。これが、遷移先がインデックスされない症状の正体です。
ワークスルー:「商品一覧」ボタンを5分で点検する
具体例で1回通します。トップページに「商品一覧」ボタンがあり、押すと /products へ遷移する。しかし /products が検索結果に出てこない。この状況を点検する手順です。
- 対象の要素を開発者ツールで見る。 Chromeでボタンを右クリックして「検証」を選ぶと、Elementsパネルに実際のHTMLが表示されます。見るのは1点だけ。その要素は「href属性付きの
<a>」か、です。 - 形を判定する。
<a href="/products">なら、リンクの形は問題ありません。別の原因を疑います。<button onclick="goTo('/products')">や<a href="javascript:...">なら、上の表のとおり直す対象です。 - 書き換える。 画面遷移はaタグ、その場の動作(開閉・送信など)はbuttonタグ、と役割で使い分けるのが基本形です。ボタンの見た目が必要なら、aタグにCSSでボタン風のスタイルを当てます。
<a href="/products" class="btn">商品一覧</a>。機能はリンク、見た目はボタン。これで両立できます。 - レンダリング後のHTMLで確かめる。 Search ConsoleのURL検査ツールで対象ページを検査し、「クロール済みのページを表示」を開くと、HTTPリクエストとレスポンス、返されたHTMLを確認できます。JavaScriptでアンカーテキストを挿入している場合は、レンダリング済みHTMLにそれが存在するかをURL検査ツールで確認するよう、公式ドキュメントも案内しています。
- 遷移先そのものも検査する。
/productsをURL検査にかけ、クロールとインデックス登録の状態を見ます。注意点がひとつ。robots.txtでクロールがブロックされているページは、Googleがnoindex(インデックス拒否の指定)を確認できないため、URL検査の「インデックス登録を許可?」は常に「はい」と表示されます。「はい」だから安心、とは限りません。
この例では、手順2で <button onclick> が見つかり、手順3で <a href="/products" class="btn"> に書き換えて完了、という流れになります。所要はおよそ5分。特別なツールは要りません。
SPAでは「最終的に何が出力されるか」で判断する
ReactやVueで作ったSPA(シングルページアプリケーション=ページ遷移をJavaScriptで行うサイトの作り方)の場合、ソースコードに <a> と直接書いていなくても、フレームワークのLinkコンポーネントが最終的にhref付きのaタグを出力していれば、形としては問題ありません。判断基準はソースコードではなく、レンダリング後のHTMLです。手順1の開発者ツールと、手順4のURL検査で実際の出力を確認してください。逆に、独自実装のルーターでhrefの無い要素にクリックイベントだけを付けている場合は、見た目が完璧でも入口が閉じています。
よくある誤解:「JavaScriptを使うこと」自体は不利ではない
「JavaScriptで作るとSEOに弱い」とひとくくりにされがちです。しかし公式ドキュメントは、GoogleがJavaScriptをクロール・レンダリング・インデックス登録の流れで処理することを前提に、見つけてもらいやすくするための方法を案内しています。JavaScriptを使うこと自体が問題なのではありません。こと「リンク」に関して問題になりやすいのは、Googleがたどれる形(href付きaタグ)で提供していないことです。もちろん、公式の案内にはタイトルや意味のあるHTTPステータスコードの使用など、リンク以外の最適化の観点もあります。それでも、フレームワークを捨てる必要はありません。出力されるHTMLを公式の形に合わせれば済みます。
公開前の自己点検チェックリスト
- 主要な導線(グローバルナビ・一覧ページへの入口・ページ送り)は、すべてhref属性付きのaタグになっているか
- hrefに
javascript:で始まる値を書いていないか - ボタンの見た目が必要な遷移を、buttonタグではなく「aタグ+CSS」で作っているか
- アンカーテキストは、リンク先の内容が分かる説明的な文言か(altも文言も空、を残さない)
- レンダリング後のHTML(開発者ツール/URL検査の「クロール済みのページを表示」)で、href付きのaタグが実在するか
サイトが大きくなると、この点検を全ページ手作業で行うのは現実的ではありません。Wemiroのようにサイト内のリンク構造をデータで俯瞰できるツールを使うと、「サイトマップには載っているのに、内部リンクからたどり着けないページ」=JavaScript遷移だけでつながっている疑いのあるページに気づきやすくなります。
リンクの形を直したら、次は張り方の設計です。どのページからどこへ張るかは 内部リンクの最適化 で、形を直してもインデックスされない場合の切り分けは インデックスされない原因の診断 で扱っています。
出典
