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

Les titres de page affichés dans les résultats de recherche sont désormais choisis en fonction de la page elle-même, et non plus en fonction de la requête de l'utilisateur. On peut utiliser une recherche 'site:' pour voir le titre actuel indexé et soumettre la page pour réindexation afin d'affiner les titres.
🎥 Vidéo source

Extrait d'une vidéo Google Search Central

💬 EN 📅 22/03/2022 ✂ 15 déclarations
Voir sur YouTube →
Autres déclarations de cette vidéo 14
  1. Changer un nom de ville suffit-il à créer des doorway pages condamnables par Google ?
  2. Faut-il vraiment centraliser son contenu compétitif plutôt que le dupliquer ?
  3. Découvert mais non indexé : Google n'a-t-il vraiment jamais crawlé ces pages ?
  4. Pourquoi Google refuse-t-il d'indexer un site techniquement parfait ?
  5. Faut-il vraiment faire confiance aux recommandations de vos outils SEO ?
  6. Faut-il encore corriger les redirections cassées longtemps après une migration ?
  7. Passer d'un ccTLD à un gTLD suffit-il pour conquérir de nouveaux marchés internationaux ?
  8. Sous-domaine ou sous-répertoire : Google a-t-il vraiment une préférence ?
  9. Pourquoi les clics par page et par requête diffèrent-ils dans Search Console ?
  10. Les erreurs de données structurées bloquent-elles vraiment l'indexation de vos pages ?
  11. Le maillage interne révèle-t-il vraiment l'importance de vos pages à Google ?
  12. L'attribut target des liens a-t-il un impact sur le référencement Google ?
  13. Faut-il vraiment supprimer tous les breadcrumbs schema sauf un pour éviter la confusion ?
  14. Pourquoi vos images CSS background-image sont-elles invisibles pour Google Images ?
📅
Declaration officielle du (il y a 4 ans)
TL;DR

Google génère désormais les titres affichés dans les SERPs uniquement à partir du contenu de la page elle-même, sans adaptation à la requête de recherche. Pour voir le titre actuellement indexé, utilisez une recherche 'site:' et soumettez à nouveau la page si nécessaire pour affiner son titre. Cette évolution réduit la variabilité des titres affichés et renforce l'importance d'optimiser directement la balise <title>.

Ce qu'il faut comprendre

Que change concrètement cette déclaration dans la manière dont Google affiche les titres ?

Avant cette évolution, Google adaptait parfois le titre affiché dans les résultats en fonction de la requête de l'utilisateur. Si quelqu'un cherchait « acheter chaussures running », Google pouvait réécrire le titre pour faire ressortir ces termes même s'ils n'étaient pas exactement dans la balise . Cette personnalisation n'existe plus.</p> <p>Désormais, le titre que vous voyez dans les SERPs est déterminé <strong>uniquement par la page elle-même</strong> — sa balise <title>, mais aussi potentiellement ses H1, son contenu visible ou même ses ancres de liens internes. Google choisit ce qu'il estime être le meilleur titre, mais ce choix reste <strong>fixe quel que soit l'utilisateur ou la requête</strong>.</p> <h3>Pourquoi Google a-t-il abandonné la personnalisation des titres par requête ?</h3> <p>Google ne donne aucune explication technique précise dans cette déclaration. On peut supposer que la personnalisation à la volée générait trop de <strong>variabilité</strong> et rendait difficile pour les webmasters de comprendre pourquoi leur titre apparaissait différemment selon les recherches.</p> <p>En figeant le titre par page, Google simplifie son travail d'indexation et rend le comportement plus <strong>prévisible</strong>. Mais cela signifie aussi que votre balise <title> doit être encore plus universelle et couvrir l'ensemble des intentions de recherche potentielles sans aide contextuelle de Google.</p> <h3>Comment savoir quel titre Google a réellement indexé pour ma page ?</h3> <p>Mueller recommande d'utiliser une <strong>recherche 'site:'</strong> pour vérifier le titre actuellement affiché. Par exemple : <code>site:votredomaine.com/page-exemple</code>. Le titre visible dans les résultats est celui que Google a choisi d'indexer.</p> <p>Si ce titre ne vous convient pas, vous pouvez <strong>soumettre la page pour réindexation</strong> via la Search Console. Google réévaluera alors le titre en fonction du contenu actuel de la page. Aucune garantie que votre balise <title> soit respectée à 100%, mais c'est le seul levier d'action direct.</p> <ul> <li><strong>Le titre affiché est fixe par page</strong>, il ne varie plus selon la requête de l'utilisateur</li> <li>Google génère ce titre à partir de la page elle-même : balise <title>, H1, contenu, ancres internes</li> <li>Utilisez <code>site:</code> pour voir le titre indexé actuellement</li> <li>Soumettez la page pour réindexation si le titre ne correspond pas à vos attentes</li> <li>Aucune garantie que Google respecte exactement votre balise <title> — il garde la main</li> </ul></div> </div> <div class="section-card ai-section"> <h2>Avis d'un expert SEO</h2> <div class="content" data-field="ai_expert_opinion"><h3>Cette déclaration correspond-elle à ce qu'on observe sur le terrain ?</h3> <p>Oui, globalement. Depuis plusieurs années, on constate que Google rééc <strong>réécrit les titres</strong> de manière plus agressive et moins prévisible. La personnalisation par requête était déjà devenue rare, voire anecdotique, dans la plupart des secteurs.</p> <p>Ce que Mueller confirme ici, c'est que Google a <strong>officiellement abandonné</strong> cette variabilité. En pratique, la plupart des SEO constataient déjà que les titres affichés restaient identiques quelle que soit la requête. Cette déclaration ne fait donc que clarifier une situation de fait.</p> <h3>Quelles zones d'ombre subsistent dans cette explication ?</h3> <p>Mueller ne détaille pas <strong>exactement comment Google choisit</strong> le titre affiché. Il mentionne « la page elle-même », mais ça reste vague. Prend-il le H1 si la balise <title> est mal rédigée ? Les ancres internes ont-elles un poids réel ? Le contenu visible influence-t-il ce choix ? <strong>[À vérifier]</strong></p> <p>De plus, Google continue de <strong>réécrire massivement les titres</strong> même quand la balise <title> semble parfaitement optimisée. On observe des cas où le titre affiché n'a aucun rapport avec la balise <title> fournie. Google invoque souvent des raisons de « meilleure pertinence », mais sans transparence sur les critères exacts.</p> <div class="alert"><strong>Attention :</strong> Google garde un pouvoir discrétionnaire total sur les titres affichés. Même avec une balise <title> irréprochable, votre titre peut être réécrit. Vérifiez régulièrement via <code>site:</code> et ajustez si nécessaire.</div> <h3>Cette évolution est-elle une bonne nouvelle pour les SEO ?</h3> <p>C'est un <strong>couteau à double tranchant</strong>. D'un côté, la prévisibilité accrue simplifie le travail : vous savez que le titre affiché sera le même pour tous les utilisateurs. Cela facilite les tests A/B et le suivi des performances.</p> <p>D'un autre côté, vous perdez la <strong>flexibilité contextuelle</strong> qui permettait à Google d'adapter finement le titre à l'intention de recherche. Votre balise <title> doit désormais être suffisamment large pour couvrir plusieurs intentions, ce qui peut diluer la pertinence pour certaines requêtes spécifiques.</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 les titres de page ?</h3> <p>Rédigez des balises <title> <strong>universelles et complètes</strong>. Puisque Google ne va plus adapter le titre à la requête, votre titre doit couvrir l'ensemble des intentions de recherche visées par la page. Évitez les titres trop spécifiques ou trop vagues.</p> <p>Vérifiez systématiquement le titre affiché via une recherche <code>site:</code> après publication ou mise à jour. Si le titre ne correspond pas à votre balise <title>, cherchez pourquoi : H1 trop différent, ancres internes contradictoires, contenu peu cohérent avec le titre fourni.</p> <p>Soumettez la page pour réindexation si le titre affiché ne vous convient pas. Cela ne garantit pas que Google respecte votre balise <title>, mais cela force une <strong>réévaluation</strong> du titre basée sur le contenu actuel de la page.</p> <h3>Quelles erreurs éviter dans la rédaction des titres ?</h3> <p>Ne multipliez pas les <strong>incohérences</strong> entre balise <title>, H1 et contenu principal. Google pioche dans ces éléments pour générer le titre affiché. Si tous racontent une histoire différente, vous perdez le contrôle total.</p> <p>Évitez les titres trop longs ou bourrés de mots-clés. Google tronque les titres au-delà de 60-70 caractères et peut décider de <strong>réécrire complètement</strong> un titre qu'il juge non pertinent ou manipulateur.</p> <p>Ne négligez pas les ancres de liens internes. Certains cas montrent que Google peut s'appuyer sur les ancres pointant vers une page pour générer son titre affiché. Veillez à la <strong>cohérence sémantique</strong> de votre maillage interne.</p> <h3>Comment vérifier que votre stratégie de titres est efficace ?</h3> <p>Auditez régulièrement vos titres affichés via des recherches <code>site:</code> ou des outils de crawl qui simulent l'affichage dans les SERPs. Comparez avec vos balises <title> pour identifier les <strong>divergences récurrentes</strong>.</p> <p>Analysez les performances dans la Search Console. Si une page performe mal malgré un bon positionnement, le titre affiché peut être en cause. Testez des ajustements et suivez l'impact sur le <strong>taux de clic</strong>.</p> <ul class="checklist"> <li>Rédigez des balises <title> universelles couvrant plusieurs intentions de recherche</li> <li>Vérifiez le titre affiché via <code>site:</code> après chaque modification</li> <li>Soumettez la page pour réindexation si le titre ne correspond pas</li> <li>Harmonisez balise <title>, H1 et contenu pour éviter les incohérences</li> <li>Limitez les titres à 60-70 caractères pour éviter la troncature</li> <li>Surveillez les ancres de liens internes qui pointent vers vos pages clés</li> <li>Auditez régulièrement les titres affichés et comparez avec vos balises</li> <li>Analysez les performances CTR dans la Search Console pour détecter les problèmes</li> </ul> <div class="summary">L'optimisation des titres de page devient un exercice d'équilibre délicat : couvrir suffisamment d'intentions sans diluer la pertinence, tout en gardant une cohérence stricte entre tous les signaux on-page. Ces ajustements techniques demandent une expertise pointue et un suivi régulier. Si vous manquez de ressources internes pour auditer et optimiser systématiquement vos titres, une agence SEO spécialisée peut vous accompagner avec une méthodologie éprouvée et des outils adaptés.</div></div> </div> <!-- FAQ --> <div class="section-card"> <h2>❓ Questions frequentes</h2> <div class="faq-list"> <details class="faq-item"> <summary class="faq-question">Google peut-il encore réécrire ma balise <title> même si elle est bien optimisée ?</summary> <div class="faq-answer">Oui, absolument. Google garde un pouvoir discrétionnaire total sur les titres affichés. Même avec une balise <title> irréprochable, votre titre peut être réécrit si Google estime qu'un autre élément de la page (H1, contenu, ancres) est plus pertinent.</div> </details> <details class="faq-item"> <summary class="faq-question">Comment forcer Google à respecter ma balise <title> exactement ?</summary> <div class="faq-answer">Il n'existe aucune méthode garantie. Vous pouvez maximiser vos chances en harmonisant balise <title>, H1 et contenu principal, en évitant les titres trop longs ou bourrés de mots-clés, et en soumettant la page pour réindexation. Mais Google garde la main.</div> </details> <details class="faq-item"> <summary class="faq-question">La recherche 'site:' affiche-t-elle vraiment le titre indexé par Google ?</summary> <div class="faq-answer">Oui, c'est la méthode recommandée par Mueller lui-même. Le titre visible dans les résultats d'une recherche 'site:' correspond au titre que Google a choisi d'indexer et d'afficher dans les SERPs pour cette page.</div> </details> <details class="faq-item"> <summary class="faq-question">Dois-je réécrire tous mes titres suite à cette déclaration ?</summary> <div class="faq-answer">Pas nécessairement. Si vos titres actuels performent bien et sont affichés comme prévu, inutile de tout refaire. Concentrez-vous sur les pages où le titre affiché diverge de votre balise <title> ou sur celles qui sous-performent en CTR.</div> </details> <details class="faq-item"> <summary class="faq-question">Les ancres de liens internes influencent-elles réellement le titre affiché ?</summary> <div class="faq-answer">C'est possible, mais Google ne donne aucune précision chiffrée. Certains cas observés suggèrent que Google peut s'appuyer sur les ancres récurrentes pointant vers une page. Veillez à la cohérence sémantique de votre maillage interne pour éviter les incohérences.</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=balise+title" class="seo-tag-pill">balise title</a> <a href="/?q=titres+SERPs" class="seo-tag-pill">titres SERPs</a> <a href="/?q=r%C3%A9indexation" class="seo-tag-pill">réindexation</a> <a href="/?q=Search+Console" class="seo-tag-pill">Search Console</a> <a href="/?q=H1" class="seo-tag-pill">H1</a> <a href="/?q=maillage+interne" class="seo-tag-pill">maillage interne</a> <a href="/?q=optimisation+on-page" class="seo-tag-pill">optimisation on-page</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/contenu" class="tag" style="background: #10b98120; color: #10b981;">Contenu</a> <a href="/c/crawl-indexation" class="tag" style="background: #3b82f620; color: #3b82f6;">Crawl & Indexation</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">14</span> </h2> <p class="yt-same-intro"> Autres enseignements SEO extraits de cette même vidéo Google Search Central · publiée le 22/03/2022 </p> <div class="related-grid yt-same-grid"> <a href="/d/eviter-les-doorway-pages-avec-du-contenu-quasi-identique" class="related-item yt-same-item"> <div class="title">Changer un nom de ville suffit-il à créer des doorway pages condamnables par Google ?</div> <div class="meta"> </div> </a> <a href="/d/dupliquer-du-contenu-dilue-sa-valeur-competitive" class="related-item yt-same-item"> <div class="title">Faut-il vraiment centraliser son contenu compétitif plutôt que le dupliquer ?</div> <div class="meta"> </div> </a> <a href="/d/le-statut-decouvert-non-indexe-signifie-que-la-page-n-a-pas-ete-crawlee" class="related-item yt-same-item"> <div class="title">Découvert mais non indexé : Google n'a-t-il vraiment jamais crawlé ces pages ?</div> <div class="meta"> </div> </a> <a href="/d/la-barre-qualite-monte-du-contenu-techniquement-correct-ne-suffit-plus" class="related-item yt-same-item"> <div class="title">Pourquoi Google refuse-t-il d'indexer un site techniquement parfait ?</div> <div class="meta"> </div> </a> <a href="/d/ne-pas-suivre-aveuglement-les-outils-seo" class="related-item yt-same-item"> <div class="title">Faut-il vraiment faire confiance aux recommandations de vos outils SEO ?</div> <div class="meta"> </div> </a> <a href="/d/les-redirections-de-migration-perdent-leur-valeur-apres-environ-2-ans" class="related-item yt-same-item"> <div class="title">Faut-il encore corriger les redirections cassées longtemps après une migration ?</div> <div class="meta"> </div> </a> <a href="/d/le-passage-d-un-domaine-national-a-global-change-radicalement-la-competition" class="related-item yt-same-item"> <div class="title">Passer d'un ccTLD à un gTLD suffit-il pour conquérir de nouveaux marchés internationaux ?</div> <div class="meta"> </div> </a> <a href="/d/les-sous-domaines-et-sous-repertoires-sont-equivalents-pour-google" class="related-item yt-same-item"> <div class="title">Sous-domaine ou sous-répertoire : Google a-t-il vraiment une préférence ?</div> <div class="meta"> </div> </a> <a href="/d/les-requetes-anonymisees-expliquent-les-ecarts-dans-search-console" class="related-item yt-same-item"> <div class="title">Pourquoi les clics par page et par requête diffèrent-ils dans Search Console ?</div> <div class="meta"> </div> </a> <a href="/d/les-erreurs-de-donnees-structurees-n-empechent-pas-l-indexation" class="related-item yt-same-item"> <div class="title">Les erreurs de données structurées bloquent-elles vraiment l'indexation de vos pages ?</div> <div class="meta"> </div> </a> <a href="/d/le-maillage-interne-revele-l-importance-des-pages-a-google" class="related-item yt-same-item"> <div class="title">Le maillage interne révèle-t-il vraiment l'importance de vos pages à Google ?</div> <div class="meta"> </div> </a> <a href="/d/l-attribut-target-des-liens-est-ignore-par-google" class="related-item yt-same-item"> <div class="title">L'attribut target des liens a-t-il un impact sur le référencement Google ?</div> <div class="meta"> </div> </a> <a href="/d/plusieurs-breadcrumbs-schema-confus-peuvent-tous-etre-ignores" class="related-item yt-same-item"> <div class="title">Faut-il vraiment supprimer tous les breadcrumbs schema sauf un pour éviter la confusion ?</div> <div class="meta"> </div> </a> <a href="/d/les-images-css-background-ne-sont-pas-indexees-pour-la-recherche-d-images" class="related-item yt-same-item"> <div class="title">Pourquoi vos images CSS background-image sont-elles invisibles pour Google Images ?</div> <div class="meta"> </div> </a> </div> <a href="https://www.youtube.com/watch?v=sH_tdGP_76o" 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/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> <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/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> </div> </div> <!-- Prev/Next --> <div class="prev-next"> <a href="/d/les-images-css-background-ne-sont-pas-indexees-pour-la-recherche-d-images"> <div class="nav-label">« Precedent</div> <div class="nav-title">Les images CSS background ne sont pas indexées pou...</div> </a> <a href="/d/importance-du-h1-sur-chaque-page-notamment-la-page-d-accueil" style="text-align: right;"> <div class="nav-label">Suivant »</div> <div class="nav-title">Importance du H1 sur chaque page, notamment la pag...</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="3456"> <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>