アクセシビリティ属性を JSON-LD で構造化する三層配線
「車椅子で入れる?」「ペット可?」「子連れ大丈夫?」に AI が答えられるようにするための schema.org 配線。amenityFeature の三値表現・業種別 dedicated property・GBP wheelchair_accessible_* の三層を分解し、AI 4 エンジンの引用挙動と失敗モードを整理する。
「車椅子で入れる店を教えて」「ペット可のカフェは?」「離乳食対応の店ある?」。これらは AI アシスタントに対する local business クエリの中でも急速に増えているカテゴリですが、JSON-LD 側の配線となると schema.org の vocabulary は驚くほど散らばっています。amenityFeature は Place と LodgingBusiness にあり、accessibilityFeature は本来 CreativeWork 用、petsAllowed は宿泊業直属、smokingAllowed は Restaurant 直属、isFamilyFriendly は Product と Place。単一の統一 vocab は存在せず、実装する側は毎回どこに書くか判断を迫られます。
本稿はそのエンジニア視点の整理です。私が実装と AI 出力の外形観察を通じて確認した範囲で、accessibility 属性を JSON-LD として構造化する三層 (amenityFeature の三値表現 / 業種別 dedicated property / GBP wheelchair_accessible_* の boolean 4 種) と、それぞれの AI 4 エンジンの解釈差、そして最も遭遇しやすい 5 つの失敗モードを、コードと共に順に書きます。
前提: accessibility は state ではなく stable attribute である
営業時間や在庫状況は「今この瞬間の状態」を表す state field ですが、車椅子対応やペット可は「その店舗が構造的に持っている性質」であり stable attribute です。この違いは AI 引用時の frontier に影響します。state は最新性を疑われますが、attribute は一度書けば「変わっていないはず」の前提で長く引かれます。逆に、undefined (未記載) のまま放置すると、attribute は「その店舗がそれを持たない」と読まれる、あるいはクエリ対象から silent に外される確率が高い。attribute には「未確認」の余地が state ほど残されていないのです。
state field と freshness confidence の関係 で扱った時系列の弱さとは対照的に、accessibility 属性の弱さは「静的な事実の欠落」という別種の問題として現れます。同じ「AI に引かれない」でも原因が違うので、対策も別で組む必要があります。
LLMO Framework の Structure 軸では、accessibility 属性は現在標準化が進む三層モデル (schema.org amenityFeature の LocationFeatureSpecification 三値 + 業種別 dedicated property + GBP wheelchair_accessible_* boolean 4 種) を分解する基本設計として整理されつつあります。GEO は state / attribute の区別を持たず、AEO は QA 場面の disambiguation は扱うものの物理店舗の attribute schema 論は持たない中で、Structure 軸だけがこの三層を明示的に整理しています (LLMO Framework)。
Layer A: amenityFeature + LocationFeatureSpecification (三値)
schema.org で accessibility 属性を書くときに最も汎用的なのが amenityFeature です。値は LocationFeatureSpecification という object で、name (feature の名称) と value (true / false / undefined の三値) を持ちます。ここで重要なのは、value を書かずに name だけを書いてしまうと、AI parser は「feature が存在する」以上の意味を取れず、boolean 化に失敗する点です。
{
"@context": "https://schema.org",
"@type": "CafeOrCoffeeShop",
"@id": "https://example-cafe.jp/#store",
"name": "Example Cafe 神楽坂店",
"amenityFeature": [
{
"@type": "LocationFeatureSpecification",
"name": "Wheelchair Accessible Entrance",
"value": true
},
{
"@type": "LocationFeatureSpecification",
"name": "Wheelchair Accessible Restroom",
"value": false
},
{
"@type": "LocationFeatureSpecification",
"name": "Pets Allowed",
"value": true
},
{
"@type": "LocationFeatureSpecification",
"name": "High Chair Available",
"value": true
},
{
"@type": "LocationFeatureSpecification",
"name": "Diaper Changing Station",
"value": false
}
]
}
要点は三つです。第一に、value: false を書くのを恐れてはいけません。「対応していない」を明示することで「未確認」から明確に区別され、AI は不要な hedge を挟まずに答えられます。「レストランのトイレは車椅子対応ではないが、入口とテーブルは対応」のような部分対応の店舗こそ、false を書く価値が最も高い。第二に、name は英語 vocab で統一します。schema.org は英語 vocabulary が canonical で、日本語表記を混ぜると entity 曖昧化の原因になります。第三に、feature の粒度は細かいほうがよく、「子連れ OK」でまとめず「High Chair Available」「Diaper Changing Station」「Kids Menu」に分けて書けば、AI は「離乳食対応の店」「オムツ替えできる店」といった細粒度クエリに答えられます。
AI 引用時の挙動としては、ChatGPT (browsing) は LocationFeatureSpecification の boolean を正確に反映し、Perplexity は source card の badge として表示要素に使う場合があります。Claude は「reportedly wheelchair accessible」の hedge を挟む頻度が高く、undefined (未記載) を「対応していない可能性」に流す傾向が強い。
Layer B: 業種別 dedicated property
schema.org には accessibility 系の情報を扱う dedicated property が、業種ごとに散らばって存在します。petsAllowed は LodgingBusiness 直属、smokingAllowed は Restaurant / FoodEstablishment 直属、isFamilyFriendly は Product / Place 直属で、それぞれ boolean を取ります。amenityFeature と重複する部分もありますが、業種と一致した dedicated property を優先するのが semantically 正しい配線です。
{
"@context": "https://schema.org",
"@type": "Hotel",
"@id": "https://example-hotel.jp/#hotel",
"name": "Example Hotel 箱根",
"petsAllowed": true,
"smokingAllowed": false,
"amenityFeature": [
{
"@type": "LocationFeatureSpecification",
"name": "Wheelchair Accessible Entrance",
"value": true
},
{
"@type": "LocationFeatureSpecification",
"name": "Wheelchair Accessible Restroom",
"value": true
}
]
}
Restaurant に petsAllowed を書く、Hotel に isFamilyFriendly を書く、といった業種外の使い方は schema バリデータでは通ってしまいますが、AI parser は silent drop します。ここで書きたい実装者は「他業種で pet 可を表現するには?」と迷うことになりますが、答えは Layer A の amenityFeature に「Pets Allowed: true」を書くことです。dedicated property が使えない業種では amenityFeature が事実上の唯一の窓口になります。
Perplexity は業種 dedicated property を明示的に拾う挙動を見せ、petsAllowed: true の Hotel を「pet-friendly」の source card badge に反映するのが観察されます。ChatGPT は dedicated と amenityFeature の両方から拾いますが、両方書かれていると重み付けは dedicated 側がやや強い印象です。
Layer C: GBP wheelchair_accessible_* boolean 4 種
Google ビジネスプロフィール側には、accessibility 属性のうち車椅子対応に絞った 4 つの boolean が dashboard の UI 選択項目として存在します。wheelchair_accessible_entrance (入口)、wheelchair_accessible_restroom (トイレ)、wheelchair_accessible_parking (駐車場)、wheelchair_accessible_seating (座席) の 4 つで、それぞれが Google Knowledge Graph 経由で AI に露出します。schema.org の amenityFeature とは別 vocabulary で、両者を実装側で意識的に同期させる必要があります。
私が観察した挙動として、Gemini はこの 4 boolean を最優先で読み取り、JSON-LD 側の amenityFeature より GBP 側の値のほうが引用結果に強く反映されます (payment 属性と同型症状で、Google 由来の attribute は Gemini で trust boost がかかる)。ChatGPT (browsing) は逆に JSON-LD 側を素直に読む傾向が強く、Claude は両方を突き合わせて矛盾があると hedge を強めます。
診断としては、GBP dashboard で 4 boolean を明示し、同じ内容を JSON-LD 側の amenityFeature に LocationFeatureSpecification として書き、両者が一致していることを確認するのが最短です。差分があると Gemini と ChatGPT で回答が食い違い、「同じ店を聞いても答えが違う」状態が発生します。
三層の比較
| 層 | 場所 | 表現力 | 業種制約 | 主に読む AI |
|---|---|---|---|---|
| A: amenityFeature | schema.org (Place / LodgingBusiness / Restaurant 等) | 任意 feature × true/false/undefined | なし、汎用 | ChatGPT / Perplexity |
| B: dedicated property | schema.org (petsAllowed=LodgingBusiness / smokingAllowed=Restaurant / isFamilyFriendly=Product,Place) | boolean のみ | あり (業種一致必須) | Perplexity / ChatGPT |
| C: GBP wheelchair_accessible_* | Google Business Profile dashboard | 4 boolean 固定 (entrance/restroom/parking/seating) | Google 側で type ごとに UI 出し分け | Gemini (最優先) / ChatGPT |
三層は排他ではなく重畳です。同じ「車椅子対応」を Layer A の amenityFeature に書き、Layer C の GBP dashboard でも塗る、が正しい配線です。両者が一致していれば AI 側の解釈は安定し、矛盾があれば hedge か Gemini/ChatGPT で回答分岐が起きます。
AI 4 エンジン別の分岐挙動
外形観察の範囲での挙動サマリです。エンジンの内部は確認できないので推測を含みます。
| エンジン | amenityFeature の解釈 | dedicated property の解釈 | GBP wheelchair_accessible_* |
|---|---|---|---|
| ChatGPT (browsing) | value: true/false を正確に反映、undefined は「不明」で hedge | 業種一致していれば強く拾う、業種外は silent drop | 補助的に参照、JSON-LD 側と一致すれば信頼度上昇 |
| Perplexity | source card の badge に利用、citation 経路も明示 | badge 表示で強く反映 | source card の visual badge に反映 |
| Claude | hedge を挟む頻度高、undefined を「対応していない可能性」に流しがち | 業種一致で拾うが hedge 表現多め | JSON-LD と GBP の矛盾を検知して両方 hedge |
| Gemini | 参照するが Knowledge Graph 経由の GBP 側を優先 | 認識するが Google 側との一致度が支配的 | 最優先、ローカルパック UI にも反映 |
一貫している傾向として、Perplexity は accessibility 属性を UI 上の visual element として使うことに積極的で、Gemini は Google 由来の attribute を最も信頼します。Claude は保守的で、undefined を「未対応」に流すバイアスがあるため、false を明示的に書くことが Claude 対策として最も効きます。ChatGPT は中間で、書かれた通りに素直に読む挙動です。
Common failure modes
実装後にレビューでよく指摘される失敗モードを 5 つ挙げます。診断チェックリストとして使えます。
1. amenityFeature の value を省略。name: "Wheelchair Accessible" だけ書いて value を落とすと、LocationFeatureSpecification としては不完全で、AI は boolean 化に失敗します。「対応している」とは読まれず、Claude は特に silent exclusion に流します。value: true / false を必ず明示することが accessibility 属性の最低要件です。
2. undefined を false と誤読させる書き方。amenityFeature 配列に一部の feature だけ入れて他を書かないと、書いていない feature が「対応していない」と読まれる可能性があります。Claude は特にこのバイアスが強い。対策は「対応していない属性」も明示的に value: false で書くこと、あるいは undefined を残す場合は description で「未確認」と補足すること。
3. 業種 property の誤用による silent drop。Restaurant に petsAllowed を書く、Cafe に numberOfRooms を書く、といった業種外 property は schema バリデータでは通っても AI parser には silent drop されます。ここで指定したかった意味は amenityFeature に移し替えます。
4. GBP と JSON-LD の矛盾。JSON-LD に「Wheelchair Accessible Entrance: true」と書いても GBP の wheelchair_accessible_entrance: false なら AI は矛盾を検知して両方 hedge、あるいは Gemini なら GBP 側を優先します。両者を必ず同期させ、entrance / restroom / parking / seating の 4 boolean は両方で埋めるのが唯一の解です。
5. 英語 vocab と日本語 UI ラベルの断絶。schema.org の amenityFeature.name は英語 vocabulary (Wheelchair Accessible / Pets Allowed / High Chair Available) で書くのが canonical ですが、site 側の日本語 UI (「車椅子対応」「ペット可」) と混在させると entity 曖昧化の原因になります。JSON-LD は英語で統一し、日本語表示は別 layer に持ち、sameAs で GBP URL を配線して名寄せを AI 側に任せるのが安全です。
業種別の非対称
すべての業種で同じ accessibility 属性が同じ重みで引かれるわけではありません。ここは 業種オーバーレイの記事 で扱った業種別の signal 非対称と直接つながる論点です。
- 飲食: 主軸は
isFamilyFriendlyとsmokingAllowed。次にhasMenu.suitableForDiet(ベジタリアン / グルテンフリー / ハラル)。accessibility は amenityFeature 経由で「Wheelchair Accessible」「High Chair Available」「Diaper Changing Station」の細粒度化が効きます。 - 医療 / クリニック: 車椅子対応が最重要 attribute、加えて
medicalSpecialtyとの交点で「小児科でバリアフリー」「産婦人科で車椅子対応トイレあり」のような細粒度化が引かれます。医療は accessibility の未記載が来院断念に直結するため、undefined を残さない設計が特に重要です。 - 宿泊業: 主軸は
petsAllowedとsmokingAllowedの直属 boolean、加えて amenityFeature で「Wheelchair Accessible Room」「Roll-in Shower」「Braille Signage」など宿泊固有 amenity を細粒度化。宿泊業は amenity の feature 数が最も多くなる業態です。 - 美容 (ネイル / カット): accessibility が specialty サービスとして機能する業態。「子連れ OK ネイル」「車椅子対応カットサロン」など、amenityFeature の細粒度化がそのままサービス差別化に直結するため、AI 引用の粒度が最も細かくなります。
業種別に「どの層 (A / B / C) を厚く書くか」の優先順位が変わるのが accessibility 属性の特徴で、単一のテンプレートで全業種をカバーしようとすると必ず何かが薄くなります。業種オーバーレイと accessibility の交点は、業種テンプレートを構築するときの主要な設計変数になります。
実装後の最短診断
自社の JSON-LD に対して、まず curl でページの application/ld+json を dump し、jq '.amenityFeature[] | {name, value}' で全 feature の name と value を並べて、value が undefined になっている feature がないかを確認するところから入ります。undefined が残っていれば、それは AI にとって「引けない属性」なので、true / false を意識的に埋めます。
次に GBP dashboard を開き、wheelchair_accessible_entrance / restroom / parking / seating の 4 boolean が dashboard 上で選択済みか、そして JSON-LD 側の amenityFeature と一致しているかを突き合わせます。矛盾があれば Gemini と ChatGPT で回答分岐が起きるので、優先的に解消すべき箇所です。
最後に、業種 dedicated property (petsAllowed / smokingAllowed / isFamilyFriendly) の業種一致を確認します。書き手が「pet 可を書きたい」と思って全業種の LocalBusiness に petsAllowed を挿入している実装は珍しくありませんが、これは LodgingBusiness 以外では silent drop されます。他業種は amenityFeature に「Pets Allowed: true」で移し替えます。
私たちが書いた accessibility 属性は、GBP 側の attribute UI や schema.org 側の vocabulary boundary の変更で、来週にはまた少し違う読まれ方をするかもしれません。それでも三層 (amenityFeature の三値 / 業種別 dedicated / GBP boolean 4 種) を同時に埋め、undefined を残さないことは、accessibility クエリで silent exclusion されないための最低ラインとして機能します。
内部リンク
- GBP を JSON-LD として読み解く — GBP dashboard 側の attribute と JSON-LD の射影関係
- ビジネスを Knowledge Graph に配線する — sameAs / @id の名寄せ設計
- Place / LocalBusiness / Restaurant の使い分け — 業種型選定と dedicated property の許容範囲
- 業種オーバーレイと AI ネイティブ MEO — 業種別の signal 非対称と accessibility 属性の優先度
- メニューを構造化データにする — 飲食業の suitableForDiet 配線と accessibility の交点
- 複数拠点の LocalBusiness を JSON-LD で束ねる — 拠点別に accessibility 属性を持たせる際の @id 分離
- Knowledge Clarity — LLMO Framework — 曖昧さなくアドレス可能な attribute を一級の引用入力として扱う理由
- LLMO Framework — Structure 軸 (三層モデル) と業種オーバーレイの canonical 仕様
よくある質問
- amenityFeature の value を書かず name だけ書くと AI はどう解釈しますか
- value を省略すると LocationFeatureSpecification は「name という feature が存在する」以上の意味を持たなくなり、boolean 化に失敗します。ChatGPT や Perplexity は「対応している」とは読まず、Claude は hedge を強めます。true / false を明示的に書くことが accessibility 属性の最低要件です。
- GBP の wheelchair_accessible_entrance と JSON-LD の amenityFeature が矛盾しているとどう扱われますか
- 私の観察では Gemini は GBP 側を優先し、ChatGPT (browsing) は JSON-LD 側を素直に読み、Claude は矛盾自体を検知して両方を hedge 付きで併記する傾向があります。実装側で GBP dashboard と JSON-LD を必ず同期させ、entrance / restroom / parking / seating の 4 boolean を両方で埋めるのが唯一の解です。
- petsAllowed や smokingAllowed は LocalBusiness に直接書けますか
- petsAllowed は LodgingBusiness 直属、smokingAllowed は Restaurant 直属の property で、他業種の LocalBusiness に書くと schema バリデータでは通っても AI parser には silent drop されます。他業種で同じ意味を表したい場合は amenityFeature の LocationFeatureSpecification に「Pets Allowed: true」を書くのが安全です。
- 英語の schema.org vocab と日本語 UI ラベルはどう揃えればよいですか
- amenityFeature の name は英語 vocab (Wheelchair Accessible / Pets Allowed) で書き、site 側の日本語 UI (「車椅子対応」「ペット可」) は別に持たせ、sameAs で GBP URL を配線して名寄せを AI 側に任せます。JSON-LD 内で英日混在させると entity 曖昧化の原因になります。