Que dit Google sur le SEO ? /
Quiz SEO Express

Testez vos connaissances SEO en 3 questions

Moins de 30 secondes. Decouvrez ce que vous savez vraiment sur le referencement Google.

🕒 ~30s 🎯 3 questions 📚 SEO Google

Declaration officielle

La fréquence des mots-clés n'est pas un facteur de classement. Cependant, si un mot n'apparaît jamais sur une page, Google ne pourra pas bien la positionner. Il faut un équilibre : au moins une mention, mais pas 100. Il n'y a pas de nombre optimal.
🎥 Vidéo source

Extrait d'une vidéo Google Search Central

💬 EN 📅 30/01/2022 ✂ 17 déclarations
Voir sur YouTube →
Autres déclarations de cette vidéo 16
  1. Google attribue-t-il vraiment le même poids à tous vos backlinks ?
  2. L'emplacement des liens internes a-t-il vraiment un impact sur le SEO ?
  3. Google classe-t-il vraiment les sites dans des catégories fixes ?
  4. La cohérence NAP impacte-t-elle vraiment le référencement local ou seulement le Knowledge Graph ?
  5. Comment éviter que Google se trompe à cause d'informations conflictuelles entre votre site et votre profil d'établissement ?
  6. Les liens réciproques sont-ils vraiment sans risque pour votre SEO ?
  7. Faut-il vraiment nettoyer TOUTES les pages hackées ou peut-on laisser Google faire le tri ?
  8. Pourquoi Google refuse-t-il d'indexer une partie de votre site même s'il est techniquement parfait ?
  9. Les emojis dans les balises title et meta description apportent-ils un avantage SEO ?
  10. L'API Search Console et l'interface affichent-elles vraiment les mêmes données ?
  11. Pourquoi vos FAQ n'apparaissent-elles pas en rich results malgré un balisage correct ?
  12. Faut-il vraiment réutiliser la même URL pour les pages saisonnières chaque année ?
  13. Les Core Web Vitals n'affectent-ils vraiment ni le crawl ni l'indexation ?
  14. Pourquoi Google réinitialise-t-il l'évaluation d'un site lors d'une migration de sous-domaine vers domaine principal ?
  15. Le TLD .edu booste-t-il vraiment votre référencement ?
  16. Les géo-redirects peuvent-ils réellement bloquer l'indexation de votre contenu ?
📅
Declaration officielle du (il y a 4 ans)
TL;DR

Google affirme que la fréquence des mots-clés n'est pas un facteur de classement direct. Le principe : le mot-clé doit apparaître au moins une fois pour que la page soit éligible, mais le bourrage n'améliore rien. Il n'existe pas de nombre optimal d'occurrences.

Ce qu'il faut comprendre

Que veut dire exactement « pas un facteur de ranking » ?

Quand Mueller dit que la fréquence n'est pas un facteur, il parle du nombre brut d'occurrences. Répéter un mot-clé 10, 20 ou 50 fois sur une page ne vous donnera pas mécaniquement un meilleur classement qu'avec 3 occurrences bien placées.

Google utilise des modèles sémantiques qui comprennent le contexte, les synonymes et l'intention. La simple densité de mots-clés — ce KPI des années 2000 — n'a plus de poids algorithmique direct. Ce qui compte, c'est que le terme soit présent et pertinent dans le contexte général de la page.

Pourquoi faut-il quand même que le mot apparaisse au moins une fois ?

Sans mention du terme, Google ne peut pas établir de signal de pertinence évident. Si vous ciblez « chaussures de running » mais que ces mots n'apparaissent jamais sur votre page, l'algorithme devra se fier uniquement au contexte sémantique — un pari risqué.

La présence minimale crée un ancrage thématique clair. C'est la différence entre laisser Google deviner votre sujet et lui donner une indication explicite. Une seule occurrence bien placée (titre, intro) suffit souvent si le reste du contenu est cohérent.

Qu'est-ce que Google entend par « équilibre » ?

Mueller évoque un équilibre entre zéro mention (inefficace) et bourrage (inutile voire contre-productif). Mais il refuse de donner un chiffre précis — parce qu'il n'y en a pas.

L'équilibre dépend du contexte : longueur du contenu, richesse sémantique, variété lexicale. Une page de 300 mots peut se permettre 2-3 occurrences naturelles. Une page de 3000 mots peut en avoir 15 sans que ça paraisse forcé. Le test : lis ton texte à voix haute. Si ça sonne robotique, c'est trop.

  • Fréquence brute ≠ facteur de ranking : répéter n'améliore pas mécaniquement le classement
  • Présence minimale obligatoire : au moins une mention pour établir la pertinence
  • Pas de nombre optimal : l'équilibre dépend du contexte et de la naturalité
  • Modèles sémantiques : Google comprend synonymes, variations, contexte global
  • Bourrage contre-productif : trop d'occurrences dégrade l'expérience utilisateur

Avis d'un expert SEO

Cette position est-elle cohérente avec ce qu'on observe sur le terrain ?

Oui et non. Sur des requêtes compétitives, les pages bien classées mentionnent effectivement le mot-clé principal plusieurs fois — mais rarement de manière mécanique. Elles utilisent des variations, des synonymes, des reformulations. La corrélation existe, mais elle ne prouve pas la causalité.

Le vrai problème : beaucoup de contenus performants ont une richesse sémantique naturelle qui inclut le terme cible sans effort conscient. Difficile de savoir si c'est la fréquence qui aide ou simplement le fait que le contenu soit exhaustif et bien structuré. [À vérifier] : la part réelle de la fréquence dans l'algorithme versus d'autres signaux sémantiques plus sophistiqués.

Dans quels cas cette règle ne s'applique-t-elle pas vraiment ?

Sur des requêtes de niche ou ultra-spécifiques, la présence exacte du terme peut faire une différence nette. Si vous ciblez une expression technique rare, ne pas l'inclure textuellement peut vous exclure de la course — même avec un excellent contexte sémantique.

Autre cas limite : les featured snippets et résultats enrichis. Google extrait souvent des passages contenant le terme exact de la requête. Ici, la correspondance lexicale redevient importante — pas pour le ranking global, mais pour l'éligibilité à ces positions premium.

Attention : Ne confondez pas « pas un facteur de ranking » avec « complètement ignoré ». La présence et le placement restent des signaux de pertinence, même si la répétition excessive ne booste rien.

Quelle nuance apporter à cette déclaration de Mueller ?

Mueller simplifie pour un public large. En réalité, la fréquence interagit avec d'autres facteurs : position dans le DOM, proximité avec d'autres termes importants, contexte sémantique immédiat. Une occurrence dans le pèse plus qu'une occurrence perdue au milieu d'un paragraphe de 200 mots.</p><p>De plus, dire « pas un facteur » ne signifie pas que Google l'ignore totalement. L'algorithme utilise probablement la fréquence comme <strong>signal secondaire ou de validation</strong> — un indice parmi cent autres. Ce n'est juste plus le levier mécanique qu'il était dans les années 2000.</p></div> </div> <div class="section-card ai-section"> <h2>Impact pratique et recommandations</h2> <div class="content" data-field="ai_practical_impact"><h3>Que faut-il faire concrètement pour optimiser la présence des mots-clés ?</h3><p>Commencez par vous assurer que votre <strong>terme cible apparaît au moins une fois</strong> dans les zones stratégiques : title, H1, premier paragraphe. C'est le minimum vital pour établir la pertinence thématique.</p><p>Ensuite, écrivez naturellement. Utilisez des <strong>variations et synonymes</strong> plutôt que de répéter mécaniquement le même terme. Google comprend « chaussures de course », « running shoes », « baskets pour courir » comme des signaux convergents. Cette richesse lexicale renforce votre pertinence sans bourrage.</p><p>Testez la lisibilité : relisez votre contenu à voix haute. Si vous trébuchez sur des répétitions forcées, <strong>simplifiez</strong>. L'expérience utilisateur prime — et Google le détecte via des signaux comportementaux (taux de rebond, temps sur page).</p><h3>Quelles erreurs éviter absolument ?</h3><p>Ne calculez pas de <strong>densité de mots-clés cible</strong> (genre « 2,5% du texte »). Cette métrique est obsolète et vous pousse à écrire pour l'algorithme plutôt que pour l'utilisateur. Oubliez les vieux outils qui vous disent « encore 3 occurrences nécessaires ».</p><p>Évitez le bourrage dans les balises meta, alt, anchors internes. Oui, ces éléments ont leur importance, mais les <strong>surcharger nuit à la cohérence globale</strong>. Un alt de 50 mots bourrés de mots-clés ne sert à rien et peut lever des flags de sur-optimisation.</p><p>Ne tombez pas dans l'excès inverse : certains rédacteurs, par peur du bourrage, évitent complètement le terme cible. Résultat : des contenus flous où Google doit <strong>deviner l'intention</strong>. Trouvez le juste milieu.</p><h3>Comment vérifier que mon contenu respecte cet équilibre ?</h3><p>Utilisez des outils d'analyse sémantique (pas de densité brute) pour identifier si votre contenu couvre bien le <strong>champ lexical attendu</strong>. Regardez les entités, les termes associés, la couverture thématique — pas juste la fréquence d'un mot.</p><p>Comparez avec les pages concurrentes bien classées. Si elles utilisent 5 variations du terme principal et vous une seule, vous manquez peut-être de <strong>richesse sémantique</strong>. Ce n'est pas une question de quantité, mais de couverture du spectre lexical.</p><ul class="checklist"><li>Inclure le mot-clé principal au moins une fois dans title, H1 et introduction</li><li>Privilégier variations et synonymes plutôt que répétitions mécaniques</li><li>Tester la lisibilité en relisant à voix haute — supprimer les répétitions forcées</li><li>Abandonner les calculs de densité de mots-clés (métrique obsolète)</li><li>Analyser le champ lexical global, pas juste la fréquence d'un terme</li><li>Comparer la richesse sémantique avec les concurrents bien classés</li><li>Ne pas surcharger balises meta, alt, anchors avec le même terme</li><li>Vérifier que le terme cible est présent sans être omniprésent</li></ul><div class="summary">La déclaration de Mueller confirme ce que les praticiens observent depuis des années : <strong>le bourrage de mots-clés est mort</strong>. L'algorithme comprend le contexte et les variations. Votre priorité : écrire pour l'utilisateur en vous assurant que les termes cibles apparaissent naturellement dans les zones stratégiques. Si l'équilibre entre pertinence technique et qualité éditoriale vous semble difficile à atteindre, un accompagnement par une agence SEO spécialisée peut vous aider à structurer vos contenus de manière optimale sans compromettre l'expérience utilisateur.</div></div> </div> <!-- FAQ --> <div class="section-card"> <h2>❓ Questions frequentes</h2> <div class="faq-list"> <details class="faq-item"> <summary class="faq-question">Combien de fois dois-je répéter mon mot-clé principal sur une page ?</summary> <div class="faq-answer">Il n'y a pas de nombre optimal. L'essentiel est qu'il apparaisse au moins une fois dans les zones stratégiques (title, H1, intro) et ensuite naturellement dans le corps du texte. Privilégiez les variations et synonymes plutôt que la répétition mécanique.</div> </details> <details class="faq-item"> <summary class="faq-question">La densité de mots-clés est-elle encore un indicateur pertinent ?</summary> <div class="faq-answer">Non. Cette métrique des années 2000 ne reflète plus la manière dont Google analyse le contenu. L'algorithme utilise des modèles sémantiques qui comprennent le contexte global, pas juste la fréquence brute d'un terme.</div> </details> <details class="faq-item"> <summary class="faq-question">Si je n'utilise que des synonymes, Google comprendra-t-il quand même ma page ?</summary> <div class="faq-answer">Oui, Google comprend les synonymes et variations. Mais incluez quand même le terme cible exact au moins une fois pour établir un signal de pertinence clair. Ne comptez pas uniquement sur la compréhension sémantique.</div> </details> <details class="faq-item"> <summary class="faq-question">Le bourrage de mots-clés peut-il encore pénaliser mon site ?</summary> <div class="faq-answer">Google ne pénalise pas directement le bourrage comme avant, mais il dégrade l'expérience utilisateur — ce qui impacte les signaux comportementaux (taux de rebond, temps sur page). Résultat : classement inférieur de facto.</div> </details> <details class="faq-item"> <summary class="faq-question">Les mots-clés dans les balises alt et meta comptent-ils dans la fréquence ?</summary> <div class="faq-answer">Ces balises ont leur propre rôle (accessibilité, meta descriptions) mais ne doivent pas être surchargées. Leur contenu contribue au contexte sémantique global, pas à un compteur de fréquence mécanique.</div> </details> </div> </div> <!-- Tags SEO --> <div class="seo-tags-block"> <span class="seo-tags-label">🏷 Sujets associes</span> <div class="seo-tags"> <a href="/?q=mots-cl%C3%A9s" class="seo-tag-pill">mots-clés</a> <a href="/?q=fr%C3%A9quence" class="seo-tag-pill">fréquence</a> <a href="/?q=ranking" class="seo-tag-pill">ranking</a> <a href="/?q=densit%C3%A9" class="seo-tag-pill">densité</a> <a href="/?q=s%C3%A9mantique" class="seo-tag-pill">sémantique</a> <a href="/?q=bourrage" class="seo-tag-pill">bourrage</a> <a href="/?q=pertinence" class="seo-tag-pill">pertinence</a> <a href="/?q=contenu" class="seo-tag-pill">contenu</a> </div> </div> <!-- Categories --> <div class="declaration-tags"> <a href="/c/anciennete-historique" class="tag" style="background: #94a3b820; color: #94a3b8;">Anciennete & Historique</a> <a href="/c/ia-seo" class="tag" style="background: #a855f720; color: #a855f7;">IA & SEO</a> </div> <!-- Syntheses thematiques liees --> <!-- Autres declarations de la meme video YouTube --> <div class="section-card yt-same-video"> <h2> 🎥 De la même vidéo <span class="yt-same-count">16</span> </h2> <p class="yt-same-intro"> Autres enseignements SEO extraits de cette même vidéo Google Search Central · publiée le 30/01/2022 </p> <div class="related-grid yt-same-grid"> <a href="/d/google-ne-donne-pas-le-meme-poids-a-tous-les-liens" class="related-item yt-same-item"> <div class="title">Google attribue-t-il vraiment le même poids à tous vos backlinks ?</div> <div class="meta"> </div> </a> <a href="/d/placement-des-liens-internes-pas-de-difference-majeure" class="related-item yt-same-item"> <div class="title">L'emplacement des liens internes a-t-il vraiment un impact sur le SEO ?</div> <div class="meta"> </div> </a> <a href="/d/pas-de-classification-binaire-des-types-de-sites" class="related-item yt-same-item"> <div class="title">Google classe-t-il vraiment les sites dans des catégories fixes ?</div> <div class="meta"> </div> </a> <a href="/d/coherence-nap-aide-a-reconnaitre-l-entite-d-entreprise" class="related-item yt-same-item"> <div class="title">La cohérence NAP impacte-t-elle vraiment le référencement local ou seulement le Knowledge Graph ?</div> <div class="meta"> </div> </a> <a href="/d/informations-conflictuelles-causent-confusion-pour-google" class="related-item yt-same-item"> <div class="title">Comment éviter que Google se trompe à cause d'informations conflictuelles entre votre site et votre profil d'établissement ?</div> <div class="meta"> </div> </a> <a href="/d/liens-reciproques-naturels-ne-posent-pas-probleme" class="related-item yt-same-item"> <div class="title">Les liens réciproques sont-ils vraiment sans risque pour votre SEO ?</div> <div class="meta"> </div> </a> <a href="/d/pour-contenu-hacke-prioriser-pages-visibles-puis-attendre" class="related-item yt-same-item"> <div class="title">Faut-il vraiment nettoyer TOUTES les pages hackées ou peut-on laisser Google faire le tri ?</div> <div class="meta"> </div> </a> <a href="/d/google-n-indexe-pas-tout-le-contenu-d-un-site" class="related-item yt-same-item"> <div class="title">Pourquoi Google refuse-t-il d'indexer une partie de votre site même s'il est techniquement parfait ?</div> <div class="meta"> </div> </a> <a href="/d/emojis-dans-titres-et-descriptions-pas-d-avantage-seo" class="related-item yt-same-item"> <div class="title">Les emojis dans les balises title et meta description apportent-ils un avantage SEO ?</div> <div class="meta"> </div> </a> <a href="/d/donnees-search-console-api-et-ui-proviennent-de-la-meme-source" class="related-item yt-same-item"> <div class="title">L'API Search Console et l'interface affichent-elles vraiment les mêmes données ?</div> <div class="meta"> </div> </a> <a href="/d/rich-results-faq-necessitent-trois-criteres" class="related-item yt-same-item"> <div class="title">Pourquoi vos FAQ n'apparaissent-elles pas en rich results malgré un balisage correct ?</div> <div class="meta"> </div> </a> <a href="/d/pages-saisonnieres-reutiliser-la-meme-url-chaque-annee" class="related-item yt-same-item"> <div class="title">Faut-il vraiment réutiliser la même URL pour les pages saisonnières chaque année ?</div> <div class="meta"> </div> </a> <a href="/d/core-web-vitals-n-est-pas-un-facteur-de-qualite" class="related-item yt-same-item"> <div class="title">Les Core Web Vitals n'affectent-ils vraiment ni le crawl ni l'indexation ?</div> <div class="meta"> </div> </a> <a href="/d/migration-sous-domaine-vers-domaine-necessite-reevaluation" class="related-item yt-same-item"> <div class="title">Pourquoi Google réinitialise-t-il l'évaluation d'un site lors d'une migration de sous-domaine vers domaine principal ?</div> <div class="meta"> </div> </a> <a href="/d/tld-edu-n-offre-aucun-avantage-de-ranking" class="related-item yt-same-item"> <div class="title">Le TLD .edu booste-t-il vraiment votre référencement ?</div> <div class="meta"> </div> </a> <a href="/d/geo-redirects-peuvent-empecher-google-de-crawler-le-contenu" class="related-item yt-same-item"> <div class="title">Les géo-redirects peuvent-ils réellement bloquer l'indexation de votre contenu ?</div> <div class="meta"> </div> </a> </div> <a href="https://www.youtube.com/watch?v=a5J73nYDU8E" target="_blank" rel="noopener" class="yt-same-source-link"> 🎥 Voir la vidéo complète sur YouTube → </a> </div> <!-- Declarations similaires --> <div class="section-card"> <h2>Declarations similaires</h2> <div class="related-grid"> <a href="/d/le-seo-est-complexe-multiforme-et-resilient" class="related-item"> <div class="title">Peut-on vraiment se permettre de faire n'importe quoi en SEO sans conséquences ?</div> <div class="meta"> John Mueller · 28/04/2026 · <span class="stars">★★</span> </div> </a> <a href="/d/celui-qui-dit-tout-savoir-sur-le-seo-est-un-imposteur" class="related-item"> <div class="title">Pourquoi personne ne peut vraiment maîtriser le SEO à 100% ?</div> <div class="meta"> John Mueller · 28/04/2026 · <span class="stars">★★★</span> </div> </a> <a href="/d/nouvelle-collecte-de-donnees-robots-txt-avec-http-archive" class="related-item"> <div class="title">Pourquoi Google publie-t-il soudainement des données massives sur l'usage des robots.txt ?</div> <div class="meta"> Gary Illyes · 23/04/2026 · <span class="stars">★★★</span> </div> </a> <a href="/d/importancia-d-http-archive-pour-le-seo" class="related-item"> <div class="title">HTTP Archive : Google révèle-t-il enfin comment il analyse vraiment vos pages ?</div> <div class="meta"> Gary Illyes · 23/04/2026 · <span class="stars">★★★</span> </div> </a> <a href="/d/requete-sql-dans-bigquery-pour-l-analyse-seo" class="related-item"> <div class="title">Faut-il vraiment maîtriser SQL et BigQuery pour faire du SEO en 2025 ?</div> <div class="meta"> Gary Illyes · 23/04/2026 · <span class="stars">★★</span> </div> </a> <a href="/d/utilisation-de-bigquery-pour-analyser-les-sites-web" class="related-item"> <div class="title">BigQuery est-il vraiment indispensable pour analyser vos données SEO à grande échelle ?</div> <div class="meta"> Martin Splitt · 23/04/2026 · <span class="stars">★★★</span> </div> </a> </div> </div> <!-- Prev/Next --> <div class="prev-next"> <a href="/d/geo-redirects-peuvent-empecher-google-de-crawler-le-contenu"> <div class="nav-label">« Precedent</div> <div class="nav-title">Géo-redirects peuvent empêcher Google de crawler l...</div> </a> <a href="/d/google-ne-donne-pas-le-meme-poids-a-tous-les-liens" style="text-align: right;"> <div class="nav-label">Suivant »</div> <div class="nav-title">Google ne donne pas le même poids à tous les liens...</div> </a> </div> <div class="back-link"> <a href="/" class="btn">« Retour aux resultats</a> </div> </div> <style> .comments-section { max-width: 860px; margin: 40px auto; padding: 0 20px; } .comments-title { font-size: 1.3rem; font-weight: 700; color: #1e293b; margin: 0 0 20px; padding-bottom: 12px; border-bottom: 2px solid #f1f5f9; } .comments-count { font-weight: 400; font-size: .9rem; color: #94a3b8; } .comments-empty { color: #94a3b8; font-style: italic; margin-bottom: 24px; } .comments-list { margin-bottom: 28px; } .comment-item { padding: 16px 0; border-bottom: 1px solid #f1f5f9; } .comment-item:last-child { border-bottom: none; } .comment-pending { background: #fffbeb; border-left: 3px solid #f59e0b; padding-left: 14px; border-radius: 6px; margin: 4px 0; } .comment-pending-badge { display: inline-block; font-size: .7rem; font-weight: 600; color: #92400e; background: #fef3c7; padding: 1px 8px; border-radius: 10px; margin-left: 8px; } .comment-meta { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; } .comment-author { font-weight: 600; font-size: .95rem; color: #1e293b; } .comment-date { font-size: .8rem; color: #94a3b8; } .comment-body { font-size: .93rem; line-height: 1.6; color: #475569; } .comment-form { background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 12px; padding: 24px; position: relative; } .comment-form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 16px; } .comment-form-field { margin-bottom: 12px; } .comment-form-field label { display: block; font-size: .85rem; font-weight: 600; color: #475569; margin-bottom: 4px; } .comment-form-field input, .comment-form-field textarea { width: 100%; padding: 10px 12px; border: 1px solid #d1d5db; border-radius: 8px; font-size: .9rem; font-family: inherit; background: #fff; transition: border-color .2s; box-sizing: border-box; } .comment-form-field input:focus, .comment-form-field textarea:focus { outline: none; border-color: #1a73e8; box-shadow: 0 0 0 3px rgba(26, 115, 232, .1); } .comment-form-field textarea { resize: vertical; min-height: 100px; } .comment-form-charcount { font-size: .75rem; color: #94a3b8; text-align: right; margin-top: 4px; } .comment-form-footer { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; } .comment-submit-btn { padding: 10px 24px; background: #1a73e8; color: #fff; border: none; border-radius: 8px; font-size: .9rem; font-weight: 600; cursor: pointer; transition: opacity .2s; } .comment-submit-btn:hover { opacity: .88; } .comment-submit-btn:disabled { opacity: .5; cursor: default; } .comment-form-notice { font-size: .8rem; color: #94a3b8; font-style: italic; } .comment-feedback { margin-top: 12px; padding: 10px 14px; border-radius: 8px; font-size: .9rem; font-weight: 500; } .comment-feedback-success { background: #d1fae5; color: #065f46; } .comment-feedback-error { background: #fee2e2; color: #991b1b; } @media (max-width: 768px) { .comment-form-row { grid-template-columns: 1fr; gap: 0; } .comments-section { padding: 0 16px; } } </style> <section class="comments-section" id="comments"> <h3 class="comments-title">💬 Commentaires <span class="comments-count">(0)</span></h3> <div class="comments-list" id="comments-list"> <p class="comments-empty" id="comments-empty">Soyez le premier à commenter.</p> </div> <form class="comment-form" id="comment-form" novalidate> <input type="hidden" name="page_type" value="declaration"> <input type="hidden" name="page_id" value="3644"> <input type="hidden" name="lang" value="fr"> <!-- Honeypot anti-spam --> <div style="position:absolute;left:-9999px;" aria-hidden="true"> <label for="website">Do not fill this field</label> <input type="text" id="website" name="website" tabindex="-1" autocomplete="off"> </div> <div class="comment-form-row"> <div class="comment-form-field"> <label for="comment-name">Nom ou pseudo *</label> <input type="text" id="comment-name" name="author_name" required maxlength="100" autocomplete="name"> </div> <div class="comment-form-field"> <label for="comment-email">Email (facultatif, non publié)</label> <input type="email" id="comment-email" name="author_email" maxlength="255" autocomplete="email"> </div> </div> <div class="comment-form-field"> <label for="comment-content">Votre commentaire *</label> <textarea id="comment-content" name="content" required maxlength="2000" rows="4"></textarea> <div class="comment-form-charcount"><span id="comment-chars">2000</span> caractères restants</div> </div> <div class="comment-form-footer"> <button type="submit" class="comment-submit-btn">Publier le commentaire</button> <span class="comment-form-notice">Les commentaires sont modérés avant publication.</span> </div> <div id="comment-feedback" class="comment-feedback" style="display:none;"></div> </form> </section> <script> (function() { var form = document.getElementById('comment-form'); if (!form) return; var textarea = document.getElementById('comment-content'); var charsEl = document.getElementById('comment-chars'); var feedback = document.getElementById('comment-feedback'); var API_URL = 'https://seoclaims.com/api/comments.php'; // Compteur de caracteres textarea.addEventListener('input', function() { var remaining = 2000 - this.value.length; charsEl.textContent = remaining; charsEl.style.color = remaining < 100 ? '#dc2626' : ''; }); form.addEventListener('submit', function(e) { e.preventDefault(); var btn = form.querySelector('.comment-submit-btn'); btn.disabled = true; var origText = btn.textContent; btn.textContent = '...'; feedback.style.display = 'none'; var data = { action: 'submit', page_type: form.querySelector('[name="page_type"]').value, page_id: parseInt(form.querySelector('[name="page_id"]').value), author_name: form.querySelector('[name="author_name"]').value.trim(), author_email: form.querySelector('[name="author_email"]').value.trim(), content: form.querySelector('[name="content"]').value.trim(), lang: form.querySelector('[name="lang"]').value, website: form.querySelector('[name="website"]').value }; fetch(API_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }) .then(function(r) { return r.json(); }) .then(function(res) { if (res.success) { feedback.className = 'comment-feedback comment-feedback-success'; feedback.textContent = res.message; feedback.style.display = 'block'; // Inserer le commentaire en ligne (en attente de moderation) var list = document.getElementById('comments-list'); var empty = document.getElementById('comments-empty'); if (empty) empty.remove(); var pendingLabel = 'En attente de moderation'; var now = new Date(); var day = String(now.getDate()).padStart(2,'0'); var month = String(now.getMonth()+1).padStart(2,'0'); var dateStr = day + '/' + month + '/' + now.getFullYear(); var div = document.createElement('div'); div.className = 'comment-item comment-pending'; div.innerHTML = '<div class="comment-meta">' + '<span class="comment-author">' + data.author_name.replace(/</g,'<') + '</span>' + '<span class="comment-date">' + dateStr + '</span>' + '<span class="comment-pending-badge">' + pendingLabel + '</span>' + '</div>' + '<div class="comment-body">' + data.content.replace(/</g,'<').replace(/\n/g,'<br>') + '</div>'; list.appendChild(div); form.querySelector('[name="content"]').value = ''; form.querySelector('[name="author_name"]').value = ''; form.querySelector('[name="author_email"]').value = ''; charsEl.textContent = '2000'; } else { feedback.className = 'comment-feedback comment-feedback-error'; feedback.textContent = res.error; feedback.style.display = 'block'; btn.disabled = false; btn.textContent = origText; } }) .catch(function() { feedback.className = 'comment-feedback comment-feedback-error'; feedback.textContent = 'Erreur réseau'; feedback.style.display = 'block'; btn.disabled = false; btn.textContent = origText; }); }); })(); </script> <section class="nl-inline-section"> <div class="nl-inline-inner"> <div class="nl-inline-icon">🔔</div> <div class="nl-inline-text"> <h2 class="nl-inline-headline">Recevez une analyse complète en temps réel des dernières déclarations de Google</h2> <p class="nl-inline-sub">Soyez alerté à chaque nouvelle déclaration officielle Google SEO — avec l'analyse complète incluse.</p> </div> <div class="nl-inline-action"> <form class="nl-inline-form" id="nl-inline-form" novalidate> <input type="email" name="email" placeholder="Votre adresse email" required autocomplete="email"> <button type="submit">S'inscrire gratuitement</button> </form> <div class="nl-inline-privacy">Aucun spam. Désinscription en 1 clic.</div> </div> </div> </section> <style> .nl-inline-section { background: linear-gradient(135deg, #0f172a 0%, #1e3a5f 50%, #0f172a 100%); padding: 52px 24px; margin: 0; } .nl-inline-inner { max-width: 960px; margin: 0 auto; display: grid; grid-template-columns: auto 1fr auto; gap: 24px 32px; align-items: center; } .nl-inline-icon { font-size: 40px; line-height: 1; } .nl-inline-headline { font-size: clamp(16px, 2vw, 20px); font-weight: 700; color: #f0f9ff; margin: 0 0 6px; line-height: 1.35; } .nl-inline-sub { font-size: 14px; color: #7fb8d8; margin: 0; line-height: 1.55; } .nl-inline-action { min-width: 300px; } .nl-inline-form { display: flex; gap: 8px; } .nl-inline-form input[type="email"] { flex: 1; padding: 11px 14px; border: 1px solid rgba(14,165,233,.4); border-radius: 8px; background: rgba(255,255,255,.07); color: #f0f9ff; font-size: 14px; outline: none; min-width: 0; transition: border-color .2s, background .2s; } .nl-inline-form input[type="email"]::placeholder { color: #5a91b0; } .nl-inline-form input[type="email"]:focus { border-color: #0ea5e9; background: rgba(255,255,255,.12); } .nl-inline-form button { padding: 11px 18px; background: linear-gradient(135deg, #0ea5e9, #7c3aed); color: #fff; border: none; border-radius: 8px; font-size: 14px; font-weight: 600; cursor: pointer; white-space: nowrap; transition: opacity .2s; } .nl-inline-form button:hover { opacity: .88; } .nl-inline-form button:disabled { opacity: .55; cursor: default; } .nl-inline-privacy { font-size: 12px; color: #4a7a96; margin-top: 7px; text-align: center; } @media (max-width: 768px) { .nl-inline-inner { grid-template-columns: auto 1fr; grid-template-rows: auto auto; } .nl-inline-action { grid-column: 1 / -1; min-width: 0; } .nl-inline-form { flex-wrap: wrap; } .nl-inline-form input[type="email"] { min-width: 200px; } } </style> <script> (function() { var form = document.getElementById('nl-inline-form'); if (!form) return; var LANG = 'fr'; var API_URL = 'https://seoclaims.com/api/subscribe'; var COOKIE = 'nl_subscribed'; var MSG = { success: 'Parfait ! Vous recevrez les prochaines analyses.', already: 'Vous êtes déjà inscrit(e).', error: 'Une erreur est survenue, veuillez réessayer.', }; function getCookie(n) { return document.cookie.split(';').some(function(c) { return c.trim().startsWith(n + '='); }); } function setCookie(n, days) { var d = new Date(); d.setDate(d.getDate() + days); document.cookie = n + '=1;expires=' + d.toUTCString() + ';path=/;SameSite=Lax'; } // Masquer si deja inscrit if (getCookie(COOKIE)) { var section = form.closest('.nl-inline-section'); if (section) section.style.display = 'none'; return; } form.addEventListener('submit', function(e) { e.preventDefault(); var email = form.querySelector('input[type="email"]').value.trim(); var btn = form.querySelector('button'); btn.disabled = true; var orig = btn.textContent; btn.textContent = '...'; fetch(API_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: email, lang: LANG }) }) .then(function(r) { return r.json(); }) .then(function(data) { if (data.success) { setCookie(COOKIE, 365); form.innerHTML = '<div style="color:#0d9488;font-weight:600;font-size:15px;padding:10px 0;">✓ ' + (data.already ? MSG.already : MSG.success) + '</div>'; // Masquer aussi banniere footer et popup si presents var banner = document.getElementById('nl-banner'); var popup = document.getElementById('nl-popup'); if (banner) banner.style.display = 'none'; if (popup) popup.style.display = 'none'; } else { btn.disabled = false; btn.textContent = orig; var err = form.querySelector('.nl-inline-err'); if (!err) { err = document.createElement('div'); err.className = 'nl-inline-err'; err.style.cssText = 'color:#dc2626;font-size:13px;margin-top:6px;'; form.parentNode.insertBefore(err, form.nextSibling); } err.textContent = data.error || MSG.error; } }) .catch(function() { btn.disabled = false; btn.textContent = orig; }); }); })(); </script> <footer class="site-footer"> <div class="footer-inner"> <!-- ====== Row 1 : About + Navigation + Resources ====== --> <div class="footer-top"> <div> <div class="footer-brand"> <picture> <source srcset="https://seoclaims.com/assets/logo.webp" type="image/webp"> <img src="https://seoclaims.com/assets/logo.png" alt="SEO Declarations" class="footer-logo" loading="lazy" width="132" height="72"> </picture> </div> <p>SEO Claims recense, analyse et traduit les <a href="/declarations">declarations officielles de Google</a> sur le referencement naturel, issues des <a href="/articles">articles publies</a> et des <a href="/videos">videos YouTube</a> de Google Search Central. Chaque declaration est enrichie par une <a href="/declarations">analyse IA</a>, classee par <a href="/declarations">categorie SEO</a> et attribuee a son <a href="/speaker/john-mueller">auteur</a>. Un outil indispensable pour les professionnels du SEO qui veulent savoir exactement ce que Google recommande.</p> </div> <div> <div class="footer-heading">Navigation</div> <nav class="footer-nav"> <a href="/declarations" class="footer-link">Declarations</a> <a href="/labs/" class="footer-link">Labs SEO</a> <a href="/speaker/john-mueller" class="footer-link">Auteurs</a> <a href="/sitemap-declarations" class="footer-link">Plan du site</a> <a href="/comparatif-agences-seo" class="footer-link">Comparatif Agences SEO</a> <a href="/mentions-legales" class="footer-link">Mentions legales</a> </nav> </div> <div> <div class="footer-heading">Ressources</div> <nav class="footer-nav"> <a href="https://search.google.com/search-console" target="_blank" rel="noopener" class="footer-link">Google Search Console</a> <a href="https://pagespeed.web.dev/" target="_blank" rel="noopener" class="footer-link">PageSpeed Insights</a> <a href="https://search.google.com/test/rich-results" target="_blank" rel="noopener" class="footer-link">Rich Results Test</a> <a href="https://developer.chrome.com/docs/lighthouse/" target="_blank" rel="noopener" class="footer-link">Lighthouse</a> <a href="https://developers.google.com/search/docs" target="_blank" rel="noopener" class="footer-link">Google Search Guidelines</a> <a href="/outils-google" class="footer-link" style="color: #60a5fa; font-weight: 600;">Tous les outils Google →</a> </nav> </div> </div> <!-- ====== Row 2 : 3 piliers SEO — Top 5 categories par vues ====== --> <div class="footer-pillars"> <!-- Semantique --> <details class="footer-pillar-details" open> <summary class="footer-pillar-title"> <span style="display:flex;align-items:center;gap:8px;"> <span class="footer-pillar-dot" style="background: #60a5fa;"></span> <span class="footer-pillar-label" style="color: #60a5fa;">Semantique</span> </span> </summary> <nav class="footer-pillar-nav"> <a href="/c/ia-seo" class="footer-pillar-link"> <span>IA & SEO</span> <span class="footer-pillar-count">9673</span> </a> <a href="/c/contenu" class="footer-pillar-link"> <span>Contenu</span> <span class="footer-pillar-count">5585</span> </a> <a href="/c/nom-domaine" class="footer-pillar-link"> <span>Nom de domaine</span> <span class="footer-pillar-count">1943</span> </a> <a href="/c/pdf-fichiers" class="footer-pillar-link"> <span>PDF & Fichiers</span> <span class="footer-pillar-count">497</span> </a> <a href="/c/discover-actualites" class="footer-pillar-link"> <span>Discover & Actualites</span> <span class="footer-pillar-count">343</span> </a> </nav> </details> <!-- Technique --> <details class="footer-pillar-details" open> <summary class="footer-pillar-title"> <span style="display:flex;align-items:center;gap:8px;"> <span class="footer-pillar-dot" style="background: #34d399;"></span> <span class="footer-pillar-label" style="color: #34d399;">Technique</span> </span> </summary> <nav class="footer-pillar-nav"> <a href="/c/anciennete-historique" class="footer-pillar-link"> <span>Anciennete & Historique</span> <span class="footer-pillar-count">6840</span> </a> <a href="/c/crawl-indexation" class="footer-pillar-link"> <span>Crawl & Indexation</span> <span class="footer-pillar-count">3560</span> </a> <a href="/c/javascript-technique" class="footer-pillar-link"> <span>JavaScript & Technique</span> <span class="footer-pillar-count">2358</span> </a> <a href="/c/search-console" class="footer-pillar-link"> <span>Search Console</span> <span class="footer-pillar-count">1848</span> </a> <a href="/c/performance-web" class="footer-pillar-link"> <span>Performance Web</span> <span class="footer-pillar-count">105</span> </a> </nav> </details> <!-- Autorite --> <details class="footer-pillar-details" open> <summary class="footer-pillar-title"> <span style="display:flex;align-items:center;gap:8px;"> <span class="footer-pillar-dot" style="background: #fbbf24;"></span> <span class="footer-pillar-label" style="color: #fbbf24;">Autorite</span> </span> </summary> <nav class="footer-pillar-nav"> <a href="/c/liens-backlinks" class="footer-pillar-link"> <span>Liens & Backlinks</span> <span class="footer-pillar-count">2076</span> </a> <a href="/c/reseaux-sociaux" class="footer-pillar-link"> <span>Reseaux sociaux</span> <span class="footer-pillar-count">541</span> </a> <a href="/c/penalites-spam" class="footer-pillar-link"> <span>Penalites & Spam</span> <span class="footer-pillar-count">515</span> </a> <a href="/c/algorithmes" class="footer-pillar-link"> <span>Algorithmes</span> <span class="footer-pillar-count">416</span> </a> <a href="/c/recherche-locale" class="footer-pillar-link"> <span>Recherche locale</span> <span class="footer-pillar-count">116</span> </a> </nav> </details> </div> <!-- ====== Row 3 : Dernieres prises de parole ====== --> <div class="footer-popular"> <div class="footer-popular-title">Dernieres prises de parole Google sur le SEO</div> <div class="footer-popular-grid"> <a href="/d/celui-qui-dit-tout-savoir-sur-le-seo-est-un-imposteur" class="footer-popular-link"> <span class="footer-popular-meta"> <span class="footer-popular-date">04/2026</span> <span class="footer-popular-speaker">John Mueller</span> </span> <span class="footer-popular-text">Pourquoi personne ne peut vraiment maîtriser le SEO à 100% ?</span> </a> <a href="/d/le-seo-est-complexe-multiforme-et-resilient" class="footer-popular-link"> <span class="footer-popular-meta"> <span class="footer-popular-date">04/2026</span> <span class="footer-popular-speaker">John Mueller</span> </span> <span class="footer-popular-text">Peut-on vraiment se permettre de faire n'importe quoi en SEO sans conséq…</span> </a> <a href="/d/usage-de-custom-javascript-metrics" class="footer-popular-link"> <span class="footer-popular-meta"> <span class="footer-popular-date">04/2026</span> <span class="footer-popular-speaker">Martin Splitt</span> </span> <span class="footer-popular-text">Google utilise-t-il des scripts JavaScript personnalisés pour évaluer vo…</span> </a> <a href="/d/requete-sql-dans-bigquery-pour-l-analyse-seo" class="footer-popular-link"> <span class="footer-popular-meta"> <span class="footer-popular-date">04/2026</span> <span class="footer-popular-speaker">Gary Illyes</span> </span> <span class="footer-popular-text">Faut-il vraiment maîtriser SQL et BigQuery pour faire du SEO en 2025 ?</span> </a> <a href="/d/recommandations-sur-la-taille-des-fichiers-robots-txt" class="footer-popular-link"> <span class="footer-popular-meta"> <span class="footer-popular-date">04/2026</span> <span class="footer-popular-speaker">Martin Splitt</span> </span> <span class="footer-popular-text">Faut-il vraiment respecter la limite de 100KB pour votre fichier robots.…</span> </a> <a href="/d/importancia-d-http-archive-pour-le-seo" class="footer-popular-link"> <span class="footer-popular-meta"> <span class="footer-popular-date">04/2026</span> <span class="footer-popular-speaker">Gary Illyes</span> </span> <span class="footer-popular-text">HTTP Archive : Google révèle-t-il enfin comment il analyse vraiment vos …</span> </a> <a href="/d/utilisation-de-bigquery-pour-analyser-les-sites-web" class="footer-popular-link"> <span class="footer-popular-meta"> <span class="footer-popular-date">04/2026</span> <span class="footer-popular-speaker">Martin Splitt</span> </span> <span class="footer-popular-text">BigQuery est-il vraiment indispensable pour analyser vos données SEO à g…</span> </a> <a href="/d/nouvelle-collecte-de-donnees-robots-txt-avec-http-archive" class="footer-popular-link"> <span class="footer-popular-meta"> <span class="footer-popular-date">04/2026</span> <span class="footer-popular-speaker">Gary Illyes</span> </span> <span class="footer-popular-text">Pourquoi Google publie-t-il soudainement des données massives sur l'usag…</span> </a> </div> </div> <!-- ====== Row 4 : Copyright ====== --> <div class="footer-bottom"> <span>© 2026 SEO Declarations. Tous droits reserves.</span> <span>Ce site n'est pas affilie a Google. Les declarations presentees sont issues de communications publiques de Google.</span> </div> </div> </footer> <!-- ====== Popup Newsletter (une fois par session) ====== --> <div class="nl-popup-overlay" id="nl-popup" style="display:none;" role="dialog" aria-modal="true" aria-label="Recevez une analyse complète en temps réel des dernières déclarations de Google"> <div class="nl-popup-box"> <button class="nl-popup-close" id="nl-popup-close" aria-label="Fermer">×</button> <div class="nl-popup-header"> <div class="nl-popup-badge">Restez informé</div> <h3 class="nl-popup-title">Recevez une analyse complète en temps réel des dernières déclarations de Google</h3> <p class="nl-popup-sub">Soyez le premier informé à chaque nouvelle déclaration officielle Google SEO, avec l'analyse complète incluse.</p> </div> <form class="nl-form nl-popup-form" data-lang="fr" id="nl-popup-form"> <div class="nl-popup-input-group"> <input type="email" name="email" placeholder="Votre adresse email" required autocomplete="email"> <button type="submit">S'inscrire gratuitement</button> </div> </form> <div class="nl-popup-trust"> <span class="nl-popup-trust-icon">🔒</span> <span>Aucun spam. Désinscription en 1 clic.</span> </div> </div> </div> <style> /* === Newsletter Popup === */ .nl-popup-overlay { position: fixed; inset: 0; background: rgba(15,23,42,.6); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); z-index: 9999; display: flex; align-items: center; justify-content: center; padding: 20px; animation: nlFadeIn .3s ease; } .nl-popup-box { background: linear-gradient(165deg, #ffffff 0%, #f8fafc 100%); border-radius: 20px; padding: 40px 36px 32px; max-width: 460px; width: 100%; position: relative; box-shadow: 0 25px 80px rgba(0,0,0,.2), 0 0 0 1px rgba(0,0,0,.05); animation: nlSlideUp .4s cubic-bezier(.16,1,.3,1); text-align: center; } .nl-popup-close { position: absolute; top: 12px; right: 14px; background: none; border: none; font-size: 22px; color: #94a3b8; cursor: pointer; line-height: 1; padding: 6px 10px; border-radius: 8px; transition: color .2s, background .2s; } .nl-popup-close:hover { color: #374151; background: #f1f5f9; } .nl-popup-header { margin-bottom: 24px; } .nl-popup-badge { display: inline-block; background: linear-gradient(135deg, #0ea5e9, #7c3aed); color: #fff; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; padding: 5px 14px; border-radius: 20px; margin-bottom: 16px; } .nl-popup-title { font-size: 22px; font-weight: 800; color: #0f172a; line-height: 1.3; margin: 0 0 10px; } .nl-popup-sub { font-size: 14px; color: #64748b; line-height: 1.6; margin: 0; } .nl-popup-input-group { display: flex; gap: 0; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,.08), 0 0 0 1px rgba(0,0,0,.06); } .nl-popup-form input[type="email"] { flex: 1; padding: 14px 16px; background: #fff; color: #1e293b; border: none; font-size: 15px; outline: none; min-width: 0; } .nl-popup-form input[type="email"]::placeholder { color: #94a3b8; } .nl-popup-form button { padding: 14px 22px; background: linear-gradient(135deg, #0ea5e9, #6d28d9); color: #fff; border: none; font-size: 14px; font-weight: 700; cursor: pointer; white-space: nowrap; transition: opacity .2s; } .nl-popup-form button:hover { opacity: .9; } .nl-popup-form button:disabled { opacity: .5; cursor: default; } .nl-popup-trust { display: flex; align-items: center; justify-content: center; gap: 6px; margin-top: 14px; font-size: 12px; color: #94a3b8; } .nl-popup-trust-icon { font-size: 13px; } .nl-popup-msg { padding: 16px; border-radius: 12px; font-weight: 600; font-size: 15px; margin-top: 4px; } .nl-popup-msg.success { background: #ecfdf5; color: #059669; } .nl-popup-msg.error { background: #fef2f2; color: #dc2626; } @media (max-width: 480px) { .nl-popup-box { padding: 32px 20px 24px; } .nl-popup-input-group { flex-direction: column; border-radius: 12px; } .nl-popup-form input[type="email"] { border-bottom: 1px solid #e2e8f0; } .nl-popup-form button { padding: 14px; border-radius: 0 0 12px 12px; } .nl-popup-title { font-size: 19px; } } @keyframes nlFadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes nlSlideUp { from { transform: translateY(30px) scale(.97); opacity: 0; } to { transform: translateY(0) scale(1); opacity: 1; } } </style> <script> (function() { var LANG = 'fr'; var API_URL = 'https://seoclaims.com/api/subscribe'; var COOKIE = 'nl_subscribed'; var SESSION_KEY = 'nl_popup_shown'; var MSG = { success: 'Parfait ! Vous êtes inscrit(e).', already: 'Vous êtes déjà inscrit(e).', error: 'Une erreur est survenue, veuillez réessayer.', }; function getCookie(n) { return document.cookie.split(';').some(c => c.trim().startsWith(n + '=')); } function setCookie(n, days) { var d = new Date(); d.setDate(d.getDate() + days); document.cookie = n + '=1;expires=' + d.toUTCString() + ';path=/;SameSite=Lax'; } function closePopup(popup) { popup.style.opacity = '0'; setTimeout(function() { popup.style.display = 'none'; }, 300); sessionStorage.setItem(SESSION_KEY, '1'); } function showMsg(container, text, type) { var existing = container.querySelector('.nl-popup-msg'); if (existing) existing.remove(); var el = document.createElement('div'); el.className = 'nl-popup-msg ' + type; el.textContent = text; container.appendChild(el); } document.addEventListener('DOMContentLoaded', function() { var popup = document.getElementById('nl-popup'); var popupForm = document.getElementById('nl-popup-form'); var closeBtn = document.getElementById('nl-popup-close'); if (!popup || !popupForm) return; // Ne pas afficher si : deja inscrit OU deja vu cette session if (getCookie(COOKIE) || sessionStorage.getItem(SESSION_KEY)) return; // Afficher apres 30% scroll OU 20 secondes var nlShown = false; function showNlPopup() { if (nlShown) return; nlShown = true; popup.style.display = 'flex'; sessionStorage.setItem(SESSION_KEY, '1'); } var scrollHandler = function() { var pct = window.scrollY / (document.body.scrollHeight - window.innerHeight); if (pct > 0.3) { showNlPopup(); window.removeEventListener('scroll', scrollHandler); } }; window.addEventListener('scroll', scrollHandler, {passive: true}); setTimeout(showNlPopup, 20000); closeBtn.addEventListener('click', function() { closePopup(popup); }); popup.addEventListener('click', function(e) { if (e.target === popup) closePopup(popup); }); document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && popup.style.display === 'flex') closePopup(popup); }); popupForm.addEventListener('submit', function(e) { e.preventDefault(); var email = popupForm.querySelector('input[type="email"]').value.trim(); var btn = popupForm.querySelector('button[type="submit"]'); btn.disabled = true; var origText = btn.textContent; btn.textContent = '...'; fetch(API_URL, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({email: email, lang: LANG}) }) .then(function(r) { return r.json(); }) .then(function(data) { btn.disabled = false; btn.textContent = origText; if (data.success) { setCookie(COOKIE, 365); popupForm.style.display = 'none'; showMsg(popup.querySelector('.nl-popup-box'), data.already ? MSG.already : MSG.success, 'success'); // Masquer aussi le bloc inline si present var inline = document.querySelector('.nl-inline-section'); if (inline) inline.style.display = 'none'; setTimeout(function() { closePopup(popup); }, 2500); } else { showMsg(popup.querySelector('.nl-popup-box'), data.error || MSG.error, 'error'); } }) .catch(function() { btn.disabled = false; btn.textContent = origText; showMsg(popup.querySelector('.nl-popup-box'), MSG.error, 'error'); }); }); }); })(); </script> <!-- WebSite + Organization Schema --> <script type="application/ld+json"> { "@context": "https://schema.org", "@graph": [ { "@type": "WebSite", "@id": "https://seoclaims.com/#website", "name": "SEO Declarations", "url": "https://seoclaims.com", "inLanguage": [ "fr-FR", "en" ], "publisher": { "@id": "https://seoclaims.com/#organization" }, "potentialAction": { "@type": "SearchAction", "target": { "@type": "EntryPoint", "urlTemplate": "https://seoclaims.com/?q={search_term_string}" }, "query-input": "required name=search_term_string" } }, { "@type": "Organization", "@id": "https://seoclaims.com/#organization", "name": "SEO Declarations", "url": "https://seoclaims.com", "logo": { "@type": "ImageObject", "url": "https://seoclaims.com/assets/logo.png", "width": 512, "height": 512 }, "description": "Moteur de recherche des declarations officielles de Google sur le SEO, avec analyse bilingue enrichie par IA.", "knowsAbout": [ "Search Engine Optimization", "Google Search", "Core Web Vitals", "Technical SEO", "Content SEO", "Link building", "Structured data", "AI search optimization" ], "sameAs": [] } ] }</script> <!-- ==================== CHATBOT WIDGET ==================== --> <button id="cbw-launcher" type="button" aria-label="Poser une question a l'assistant SEO" title="Poser une question a l'assistant SEO"> <svg viewBox="0 0 24 24" width="26" height="26" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path> </svg> <span class="cbw-launcher-label">Assistant SEO</span> <span class="cbw-launcher-pulse" aria-hidden="true"></span> </button> <div id="cbw-panel" role="dialog" aria-label="Assistant SEO" aria-hidden="true"> <div class="cbw-head"> <div class="cbw-head-txt"> <strong>Assistant SEO</strong> <span>Base sur les declarations officielles de Google</span> </div> <div class="cbw-head-actions"> <a href="https://seoclaims.com/chatbot" class="cbw-icon-btn" title="Ouvrir la version complete" aria-label="Ouvrir la version complete"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h6v6"></path><path d="M10 14L21 3"></path><path d="M21 14v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5"></path></svg> </a> <button type="button" id="cbw-close" class="cbw-icon-btn" title="Fermer" aria-label="Fermer"> <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6L6 18"></path><path d="M6 6l12 12"></path></svg> </button> </div> </div> <div class="cbw-body" id="cbw-messages" aria-live="polite"> <div class="cbw-msg assistant cbw-welcome">Bonjour ! Posez-moi une question sur le SEO et Google — je reponds en citant les sources officielles.</div> </div> <form class="cbw-form" id="cbw-form" autocomplete="off"> <textarea id="cbw-input" rows="1" placeholder="Posez votre question..." maxlength="500" required></textarea> <button type="submit" id="cbw-send" aria-label="Envoyer"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg> </button> </form> </div> <style> #cbw-launcher { position: fixed; bottom: 24px; right: 24px; z-index: 9998; display: flex; align-items: center; gap: 8px; padding: 14px 20px 14px 16px; background: linear-gradient(135deg, #7c3aed 0%, #5b21b6 100%); color: #fff; border: none; border-radius: 999px; box-shadow: 0 8px 24px rgba(124,58,237,.35); font-family: inherit; font-size: .93rem; font-weight: 600; cursor: pointer; transition: transform .15s ease, box-shadow .15s ease; } #cbw-launcher:hover { transform: translateY(-2px); box-shadow: 0 12px 28px rgba(124,58,237,.45); } #cbw-launcher svg { flex-shrink: 0; } .cbw-launcher-label { white-space: nowrap; } .cbw-launcher-pulse { position: absolute; top: -2px; right: -2px; width: 12px; height: 12px; background: #10b981; border: 2px solid #fff; border-radius: 50%; animation: cbwPulse 2s infinite; } @keyframes cbwPulse { 0%,100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.3); opacity: .7; } } #cbw-panel { position: fixed; bottom: 24px; right: 24px; z-index: 9999; width: 400px; max-width: calc(100vw - 32px); height: 560px; max-height: calc(100vh - 48px); background: #fff; border-radius: 16px; box-shadow: 0 20px 60px rgba(0,0,0,.2); display: grid; grid-template-rows: auto 1fr auto; overflow: hidden; transform: translateY(20px) scale(.96); opacity: 0; pointer-events: none; transition: transform .22s ease, opacity .22s ease; font-family: inherit; } #cbw-panel[aria-hidden="false"] { transform: translateY(0) scale(1); opacity: 1; pointer-events: auto; } #cbw-panel[aria-hidden="false"] ~ #cbw-launcher, body.cbw-open #cbw-launcher { opacity: 0; pointer-events: none; transform: scale(.8); } .cbw-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 16px; background: linear-gradient(135deg, #7c3aed, #5b21b6); color: #fff; } .cbw-head-txt strong { display: block; font-size: .97rem; line-height: 1.2; } .cbw-head-txt span { display: block; font-size: .75rem; opacity: .85; margin-top: 2px; } .cbw-head-actions { display: flex; gap: 6px; } .cbw-icon-btn { width: 32px; height: 32px; display: inline-flex; align-items: center; justify-content: center; background: rgba(255,255,255,.12); color: #fff; border: none; border-radius: 8px; cursor: pointer; text-decoration: none; transition: background .15s; } .cbw-icon-btn:hover { background: rgba(255,255,255,.22); } .cbw-body { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 12px; background: #fafafa; } .cbw-msg { max-width: 92%; padding: 10px 14px; border-radius: 12px; font-size: .9rem; line-height: 1.55; animation: cbwIn .2s ease-out; } @keyframes cbwIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } } .cbw-msg.user { align-self: flex-end; background: linear-gradient(135deg, #1a73e8, #1557b0); color: #fff; border-bottom-right-radius: 3px; } .cbw-msg.assistant { align-self: flex-start; background: #fff; border: 1px solid #e2e8f0; border-bottom-left-radius: 3px; color: #1e293b; } .cbw-msg.assistant.error { background: #fef2f2; border-color: #fecaca; color: #991b1b; } .cbw-msg.cbw-welcome { background: linear-gradient(135deg, #f3e8ff, #ede9fe); border-color: #c4b5fd; color: #5b21b6; } .cbw-citation { display: inline-block; background: #ede9fe; color: #5b21b6; font-size: .75rem; font-weight: 700; padding: 0 6px; border-radius: 8px; margin: 0 2px; text-decoration: none; vertical-align: 1px; } .cbw-hint { display: inline-block; background: #fef3c7; color: #92400e; font-style: normal; font-size: .82rem; padding: 1px 7px; border-radius: 6px; margin-left: 4px; font-weight: 500; } .cbw-citation:hover { background: #ddd6fe; } .cbw-sources { margin-top: 10px; padding-top: 9px; border-top: 1px dashed #cbd5e1; } .cbw-sources-title { font-size: .7rem; text-transform: uppercase; letter-spacing: .4px; font-weight: 700; color: #64748b; margin-bottom: 6px; } .cbw-src { display: block; padding: 8px 10px; background: #fff; border: 1px solid #e2e8f0; border-left: 3px solid #7c3aed; border-radius: 6px; margin-bottom: 5px; font-size: .78rem; color: inherit; text-decoration: none; transition: transform .12s; } .cbw-src:hover { transform: translateX(2px); border-color: #7c3aed; } .cbw-src strong { display: block; color: #1e293b; margin-bottom: 1px; font-size: .8rem; line-height: 1.3; } .cbw-src .cbw-src-meta { color: #64748b; font-size: .7rem; } .cbw-src .cbw-src-id { display: inline-block; background: #ede9fe; color: #5b21b6; font-family: monospace; font-size: .68rem; font-weight: 700; padding: 0 5px; border-radius: 4px; margin-right: 4px; } .cbw-typing { display: flex; gap: 4px; padding: 10px 14px; } .cbw-typing span { width: 7px; height: 7px; border-radius: 50%; background: #7c3aed; opacity: .5; animation: cbwTyping 1.2s infinite; } .cbw-typing span:nth-child(2) { animation-delay: .15s; } .cbw-typing span:nth-child(3) { animation-delay: .3s; } @keyframes cbwTyping { 0%,80%,100% { transform: scale(.7); opacity: .4; } 40% { transform: scale(1); opacity: 1; } } .cbw-form { display: flex; gap: 8px; padding: 12px; background: #fff; border-top: 1px solid #e2e8f0; } .cbw-form textarea { flex: 1; padding: 10px 12px; border: 1px solid #cbd5e1; border-radius: 10px; font-size: .9rem; font-family: inherit; resize: none; min-height: 40px; max-height: 110px; outline: none; transition: border-color .15s; } .cbw-form textarea:focus { border-color: #7c3aed; box-shadow: 0 0 0 3px rgba(124,58,237,.12); } .cbw-form button { width: 42px; height: 42px; display: inline-flex; align-items: center; justify-content: center; background: linear-gradient(135deg, #7c3aed, #5b21b6); color: #fff; border: none; border-radius: 10px; cursor: pointer; flex-shrink: 0; } .cbw-form button:disabled { opacity: .5; cursor: not-allowed; } @media (max-width: 640px) { #cbw-launcher { bottom: 16px; right: 16px; padding: 12px 16px 12px 14px; font-size: .85rem; } .cbw-launcher-label { display: none; } #cbw-launcher { padding: 14px; } #cbw-panel { top: 0; bottom: 0; left: 0; right: 0; width: 100vw; max-width: 100vw; /* dvh = dynamic viewport height : se reduit quand le clavier mobile s'ouvre */ /* fallback vh pour navigateurs tres anciens */ height: 100vh; height: 100dvh; max-height: 100vh; max-height: 100dvh; border-radius: 0; } /* Laisse le clavier rogner l'espace du body, pas de la frame entiere */ .cbw-body { overscroll-behavior: contain; } } @media print { #cbw-launcher, #cbw-panel { display: none !important; } } </style> <script> (function() { const LANG = "fr"; const T = {"sending":"...","send":"Envoyer","sources":"Sources","rate_limit":"Limite de 10 questions par heure atteinte.","error":"Erreur. Merci de reessayer.","too_short":"Question trop courte."}; const launcher = document.getElementById('cbw-launcher'); const panel = document.getElementById('cbw-panel'); const closeBtn = document.getElementById('cbw-close'); const msgsEl = document.getElementById('cbw-messages'); const formEl = document.getElementById('cbw-form'); const inputEl = document.getElementById('cbw-input'); const sendBtn = document.getElementById('cbw-send'); // Sync panel height to the visual viewport (keyboard-aware) sur mobile // Necessaire car Chrome Android n'honore pas toujours 100dvh correctement // quand le clavier virtuel s'ouvre : la panel reste a 100vh et le contenu // du haut est pousse hors ecran. function syncViewport() { if (!window.visualViewport) return; if (panel.getAttribute('aria-hidden') !== 'false') return; if (window.innerWidth > 640) { panel.style.height = ''; return; } panel.style.height = window.visualViewport.height + 'px'; } function open() { panel.setAttribute('aria-hidden', 'false'); document.body.classList.add('cbw-open'); syncViewport(); if (window.visualViewport) { window.visualViewport.addEventListener('resize', syncViewport); window.visualViewport.addEventListener('scroll', syncViewport); } // Afficher le message de bienvenue au chargement msgsEl.scrollTop = 0; setTimeout(() => inputEl.focus(), 200); } function close() { panel.setAttribute('aria-hidden', 'true'); document.body.classList.remove('cbw-open'); panel.style.height = ''; if (window.visualViewport) { window.visualViewport.removeEventListener('resize', syncViewport); window.visualViewport.removeEventListener('scroll', syncViewport); } } launcher.addEventListener('click', open); closeBtn.addEventListener('click', close); document.addEventListener('keydown', e => { if (e.key === 'Escape' && panel.getAttribute('aria-hidden') === 'false') close(); }); function esc(s) { return String(s).replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); } function renderAnswer(answer, sources, queryId) { const byId = {}; (sources || []).forEach(s => { byId[s.id] = s; }); let html = esc(answer).replace(/\[#(\d+)\]/g, (m, id) => { const s = byId[id]; if (!s) return ''; return '<a class="cbw-citation" href="' + esc(s.url) + '" target="_blank" rel="noopener" data-qid="' + (queryId||0) + '" data-sid="' + id + '" data-kind="citation">#' + id + '</a>'; }); // Markdown italique *texte* -> <em>texte</em> (non greedy, non multiligne) html = html.replace(/\*([^*\n]+?)\*/g, '<em class="cbw-hint">$1</em>'); return html.replace(/\n/g, '<br>'); } function renderSources(sources, queryId) { if (!sources || !sources.length) return ''; let out = '<div class="cbw-sources"><div class="cbw-sources-title">' + esc(T.sources) + '</div>'; sources.forEach(s => { const meta = [s.speaker, s.date].filter(Boolean).join(' · '); out += '<a class="cbw-src" href="' + esc(s.url) + '" target="_blank" rel="noopener" data-qid="' + (queryId||0) + '" data-sid="' + s.id + '" data-kind="source_card">' + '<strong><span class="cbw-src-id">#' + s.id + '</span>' + esc(s.title || '') + '</strong>' + '<div class="cbw-src-meta">' + meta + '</div></a>'; }); return out + '</div>'; } // Beacon de clic : non bloquant, n'empeche pas la navigation function logClick(qid, sid, kind) { if (!qid || !sid) return; const payload = JSON.stringify({ query_id: qid, source_id: sid, kind }); try { if (navigator.sendBeacon) { navigator.sendBeacon('/api/chatbot-click', new Blob([payload], {type: 'application/json'})); } else { fetch('/api/chatbot-click', { method: 'POST', headers: {'Content-Type':'application/json'}, body: payload, keepalive: true }).catch(() => {}); } } catch (e) {} } // Delegation d'evenement sur le conteneur messages msgsEl.addEventListener('click', function(e) { const a = e.target.closest('a[data-qid][data-sid]'); if (!a) return; logClick(parseInt(a.dataset.qid, 10), parseInt(a.dataset.sid, 10), a.dataset.kind || 'source_card'); }); function addUserMsg(txt) { const d = document.createElement('div'); d.className = 'cbw-msg user'; d.innerHTML = esc(txt).replace(/\n/g, '<br>'); msgsEl.appendChild(d); scroll(); } function addBot(data, isError) { const d = document.createElement('div'); d.className = 'cbw-msg assistant' + (isError ? ' error' : ''); if (typeof data === 'string') d.innerHTML = esc(data); else { const qid = data.query_id || 0; d.innerHTML = renderAnswer(data.answer || '', data.sources || [], qid) + renderSources(data.sources || [], qid); } msgsEl.appendChild(d); // Pas de scroll : on laisse l'utilisateur sur sa question, il scrolle lui-meme pour lire la reponse } function showTyping() { const d = document.createElement('div'); d.className = 'cbw-msg assistant'; d.id = 'cbw-typing'; d.innerHTML = '<div class="cbw-typing"><span></span><span></span><span></span></div>'; msgsEl.appendChild(d); // Pas de scroll sur l'indicateur de frappe non plus } function hideTyping() { const t = document.getElementById('cbw-typing'); if (t) t.remove(); } function scroll() { msgsEl.scrollTop = msgsEl.scrollHeight; } async function ask(question, origin) { origin = origin || 'widget'; addUserMsg(question); inputEl.value = ''; inputEl.style.height = 'auto'; sendBtn.disabled = true; showTyping(); try { const resp = await fetch('/api/chatbot', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ question, lang: LANG, referer: window.location.pathname, origin }) }); hideTyping(); const data = await resp.json(); if (!resp.ok) { addBot(data.error === 'rate_limit' ? T.rate_limit : T.error, true); } else { addBot(data, false); } } catch (e) { hideTyping(); addBot(T.error, true); } finally { sendBtn.disabled = false; inputEl.focus(); } } // API publique pour declencher le chatbot depuis d'autres pages // Usage : window.ChatbotSEO.ask("Ma question", "search_fallback") window.ChatbotSEO = { open, close, ask: function(question, origin) { if (!question || question.length < 3) return; open(); // Laisser l'animation d'ouverture se lancer puis envoyer setTimeout(() => ask(question, origin || 'search_fallback'), 350); } }; inputEl.addEventListener('input', function() { this.style.height = 'auto'; this.style.height = Math.min(this.scrollHeight, 110) + 'px'; }); inputEl.addEventListener('keydown', function(e) { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); formEl.requestSubmit(); } }); formEl.addEventListener('submit', function(e) { e.preventDefault(); const q = inputEl.value.trim(); if (q.length < 3) { addBot(T.too_short, true); return; } ask(q); }); })(); </script> <nav class="mobile-nav" aria-label="Navigation mobile"> <a href="/" class="mobile-nav-item"> <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg> <span>Recherche</span> </a> <a href="/declarations" class="mobile-nav-item"> <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg> <span>Catégories</span> </a> <a href="/?browse=1&sort=date_desc" class="mobile-nav-item"> <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg> <span>Récentes</span> </a> <a href="/en/" class="mobile-nav-item mobile-nav-lang"> <svg width="22" height="16" viewBox="0 0 640 480"> <rect width="213" height="480" fill="#00247d"/><rect x="213" width="214" height="480" fill="#fff"/><rect x="427" width="213" height="480" fill="#cf142b"/> </svg> <span>EN</span> </a> </nav> <!-- Lightbox (self-contained) --> <div id="lightbox" style="display:none;position:fixed;inset:0;z-index:99999;background:rgba(0,0,0,.9);align-items:center;justify-content:center;padding:16px;cursor:zoom-out;" onclick="closeLightbox()"> <button onclick="closeLightbox();event.stopPropagation();" style="position:absolute;top:12px;right:16px;z-index:100000;width:44px;height:44px;border:none;background:rgba(255,255,255,.2);color:#fff;font-size:1.6rem;border-radius:50%;cursor:pointer;" aria-label="Fermer">×</button> <img id="lightbox-img" src="" alt="" style="max-width:95%;max-height:90vh;border-radius:8px;box-shadow:0 8px 40px rgba(0,0,0,.5);" onclick="event.stopPropagation()"> </div> <script> function openLightbox(src){ var lb=document.getElementById('lightbox'); document.getElementById('lightbox-img').src=src; lb.style.display='flex'; document.body.style.overflow='hidden'; } function closeLightbox(){ document.getElementById('lightbox').style.display='none'; document.body.style.overflow=''; } document.addEventListener('keydown',function(e){if(e.key==='Escape')closeLightbox();}); function ytPlay(card) { var vid = card.dataset.vid; var ts = parseInt(card.dataset.ts) || 0; card.classList.add('playing'); card.innerHTML = '<iframe src="https://www.youtube-nocookie.com/embed/' + vid + '?autoplay=1&rel=0&modestbranding=1' + (ts > 0 ? '&start=' + ts : '') + '" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>'; } </script> </body> </html>