# 09 — Structured data (JSON-LD) : raffinements

> **Spec** : Structured data (JSON-LD) — tier **recommended**
> **Verdict** : 🟠 **PARTIAL** (socle très solide, défauts ciblés) · **Priorité : P3**
> **Effort estimé** : 0,5 jour
> **Lié** : [03 — Breadcrumbs](03-breadcrumbs.md) (BreadcrumbList cassé traité là-bas), [06 — Open Graph](06-open-graph-image.md) (dimensions logo)

## Ce qui est conforme (et remarquablement complet)

L'accueil émet un `@graph` JSON-LD pré-rendu de ~4,4 Ko avec :

- **`@type: ["LocalBusiness", "PestControlService"]`** — double typage correct pour le métier ✓
- `name`, `alternateName`, `url`, `logo`, `description`, **`telephone`** (+33631266384, format E.164 ✓), `email`
- `address` (PostalAddress : Melun, 77000, Île-de-France, FR), **`geo`** (48.5426, 2.6545)
- **`openingHoursSpecification`** (lun-ven 07:00-21:00, sam-dim 08:00-20:00)
- `areaServed` (77/91/94/89/75), `priceRange`, `paymentAccepted`, `currenciesAccepted`
- `hasOfferCatalog` : 4 services, dont un avec prix (80 EUR)
- `sameAs` (Facebook, Instagram)
- Nœud `WebSite` (avec `publisher` par référence `@id` ✓, `inLanguage: fr-FR`)
- Nœud `FAQPage` (4 questions) dont le contenu **est réellement visible sur la page** ✓ (exigence spec)

## Problèmes & preuves

| # | Défaut | Détail |
|---|---|---|
| 1 | `PostalAddress` sans **`streetAddress`** | Ville + CP seulement. Pour un LocalBusiness, l'adresse complète renforce l'entité (Google Business Profile matching) |
| 2 | **`unitText: "à partir de"`** détourné | `priceSpecification: { price: "80", unitText: "à partir de" }` — `unitText` désigne une unité (heure, m²…). « À partir de » se modélise avec **`minPrice`** |
| 3 | `WebSite` sans `potentialAction` | Pas de `SearchAction` (sitelinks searchbox) — pertinent seulement si une recherche interne existe ; sinon ignorer |
| 4 | **Incohérence des dimensions du logo** | JSON-LD déclare 512×512, `og:image` déclare 1200×630, le fichier réel fait 1239×1077 — trois vérités pour un fichier (fix global en [issue 06](06-open-graph-image.md)) |
| 5 | `FAQPage` : rich result retiré | Google a retiré le rich result FAQ pour les sites non-gouv/santé — le markup reste utile aux agents IA, le conserver, mais ne pas en attendre de SERP feature |
| 6 | Pas de `BreadcrumbList` sur départements/services/tarifs/contact ; cassé sur les villes | Traité en [issue 03](03-breadcrumbs.md) |
| 7 | 3 offres du catalogue sans prix | Frelons, chenilles, dératisation : pas de `priceSpecification` — ajouter au moins un `minPrice` si les tarifs sont publics (ils le sont sur `/tarifs`) |

## Correctif

Correction du bloc prix (défauts 2 et 7) :

```json
"priceSpecification": {
  "@type": "PriceSpecification",
  "priceCurrency": "EUR",
  "minPrice": 80
}
```

Adresse (défaut 1) :

```json
"address": {
  "@type": "PostalAddress",
  "streetAddress": "<adresse réelle>",
  "addressLocality": "Melun",
  "postalCode": "77000",
  "addressRegion": "Île-de-France",
  "addressCountry": "FR"
}
```

Logo (défaut 4) : déclarer les dimensions **réelles** du fichier référencé, ou servir un logo carré dédié (Google : ≥ 112×112, 1:1) :

```json
"logo": { "@type": "ImageObject", "url": ".../images/logo-square.png", "width": 512, "height": 512 }
```

Bonus agents IA / SEO local : dupliquer un nœud `LocalBusiness` allégé (name, telephone, areaServed localisé, url de la page) sur les pages **départements et villes** avec `areaServed` réduit à la zone de la page — aujourd'hui seule l'accueil porte l'entité.

## Vérification

- https://validator.schema.org : 0 erreur, 0 warning sur `/`, une page département, une page ville, un article.
- https://search.google.com/test/rich-results : LocalBusiness reconnu, BreadcrumbList valide (après issue 03).
- Cohérence interne : les dimensions déclarées de chaque image = dimensions réelles (`identify`).
