Page vide : audit SEO des balises H1-H6 et contenus manquants

Guide pratique pour auditer et remédier aux pages « vides » sur PrestaShop : extraction H1–H6, crawl no‑JS/JS, corrections Smarty, requêtes SQL et priorisation.

Tableau d'audit SEO affichant l'analyse des balises H1-H6.

Table des matières :

  1. Balises H1–H6 : ce que Google “voit” quand votre page est vide
  2. Typologie des pages “vides” en e-commerce PrestaShop (8.1/8.2/9.x)
  3. Audit SEO industrialisé : crawler, extraction Hn, et détection des contenus manquants
  4. Corrections côté thème (Smarty) : rendre les H1 robustes et éviter les faux positifs
  5. Remédiation “contenu manquant” : requêtes SQL, contraintes de qualité, et flux ERP
  6. Contrôles post-correction : non-régression, indexation, et signaux “soft 404”
  7. Priorisation et stratégie : corriger ce qui impacte vraiment (et arrêter de “bricoler du H2”)

Balises H1–H6 : ce que Google “voit” quand votre page est vide

Sur un audit SEO, une « page vide » n’est pas forcément une page blanche au sens navigateur. C’est souvent une page dont le contenu principal (<main>) est inexistant, trop pauvre, ou non interprétable par un crawler : un <main> rempli de blocs décoratifs, un contenu injecté en JS non rendu côté bot, ou une page produit/catégorie qui n’expose que des gabarits sans texte. Dans ces cas, les balises H1–H6 deviennent un signal de secours : quand le texte manque, la structure de titres est parfois le seul indice thématique exploitable.

D’un point de vue HTML, les heading elements (<h1> à <h6>) définissent une hiérarchie et structurent le document (HTML Living Standard, section “Headings and sections”, WHATWG). En SEO, Google ne “récompense” pas une page parce qu’elle a un H2 ou un H3, mais utilise la structure pour comprendre la page, faciliter la lecture, et mieux relier le contenu à une intention. Autrement dit : sur une page riche, les Hn renforcent une organisation déjà claire ; sur une page pauvre, ils peuvent être le seul signal sémantique propre.

Le piège classique : confondre H1 (titre de la page) et logo + claim (souvent en H1 dans certains thèmes). Résultat : H1 dupliqué sur tout le site, et sur certaines pages « vides », aucune autre information utile. Sur PrestaShop, ce problème est souvent un mélange de dette front (thème) et de dette data (contenus non saisis), et il ne se corrige pas avec un “plugin SEO” magique : il faut instrumenter l’audit, corriger les templates, puis verrouiller la production de contenus.

Pour cadrer l’audit, gardez en tête une règle simple (utile en recette comme en production) : un H1 peut être “correct” tout en masquant une page vide. Par exemple :

  • H1 = “Chaussures de sécurité”, mais aucun texte explicatif, uniquement une grille produits → contexte faible sur des requêtes génériques.
  • H1 = “Marque X”, mais page “fabricant” vide + produits non disponibles → page souvent perçue comme inutile (risque soft 404).
  • H1 = “Mentions légales”, mais le contenu est injecté via un module tiers qui ne rend rien côté bot → page “légale” incomplète (et parfois problématique côté conformité).

Typologie des pages “vides” en e-commerce PrestaShop (8.1/8.2/9.x)

Sur PrestaShop 8.x (front-office majoritairement en Smarty) et PrestaShop 9.x (cœur modernisé basé sur Symfony, mais FO encore très souvent Smarty selon le thème), les pages vides en SEO se rencontrent surtout sur : catégories sans texte, pages CMS non renseignées, produits avec description courte/longue à NULL, pages de marque/fournisseur maigres, et résultats de recherche interne (ou pages de facettes) sans contenu éditorial. Vous pouvez avoir une page “visuellement correcte” (grille produits, pagination, filtres), mais zéro contexte sémantique.

Pour rendre l’audit exploitable, il est utile de classer les “pages vides” par symptômes (ce qui se voit dans un crawl) et par causes (ce qui se corrige). Exemple de typologie rapide :

Type de page “vide” Symptômes dans un crawl Causes fréquentes sur PrestaShop Risque SEO typique
Catégorie sans contenu H1 présent, main word count faible, beaucoup de liens/filtres Description non saisie, bloc CMS absent, template minimal Thin content, cannibalisation, faible pertinence
Produit incomplet H1 OK, description courte/longue vide, parfois avis/FAQ en JS Flux PIM/ERP incomplet, champs non mappés, traduction manquante Faible couverture requêtes, page peu différenciante
Marque / fournisseur maigre H1 = nom, aucun texte Données fournisseur non enrichies, page “listing” pure Faible valeur, indexation aléatoire
Recherche interne / facettes Beaucoup d’URLs, contenu quasi nul, titres répétitifs Paramètres, module de facettes, navigation à filtres Crawl budget, duplication, soft 404
Page rendue partiellement HTML tronqué, main incomplet, headings manquants Exception module, hook cassé, cache instable Page inutilisable pour Googlebot

Deuxième famille : pages cassées côté rendu mais pas forcément visibles immédiatement. Exemple : un module qui injecte un bloc via hook, déclenche une exception silencieuse, et vous retrouvez un <main> tronqué (ou un HTML incomplet) sur certaines routes. Pour la partie diagnostic « page blanche / HTML tronqué », il est plus pertinent de traiter le rendu et les erreurs serveur avant d’interpréter des signaux SEO : voir “Page vide HTML : détection d’erreurs de rendu serveur et CMS”.

Troisième famille : pages « vides » parce que le contenu principal est déporté côté client. Certains thèmes sur-optimisent en poussant du contenu en lazy-loading JS (FAQ, descriptions, avis) sans SSR. Les bots modernes rendent du JS, mais pas avec les mêmes contraintes de budget, de timeouts, ni de cohérence qu’un navigateur utilisateur. En e-commerce, ça se traduit par des pages indexées avec un H1 et des blocs navigationnels — et donc assimilées à du thin content.

À l’échelle d’un site francophone (FR/BE/CH par exemple), cette typologie se complique en multi-langue : une page peut être “pleine” en fr-FR et quasi vide en fr-BE (traductions manquantes), tout en restant indexable. Dans ce cas, votre audit H1–H6 doit segmenter par langue (et idéalement par boutique si multi-store), sinon vous sous-estimez le volume de pages pauvres.

Audit SEO industrialisé : crawler, extraction Hn, et détection des contenus manquants

Le bon audit « page vide » est d’abord un audit de crawl, pas un audit “au doigt mouillé”. Objectif : obtenir un dataset exploitable : URL, type (produit/catégorie/CMS), code HTTP, canonicals, meta title, word count, H1–H6, présence de <main>, et éventuellement rendu JS. Outils courants : Screaming Frog, Sitebulb, Oncrawl, ou un pipeline maison (curl + parsing). Sur PrestaShop, je recommande de faire deux passes :

  • Pass 1 (HTML brut) : sans rendu JS, pour voir ce que sort réellement le serveur (et ce que verra un bot en mode “no JS”).
  • Pass 2 (rendu JS) : uniquement sur un échantillon de templates suspects, sinon vous explosez votre temps de crawl.

Sur Screaming Frog, la mécanique minimale : activer l’extraction des headings, activer “Store HTML”, et définir des extractions personnalisées sur des sélecteurs fiables (main h1, #content h1, etc.). L’indicateur “Word Count” doit être interprété avec prudence (un menu peut “gonfler” artificiellement). Une stratégie robuste consiste à extraire le contenu textuel du <main> (ou de #content) et à calculer un “main word count” séparé.

Deux heuristiques simples qui font gagner du temps en tri :

  • H1 “hors contenu” : détectez si le H1 est dans un header global (ex. header h1) plutôt que dans main. Ce n’est pas “interdit” en HTML, mais en SEO e-commerce c’est souvent le symptôme d’un H1 sitewide.
  • Headings décoratifs : repérez les Hn qui ne contiennent que des pictos, des spans vides, ou du texte “UI” (“Filtres”, “Tri”, “Newsletter”). Sur une page pauvre, ces headings peuvent dominer l’analyse thématique.

Si vous automatisez, un parsing simple en Python suffit (à adapter : timeouts, user-agent, gestion des redirections, etc.) :

from bs4 import BeautifulSoup
import requests

html = requests.get(url, timeout=10).text
soup = BeautifulSoup(html, "lxml")
main = soup.select_one("main")
main_text = " ".join(main.stripped_strings) if main else ""
h1 = [h.get_text(" ", strip=True) for h in soup.select("h1")]
# Détection simple
is_thin = len(main_text.split()) < 150
has_h1 = len(h1) >= 1

Pour l’audit H1–H6, les patterns à remonter ne se limitent pas à “H1 manquant”. Les vrais problèmes sont : H1 non unique, H1 hors du main content (ex : header global), sauts de hiérarchie (H1 → H4), headings “vides” (icônes, spans), headings utilisés comme wrappers CSS, et headings générés par des modules (facettes, cross-selling) qui contaminent le plan.

Sur des sites volumineux, vous devez prioriser avec des métriques : % d’URLs indexables avec H1 manquant, corrélation avec pages ayant faible trafic, et surtout pages en soft-404 (Google peut considérer une page comme inutile même si elle renvoie 200). Une bonne pratique “audit industrialisé” consiste à taguer chaque URL avec un statut :

  • OK (H1 unique + main word count au-dessus de votre seuil),
  • Structure KO (H1 absent/dupliqué/hors main),
  • Donnée KO (templates OK mais texte manquant),
  • Rendu KO (HTML tronqué / rendu JS nécessaire / incohérences).

Cette segmentation évite le piège du backlog “SEO” où tout part dans la même colonne.

Corrections côté thème (Smarty) : rendre les H1 robustes et éviter les faux positifs

Sur PrestaShop, la majorité des problèmes de balises Hn vient du thème : H1 mis dans le header du layout, titre du produit en <div>, ou duplication via un module “builder”. Le correctif “propre” est d’assurer : (1) un H1 contextualisé dans le contenu principal, (2) une hiérarchie cohérente pour les sections, et (3) des fallbacks quand la donnée est manquante (sans masquer le problème).

Exemple typique : page catégorie. Beaucoup de thèmes affichent le nom de catégorie en H1, mais la description est optionnelle. Si la description est vide, la page devient une grille produits + filtres, donc “faible contexte”. Vous pouvez au moins garantir un H2 d’intro, et afficher une note éditoriale conditionnelle (ou un bloc CMS attaché). Côté Smarty, l’idée est d’éviter le H1 vide et de ne pas injecter un Hn uniquement décoratif :

{* category.tpl (PrestaShop 8.x/9.x thème Smarty) *}
<main id="content" class="category-page">
  {assign var=catName value=$category.name|strip_tags|trim}
  <h1>{$catName|escape:'htmlall':'UTF-8'}</h1>

  {if $category.description|strip_tags|trim}
    <section class="category-intro">
      <h2>Description</h2>
      <div class="rte-content">{$category.description nofilter}</div>
    </section>
  {else}
    {* fallback volontairement minimal : ne pas inventer du texte, mais signaler le vide *}
    <section class="category-intro is-empty" aria-hidden="true"></section>
  {/if}
</main>

Deux points importants. D’abord, le fallback “vide” ne doit pas être une rustine qui génère du texte artificiel : vous allez simplement déplacer le problème (thin content) vers du contenu générique dupliqué. Ensuite, faites attention aux modules qui réécrivent les templates ou surchargent des hooks : une correction dans themes/votretheme/templates/ peut être annulée par une surcharge ou par un “page builder”.

Dans un contexte e-commerce, un autre faux positif fréquent vient des pages produit : certains thèmes mettent le nom produit dans un div.product-title (stylé comme un H1) et utilisent un H1 ailleurs (souvent le logo). Dans ce cas, votre audit “voit” un H1, mais il ne correspond pas au produit. La correction consiste moins à “ajouter des H2” qu’à ré-aligner le DOM : le H1 doit être le nom produit, dans main, et les blocs annexes (avis, livraison, cross-sell) doivent descendre en H2/H3 sans “voler” le plan.

Si vous devez intervenir à ce niveau, sécurisez la prod avec une hygiène modules stricte (désinstallation propre, audit perf/sécurité) — voir “Modules PrestaShop : désinstallation propre, performances et sécurité en production”.

Remédiation “contenu manquant” : requêtes SQL, contraintes de qualité, et flux ERP

Si votre audit SEO des balises H1–H6 est “mauvais”, 50% du temps c’est le thème. Les 50% restants, c’est la donnée : descriptions non renseignées, CMS vides, traductions absentes, ou contenu tronqué sur certaines langues. Pour objectiver, partez de la base. Sur MySQL/MariaDB, ces requêtes donnent un premier inventaire (pré-requis : accès SQL, sauvegarde avant toute opération ; valable sur PrestaShop 8.x/9.x avec préfixe ps_ à adapter) :

-- Produits sans description longue (par langue)
SELECT pl.id_lang, pl.id_product
FROM ps_product_lang pl
WHERE (pl.description IS NULL OR TRIM(pl.description) = '')
  AND pl.id_shop = 1;

-- Catégories sans description (par langue)
SELECT cl.id_lang, cl.id_category
FROM ps_category_lang cl
WHERE (cl.description IS NULL OR TRIM(cl.description) = '')
  AND cl.id_shop = 1;

-- Pages CMS sans contenu
SELECT cl.id_lang, cl.id_cms
FROM ps_cms_lang cl
WHERE (cl.content IS NULL OR TRIM(cl.content) = '')
  AND cl.id_shop = 1;

Pour compléter l’analyse “page vide” côté catalogue, ajoutez souvent deux vues utiles :

  • Catégories indexables mais sans produits actifs (fréquent après un import, une rupture stock généralisée, ou un mauvais mapping d’activation).
  • Produits actifs mais descriptions vides dans une langue (effet “catalogue OK en FR, vide en EN/DE”, typique des déploiements internationaux).

Ensuite, vous devez décider : corriger à la source (PIM/ERP), ou corriger dans PrestaShop. Le “quick fix” (remplir à la main dans le BO) tient rarement sur des catalogues vivants. Sur des équipes structurées, la bonne approche est de remonter une contrainte dans le pipeline data : pas de publication si description < N caractères, ou si champs SEO (title/meta) manquants. Quand le catalogue est synchronisé, l’ERP/PIM doit devenir la source de vérité, sinon vous allez écraser vos contenus à la prochaine synchro. Sur ce sujet, l’architecture d’intégration et la notion de donnée unique sont déterminantes : “Intégration ERP : API, connecteurs et donnée unique en temps réel”.

Enfin, ne traitez pas toutes les pages de la même façon. Une catégorie “Marques A–Z” peut être volontairement minimaliste ; une page produit, non. Pour l’e-commerce, visez des seuils pragmatiques (à adapter selon concurrence et intention) :

  • Produit (requêtes concurrentielles) : description courte ≥ 300–500 caractères ou un bloc “bénéfices + usages + compatibilités” réellement utile.
  • Catégorie SEO générique : 150–250 mots de contexte unique (au moins), idéalement placé avant ou après la grille selon UX.
  • Marque / fournisseur : 80–150 mots (positionnement, gammes, éléments différenciants) + éventuellement une FAQ courte si pertinente.
  • CMS (livraison/retours/garanties) : contenu complet et à jour, surtout si la page est accessible depuis le tunnel d’achat (enjeu conversion + confiance).

Si vous manquez de temps, priorisez par marge, trafic, et profondeur de crawl (pages proches de la home en premier). Une règle efficace en boutique réelle : commencez par 20% des pages qui font 80% du chiffre (top catégories, top produits, pages d’aide consultées), puis élargissez.

Contrôles post-correction : non-régression, indexation, et signaux “soft 404”

Après correction, ne vous contentez pas d’un crawl unique. Mettez en place un contrôle récurrent (hebdo ou à chaque release). Côté dev, le plus simple est un test de non-régression sur un échantillon d’URLs critiques (produits top ventes, catégories SEO, CMS légaux). Avec Playwright/Puppeteer, vous pouvez vérifier que main h1 existe, que la chaîne n’est pas vide, et que le main text dépasse un seuil :

// Playwright (Node.js)
const { test, expect } = require('@playwright/test');

test('Produit : H1 et contenu minimal', async ({ page }) => {
  await page.goto(process.env.URL_PRODUIT, { waitUntil: 'domcontentloaded' });
  const h1 = await page.locator('main h1').innerText();
  expect(h1.trim().length).toBeGreaterThan(3);
  const mainText = await page.locator('main').innerText();
  expect(mainText.split(/\s+/).length).toBeGreaterThan(120);
});

Côté SEO, surveillez Google Search Console : pages exclues “Explorée, actuellement non indexée”, pics de “Soft 404”, et anomalies de snippets. Le “soft 404” correspond typiquement à une page qui renvoie 200 mais ressemble, pour Google, à une page introuvable ou sans valeur (ex. page catégorie vide, recherche interne sans résultat, filtre menant à zéro produit). La documentation d’aide Google sur le sujet est ici.

Dans la pratique, ajoutez aussi des contrôles simples côté crawl :

  • Comparer avant/après : nombre d’URLs indexables avec main_word_count < seuil.
  • Vérifier la stabilité des H1 : un H1 qui change selon le cache, une A/B test, ou un module, est un signal de dette front.
  • Contrôler les templates : si 80% des pages vides sont “category.tpl”, vous n’êtes pas sur un problème éditorial, mais sur un problème de modèle + process.

Enfin, ne séparez pas “page vide” et performance : des pages rendues partiellement à cause de timeouts back (TTFB élevé, erreurs intermittentes, cache mal réglé) peuvent se transformer en pages vides côté bot. Si vous constatez des inconsistances selon les crawls, commencez par stabiliser le serveur et le cache, puis refaites l’audit SEO. Pour les bases : “SEO PrestaShop : roadmap 3 mois audit, contenu, performance et popularité” et “Core Web Vitals : actions concrètes pour améliorer LCP, INP et CLS”.

Priorisation et stratégie : corriger ce qui impacte vraiment (et arrêter de “bricoler du H2”)

Dans un backlog, l’audit des balises H1–H6 et des contenus manquants doit être priorisé par risque SEO et valeur business, pas par esthétique du code HTML. Typiquement : pages indexables (canonicals cohérents, pas de noindex) + requêtes stratégiques + fort potentiel de trafic. Les corrections sur pages paginées, tri, facettes, recherche interne, doivent être encadrées par une stratégie d’indexation (canonicals, noindex, paramètres) sinon vous allez “améliorer” des pages qui ne devraient pas ranker.

Évitez deux antipatterns. Le premier : ajouter un H2 “Description” vide partout, pour “faire joli”. Ça n’ajoute aucun contenu, et vous fabriquez un bruit de crawl. Le second : générer automatiquement du texte générique (ex : “Découvrez nos produits de la catégorie X”) sur des centaines de pages. C’est du contenu dupliqué à faible valeur, et c’est souvent contre-productif en qualité perçue.

Une approche plus saine est un plan en trois niveaux : (1) corriger les templates pour garantir un H1 utile et une structure stable, (2) traiter les pages réellement vides avec un plan de contenu ou une désindexation raisonnée, (3) industrialiser (tests + monitoring) pour éviter la régression.

Concrètement, pour décider “quoi faire en premier”, vous pouvez scorer chaque type de page avec une grille simple :

  • Impact (fort si page cible requêtes génériques / marge élevée / proche de la home),
  • Risque (fort si beaucoup d’URLs similaires → duplication / facettes / soft 404),
  • Effort (faible si correction template, moyen si enrichissement éditorial, fort si refonte flux PIM/ERP).

Vous obtenez très vite une feuille de route pragmatique : corriger 1–2 templates structurants (catégorie/produit), puis enrichir un lot de pages prioritaires, tout en désindexant ou cadrant les pages “à risque” (recherche interne, facettes sans valeur).

Si vous cherchez une checklist pure “contenu vide” (au-delà des Hn), la ressource la plus directe est “Contenu de page vide : checklist d’audit et plan de remédiation”.


À lire aussi