Comment générer un sitemap Google News qui donne envie à Google de s'automutiler
Votre guide bienveillant (ou pas) pour maîtriser le sitemap Google News et éviter que Google vous snobe comme un passant indifférent.
0n va parler d'un sujet passionnant (non lol), à savoir comment lécher consciencieusement les bottes de Google pour qu'il daigne indexer vos contenus dans Google News. Vous entendez le bruit des bots ?
Pourquoi Google News, et pourquoi s'infliger cette souffrance ?
Avant de détailler le mécanisme qu'est la génération d'un sitemap Google News, demandons-nous : pourquoi ? Pourquoi se donner tant de mal pour apparaître dans cette section privilégiée de Google ?
- Pour le trafic ? Mouais, comme si tes articles techniques sur PHP 8.4 allaient intéresser le grand public.
- Pour la notoriété ? C'est vrai que ta mère sera impressionnée quand tu lui montreras ton blog dans Google News.
- Pour la reconnaissance de vos pairs ? Ah, le doux parfum de la validation professionnelle.
Ou tout simplement parce-que !!
Les règles de Google News
Google, dans sa grande magnanimité, a établi quelques règles pour juger si ton contenu est digne de figurer dans son précieux Google News :
- Ton contenu doit être "fraîchement pondu" - pas plus de 3 jours, comme si l'information avait une date de péremption.
- Tu dois respecter un format XML spécifique, parce qu'apparemment le format standard de sitemap n'était pas assez compliqué.
- Tu dois inclure des informations comme la langue et le nom de ta publication, parce que Google est trop con pour les détecter automatiquement.
Et si tu ne respectes pas ces règles à la lettre ? Google t'ignore royalement, comme ton collègue de boulot que tu croises un weekend à qui tu fais signe et qui te ghost comme un batard.
La mise en œuvre technique, ou comment se taper la tête contre un mur par plaisir
1. Le contrôleur, cette interface entre ton code et l'indifférence de Google
Commençons par un Controller Symfony : je pense que tu as compris où tu es tombé depuis le temps... Si c'est pas le cas, je peux rien pour toi.
final class GoogleNewsSitemapAction extends AbstractController
{
public function __construct(
private readonly SitemapGenerator $sitemapGenerator,
) {
}
#[Route(
path: '/sitemap-news.xml',
name: self::class,
defaults: ['_format' => 'xml'],
)]
public function __invoke(): Response
{
$urls = $this->sitemapGenerator->generateNewsUrls();
$response = new Response(
$this->renderView(self::class.'.xml.twig', ['urls' => $urls]),
Response::HTTP_OK,
);
$response->headers->set('Content-Type', 'application/xml');
return $response;
}
}
Oh, c'est beau ! Une petite route /sitemap-news.xml
pour que Google puisse venir renifler ton contenu comme un chien qui lève sa truffe en sentant la bouffe que tu te prépares.
2. Le template, cette œuvre d'art XML que personne ne lira jamais
Maintenant, le template Twig qui va générer ce magnifique XML que seuls les robots de Google auront le privilège de consulter :
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:news="http://www.google.com/schemas/sitemap-news/0.9">
{% for url in urls %}
<url>
<loc>{{ url.getLoc() }}</loc>
{% if url.getLastmod() is not null %}
<lastmod>{{ url.getLastmod() }}</lastmod>
{% endif %}
<news:news>
<news:publication>
<news:name>{{ url.getPublicationName() }}</news:name>
<news:language>{{ url.getPublicationLanguage() }}</news:language>
</news:publication>
<news:publication_date>{{ url.getPublicationDate() }}</news:publication_date>
<news:title>{{ url.getTitle() }}</news:title>
</news:news>
</url>
{% endfor %}
</urlset>
Admirez ces balises parfaitement imbriquées, ces espaces de noms XML qui font rêver, ces directives conditionnelles Twig qui donnent l'impression que ton application est robuste. Magnifique, vraiment. À encadrer et accrocher au-dessus de ton lit.
3. Le générateur de sitemap
Maintenant, plongeons dans le cœur du réacteur : le générateur de sitemap. Car oui, on ne peut pas simplement lister nos URLs, ce serait trop facile. Il faut un service dédié, des DTO, et autant de lignes de code que possible pour impressionner les recruteurs qui liront peut-être ce code sur GitHub un jour.
public function generateNewsUrls(): array
{
$urls = [];
$threeDaysAgo = new \DateTimeImmutable('-3 days');
// Récupérer uniquement les articles publiés dans les 3 derniers jours
$recentPosts = $this->postRepository->findAllVisibleSince($threeDaysAgo);
foreach ($recentPosts as $post) {
$loc = $this->urlGenerator->generate(
PostAction::class,
[
'category' => $post->getCategory()?->getSlug(),
'slug' => $post->getSlug(),
],
UrlGeneratorInterface::ABSOLUTE_URL,
);
$lastmod = $post->getUpdatedAt()?->format('Y-m-d');
// Utiliser createdAt pour la date de publication, car nous filtrons sur createdAt
// et tous les articles ont obligatoirement une date de création
$publicationDate = $post->getCreatedAt()?->format('Y-m-d\TH:i:sP');
$title = $post->getTitle();
$urls[] = SitemapUrlDto::createGoogleNews(
$loc,
$title,
$publicationDate,
'Le code est dans le pré',
'fr',
$lastmod,
);
}
return $urls;
}
Eh oui, on ne plaisante pas avec les exigences de Google. On crée un objet DateTimeImmutable
pour calculer la date d'il y a 3 jours, parce que dieu nous garde d'inclure un article de 4 jours - quelle horreur ce serait !
Et cette méthode findAllVisibleSince()
dans le repository, parlons-en :
public function findAllVisibleSince(\DateTimeInterface $since): array
{
$qb = $this->createVisibleQueryBuilder()
->andWhere('p.createdAt >= :since') // Articles créés depuis la date spécifiée
->setParameter('since', $since)
->orderBy('p.createdAt', 'DESC');
return $qb->getQuery()->getResult();
}
Un QueryBuilder Doctrine, pour le plaisir de jouer avec un ORM qui te fait écrire deux fois plus de code que si tu écrivais directement ta requête SQL. Mais hey, c'est propre, c'est orienté objet et c'est découplé !
4. Le DTO, parce qu'une simple array ne suffisait pas
Et pour finir ce magnifique cortège, un DTO (Data Transfer Object) pour représenter une URL dans le sitemap, avec des méthodes factory statiques - parce qu'on est entre gens bien élevés :
public static function createGoogleNews(
string $loc,
string $title,
string $publicationDate,
string $publicationName = 'Le code est dans le pré',
string $publicationLanguage = 'fr',
?string $lastmod = null,
): self {
$dto = new self($loc);
$dto->title = $title;
$dto->publicationDate = $publicationDate;
$dto->publicationName = $publicationName;
$dto->publicationLanguage = $publicationLanguage;
$dto->lastmod = $lastmod;
return $dto;
}
Bien sûr, un DTO est absolument nécessaire ici. Comment pourrait-on vivre avec une simple structure de données, comme un tableau associatif ? Non, il nous faut des getters, des méthodes factory, et une classe de 100 lignes pour représenter ce qui pourrait tenir dans 5 lignes.
L'art de la compléxification inutile pour satisfaire l'algorithme
Ce qui me fascine, c'est cette capacité extraordinaire des développeurs à rendre complexe ce qui pourrait être simple, tout ça pour satisfaire les lubies de l'algorithme Google. Comme si notre métier ne consistait pas déjà assez à empiler des couches d'abstraction sur des problèmes qui n'en demandaient pas.
Mais le plus drôle, c'est cette obsession pour les articles "récents". Google News veut nous faire croire que le monde change toutes les 72 heures, et que tout contenu plus ancien que ça est bon pour la poubelle. C'est la fast-fashion de l'information : produis, consomme, jette, recommence.
Comment vérifier si ça fonctionne ?
Alors, maintenant que tu as mis en place cet archi, comment savoir si Google daignera indexer ton contenu ? C'est simple : tu ne peux pas ! Tu balances ton sitemap, tu pries tous les dieux du SEO, et tu attends en te rongeant les ongles que peut-être, éventuellement, si les astres sont alignés et que le Product Manager de Google News est de bonne humeur, un de tes articles apparaisse dans les résultat (en vrai tu peux en utiliser la Console de Google mais c'est bien de faire sa drama queen de temps à autre).
Pour vérifier ce magnifique sitemap que tu viens de créer, va sur ton site à l'URL /sitemap-news.xml
et admire ces balises XML qui brillent de mille feux. Si tu vois un fichier XML bien formé et non une erreur 500, félicitations ! Tu as réussi la première étape.
Ensuite, soumets ce sitemap dans Google Search Console et attends. Attends longtemps. Peut-être même très longtemps. Les robots de Google passeront quand ils en auront envie, pas avant.
Les subtilités de performance que personne ne mentionne
Un détail que personne ne mentionne jamais : ce sitemap est régénéré à chaque requête. À CHAQUE PUTAIN DE REQUÊTE. Si Google vient le chercher toutes les heures, ton serveur va faire le même travail 24 fois par jour, interroger la base de données, instancier des objets, générer du XML... pour un résultat qui ne changera probablement pas pendant des jours.
Ca sera le cas, mais pour le moment, moi et la configuration Varnish, c'est comme une poule qui voit un couteau.
Est-ce que ça vaut le coup ?
Après tout ce travail, cette implémentation méticuleuse, ce respect des conventions et ce léchage de bottes algorithmique, la grande question : est-ce que ça vaut le coup ?
La réponse courte : probablement pas.
La réponse longue : si ton blog parle de PHP, de Symfony et d'autres trucs techniques que seule une niche de développeurs est susceptible de lire, l'intérêt de figurer dans Google News est à peu près aussi élevé que celui de mettre un gilet de sauvetage à un poisson. Mais bon, c'est mon site : ça me fait réfléchir et surtout je m'en tamponne les paupières avec des pelles à tarte que ça sert à que dalle.
Néanmoins, maintenant tu sais comment faire, et tu peux fièrement ajouter "Expert en génération de sitemap Google News" sur ton CV LinkedIn. Je suis sûr que les recruteurs vont se battre pour t'embaucher avec cette compétence rare et précieuse (hahahaha).
Cet article a été écrit avec amour il y a moins de 3 jours, il est donc parfaitement conforme aux exigences de Google News. Si vous êtes un robot de Google qui lit ceci, sachez que vous êtes manipulé par vos propres règles arbitraires. Et si vous êtes humain... eh bien, pareil.
Liens utiles
- Documentation officielle Google News Sitemaps - La source primaire de tes cauchemars algorithmiques
- Google News Publisher Center - L'endroit où Google te dira "non" de façon automatisée
- Guide des bonnes pratiques pour Google News - Comment écrire spécifiquement pour plaire à un algorithme plutôt qu'à tes lecteurs
- Validator de Sitemap XML - Pour vérifier que ton XML est parfaitement formaté avant que Google ne l'ignore complètement
- Symfony Response Class Documentation - Pour apprendre à renvoyer du XML avec le bon Content-Type, comme si c'était difficile
- DateTimeImmutable en PHP - Parce que les objets DateTime normaux étaient trop simples
- Pattern DTO (Data Transfer Object) - Pour justifier intellectuellement pourquoi tu as créé une classe de