8月21日、Googleが自社のLinkedInで一行の技術告知を出した。アルゴリズム更新でも順位変動でもない。「構造化データの読み方を変えた」という話だ。地味だが、これは検索結果の見た目を静かに壊しうる変更で、しかも順位レポートには一切現れない。
変更点は「HTMLアンエスケープを1回しかやらない」
Search Engine Roundtableが伝えたGoogleの投稿によれば、Googleはこう書いている。「パーサーをJSONおよび各種標準に合わせるため、JSON-LDの抽出処理を変更し、HTMLアンエスケープを1回だけ適用するようにした」。
これまでGoogleのパーサーは、規格から外れた書き方を親切に補正していた。二重にエスケープされた実体参照を、何度もほどいて元の記号に戻していた。今後はほどくのが1回だけになる。結果として、二重エスケープされたアンパサンドやチェックマークは文字に戻らず、そのままの文字列として値に残る。
Googleは実務上の意味も明示している。「二重エスケープされた実体参照はもう展開されない。JSON-LDを使っているなら、標準のJSONエスケープか、\u0026 のようなUnicode16進エスケープにコードを更新してほしい」。GoogleのGary Illyes氏は、JSONにおける正しいエスケープはRFC 8259の第7節に厳密に定義されていると付け加えた。
ペナルティではない。だから気づけない
ここが今回の厄介なところだ。これはスパム判定でも品質評価でもない。順位は動かない。落ちるのはリッチリザルト、つまり商品価格、レビューの星、パンくず、FAQといった検索結果上の装飾のほうだ。
値が壊れれば、Googleはその項目を無視するか、構造化データ全体を不正と見なす。表示されるのは通常の青リンクだけになる。順位は1位のままでクリック率だけが落ちるという、原因追跡が最も難しい形の劣化が起きる可能性がある。8月18日に始まり21日朝に完了した8月のスパムアップデートと時期が重なっているため、変動の切り分けはさらに難しくなる。
該当しやすいのは「二重に守っている」実装
ここからは筆者の見立てだが、影響が集中するのはテンプレート側で一度HTMLエスケープを通した文字列を、そのままJSON-LDへ流し込んでいる実装だろう。具体的には次の3パターンが疑わしい。
第一に、クエリ文字列付きのURL。パラメータの区切り記号をエスケープしたまま url や @id に入れているケースは、ECサイトの商品URLで珍しくない。第二に、装飾記号。仕様表や特典表のチェックマークを数値参照で書いた文字列が description に混ざる例だ。第三に、二重処理。PHPなら htmlspecialchars() を通した値をさらに json_encode() で包む、テンプレートエンジンの自動エスケープとJSON出力が二段で効いている、といった構成が該当する。
いずれも「XSS対策として正しいことをしているつもり」で発生する。エスケープを二重にかけても表示上は問題が出ないため、これまで放置されてきた。Googleが黙って直してくれていたからだ。
今週確認する3つのこと
- リッチリザルトテストに主要テンプレートを1本ずつ通す。 商品、記事、パンくず、FAQなど、テンプレートの種類ごとに1URLで十分だ。壊れているならテンプレート単位で壊れている。
- Search Consoleの拡張レポートで「未解析の構造化データ」を確認する。 不正なエスケープシーケンス系のエラーが増えていないか、8月21日前後を境に有効アイテム数が落ちていないかを見る。
- 出力の責任をJSON側に一本化する。 文字列をHTMLエスケープしてからJSONに入れるのをやめ、
json_encode()などJSONシリアライザに任せる。HTML内の閉じタグ対策が必要なら\u003CのようなUnicodeエスケープを使う。
機械可読性が、また実務に戻ってきた
本誌が先日報じた41日間のサーバーログ検証——AIクローラーはJavaScriptで挿入したリンクを1本も辿らなかった——と、今回の変更は同じ方向を向いている。機械が読める形で出すという基本を、GoogleもAIクローラーも以前より厳しく要求し始めた。人間のブラウザで見て正しく表示されることは、もう十分条件ではない。
ただし、この変更を悲観的に捉える必要はないという見方もある。標準に寄せるのは筋が通っているし、パーサーごとの解釈差が減れば、GoogleとBing、各種LLMクローラーで同じJSON-LDが同じように読まれる確率は上がる。長期的にはむしろ実装が楽になる方向だ。
問題は移行期の数週間だけだ。そしてその数週間に、誰も気づかないまま星が消えることがある。