Aller au contenu

Comment vérifier la hiérarchie des balises h1 à h6 avec Screaming Frog ?

Antoine Brisset
Antoine Brisset
Temps de lecture : 4 min
Comment vérifier la hiérarchie des balises h1 à h6 avec Screaming Frog ?
Photo by Stephanie LeBlanc / Unsplash

Table des matières

Est-ce que tu t'es déjà demandé comment faire pour identifier facilement les pages d'un site où la hiérarchie des balises h1, h2, h3, h4, h5 et h6 n'est pas respectée ?

Si la réponse à cette question est oui, l'astuce du jour va te plaire.

Petit rappel

Pour rappel, la bonne pratique consiste à imbriquer correctement les balises Hn : le h2 dépend hiérarchiquement du h1, le h3 dépend hiérarchiquement du h2, etc.

En gros, ça c'est OK ✅

– h1
– – h2
– – h2
– – – h3
– – – h4

Mais ça non ❌

– – h2
– – – – – h5
– – – – – – h6

Pourquoi ?

Parce que sur ce 2ème exemple il manque à la fois un h3 et un h4 avant le h5.

Bref, tu as saisi l'idée. Revenons-en à nos moutons.

Les outils existants

Pour vérifier la cohérence de ces titres "à la main", page par page, il existe deux solutions assez pratiques :

HeadingsMap
Web Developer Toolbar

En revanche, dès qu'il s'agit d'automatiser l'analyse, de le faire en masse, c'est beaucoup plus compliqué.

À ma connaissance, aucun logiciel ne propose cette fonctionnalité.

Je me suis donc retroussé les manches et j'ai trouvé la solution... avec Screaming Frog.

La solution en mode bulk avec Screaming Frog

Ce n'est plus un secret, tu sais que j'adore cet outil et en particulier sa feature "custom extraction".

C'est précisément celle-ci que je vais utiliser.

L'objectif, c'est de trouver l'expression XPath permettant de récupérer les Hn qui sont au mauvais endroit dans le code HTML.

Trouver les h1 et h2 mal positionnés

Pour le h1, c'est assez simple, il suffit de vérifier s'il est précédé d'une balise Hn, quelle qu'elle soit.

La requête XPath est la suivante :

//h1[preceding::h2 or preceding::h3 or preceding::h4 or preceding::h5 or preceding::h6]

Explications :

  • //h1 : je cherche tous les h1
  • [preceding::h2] : précédés dans le document d'un ou plusieurs h2
  • or preceding::h3 or preceding::h4 or preceding::h5 or preceding::h6 : ou précédés d'un ou plusieurs h3, h4, h5 ou h6

Et pour le h2, c'est la même idée, il suffit d'isoler les balises qui ne sont pas précédées d'un h1.

//h2[not(preceding::h1)]

Plus d'infos sur not ici et sur preceding ici.

Trouver les h3 à h6 mal positionnés

Naïvement, je me suis dit que je pouvais utiliser la même requête pour toutes les autres balises, de h3 à h6.

Par exemple, pour les h3 :

//h3[not(preceding::h2)]

Sauf qu'en réalité, c'est un poil plus complexe.

Prenons un 1er exemple.

– h1
– h1
– – – h3

Dans le cas ci-dessus, ça fonctionne, le XPath cible bien le h3 qui pose problème ✅

OK. Passons au 2ème exemple.

– – h2
– – h2
– h1
– – – h3

Ici, ça ne fonctionne pas ❌

Pourquoi ? On a pourtant un h3 qui suit immédiatement un h1, non ?

Oui. Mais comme avant le h1, on trouve un h2 (en gras dans l'exemple), le h3 en erreur n'est pas comptabilisé.

Conclusion : l'expression //h3[not(preceding::h2)] produit des faux négatifs.

Pour corriger cela, il faut donc ajouter un niveau de vérification supplémentaire, en s'assurant que le h3 qui arrive après le h1 n'est pas précédé d'un h2 ayant lui-même un h1 après lui.

(Désolé pour le mal de tête.)

Et donc, ça se traduit comment en XPath ?

//h1/following::h3[not(preceding::h2[count(./following::h1)=0])]

Explications :

  • //h1/following::h3 : je cherche les h3 situés après le(s) h1 dans le DOM
  • [not(preceding::h2[count(./following::h1)=0])] : ces h3 ne doivent pas être précédés d'un h2 n'ayant aucun h1 situé après lui

Si on veut être complet dans l'analyse des h3 en erreur, il faudra donc "chaîner" les expressions à l'aide d'un pipe (|) :

//h3[not(preceding::h2)]|//h1/following::h3[not(preceding::h2[count(./following::h1)=0])]

Bien entendu, plus on descend dans la hiérarchie, plus le nombre de vérifications va augmenter.

Prenons un nouvel exemple avec les h4 pour illustrer.

– – h2
– – – h3
– h2
– – – – h4
– – h2
– – – – h4

Si j'utilise uniquement l'expression //h4[not(preceding::h3)]|//h1/following::h4[not(preceding::h3[count(./following::h1)=0])] , c'est insuffisant.

Pourquoi ?

Parce qu'il n'y a pas de h1 dans la page. Du coup, les 2 balises h4 qui posent problème ne sont pas ciblées par mon XPath.

Il faut donc prévoir ce cas particulier supplémentaire avec //h2/following::h4[not(preceding::h3[count(./following::h2)=0])].

Récapitulatif

Allez, pour t'aider, un petit récap'.

h1 en erreur

//h1[preceding::h2 or preceding::h3 or preceding::h4 or preceding::h5 or preceding::h6]

h2 en erreur

//h2[not(preceding::h1)]

h3 en erreur

//h3[not(preceding::h2)]|//h1/following::h3[not(preceding::h2[count(./following::h1)=0])]

h4 en erreur

//h4[not(preceding::h3)]|//h1/following::h4[not(preceding::h3[count(./following::h1)=0])]|//h2/following::h4[not(preceding::h3[count(./following::h2)=0])]

h5 en erreur

//h5[not(preceding::h4)]|//h1/following::h5[not(preceding::h4[count(./following::h1)=0])]|//h2/following::h5[not(preceding::h4[count(./following::h2)=0])]|//h3/following::h5[not(preceding::h4[count(./following::h3)=0])]

h6 en erreur

//h6[not(preceding::h5)]|//h1/following::h6[not(preceding::h5[count(./following::h1)=0])]|//h2/following::h6[not(preceding::h5[count(./following::h2)=0])]|//h3/following::h6[not(preceding::h5[count(./following::h3)=0])]|//h4/following::h6[not(preceding::h5[count(./following::h4)=0])]

Une précision pour terminer.

Dans Screaming Frog, tu peux, au choix :

  • utiliser chaque XPath tel quel : tu retrouveras donc dans ton onglet Custom Extraction le contenu textuel de chacune des balises mal hiérarchisées
  • compter les balises en erreur avec la fonction count, par exemple pour les h3 ça donnerait :count(//h3[not(preceding::h2)]|//h1/following::h3[not(preceding::h2[count(./following::h1)=0])])
  • tester si oui ou non des balises sont en erreur avec la fonction boolean, par exemple pour les h3 ça donnerait : boolean(//h3[not(preceding::h2)]|//h1/following::h3[not(preceding::h2[count(./following::h1)=0])])
Comptage des h2 et h3 en erreur

Et voilà, y'a plus qu'à !

Screaming Frog

Antoine Brisset Twitter

Consultant SEO depuis 2010. Je traque les clics inutiles et automatise les tâches répétitives pour gagner du temps dans mon quotidien de travailleur du web.