What does Google say about SEO? /
Quick SEO Quiz

Test your SEO knowledge in 5 questions

Less than a minute. Find out how much you really know about Google search.

🕒 ~1 min 🎯 5 questions

Official statement

Using sitemaps and ensuring that the information is easily extractable helps to quickly bring new content to the forefront of Google searches.
61:48
🎥 Source video

Extracted from a Google Search Central video

⏱ 58:40 💬 EN 📅 30/10/2019 ✂ 13 statements
Watch on YouTube (61:48) →
Other statements from this video 12
  1. 2:11 Faut-il optimiser son contenu pour BERT ou est-ce une perte de temps ?
  2. 3:46 YouTube bénéficie-t-il d'un avantage SEO dans Google Search ?
  3. 6:09 Problèmes d'indexation qui traînent : bug Google ou faille technique de votre site ?
  4. 8:54 Comment Google comptabilise-t-il vraiment les impressions dans Search Console ?
  5. 11:36 Faut-il vraiment implémenter hreflang sur tous les sites multilingues ?
  6. 18:42 Peut-on vraiment tricher avec les données structurées pour obtenir des rich snippets ?
  7. 22:06 Faut-il vraiment arrêter d'utiliser la commande site: pour compter vos pages indexées ?
  8. 28:38 Les pages non mobile-friendly peuvent-elles vraiment survivre à l'indexation mobile-first ?
  9. 35:51 Le budget de crawl se gère-t-il vraiment au niveau du serveur et non du dossier ?
  10. 43:40 Faut-il bloquer les URL paramétrées en robots.txt ou via les réglages Search Console ?
  11. 49:39 Faut-il vraiment « réparer » une pénalité algorithmique pour retrouver son trafic ?
  12. 69:08 Le contenu réutilisé dans les sites d'actualités : quelle est vraiment la limite avant la pénalité ?
📅
Official statement from (6 years ago)
TL;DR

John Mueller confirms that sitemaps and content extractability are the two levers for speeding up the appearance of new articles in Google’s index. For news sites, this statement reminds us that a robust technical architecture outweighs mere publication frequency. In practice, you need to optimize the crawl budget and structure the data so that Googlebot can instantly identify what's just been released.

What you need to understand

Why does Google emphasize sitemaps for news?

News sites operate under an extreme freshness logic: an article published 2 hours ago may already be outdated in the face of competition. Google knows this and has built specific mechanisms — particularly the Google News Sitemap — to detect new content in nearly real-time.

The standard XML sitemap operates in a pull mode: Googlebot visits at regular intervals. For news, the news sitemap explicitly signals freshness with and tags. This allows Google to prioritize crawling and indexing without waiting for the next traditional cycle.</p><p>But Mueller doesn't stop there. He mentions "easily extractable information." What does this mean concretely? He refers to <strong>structured data</strong> (Schema.org Article, NewsArticle), correct meta tags (visible publication date, clearly identified author), and a clear HTML architecture where Googlebot doesn’t have to guess what constitutes editorial content versus navigation or ads.</p><h3>What does "easily extractable" mean in today's Google context?</h3><p>Google no longer just crawls raw HTML. It analyzes the <strong>rendered DOM</strong>, extracts entities, compares declared dates (meta, Schema, sitemap), and detects inconsistencies. A site that publishes an article at 2:22 PM but whose sitemap is only regenerated at midnight loses 10 hours of potential lead.</p><p>“Easily extractable” also means that the main content must be unambiguously identifiable. Sites that drown the article in <strong>advertising blocks</strong>, poorly implemented lazy-loading, or opaque paywalls slow down processing. Google can crawl, but semantic extraction takes longer — and in news, every second counts.</p><p>On the technical side, this means: <strong>server response time < 200ms</strong>, no unnecessary redirects, no soft-404s on critical resources (CSS, JS necessary for rendering content). A server that takes 800ms to serve the HTML page kills the sitemap advantage.</p><h3>How applicable is this recommendation to non-news sites?</h3><p>Mueller explicitly mentions <strong>news sites</strong>, but the underlying principle applies to any site regularly publishing fresh content: corporate blogs, e-commerce sites adding new products daily, content platforms like Substack or Medium.</p><p>The difference? Urgency. An <strong>e-commerce</strong> site adding 50 new SKUs a day can afford to wait 24-48 hours without issue. A media outlet covering an election or a sporting event loses everything if indexing takes 6 hours. Google adjusts its crawling behavior based on the historically detected "freshness rate" on the site.</p><p>For a B2B blog that publishes 2 articles per week, a standard sitemap is more than sufficient. There's no need to over-optimize with a news sitemap — Google won’t prioritize it anyway due to lack of volume and frequency.</p><ul><li><strong>News Sitemap</strong>: mandatory for any site wanting to appear in Google News or to climb quickly in Top Stories</li><li><strong>Extractability</strong>: Schema NewsArticle markup, consistent dates (meta, JSON-LD, sitemap), clean HTML without blocking JS layers</li><li><strong>Crawl Budget</strong>: responsive server, no redirect chains, real-time or near-real-time sitemap regeneration (API or cron every 5-10 minutes)</li><li><strong>Freshness History</strong>: Google adjusts its crawl frequency based on the observed pace — a site that publishes sporadically will never be crawled in real-time, even with a perfect sitemap</li><li><strong>Signal Consistency</strong>: identical publication date across all channels (HTML, Schema, sitemap, RSS feed) — any discrepancy slows down processing</li></ul></div> </div> <div class="section-card ai-section"> <h2>SEO Expert opinion</h2> <div class="content" data-field="ai_expert_opinion"><h3>Is this statement consistent with field observations?</h3><p>Yes, but with <strong>critical nuances</strong>. News sites with a well-configured news sitemap AND good domain authority are indeed seeing their articles indexed in 5-15 minutes. But that "AND" is crucial: a small local blog with a flawless sitemap may wait 2-3 hours if Google hasn’t allocated significant crawl budget.</p><p>“Extractability” is a trickier concept. <strong>[To be verified]</strong>: Google has never published precise criteria on what makes content “easily extractable.” It’s assumed to involve structured data + semantic HTML + absence of technical barriers, but no official document details it. Field tests show that a complete Schema NewsArticle speeds up indexing, but it’s impossible to quantify the precise gap compared to a site without Schema.</p><p>Another point: Mueller doesn’t mention <strong>domain authority</strong> or historical content quality. In practice, a site that has published 80% clickbait in the last 6 months will be crawled less frequently, even with a perfect sitemap. Google adjusts its crawl based on “trust” — a signal it never openly documents.</p><h3>What common errors does this statement obscure?</h3><p>Many sites think that simply adding a <strong>news sitemap</strong> is enough. A classic error: the sitemap is generated on the fly, but the server takes 1.2 seconds to build it because it queries a poorly indexed database. Result: Googlebot times out or gives up. The sitemap must be <strong>pre-generated and served from cache</strong>, with a response time < 100ms.</p><p>Another pitfall: sites that regenerate their sitemap once an hour, but add articles every 10 minutes. Google crawls the sitemap at 2:00 PM, it misses the articles published at 2:05 PM, 2:15 PM, 2:25 PM… and only sees them at 3:00 PM. For real responsiveness, either an <strong>instant indexing system</strong> (via IndexNow or Indexing API — although Google has shut the API to traditional news sites), or a sitemap regenerated every 5 minutes maximum is essential.</p><p><strong>[To be verified]</strong>: Mueller says nothing about the order of URLs in the sitemap. Some SEOs claim that placing the newest URLs at the top of the XML file speeds up processing. No official confirmation. In theory, Google parses the entire XML — but if the sitemap contains 50,000 URLs and only the last 10 are new, it’s hard to believe Googlebot doesn’t prioritize the first lines.</p><h3>In what cases does this recommendation not apply?</h3><p>If your site publishes <strong>less than one article per day</strong>, the news sitemap adds no value. Google will crawl it with the same frequency as a standard sitemap. You’re wasting time configuring a specific system for zero measurable gain.</p><p>Sites behind <strong>hard paywalls</strong> (fully locked content) present another problem. Google can crawl via a specific agreement (First Click Free, Flexible Sampling), but extractability is inherently limited. In this case, the sitemap helps signal freshness, but indexing will never be as fast as 100% open content — Google cannot analyze deeply what it cannot see.</p><div class="alert"><strong>Attention:</strong> Sites using <strong>client-side JavaScript</strong> to load editorial content (like React without SSR) sabotage extractability. Googlebot can execute JS, but it extends processing time by several seconds. For news, this is prohibitive. Prefer server-side rendering or static generation.</div></div> </div> <div class="section-card ai-section"> <h2>Practical impact and recommendations</h2> <div class="content" data-field="ai_practical_impact"><h3>What should be implemented for a news site?</h3><p>First, implement a compliant <strong>Google News sitemap</strong> (max 1000 URLs, articles published in the last 2 days, correct <publication> tags). The sitemap should be declared in Google Search Console and automatically regenerated with each publication — ideally via a webhook or an event listener on your CMS.</p><p>Next, ensure that each article contains <strong>Schema.org NewsArticle markup</strong> with datePublished, dateModified, headline, image, author, publisher. These data must be consistent with standard HTML meta tags (og:article:published_time, etc.). A 5-minute divergence between Schema and the sitemap can be enough to slow down processing.</p><p>On the infrastructure side: server response time < 200ms for the HTML page, < 100ms for the XML sitemap. If you're on a <strong>shared hosting</strong> service that is at 800ms during peak times, you’re losing the battle even before it starts. Switching to a VPS or a CDN with edge rendering becomes essential once you exceed 10-20 articles per day.</p><h3>What technical errors block rapid indexing?</h3><p><strong>Soft-404s</strong> on new URLs: your CMS generates the article, adds the URL to the sitemap, but returns a 200 with a message saying “article under moderation” or “content not available.” Googlebot crawls, sees empty or inconsistent content, and quarantines the URL. When the article becomes available 30 minutes later, Google might not revisit for another 2-3 hours.</p><p>Another classic issue: <strong>temporary redirects (302)</strong> between initial publication and final URL. Some CMSs publish first at /draft/article then redirect to /article once validated. Google follows the 302 but doesn’t immediately index the final URL — it waits to see if the redirect becomes permanent (301). Result: 1-2 hours lost.</p><p>Misconfigured <strong>self-referential canonicals</strong>: the article points to an AMP version or a URL with tracking parameters as canonical. Google hesitates, crawls both, and wastes time determining the master version. For news, the canonical should point to the final definitive URL from the second of publication.</p><h3>How to check that everything is working correctly?</h3><p>Use the <strong>URL inspection tool</strong> in Search Console immediately after publication. If Google sees the URL in the sitemap and the content is extractable, you’ll receive feedback in 30-60 seconds. If the tool says “URL not found in the sitemap,” your regeneration system is broken.</p><p>Monitor the <strong>server logs</strong> to trace Googlebot's visits to the news sitemap. An active news site should see Googlebot crawling the sitemap every 10-30 minutes. If you’re only getting a crawl once an hour, it means Google doesn’t consider you sufficiently “fresh” — either due to lack of historical volume or quality content issues.</p><p>Test the <strong>actual indexing</strong> with a site:votredomain.com intitle:“exact article title” search within 15 minutes of publication. If the article does not appear, dig deeper: either the crawl did not happen, the extractability is an issue, or Google decided not to index (duplicate content, insufficient quality).</p><ul class="checklist"><li>News sitemap automatically regenerated every 5-10 minutes maximum</li><li>Complete NewsArticle Schema on every article, consistent dates everywhere</li><li>Server response time < 200ms for HTML, < 100ms for XML sitemap</li><li>No soft-404s, no temporary 302s, clean canonical from the moment of publication</li><li>Monitoring of Googlebot crawls on the sitemap via server logs</li><li>Real indexing test within 15 minutes post-publication with site:</li></ul><div class="summary">For news sites, indexing speed is a <strong>direct competitive advantage</strong>. An article indexed in 5 minutes can capture the early waves of search and generate traffic before competitors even appear in the results. But this technical performance demands a <strong>solid infrastructure</strong>: responsive server, real-time sitemap, flawless markup, zero technical friction. If you find that your articles consistently take more than 30 minutes to index despite having a news sitemap in place, likely a technical bottleneck or crawl budget issue is slowing the process. In these situations, engaging a <strong>specialized SEO agency</strong> can quickly unlock the situation: precise diagnosis of crawl logs, optimization of rendering architecture, auditing of structured markup and compliance with Google News's specific requirements. The investment pays off within weeks if you're operating in a sector where every hour's lead over competitors translates to thousands of additional visitors.</div></div> </div> <!-- FAQ --> <div class="section-card"> <h2>❓ Frequently Asked Questions</h2> <div class="faq-list"> <details class="faq-item"> <summary class="faq-question">Le sitemap news est-il obligatoire pour apparaître dans Google News ?</summary> <div class="faq-answer">Non, mais il accélère drastiquement l'indexation. Google peut découvrir vos articles via crawl classique ou liens externes, mais le sitemap news lui signale explicitement la fraîcheur et priorise le traitement. Sans lui, comptez plusieurs heures voire une journée pour l'indexation.</div> </details> <details class="faq-item"> <summary class="faq-question">Quelle est la différence entre sitemap XML classique et sitemap news ?</summary> <div class="faq-answer">Le sitemap news contient des balises spécifiques (<publication>, <publication_date>, <title>) et ne liste que les articles des 2 derniers jours (max 1000 URLs). Google le crawl beaucoup plus fréquemment qu'un sitemap classique — parfois toutes les 10-15 minutes pour les sites à forte autorité.</div> </details> <details class="faq-item"> <summary class="faq-question">Faut-il regénérer le sitemap news après chaque publication ?</summary> <div class="faq-answer">Idéalement oui, via un système automatisé (webhook, cron fréquent). Si vous publiez 20 articles par jour, une régénération horaire vous fait perdre jusqu'à 59 minutes d'avance sur chaque article. Les sites professionnels régénèrent toutes les 5-10 minutes ou en temps réel.</div> </details> <details class="faq-item"> <summary class="faq-question">Le balisage Schema NewsArticle est-il indispensable ?</summary> <div class="faq-answer">Pas strictement obligatoire, mais fortement recommandé. Il aide Google à extraire rapidement les métadonnées (auteur, date, titre) sans parser tout le HTML. Un article sans Schema peut s'indexer, mais le traitement prendra quelques minutes de plus — ce qui peut suffire à perdre une position dans Top Stories.</div> </details> <details class="faq-item"> <summary class="faq-question">Comment savoir si Google crawl mon sitemap news régulièrement ?</summary> <div class="faq-answer">Analysez vos logs serveur pour tracer les requêtes Googlebot sur l'URL du sitemap. Un site d'actualités actif devrait voir plusieurs crawls par heure. Si vous n'avez qu'un crawl par jour, Google ne vous considère pas comme prioritaire — probablement par manque de volume ou de qualité historique.</div> </details> </div> </div> <!-- Tags SEO --> <div class="seo-tags-block"> <span class="seo-tags-label">🏷 Related Topics</span> <div class="seo-tags"> <a href="/en/?q=indexation" class="seo-tag-pill">indexation</a> <a href="/en/?q=sitemap+news" class="seo-tag-pill">sitemap news</a> <a href="/en/?q=crawl+budget" class="seo-tag-pill">crawl budget</a> <a href="/en/?q=Schema+NewsArticle" class="seo-tag-pill">Schema NewsArticle</a> <a href="/en/?q=Google+News" class="seo-tag-pill">Google News</a> <a href="/en/?q=fra%C3%AEcheur+contenu" class="seo-tag-pill">fraîcheur contenu</a> <a href="/en/?q=extractabilit%C3%A9" class="seo-tag-pill">extractabilité</a> <a href="/en/?q=actualit%C3%A9s+SEO" class="seo-tag-pill">actualités SEO</a> </div> </div> <!-- Categories --> <div class="declaration-tags"> <a href="/en/c/contenu" class="tag" style="background: #10b98120; color: #10b981;">Content</a> <a href="/en/c/crawl-indexation" class="tag" style="background: #3b82f620; color: #3b82f6;">Crawl & Indexing</a> <a href="/en/c/ia-seo" class="tag" style="background: #a855f720; color: #a855f7;">AI & SEO</a> <a href="/en/c/javascript-technique" class="tag" style="background: #eab30820; color: #eab308;">JavaScript & Technical SEO</a> <a href="/en/c/search-console" class="tag" style="background: #4f46e520; color: #4f46e5;">Search Console</a> </div> <!-- Syntheses thematiques liees --> <!-- Autres declarations de la meme video YouTube --> <div class="section-card yt-same-video"> <h2> 🎥 From the same video <span class="yt-same-count">12</span> </h2> <p class="yt-same-intro"> Other SEO insights extracted from this same Google Search Central video · duration 58 min · published on 30/10/2019 </p> <div class="related-grid yt-same-grid"> <a href="/en/d/impact-du-bert-sur-le-referencement-naturel" class="related-item yt-same-item"> <div class="title">Faut-il optimiser son contenu pour BERT ou est-ce une perte de temps ?</div> <div class="meta"> <span class="yt-same-ts">⏱ 2:11</span> </div> </a> <a href="/en/d/youtube-comme-signal-dans-le-classement-de-recherche" class="related-item yt-same-item"> <div class="title">YouTube bénéficie-t-il d'un avantage SEO dans Google Search ?</div> <div class="meta"> <span class="yt-same-ts">⏱ 3:46</span> </div> </a> <a href="/en/d/probleme-d-indexation-post-bug-du-8-aout" class="related-item yt-same-item"> <div class="title">Problèmes d'indexation qui traînent : bug Google ou faille technique de votre site ?</div> <div class="meta"> <span class="yt-same-ts">⏱ 6:09</span> </div> </a> <a href="/en/d/comprehension-des-impressions-dans-search-console" class="related-item yt-same-item"> <div class="title">Comment Google comptabilise-t-il vraiment les impressions dans Search Console ?</div> <div class="meta"> <span class="yt-same-ts">⏱ 8:54</span> </div> </a> <a href="/en/d/utilisation-des-balises-hreflang" class="related-item yt-same-item"> <div class="title">Faut-il vraiment implémenter hreflang sur tous les sites multilingues ?</div> <div class="meta"> <span class="yt-same-ts">⏱ 11:36</span> </div> </a> <a href="/en/d/utilisation-correcte-des-balises-schema-org" class="related-item yt-same-item"> <div class="title">Peut-on vraiment tricher avec les données structurées pour obtenir des rich snippets ?</div> <div class="meta"> <span class="yt-same-ts">⏱ 18:42</span> </div> </a> <a href="/en/d/precision-du-nombre-de-pages-indexees" class="related-item yt-same-item"> <div class="title">Faut-il vraiment arrêter d'utiliser la commande site: pour compter vos pages indexées ?</div> <div class="meta"> <span class="yt-same-ts">⏱ 22:06</span> </div> </a> <a href="/en/d/impact-de-l-indexation-mobile-sur-le-contenu-non-adapte" class="related-item yt-same-item"> <div class="title">Les pages non mobile-friendly peuvent-elles vraiment survivre à l'indexation mobile-first ?</div> <div class="meta"> <span class="yt-same-ts">⏱ 28:38</span> </div> </a> <a href="/en/d/planification-du-budget-de-crawl" class="related-item yt-same-item"> <div class="title">Le budget de crawl se gère-t-il vraiment au niveau du serveur et non du dossier ?</div> <div class="meta"> <span class="yt-same-ts">⏱ 35:51</span> </div> </a> <a href="/en/d/valeur-des-liens-externes-vers-des-url-parametrees-bloquees" class="related-item yt-same-item"> <div class="title">Faut-il bloquer les URL paramétrées en robots.txt ou via les réglages Search Console ?</div> <div class="meta"> <span class="yt-same-ts">⏱ 43:40</span> </div> </a> <a href="/en/d/penalites-algorithmiques-et-recuperations" class="related-item yt-same-item"> <div class="title">Faut-il vraiment « réparer » une pénalité algorithmique pour retrouver son trafic ?</div> <div class="meta"> <span class="yt-same-ts">⏱ 49:39</span> </div> </a> <a href="/en/d/unique-et-contenu-reutilise-dans-les-sites-d-actualites" class="related-item yt-same-item"> <div class="title">Le contenu réutilisé dans les sites d'actualités : quelle est vraiment la limite avant la pénalité ?</div> <div class="meta"> <span class="yt-same-ts">⏱ 69:08</span> </div> </a> </div> <a href="https://www.youtube.com/watch?v=CxnLVWhc0Lc" target="_blank" rel="noopener" class="yt-same-source-link"> 🎥 Watch the full video on YouTube → </a> </div> <!-- Declarations similaires --> <div class="section-card"> <h2>Related statements</h2> <div class="related-grid"> <a href="/en/d/revolutionary-change-in-ai-powered-search" class="related-item"> <div class="title">Is AI really transforming how Google handles our SEO queries?</div> <div class="meta"> Nikola Todorovic · May 2026 · <span class="stars">★★★</span> </div> </a> <a href="/en/d/use-of-ai-in-google-search" class="related-item"> <div class="title">How is AI truly reshaping the ranking of results in Google Search?</div> <div class="meta"> Nikola Todorovic · May 2026 · <span class="stars">★★★</span> </div> </a> <a href="/en/d/the-impact-of-ai-summaries-and-ai-mode" class="related-item"> <div class="title">Will Google's AI Summaries Kill Traditional Organic Traffic?</div> <div class="meta"> Nikola Todorovic · May 2026 · <span class="stars">★★★</span> </div> </a> <a href="/en/d/human-interaction-and-expertise-in-content" class="related-item"> <div class="title">Does human expertise still play a crucial role in ranking against generative AI?</div> <div class="meta"> Martin Splitt · May 2026 · <span class="stars">★★★</span> </div> </a> <a href="/en/d/assessment-of-changes-in-google-search" class="related-item"> <div class="title">How does Google truly evaluate changes in its algorithm before deployment?</div> <div class="meta"> Nikola Todorovic · May 2026 · <span class="stars">★★★</span> </div> </a> <a href="/en/d/the-importance-of-valuable-content-for-seo" class="related-item"> <div class="title">Is AI really changing the rules for valuable content in SEO?</div> <div class="meta"> Nikola Todorovic · May 2026 · <span class="stars">★★★</span> </div> </a> </div> </div> <!-- Prev/Next --> <div class="prev-next"> <a href="/en/d/page-speed-score-complexity"> <div class="nav-label">« Previous</div> <div class="nav-title">Page Speed Score Complexity...</div> </a> <a href="/en/d/accuracy-of-the-number-of-indexed-pages" style="text-align: right;"> <div class="nav-label">Next »</div> <div class="nav-title">Accuracy of the Number of Indexed Pages...</div> </a> </div> <div class="back-link"> <a href="/en/" class="btn">« Back to results</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">💬 Comments <span class="comments-count">(0)</span></h3> <div class="comments-list" id="comments-list"> <p class="comments-empty" id="comments-empty">Be the first to comment.</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="8967"> <input type="hidden" name="lang" value="en"> <!-- 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">Name or alias *</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 (optional, not published)</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">Your comment *</label> <textarea id="comment-content" name="content" required maxlength="2000" rows="4"></textarea> <div class="comment-form-charcount"><span id="comment-chars">2000</span> characters remaining</div> </div> <div class="comment-form-footer"> <button type="submit" class="comment-submit-btn">Post comment</button> <span class="comment-form-notice">Comments are moderated before 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 = 'Awaiting 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">Get real-time analysis of the latest Google SEO declarations</h2> <p class="nl-inline-sub">Be the first to know every time a new official Google statement drops — with full expert analysis.</p> </div> <div class="nl-inline-action"> <form class="nl-inline-form" id="nl-inline-form" novalidate> <input type="email" name="email" placeholder="Your email address" required autocomplete="email"> <button type="submit">Subscribe for free</button> </form> <div class="nl-inline-privacy">No spam. Unsubscribe in one click.</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 = 'en'; var API_URL = 'https://seoclaims.com/api/subscribe'; var COOKIE = 'nl_subscribed'; var MSG = { success: 'You\'re in! You\'ll receive the next analyses.', already: 'You are already subscribed.', error: 'Something went wrong, please try again.', }; 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 collects, analyzes and translates <a href="/en/declarations">official Google statements</a> about search engine optimization, sourced from <a href="/en/articles">published articles</a> and <a href="/en/videos">YouTube videos</a> by Google Search Central. Each statement is enriched with <a href="/en/declarations">AI analysis</a>, classified by <a href="/en/declarations">SEO category</a> and attributed to its <a href="/en/speaker/john-mueller">author</a>. An essential tool for SEO professionals who want to know exactly what Google recommends.</p> </div> <div> <div class="footer-heading">Navigation</div> <nav class="footer-nav"> <a href="/en/declarations" class="footer-link">Statements</a> <a href="/en/labs/" class="footer-link">Labs SEO</a> <a href="/en/speaker/john-mueller" class="footer-link">Authors</a> <a href="/en/sitemap-declarations" class="footer-link">Sitemap</a> <a href="/en/rss.xml" class="footer-link footer-link-rss" rel="alternate" type="application/rss+xml"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 8 8" fill="#f26522" aria-hidden="true" style="vertical-align:-2px;margin-right:6px;"> <rect width="8" height="8" rx="1.5" fill="#f26522"/> <circle cx="2" cy="6" r="1" fill="#fff"/> <path d="M1 4a3 3 0 0 1 3 3h1a4 4 0 0 0-4-4z" fill="#fff"/> <path d="M1 2a5 5 0 0 1 5 5h1a6 6 0 0 0-6-6z" fill="#fff"/> </svg>RSS feed </a> <a href="/en/top-seo-agencies-france" class="footer-link">Top SEO Agencies</a> <a href="/en/legal" class="footer-link">Legal Notice</a> </nav> </div> <div> <div class="footer-heading">Resources</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="/en/google-tools" class="footer-link" style="color: #60a5fa; font-weight: 600;">All Google Tools →</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;">Semantic</span> </span> </summary> <nav class="footer-pillar-nav"> <a href="/en/c/ia-seo" class="footer-pillar-link"> <span>AI & SEO</span> <span class="footer-pillar-count">9673</span> </a> <a href="/en/c/contenu" class="footer-pillar-link"> <span>Content</span> <span class="footer-pillar-count">5585</span> </a> <a href="/en/c/nom-domaine" class="footer-pillar-link"> <span>Domain Name</span> <span class="footer-pillar-count">1943</span> </a> <a href="/en/c/pdf-fichiers" class="footer-pillar-link"> <span>PDF & Files</span> <span class="footer-pillar-count">497</span> </a> <a href="/en/c/discover-actualites" class="footer-pillar-link"> <span>Discover & News</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;">Technical</span> </span> </summary> <nav class="footer-pillar-nav"> <a href="/en/c/anciennete-historique" class="footer-pillar-link"> <span>Domain Age & History</span> <span class="footer-pillar-count">6840</span> </a> <a href="/en/c/crawl-indexation" class="footer-pillar-link"> <span>Crawl & Indexing</span> <span class="footer-pillar-count">3560</span> </a> <a href="/en/c/javascript-technique" class="footer-pillar-link"> <span>JavaScript & Technical SEO</span> <span class="footer-pillar-count">2358</span> </a> <a href="/en/c/search-console" class="footer-pillar-link"> <span>Search Console</span> <span class="footer-pillar-count">1848</span> </a> <a href="/en/c/performance-web" class="footer-pillar-link"> <span>Web Performance</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;">Authority</span> </span> </summary> <nav class="footer-pillar-nav"> <a href="/en/c/liens-backlinks" class="footer-pillar-link"> <span>Links & Backlinks</span> <span class="footer-pillar-count">2076</span> </a> <a href="/en/c/reseaux-sociaux" class="footer-pillar-link"> <span>Social Media</span> <span class="footer-pillar-count">541</span> </a> <a href="/en/c/penalites-spam" class="footer-pillar-link"> <span>Penalties & Spam</span> <span class="footer-pillar-count">515</span> </a> <a href="/en/c/algorithmes" class="footer-pillar-link"> <span>Algorithms</span> <span class="footer-pillar-count">416</span> </a> <a href="/en/c/recherche-locale" class="footer-pillar-link"> <span>Local Search</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">Latest Google statements on SEO</div> <div class="footer-popular-grid"> <a href="/en/d/interaction-humaine-et-expertise-dans-le-contenu" class="footer-popular-link"> <span class="footer-popular-meta"> <span class="footer-popular-date">May 2026</span> <span class="footer-popular-speaker">Martin Splitt</span> </span> <span class="footer-popular-text">L'expertise humaine reste-t-elle vraiment un facteur de classement face …</span> </a> <a href="/en/d/adaptation-de-google-search-a-la-competitivite-de-l-ia" class="footer-popular-link"> <span class="footer-popular-meta"> <span class="footer-popular-date">May 2026</span> <span class="footer-popular-speaker">Nikola Todorovic</span> </span> <span class="footer-popular-text">Comment Google Search restructure-t-il son moteur pour contrer l'offensi…</span> </a> <a href="/en/d/impact-des-resumes-d-ia-et-du-mode-ia" class="footer-popular-link"> <span class="footer-popular-meta"> <span class="footer-popular-date">May 2026</span> <span class="footer-popular-speaker">Nikola Todorovic</span> </span> <span class="footer-popular-text">Les résumés d'IA de Google vont-ils tuer le trafic organique traditionne…</span> </a> <a href="/en/d/importance-du-contenu-de-valeur-pour-le-seo" class="footer-popular-link"> <span class="footer-popular-meta"> <span class="footer-popular-date">May 2026</span> <span class="footer-popular-speaker">Nikola Todorovic</span> </span> <span class="footer-popular-text">L'IA transforme-t-elle vraiment les règles du contenu à valeur ajoutée e…</span> </a> <a href="/en/d/utilisation-de-l-ia-dans-google-search" class="footer-popular-link"> <span class="footer-popular-meta"> <span class="footer-popular-date">May 2026</span> <span class="footer-popular-speaker">Nikola Todorovic</span> </span> <span class="footer-popular-text">Comment l'IA transforme-t-elle réellement le classement des résultats da…</span> </a> <a href="/en/d/evaluation-des-changements-dans-google-search" class="footer-popular-link"> <span class="footer-popular-meta"> <span class="footer-popular-date">May 2026</span> <span class="footer-popular-speaker">Nikola Todorovic</span> </span> <span class="footer-popular-text">Comment Google évalue-t-il réellement les changements de son algorithme …</span> </a> <a href="/en/d/changement-revolutionnaire-de-la-recherche-par-ia" class="footer-popular-link"> <span class="footer-popular-meta"> <span class="footer-popular-date">May 2026</span> <span class="footer-popular-speaker">Nikola Todorovic</span> </span> <span class="footer-popular-text">L'IA révolutionne-t-elle vraiment la façon dont Google traite nos requêt…</span> </a> <a href="/en/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">Apr 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> </div> </div> <!-- ====== Row 4 : Copyright ====== --> <div class="footer-bottom"> <span>© 2026 SEO Declarations. All rights reserved.</span> <span>This site is not affiliated with Google. Statements presented are from public Google communications.</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="Get a complete real-time analysis of the latest Google SEO declarations"> <div class="nl-popup-box"> <button class="nl-popup-close" id="nl-popup-close" aria-label="Close">×</button> <div class="nl-popup-header"> <div class="nl-popup-badge">Stay ahead</div> <h3 class="nl-popup-title">Get a complete real-time analysis of the latest Google SEO declarations</h3> <p class="nl-popup-sub">Be the first to know every time a new official Google SEO statement drops, with full analysis included.</p> </div> <form class="nl-form nl-popup-form" data-lang="en" id="nl-popup-form"> <div class="nl-popup-input-group"> <input type="email" name="email" placeholder="Your email address" required autocomplete="email"> <button type="submit">Subscribe for free</button> </div> </form> <div class="nl-popup-trust"> <span class="nl-popup-trust-icon">🔒</span> <span>No spam. Unsubscribe in one click.</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 = 'en'; var API_URL = 'https://seoclaims.com/api/subscribe'; var COOKIE = 'nl_subscribed'; var SESSION_KEY = 'nl_popup_shown'; var MSG = { success: 'You\'re in! Check your inbox.', already: 'You are already subscribed.', error: 'Something went wrong, please try again.', }; 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": "Search engine for official Google SEO declarations, bilingual analysis and AI-enriched context.", "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="Ask the SEO assistant a question" title="Ask the SEO assistant a question"> <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">SEO Assistant</span> <span class="cbw-launcher-pulse" aria-hidden="true"></span> </button> <div id="cbw-panel" role="dialog" aria-label="SEO Assistant" aria-hidden="true"> <div class="cbw-head"> <div class="cbw-head-txt"> <strong>SEO Assistant</strong> <span>Powered by official Google declarations</span> </div> <div class="cbw-head-actions"> <a href="https://seoclaims.com/en/chatbot" class="cbw-icon-btn" title="Open full version" aria-label="Open full version"> <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="Close" aria-label="Close"> <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">Hi! Ask me anything about SEO and Google — I answer with cited sources from official declarations.</div> </div> <form class="cbw-form" id="cbw-form" autocomplete="off"> <textarea id="cbw-input" rows="1" placeholder="Ask a question..." maxlength="500" required></textarea> <button type="submit" id="cbw-send" aria-label="Send"> <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 = "en"; const T = {"sending":"...","send":"Send","sources":"Sources","rate_limit":"Limit of 10 questions per hour reached.","error":"Error. Please try again.","too_short":"Question too short."}; 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="Mobile navigation"> <a href="/en/" 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>Search</span> </a> <a href="/en/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>Categories</span> </a> <a href="/en/?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>Recent</span> </a> <a href="/" class="mobile-nav-item mobile-nav-lang"> <svg width="22" height="16" viewBox="0 0 640 480"> <rect width="213" height="480" fill="#002654"/><rect x="213" width="214" height="480" fill="#fff"/><rect x="427" width="213" height="480" fill="#ce1126"/> </svg> <span>FR</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>