À compléter avant l'envoi
[nom du serveur][nom de l'entreprise][service][quartiers][téléphone][numéro][lien ou "aucun"][adresse][horaires d'ouverture][titres et offre][GTM-XXXXXXX][nom du compte]
Sur mon serveur d'hébergement Opus Growth [nom du serveur], crée une page de campagne unique pour le trafic des annonces Google Ads et Meta, ainsi qu'une page de confidentialité. Il n'y a pas de formulaire ; les visiteurs nous joignent par téléphone, WhatsApp ou via un lien de réservation. Détails : entreprise [nom de l'entreprise], service [service], zone [quartiers], téléphone [téléphone], WhatsApp [numéro], lien de réservation [lien ou "aucun"], adresse [adresse], horaires [horaires d'ouverture], titres des annonces et offre principale [titres et offre], conteneur Tag Manager [GTM-XXXXXXX], compte Google Ads [nom du compte], compte publicitaire Meta [nom du compte].
Cohérence du message : le h1 reprend la promesse du titre de l'annonce dans les mêmes mots (service, zone, offre principale). Ne mets pas sur la page de promesse absente de l'annonce, ni dans l'annonce de promesse absente de la page. Si les titres Google et Meta diffèrent, utilise le titre de l'annonce qui dépense le plus et propose comment aligner l'autre annonce sur la page. Dans la santé, le juridique ou la finance, ne promets aucune certitude ("garanti", "100 %").
Structure de la page : la barre du haut ne contient que le nom de la marque et un bouton d'appel, sans menu, pour que les visiteurs ne soient pas détournés. Section hero : h1, description en une phrase, trois boutons (Appeler maintenant, Écrire sur WhatsApp, Choisir un créneau), quatre courts points de réassurance en dessous et une image. Ensuite, le déroulement en trois étapes, ce qui détermine le prix (réponse d'abord, si vous ne publiez pas de tarifs), la FAQ, un appel à l'action final, et un pied de page avec le nom, l'adresse, le téléphone et le lien vers la confidentialité. Sur mobile, fixe en bas de l'écran une barre de deux boutons (Appeler, WhatsApp) et donne au body un padding bas de même hauteur pour que rien ne se cache dessous et que rien ne bouge. Le lien WhatsApp utilise wa.me avec un message prérempli. Garde un style sobre et rassurant : une seule famille de polices (par exemple General Sans, deux graisses), une seule couleur d'accent, et un bouton WhatsApp vert foncé avec un contraste d'au moins 4,5:1 face au texte blanc.
Règles de mouvement et de mesure :
1. Mouvement léger sans bibliothèque : ne charge ni GSAP, ni Lenis, ni Swiper. Transitions au survol et à l'appui sur les boutons ; sur les cartes d'étapes, une petite montée pilotée par le défilement qui n'utilise que transform, à l'intérieur de `@supports (animation-timeline: view())` et uniquement pour les visiteurs qui ne demandent pas de mouvement réduit. N'utilise pas opacity : dans la démo, des cartes estompées sous la ligne de flottaison échouaient au contraste et faisaient tomber l'Accessibilité à 96. Rien sur le premier écran ne démarre par une animation d'entrée.
2. Charge la couche de mesure sous la forme `assets/tag.js` avec defer :
a. `window.dataLayer` et les valeurs par défaut de Consent Mode v2 : ad_storage, ad_user_data, ad_personalization et analytics_storage "denied", wait_for_update 500.
b. Donne à chaque lien d'action data-conv="phone", "whatsapp" ou "booking" et un data-conv-place indiquant sa section. Un seul écouteur de clic les envoie dans dataLayer sous la forme `{event: "phone_click" | "whatsapp_click" | "booking_click", conv_place, page_path}`.
c. Ne mets pas le snippet GTM classique dans `<head>` ; injecte-le après l'événement load avec requestIdleCallback, afin que les balises ne retardent jamais le premier affichage.
d. Ajoute une petite bannière de consentement fixe : Refuser et Accepter sous forme de boutons de même poids, le choix étant conservé dans le navigateur et transmis comme mise à jour du consentement. Sur mobile, elle se place au-dessus de la barre d'action et assez bas pour ne pas masquer le bouton principal du hero.
3. Tag Manager : montre d'abord l'état actuel avec list_gtm_containers, list_gtm_triggers et gtm_workspace_status. Propose trois déclencheurs Custom Event avec create_gtm_trigger (phone_click, whatsapp_click, booking_click). Trouve la conversion de contact et sa valeur send_to dans Google Ads avec list_conversion_actions et get_conversion_tags. Pour qu'une personne qui appelle et écrit à la fois ne soit pas comptée deux fois, propose de relier téléphone et WhatsApp à une seule conversion "Clic de contact" comptée une fois ; s'il n'en existe pas, dis ce que tu créerais et attends ma validation. Propose une balise de conversion Google Ads avec create_gtm_tag (tag_type "sp"). Pour Meta, trouve le pixel avec list_meta_pixels ; si le code de base du pixel n'est pas dans le conteneur, propose-le sous forme de balise Custom HTML sur toutes les pages, puis séparément les balises qui envoient `fbq('track','Contact')` aux clics et `fbq('track','Schedule')` à la réservation. Exécute chaque outil d'abord avec confirm=false, montre la liste des modifications et crée-les après ma validation. Montre d'abord publish_gtm_container avec confirm=false, publie après ma validation et indique la version restaurable.
4. Plan de test : rédige étape par étape comment voir dans le mode aperçu de GTM quelle balise se déclenche pour chacun des trois boutons, et qu'aucun cookie publicitaire n'est écrit lorsque le consentement est refusé.
5. Après l'ajout de GTM et des balises, relance core_web_vitals, car les balises peuvent faire baisser le score, et présente la différence dans un tableau. Pour que la balise Google ne soit pas bloquée par les bloqueurs de publicités, prévisualise le chemin de mesure first-party avec site_tag_gateway et mets-le en place après ma validation.
Mise en place et pièges connus (chacun a fait baisser un score lors des mesures de la démo, ne les saute pas) :
1. Si un site est déjà en ligne sur le serveur, préviens-moi d'abord, car l'installation écrase index.html et le dossier assets. Prévisualise scaffold_site avec confirm=false et appelle-le avec confirm=true après ma validation. Lis ensuite site_design_guide et site_seo_guide. Avant d'écrire du code, consigne la direction de design (typographie, couleur, grille, élément signature, langage de mouvement et bibliothèques qui ne seront PAS chargées) dans un court ART.md en dehors de assets et montre-le-moi.
2. Compile Tailwind au lieu de le charger depuis le CDN. Installe-le avec site_run_command et background=true : `npm i -D tailwindcss@3`, puis enchaine avec site_command_status. Les chemins content de `tailwind.config.js` doivent couvrir tous les fichiers HTML, les templates et tout fichier JS qui écrit des noms de classes. `_src/tw.css` contient la ligne `@import "../assets/app.css";` et les trois lignes `@tailwind` ; compile-le en un seul fichier avec `npx tailwindcss -c tailwind.config.js -i _src/tw.css -o assets/site.css --minify`. Supprime le script cdn.tailwindcss.com et le tailwind.config en ligne de chaque page et ne lie que `/assets/site.css`. Recompile après chaque modification du HTML.
3. Héberge les polices toi-même. Lis le CSS des familles Fontshare choisies, télécharge le fichier woff2 de chaque graisse dans `assets/fonts/` avec site_fetch, et écris les règles @font-face avec `font-display: swap` dans `assets/app.css` ; design-check y cherche une police personnalisée. Vérifie le nom font-family dans le CSS téléchargé, car Fontshare peut renvoyer une autre famille lorsqu'une graisse n'existe pas. Précharge la police du titre du premier écran et la police du texte sur chaque page avec `<link rel="preload" as="font" type="font/woff2" crossorigin>` ; dans la démo, cela a supprimé le décalage de mise en page causé par le changement de police (CLS de 0,024 à 0). La plupart des polices Fontshare n'ont pas de glyphe ₺, écris donc "TL" pour les prix.
4. Rends le menu et le pied de page en HTML statique. Ne charge pas chrome.js ni site.config.js sur les pages. Écris un petit `chrome-stamp.mjs` qui lit la liste de navigation dans site.config.js et estampille `_src/header.tpl` et `_src/footer.tpl` entre les marqueurs `<!-- nav:start --><!-- nav:end -->` et `<!-- footer:start --><!-- footer:end -->` de chaque page, en ajoutant aria-current="page" au lien courant. Ne donne pas aux templates d'extension .html et utilise des placeholders comme `[[NAV]]` au lieu de `{{...}}`, sinon design-check et seo-check les lisent comme des pages inachevées. Construis le menu mobile sans JS avec `<details>`. Garde le nom de l'entreprise, l'adresse et le téléphone en texte brut dans le pied de page.
5. Convertis les images pendant leur téléchargement avec site_fetch : écris la même photo dans des fichiers distincts avec resize="480x", "800x" et "1200x", image_format="webp", quality=65. Donne à chaque `<img>` srcset, sizes, width et height. L'image principale du premier écran reçoit fetchpriority="high" et n'est jamais en lazy ; les autres reçoivent loading="lazy" decoding="async". Si l'image principale remplit l'écran du téléphone, sers sur mobile un recadrage plus large et plus léger avec `<picture>` (dans la démo, le hero mobile est passé de 89 Ko à 43 Ko).
6. Crée un favicon PNG de 48 px à partir du logo avec site_fetch et ajoute `<link rel="icon">` à chaque page. Sans lui, le navigateur enregistre une erreur 404 et les Bonnes pratiques tombent à 96.
7. Règles du validateur HTML : commence chaque document par un `<!DOCTYPE html>` en majuscules (les fichiers de départ du kit utilisent des minuscules), utilise ` ` pour les espaces dans le texte visible des liens tel:, n'utilise jamais d'attribut style="" et donne à chaque bouton type="button".
SEO, AEO et GEO :
1. Utilise des URL de répertoire avec une barre oblique finale (/gizlilik/). Renseigne le bloc seo de site.config.js et exécute `node seo-stamp.mjs`. Écris le schema propre à chaque page (sur la page de campagne WebPage, un Service lié à #business comme provider avec areaServed, et FAQPage ; sur la page de confidentialité WebPage et BreadcrumbList. Dans site.config.js, utilise le sous-type LocalBusiness le plus précis, par exemple HousePainter, Plumber, Dentist). La page de confidentialité explique les cookies, les balises de mesure et la façon de modifier le choix de consentement) dans des blocs `<script type="application/ld+json">` séparés et relie-le au graphe de base avec @id. N'enfouis pas BreadcrumbList dans un @graph ; donne-lui son propre bloc, car c'est la seule façon pour seo-check de le voir.
2. Titres de 48 à 60 caractères (seo-check signale comme erreur tout ce qui dépasse 65), descriptions de 145 à 158 caractères, un seul h1 par page. Chaque page doit avoir au moins 150 mots de contenu principal ; les pages de contact et de confidentialité ont tendance à rester en dessous.
3. Le premier paragraphe de chaque page répond directement à la question de la page. Rédige une FAQ propre à la page avec `<details>` et balise-la en FAQPage. Affiche l'organisation éditrice et une date de "Dernière mise à jour" avec `<time>`.
4. Dans robots.txt, écris ta décision et sa raison pour GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-User, Claude-SearchBot, PerplexityBot, Perplexity-User, Google-Extended, Applebot-Extended, Bingbot et CCBot, et indique le sitemap. sitemap.xml contient de vraies dates lastmod. llms.txt contient un résumé exact du site en deux phrases et la liste des pages clés.
5. N'invente rien : ni avis, ni notes, ni récompenses, ni nombre de clients, ni certificats, ni horaires, ni coordonnées, ni prix, sauf si je te les donne. Laisse de côté du schema les champs inconnus.
Contrôles (dans l'ordre ; ne considère pas le travail terminé tant que tous ne sont pas passés) :
1. Avec site_run_command, exécute `node chrome-stamp.mjs`, la compilation Tailwind, `node seo-stamp.mjs`, `node seo-check.mjs` (0 erreur, 0 avertissement), `node design-check.mjs` (0 erreur ; justifie tout avertissement restant) et `npx html-validate "**/*.html"` (0 erreur).
2. Consulte chaque page avec site_preview, view="mobile" et view="desktop". site_preview capture la page avec le mouvement désactivé (reduced-moti