# 02 — Diagnostic CX et conversion, étape par étape

**Site** : TERO Padel Club — Astro 7, statique, trilingue FR / NL / EN, 6 clubs.
**Périmètre mesuré** : 63 URL publiées (66 fichiers HTML dans `dist/`, dont 3 pages 404 ;
21 URL par langue, cf. `docs/matrice/matrice-tero.architecture.json:23,481`).
**Règle appliquée** : chaque affirmation porte un chemin de fichier + un numéro de ligne, ou une
mesure reproductible. Quand la donnée n'existe pas, c'est écrit **ABSENT** ou **non mesuré** —
jamais déduit.

---

## 0. Méthode, et avertissement sur les preuves

**Preuves utilisées.** Trois niveaux, cités séparément :
1. **source** — le fichier du dépôt qui décide du rendu (`src/**`) ;
2. **sortie** — le HTML réellement construit (`dist/**`), qui prouve ce que le visiteur reçoit ;
3. **mesure** — un comptage exécuté (grep), avec son résultat.

**Avertissement.** `docs/qa/logs/*.log` et `docs/qa/RAPPORT-VERIFICATION.md` datent du
13/10/2026 et décrivent un build à **29 pages** avec NL/EN absentes (`docs/qa/logs/check-build.log:1`).
Ils ne décrivent **pas** l'état actuel : `dist/` contient aujourd'hui 66 fichiers HTML.
Ces logs ne sont donc jamais utilisés ci-dessous comme preuve d'un état courant.

**Ce qui manque structurellement, d'entrée.** Aucun outil de mesure n'est installé :
0 occurrence de `gtag|googletagmanager|analytics|plausible|umami|matomo|fathom|posthog|clarity|hotjar`
dans `src/` ; le bandeau cookies a été retiré au motif explicite « aucune donnée n'est collectée,
ZERO cookie » (`src/layouts/BaseLayout.astro:208-218`). Toute la section D en découle.

---

## A. Carte CX par étape

Pour chaque étape : ce que le visiteur cherche, ce que le site fournit (preuve), le risque de
fuite, la micro-conversion réellement disponible, et la mesure.

### A1. Déclencheur (avant le site)
- **Cherche** : « padel + ville », « combien coûte une séance », avis, réservation.
- **Fournit** : sitemap trilingue (`public/robots.txt:1`), `public/llms.txt`, `public/llms-full.txt`,
  JSON-LD (`src/data/schema-core.ts`), 2 guides de réponse (`src/pages/guides/*`).
- **Fuite** : aucune donnée d'acquisition n'est disponible dans le dépôt → **non mesuré**.
- **Micro-conversion** : aucune à ce stade (page vue).
- **Mesure** : impossible sans log serveur exploité (cf. D). Référencement : aucun fichier de
  vérification Search Console dans `public/` → **non mesuré**.

### A2. Découverte (accueil)
- **Cherche** : est-ce que ça existe près de moi, combien ça coûte, puis-je réserver.
- **Fournit** : accueil avec 4 faits en hero — « 6 clubs », « 58 terrains couverts », « 90 min dès 5 €
  par joueur », « Réservation en ligne 24/7 » (`src/components/ContentPage.astro:190-197` ; rendu
  vérifié dans `dist/index.html`, classe `hero-facts`).
- **Fuite** : le CTA « Réservez votre terrain » ne mène pas à une réservation mais à une page de
  sélection. Mesure sur `dist/index.html` : **0** occurrence de `playtomic.io`, **7** occurrences de
  `href="/reserver/"`. Deux clics minimum avant le moteur de réservation.
- **Micro-conversion** : clic sur le hub `/reserver/` (`src/components/ContentPage.astro:184`).
- **Mesure** : aucun événement. Clic sortant non instrumenté.

### A3. Comparaison (choisir un club)
- **Cherche** : quel club, quel prix, quelle distance, combien de terrains.
- **Fournit** : page `/clubs/` — tableau 10 colonnes par club (courts, couverts, extérieurs, simples,
  surface, prix 90 min, tarif annuel) dans `src/components/ClubsCompare.astro:94-155`, plus un lien
  direct Playtomic par ligne (`:147-149`).
- **Fuite** : les deux guides de décision sont quasi orphelins — **0** entrée dans la navigation
  (`src/data/ui.ts:746-849`), **0** lien depuis le contenu (grep `guides/|gids/` dans
  `src/content` = 0), et **1 seul lien entrant** chacun (`ClubsCompare.astro:162` ;
  `GuideTarifs.astro:273`). Le guide tarifaire n'est atteignable que depuis `/clubs/`.
- **Micro-conversion** : comparateur + lien guide (`ClubsCompare.astro:157-169`).
- **Mesure** : aucune.

### A4. Décision (fiche club)
- **Cherche** : prix, horaires, adresse, comment réserver maintenant.
- **Fournit** : fiche club = réponse en 5 secondes + tarifs + itinéraire + Playtomic
  (`src/components/ClubPage.astro:135-191` bande « essentiel », `:197-231` tarifs, `:273-330`
  adresse/contact). `ClubAnswer` produit un paragraphe autoportant de 40-60 mots
  (`src/components/ClubAnswer.astro:94-111`).
- **Fuite** : la fiche club est la seule page qui cumule prix, adresse et lien Playtomic direct au
  même endroit ; **ABSENT** d'avis clients (cf. C).
- **Micro-conversion** : « Réserver sur Playtomic » (`ClubPage.astro:168,224,286,314`).
- **Mesure** : aucune.

### A5. Réservation (hub `/reserver/`)
- **Cherche** : réserver en 3 clics, connaître le prix avant de partir.
- **Fournit** (gabarit) : 6 cartes club avec ville, nom, terrains, adresse, bouton « Réserver un
  terrain » (Playtomic) et « Cours et stages » (a4tp) — `src/components/BookingPage.astro:59-79`.
- **Fuite** : **aucun prix sur cette page** (les tarifs sont sur les fiches club :
  `ClubPage.astro:204-222`). Le visiteur quitte le site sans savoir ce qu'il va payer.
  Le second CTA « Cours et stages » n'apparaît que sur **1 carte sur 6** : mesure sur
  `dist/reserver/index.html`, 6 liens `playtomic.io`, **1** lien `a4tp.be` (carte Garisart) et
  **1** occurrence du libellé « Cours et stages », alors que le chapô promet cours et stages via
  Tero Academy sans distinguer les clubs (`BookingPage.astro:26,72-74`). Voir F15.
- **Micro-conversion** : 6 liens Playtomic et 1 lien académie, sur 6 cartes.
- **Mesure** : `scripts/check-reservation.mjs` vérifie la présence des liens
  (cf. `docs/qa/site-expectations.json:67-73`), pas leur performance.

### A6. Pré-visite (avant d'arriver)
- **Cherche** : adresse exacte, itinéraire, horaires, que faut-il apporter.
- **Fournit** : adresse NAP + carte `clubMapUrl` (`ClubPage.astro:156-169`), créneaux détaillés
  (`src/content/fr/clubs/limelette.json:82-97`), location de raquette 7 € et balles 8,90 €
  (`limelette.json:106-116`).
- **Fuite** : **téléphone ABSENT partout** — `PHONE` volontairement non publié
  (`src/data/site.ts:21-25`), 0 clé `"phone"` dans `src/content/**`, et **0** lien `href="tel:"`
  dans `dist/` (grep). Le bloc téléphone conditionnel `ClubPage.astro:299-304` n'est jamais rendu.
  Un visiteur qui a un imprévu le jour J n'a aucun canal immédiat.
- **Micro-conversion** : itinéraire (lien Maps) ; e-mail en repli (`ClubPage.astro:305-310`).
- **Mesure** : aucune.

### A7. Visite
- **Cherche** : rien sur le site (il est sur place).
- **Fournit** : **rien** — aucune page « sur place », aucun QR code de club, aucun lien de
  demi-tarif. Le site n'accompagne pas le moment de la visite.
- **Fuite** : n/a.
- **Micro-conversion** : **ABSENT**.
- **Mesure** : impossible.

### A8. Post-visite
- **Cherche** : retrouver le créneau, s'inscrire, être rappelé des nouveautés.
- **Fournit** : **rien**. Aucune capture d'e-mail, aucun formulaire, aucune confirmation.
- **Fuite** : **maximale** — le visiteur satisfait repart sans laisser de trace exploitable.
- **Micro-conversion** : **ABSENT** (cf. F4, F5).
- **Mesure** : impossible.

### A9. Fidélisation
- **Cherche** : rejouer, s'abonner, rejoindre la communauté.
- **Fournit** : réservation à l'année sur 50 semaines, visible en tarifs club
  (`ClubPage.astro:83-97` + `src/content/fr/clubs/waterloo.json:208-221`) ; groupes
  WhatsApp **présents dans les données** (12 clés `"whatsapp"` dans `src/content/**`) et un libellé
  dédié (`src/data/ui.ts:202`).
- **Fuite** : les 12 liens WhatsApp ne sont **rendus nulle part** — 0 occurrence de `whatsapp` dans
  `src/components/**` et `src/pages/**`, 0 occurrence de `chat.whatsapp.com` dans `dist/` (greps).
  Idem pour le champ `rental` : 18 clés dans le contenu, 0 rendu.
- **Micro-conversion** : **ABSENTE** en pratique (le seul levier communautaire est dormant).
- **Mesure** : impossible.

### A10. Recommandation
- **Cherche** : partager, recommander, s'inscrire à un tournoi.
- **Fournit** : réseaux sociaux en pied de page (`src/components/Footer.astro:26-28`), tournoi
  digitalisé avec QR code **réservé à l'offre B2B** (`src/content/fr/pages/groupes.json:82-83`).
- **Fuite** : aucun bouton de partage, aucun programme de parrainage, aucune preuve sociale à
  transmettre (pas d'avis) → recommandation non captée.
- **Micro-conversion** : **ABSENTE**.
- **Mesure** : impossible.

---

## B. Frictions mesurées

Chaque friction est prouvée par une source (`src/**`) et, quand le doute existe, confirmée dans
la sortie construite (`dist/**`).

**F1 — Barre d'action mobile : deux libellés, une seule destination.**
Défauts : `primary = { label: « Réserver », href: bookingPath(lang) }` et
`second = { label: « Choisir mon club », href: bookingPath(lang) }` —
`src/components/BookingBar.astro:29-30` ; rendu `:34-45` ; monté sur toutes les pages par
`src/layouts/BaseLayout.astro:243`. Constaté : `dist/academie/index.html` contient
`booking-bar__primary href="/reserver/"` **et** `booking-bar__secondary href="/reserver/"`.
Mesure sur les 66 fichiers HTML de `dist/` : **63** pages rendent la barre (les 3 hubs ne l'affichent
pas, `BookingBar.astro:27,34`) et, sur ces 63, **42** affichent deux liens **identiques**. Les 21
autres sont les 18 fiches club (Playtomic + itinéraire) et les 3 pages `/groupes/` (CTA métier vers
`/contact/`, `ContentPage.astro:37-42`). Sur 42 pages, la barre promet deux chemins et n'en offre qu'un.

**F2 — La bande d'appel finale annonce « Réserver » et ne réserve pas.**
`src/components/ContentPage.astro:270` : titre = `t.bookCourt` (« Réserver »). Boutons
`:274-275` : « Contactez-nous » → `/contact/` et « Voir les 6 clubs » → `/terrains/`.
Aucun lien vers Playtomic ni vers `/reserver/` dans ce bloc, sur les 27 pages éditoriales non-club.

**F3 — « Demander une offre » ne demande rien, et les deux boutons mènent au même endroit.**
`src/components/GuideB2B.astro:259-260` : les deux CTA pointent sur `pagePath('groupes')` /
`GROUPES[lang]`, soit `/groupes/`. Constaté dans
`dist/guides/team-building-padel/index.html` : `href="/groupes/"` (label « Demander une offre »)
puis `href="/groupes/"` (label « Voir les formules »). Le devis réel est un `mailto:` trois clics
plus loin (`src/content/fr/pages/groupes.json:178`).

**F4 — Aucun formulaire sur tout le site, y compris `/contact/`.**
Mesure : **0** occurrence de `<form|<input|<textarea|<select` dans `src/**` ; **0** dans
`dist/contact/index.html`. Les chaînes d'interface existent pourtant et ne sont **jamais** utilisées :
`forms.*` (`src/data/ui.ts:88-92, 256-273`) et `thanks.*` (`ui.ts:93, 274-278`) → grep
`t.forms|\.forms\.|t\.thanks` = 0 occurrence. Seul canal : `mailto:` (`Footer.astro:53-54`,
`BookingPage.astro:87`, `Section.astro:282`, `ClubsCompare.astro:184`). La CSP réserve pourtant
`form-action 'self' mailto:` (`scripts/build-csp.mjs:36`), trace d'une intention abandonnée.

**F5 — Les pages de confirmation déclarées n'existent pas.**
`THANKS_PATH` définit `/merci/`, `/nl/bedankt/`, `/en/thank-you/` (`src/data/ui.ts:879-883`) et le
contrat QA les exempte de maillage (`docs/qa/site-expectations.json:34`) : **aucune** n'est routée
(0 page correspondante dans `src/pages/**`, 0 fichier dans `dist/`). Il n'existe donc aucune
confirmation de contact — cohérent avec F4, mais le contrat, lui, les attend.

**F6 — Le téléphone est absent, par décision, et sans substitut synchrone.**
`src/data/site.ts:21-25` : « AUCUN TELEPHONE PUBLIE […] Ne pas publier de telephone avant
confirmation ecrite du client. » Mesures : 0 clé `"phone"` dans `src/content/**` ;
0 `href="tel:"` dans `dist/`. Le numéro provisoire `+32 2 588 20 40` subsiste dans
`docs/qa/site-expectations.json:58` — contradiction latente à trancher.

**F7 — Pas de prix sur la page de réservation.**
`src/components/BookingPage.astro:62-67` (ville, nom, terrains, adresse) : aucun montant.
Les prix ne vivent que sur les fiches club (`ClubPage.astro:204-222`) et `/terrains/`. La page où
l'on choisit n'affiche pas le critère de choix n° 2 après la distance.

**F8 — Le chemin vers Playtomic est indirect là où le trafic arrive.**
Mesure sur `dist/` : **27 pages HTML sur 63** contiennent un lien `playtomic.io` (18 fiches club,
3 `/clubs/`, 3 hubs, 3 `/terrains/`) ; l'accueil n'en contient **aucun** (`dist/index.html` :
0 occurrence, 7 occurrences de `href="/reserver/"`). Le moteur de réservation est donc à 2 clics
depuis la page d'entrée la plus visitée. Liens directs : `ClubPage.astro:62,168,224` via
`courtBookingUrl()` (`src/data/content.ts:157-163`) et `BookingPage.astro:70`.

**F9 — Données structurées : une ReserveAction qui ne réserve pas un terrain.**
`src/data/schema-core.ts:128` publie `potentialAction: ReserveAction → club.booking.href` **sans
normalisation**. Pour Garisart, `booking.href` = `a4tp.be/garisartsportsclub/academy/adults`
(`src/content/fr/clubs/garisart.json:61`) : une action « réserver » qui mène aux cours, pas aux
terrains. Constaté dans le JSON-LD de `dist/terrains/index.html`. Pour les 5 autres clubs, la
réécriture `content.ts:81` renvoie vers `/reserver/` — page de sélection, pas de réservation.

**F10 — Chiffre affiché faux : « 58 terrains couverts ».**
`src/components/ContentPage.astro:193` compose `totalCourts + " terrains couverts"` ;
`src/content/fr/pages/accueil.json:9` écrit la même chose. Or Charleroi compte 3 terrains
`outdoor` sur 12 (`src/content/fr/clubs/charleroi.json:46-51` ; `docs/SOURCES-TERO.md:24`).
Le total réel de terrains **couverts** est 55, pas 58. Confirmé dans `dist/index.html`
(`hero-facts` → « 58 terrains couverts »). C'est le premier chiffre lu par le visiteur.

**F11 — Anglais et néerlandais non relus sur deux pages de décision.**
`src/components/ClubsCompare.astro:28` (EN) : « The rates below are each club. » — phrase
incomplète, présente dans `dist/en/clubs/index.html`. `src/components/GuideTarifs.astro:75` (NL) :
« deel dus door het aantal spelers » (majuscule manquante, tournure cassée), présente dans
`dist/nl/gids/padelprijzen-belgie/index.html`. Ce sont exactement les deux pages où l'on décide.

**F12 — Les guides de décision sont quasi orphelins.**
2 pages (`/guides/prix-padel-belgique/`, `/guides/team-building-padel/`), **0** entrée de
navigation (`src/data/ui.ts:746-849` ne les contient pas, seul `LEGAL_NAV` `:855-871` ajoute la
presse), **0** lien depuis le contenu (grep `guides/|gids/` dans `src/content` = 0), et **1** lien
entrant chacune (`ClubsCompare.astro:162` ; `GuideTarifs.astro:273`).

**F13 — Le hero de `/contact/` n'envoie pas vers le contact.**
`src/content/fr/pages/contact.json:12-15` : CTA « Voir les clubs » → `/terrains/`. La page de
contact envoie son visiteur ailleurs dès le premier écran ; le contact réel est 2 sections plus bas
(`contact.json:19-48`).

**F14 — Deux leviers de rétention dormants dans les données.**
`"whatsapp"` : 12 clés dans `src/content/**`, 0 dans `src/components/**` ou `src/pages/**`,
0 dans `dist/`. `"rental"` : 18 clés dans le contenu, 0 rendu (le mot « rental » apparaît dans
8 chaînes anglaises de composants, jamais le champ). Le contenu a été produit et traduit, puis
jamais branché.

**F15 — Sur le hub de réservation, la promesse « cours et stages » n'est tenue que pour 1 club sur 6.**
`BookingPage.astro:26` annonce les cours et stages « sur la plateforme Tero Academy » et `:72-74`
rend le bouton `academyUrl(club)`. Mesure sur `dist/reserver/index.html` : 6 liens `playtomic.io`,
**1** lien `a4tp.be` (Garisart) et **1** occurrence de « Cours et stages ». Cause : `content.ts:81`
réécrit `https://a4tp.be/<club>/club` en `/reserver/` au chargement, puis `academyUrl()`
(`content.ts:166-169`) cherche `a4tp.be` dans `booking.href` : 5 clubs sur 6 perdent le bouton
académie. Charleroi n'en a jamais eu (aucun lien a4tp d'académie dans l'ancien site,
`src/lib/tero-clubs.ts:250`).

---

## C. Leviers comportementaux : APPLIQUÉ vs ABSENT

### C.1 APPLIQUÉ (preuve de rendu)

| Levier | Preuve |
|---|---|
| **Saillance de l'action** | Bouton lime unique dans l'en-tête (`src/components/Header.astro:62`), style `.btn-lime` avec contraste imposé (`src/styles/global.css:502-511`), cible 48 px de la barre collante (`BookingBar.astro:75`) |
| **Réduction d'effort** | Faits prix/terrains dans les 5 s (`ContentPage.astro:186-197`) ; lien Playtomic direct par club (`ClubPage.astro:168,224,286`) ; comparateur 10 colonnes (`ClubsCompare.astro:94-155`) ; 6 raccourcis club dans la bande CTA (`Section.astro:329-343`) |
| **Ancrage prix** | Fourchette « 20 € à 60 € », puis division par joueur (`GuideTarifs.astro:41,51`) ; tarif d'appel minimal calculé depuis le contenu (`src/data/content.ts:138-149`) |
| **Rareté** | « Les créneaux du lundi au jeudi de 18h30 à 21h30 sont complets » (`src/content/fr/clubs/waterloo.json:87,245` ; `terrains.json:191`) ; « les créneaux de soirée partent le plus vite » (`BookingPage.astro:40`) ; « les places partent vite pendant les vacances » (6 fiches club FR, ex. `limelette.json:146`) |
| **Autorité** | Académie dirigée par Gilles Darquenne (`src/content/fr/pages/academie.json:9`, `contact.json` et les 6 fiches club FR) ; Lime Sports Hub avec Justine Henin (`limelette.json:68,76`) ; « plus de 25 ans » (`groupes.json:125-126`) |
| **Réciprocité** | Garderie gratuite jusqu'à 17 h (`academie.json:71`) ; t-shirt de stage offert (`limelette.json:139`) ; balles/raquettes détaillées prix par prix |
| **Preuve sociale (partielle)** | Bandeau des partenaires réels du club, 18 pages club (`src/components/ClubPartners.astro:39-42,51-77`, monté en `ClubPage.astro:345`) ; réseaux sociaux (`Footer.astro:26-28`) |
| **États d'interaction** | `:focus-visible` global (`global.css:284-288`), pression `.btn:active` (`:482`), survols conditionnés à `(hover:hover) and (pointer:fine)` (`:498,509`) donc pas de survol collant au doigt, cibles 44 px (`Header.astro:167-183`) |

### C.2 ABSENT (preuve d'absence)

| Levier | Preuve d'absence |
|---|---|
| **Avis clients / notes** | 0 occurrence de `avis|témoignage|review|rating` dans `src/content/**` ; la pauvreté en avis est nommée par le projet lui-même comme « le premier frein » (`src/components/Gallery.astro:21`, `ClubGallery.astro:17`) |
| **Preuve sociale chiffrée** (membres, matchs joués, taux de remplissage) | aucune donnée de ce type dans `src/content/**` (grep) : les seuls chiffres publiés décrivent l'offre (terrains, prix, durée), pas la communauté |
| **Formulaire de contact** | 0 `<form>` / `<input>` dans `src/**` et dans `dist/contact/index.html` (F4) |
| **Capture d'e-mail / newsletter** | libellés présents (`ui.ts:312-313`) mais aucun champ, et le pied de page ne les rend pas (`Footer.astro:50-58`) |
| **Messagerie instantanée / WhatsApp** | 12 URL en contenu, 0 rendue (F14) |
| **Disponibilité en temps réel** | impossible : le site n'a aucun moteur et ne connaît pas les créneaux (`src/data/content.ts:128-134`) |
| **Relance post-visite** | aucun dispositif (A8) |
| **Parrainage / partage** | aucun bouton de partage, aucun programme (A10) |
| **Urgence vérifiable** | aucune rareté adossée à un stock affiché : le site ne connaît ni les créneaux ni les disponibilités (`src/data/content.ts:128-134`) — les mentions de rareté restent déclaratives |

---

## D. Plan de mesure

### D.1 État réel : rien n'est mesuré
- **0 outil** : aucune occurrence analytics dans `src/**` (grep sur 9 noms d'outils).
- **Bandeau cookies supprimé** parce qu'aucune donnée n'est collectée
  (`src/layouts/BaseLayout.astro:208-218`), avec la mention « ZERO cookie ».
- **La CSP interdit tout tiers** : `script-src 'self'` (`scripts/build-csp.mjs:43`),
  `connect-src 'self'` (`:45`), `img-src 'self' data:` (`:40`). Aucun outil hébergé ne peut
  émettre sans modifier la CSP et la politique de confidentialité.
- **La convention UTM existe mais n'est pas appliquée** : `docs/seo/utm.json:4-28` définit
  `utm_source=tero-padel-club`, `utm_medium=site-web`, `utm_campaign=<page>`,
  `utm_content=<type>-<slug>` ; mesure : **0** lien interne portant une UTM
  (`docs/qa/logs/verify-utm.log:4` : « 2042 liens internes analysés, 0 portant une UTM » ;
  grep `utm_source=tero-padel-club` dans `src` = 0). Les seules UTM sortantes sont celles
  héritées des plateformes (`docs/seo/utm.json:143-152`).
- **Conséquence directe** : toute la section A est aujourd'hui non instrumentée. Les seuls
  rapports existants sont ceux des plateformes tierces (Playtomic, a4tp) — **non consolidés ici,
  donc non mesurés**.

### D.2 Ce qui est déjà mesurable sans outil
1. **Logs d'accès HTML** : le conteneur nginx ne coupe le log que pour les assets
   (`deploy/nginx/container.conf:101-114`), la racine `/` reste journalisée par défaut. Donne des
   pages vues par URL et par statut — pas d'événement de clic, pas de source. Aucun relevé n'est
   versionné : **non mesuré** à ce jour.
2. **Contrôles de présence** : `scripts/check-reservation.mjs`, `scripts/verify-utm.mjs`,
   `scripts/check-visibilite.mjs` vérifient que les liens et les faits sont bien publiés. C'est de
   la conformité, pas de la conversion.
3. **Côté plateformes** : Playtomic / a4tp voient l'arrivée des clics ; sans `utm_content`, ils ne
   peuvent pas distinguer l'origine interne.

### D.3 Événements à instrumenter (ordre d'utilité)
| Événement | Où | KPI d'étape |
|---|---|---|
| `booking_click` (externe Playtomic) | `ClubPage.astro:168,224,286,314` ; `BookingPage.astro:70` ; `ClubsCompare.astro:148` | Décision → Réservation |
| `hub_click` (vers `/reserver/`) | `Header.astro:62` ; `Hero.astro:118` | Découverte → Réservation |
| `club_card_click` | `BookingPage.astro:75` ; `ClubsCompare.astro:133` | Comparaison → Décision |
| `academy_click` (externe a4tp) | `BookingPage.astro:73` ; `ClubPage.astro:314` | Décision → Inscription cours |
| `mailto_click` | `Footer.astro:53-54` ; `BookingPage.astro:87` ; `Section.astro:282` | Contact, faute de formulaire |
| `language_switch` | `Header.astro:50-60` | Friction de langue |
| `guide_cta_click` | `GuideTarifs.astro:271-273` ; `GuideB2B.astro:259-260` | Comparaison → Décision |
| `directions_click` | `ClubPage.astro:169,285` | Décision → Pré-visite |

**Prérequis technique** : élargir `connect-src` et `script-src` dans `scripts/build-csp.mjs:40-45`,
mettre à jour `/confidentialite/` en même temps que le bandeau cookies (consigne déjà écrite dans
`BaseLayout.astro:216-218`), et appliquer la convention `docs/seo/utm.json` sur les liens sortants.

### D.4 KPI par étape (à défaut d'historique, valeurs de départ non mesurées)
Déclencheur : impressions/positions — **non mesuré**. Découverte : vues `/` + taux de clic vers
`/reserver/`. Comparaison : vues `/clubs/` + `guide_cta_click`. Décision : vues fiches club +
`booking_click`. Réservation : `booking_click` externes / vues hub. Pré-visite : `directions_click`.
Visite : **non mesurable** (aucun point de contact). Post-visite : **non mesurable** (aucun dispositif).
Fidélisation : **non mesurable** tant que WhatsApp/newsletter ne sont pas rendus. Recommandation :
**non mesurable** (aucun mécanisme).

---

## E. Top 10 des corrections, classé par levier réel

Effort : **S** < 1 h, **M** = 1 jour, **L** > 1 jour (refonte ou dépendance cliente).

| # | Correction | Page / preuve | Effet attendu | Effort |
|---|---|---|---|---|
| 1 | **Rendre le second bouton de la barre collante réellement distinct** : « Choisir mon club » → `/reserver/`, « Réserver » → Playtomic du club le plus proche **ou** supprimer le doublon | `BookingBar.astro:29-30` ; mesuré : 42 pages sur 63 avec deux liens identiques | Supprime une fausse alternative sur 42 pages ; un seul chemin clair vers le moteur | S |
| 2 | **Corriger « 58 terrains couverts » → « 58 terrains, 55 couverts »** (ou « 55 terrains couverts ») | `ContentPage.astro:193` ; `accueil.json:9` ; `charleroi.json:46-51` ; rendu dans `dist/index.html` | Le premier chiffre lu devient exact : crédibilité immédiate | S |
| 3 | **Faire du CTA final des pages éditoriales un vrai CTA de réservation** (ajouter `/reserver/` et/ou Playtomic) | `ContentPage.astro:270,274-275` | Arrête une promesse non tenue sur 27 pages | S |
| 4 | **Corriger les deux CTA du guide B2B** : « Demander une offre » → formulaire ou `mailto:` direct ; « Voir les formules » → ancre de la table des formules | `GuideB2B.astro:259-260` ; `dist/guides/team-building-padel/index.html` | Requête B2B à forte valeur : supprime 2 clics sur le chemin du devis | S |
| 5 | **Rendre `/reserver/` complet : prix d'appel par carte + bouton « Cours et stages » rétabli sur les 5 clubs où il manque** (normaliser `academyUrl()` après `sanitizeUrl`) | `BookingPage.astro:62-67` ; mesuré : 1 seul lien a4tp sur 6 cartes ; `content.ts:81` contre `:166-169` | La page de choix affiche le prix et tient sa promesse pour les 6 clubs | S |
| 6 | **Rendre les avis / la preuve sociale manquante** : au minimum afficher les partenaires déjà disponibles + un bloc « ils jouent ici » alimenté par le client | `Gallery.astro:21` ; `ClubPartners.astro:39-42` | Lève le frein n° 1 désigné par les audits internes | L (donnée cliente) |
| 7 | **Rendre les 12 liens WhatsApp et le champ `rental`** déjà rédigés et traduits | 12 clés `whatsapp` / 18 clés `rental` dans `src/content/**` ; 0 dans `src/components/**` ; 0 dans `dist/` | Active la seule mécanique de rétention déjà payée | S |
| 8 | **Corriger le JSON-LD `ReserveAction`** : normaliser comme le rendu (`courtBookingUrl`), jamais `booking.href` brut | `schema-core.ts:128` ; `fr/clubs/garisart.json:61` | Évite d'annoncer aux moteurs une réservation qui mène aux cours | S |
| 9 | **Relire l'EN et le NL des deux pages de décision** | `ClubsCompare.astro:28` ; `GuideTarifs.astro:75` ; constaté dans `dist/en/clubs/`, `dist/nl/gids/` | Supprime deux fautes visibles au moment exact de la décision | S |
| 10 | **Donner une entrée de navigation (ou un maillage depuis `/groupes/`, `/terrains/`) aux 2 guides et un formulaire de contact** | `ui.ts:746-849` ; grep `guides/` dans `src/content` = 0 ; F4, F5, F12 | Rend visible le contenu de décision déjà produit et remplace `mailto:` par un canal tractable | M |

**Trois corrections hors top 10 mais bloquantes pour la mesure** : élargir la CSP
(`scripts/build-csp.mjs:40-45`), appliquer les UTM internes de `docs/seo/utm.json`, et trancher le
téléphone (`src/data/site.ts:21-25` contre `docs/qa/site-expectations.json:58`).

---

## Ce qui n'est pas mesurable dans ce dépôt

- **Taux de conversion réel** : aucun outil, aucune donnée — non mesuré.
- **Disponibilités et taux de remplissage** : détenus par Playtomic / a4tp — non consolidés.
- **Horaires des clubhouses et du Bistrot Pilko** : à confirmer par le client
  (`docs/SOURCES-TERO.md:156-157`) ; la réponse publiée renvoie à une confirmation
  (`src/content/fr/pages/bistrot-pilko.json:147`).
- **Statut d'ouverture de Charleroi** : à confirmer (`docs/SOURCES-TERO.md:148`).
- **Téléphone** : absent par décision, contradictoire avec le contrat QA — à trancher.
- **Trafic, sources, parcours** : nécessitent un outil et une CSP élargie.
