# DF Faceted SEO — Recherche à facettes et SEO PrestaShop

> DF Faceted SEO transforme la recherche à facettes de PrestaShop en levier SEO durable et accélère vos pages catégorie de 10 à 30 fois grâce à un index dénormalisé. Cette…

- Page: <https://www.datafirefly.com/documentation/dffacetedseo/>
- Langue: fr
- Mis à jour le: 2026-06-29
- Autres langues: [en](https://www.datafirefly.com/en/documentation/dffacetedseo/index.md), [es](https://www.datafirefly.com/es/documentation/dffacetedseo/index.md), [de](https://www.datafirefly.com/de/documentation/dffacetedseo/index.md), [it](https://www.datafirefly.com/it/documentation/dffacetedseo/index.md), [pl](https://www.datafirefly.com/pl/documentation/dffacetedseo/index.md), [pt](https://www.datafirefly.com/pt/documentation/dffacetedseo/index.md), [nl](https://www.datafirefly.com/nl/documentation/dffacetedseo/index.md)
- Index: <https://www.datafirefly.com/documentation/llms.txt>

DF Faceted SEO transforme la recherche à facettes de PrestaShop en levier SEO durable et accélère vos pages catégorie de 10 à 30 fois grâce à un index dénormalisé. Cette documentation couvre l'installation, la configuration des règles d'indexation, la création de landing pages SEO et l'exploitation des statistiques de combinaisons populaires.

## Présentation

Le module natif `ps_facetedsearch` génère mécaniquement une URL pour chaque combinaison de filtres possible. Sur un catalogue de quelques milliers de produits avec cinq facettes, cela représente des millions d'URLs que Google explore, diluant votre budget de crawl et votre PageRank entre des pages quasi identiques.

DF Faceted SEO résout ce problème en parallèle de deux manières :

- **Indexation intelligente** : des règles métier décident quelles combinaisons sont indexables, lesquelles reçoivent `noindex follow`, et où pointe le canonical.
- **Landing pages SEO dédiées** : pour vos combinaisons à fort potentiel commercial (par exemple « chaussures rouges taille 42 »), créez des pages d'atterrissage avec URL propre, H1, meta et contenus personnalisés par langue.

En bonus, le moteur de recherche du module remplace le moteur natif par un système beaucoup plus rapide basé sur un index dénormalisé et un cache deux niveaux.

## Pré-requis

- PrestaShop 8.0 à 9.x
- PHP 8.1 ou supérieur
- MySQL 5.7 ou MariaDB 10.3 minimum
- URLs simplifiées activées (_Préférences → SEO et URLs_)
- Permissions standards pour création de tables MySQL

## Installation

1. Téléversez l'archive ZIP via _Modules → Module Manager → Téléverser un module_.
2. Cliquez sur **Installer**. Le module crée automatiquement 10 tables `ps_dffacetedseo_*` et 5 onglets sous _Améliorer_.
3. Allez dans _Améliorer → DF Faceted SEO → Tableau de bord_.
4. Cliquez sur **Reconstruire l'index**. _Cette étape est obligatoire la première fois_ : sans index, le moteur de recherche du module n'a aucune donnée à exploiter.
5. Videz le cache PrestaShop : _Paramètres avancés → Performance → Vider le cache_.

Sur un catalogue de 50 000 produits, la reconstruction de l'index prend typiquement entre 2 et 5 minutes. Le module insère les lignes par lots de 500.

## Premiers pas — Tableau de bord

Le tableau de bord (_Améliorer → DF Faceted SEO_) affiche six tuiles statistiques :

- **Règles actives** : nombre de règles d'indexation activées
- **Landing pages** : nombre de pages d'atterrissage SEO créées
- **Produits dans l'index** : nombre de produits indexés (doit être proche du total catalogue)
- **Lignes dans l'index** : nombre de couples (produit, valeur de filtre) — c'est la table dénormalisée
- **Entrées en cache** : nombre de requêtes mises en cache
- **Combinaisons populaires** : nombre de combinaisons de filtres observées

Sous les tuiles, deux blocs d'opérations :

- **Reconstruire l'index** : utile après une grosse modification catalogue (import en masse, changement de structure d'attributs)
- **Vider le cache** : utile après une modification de règles ou de paramètres

## Règles d'indexation

Les règles décident, pour chaque combinaison de filtres visitée, quelle balise `robots` et quel `canonical` sont envoyés au navigateur et à Google. Une règle a un **scope** (zone d'application) et une **politique** (décision).

### Scopes disponibles

- **Global** : s'applique à toutes les pages facettées du catalogue
- **Catégorie spécifique** : s'applique uniquement aux pages d'une catégorie donnée
- **Groupe d'attributs** : s'applique aux combinaisons contenant un groupe précis (par exemple toutes les pages où Couleur est filtrée)
- **Feature** : idem, pour une caractéristique produit
- **Marque** : idem, pour une marque (manufacturer)
- **Fourchette de prix** : s'applique aux pages filtrées sur une plage tarifaire donnée

### Politiques disponibles

- **Index, follow** : page indexable, canonical pointant sur elle-même normalisée
- **Noindex, follow** : page non indexée, mais les liens sont suivis (recommandé pour les combinaisons rares)
- **Canonical parent** : page accessible mais le canonical pointe sur la catégorie parente (la valeur SEO est transférée)
- **Canonical self normalisé** : canonical sur la page elle-même avec les filtres triés et regroupés (élimine les doublons d'URL pour la même combinaison)

### Chaîne de priorité

Le module évalue les règles de la **plus spécifique à la plus générique**. Concrètement, pour une page de la catégorie Chaussures filtrée par couleur :

1. Le module cherche d'abord une règle scope `category` sur Chaussures
2. Si elle existe et matche, elle est appliquée
3. Sinon il cherche une règle scope `attribute_group` sur Couleur
4. Sinon il remonte vers la règle globale
5. Si aucune règle ne matche, la politique par défaut du tableau de bord est appliquée

### Champs avancés d'une règle

- **Maximum de filtres indexables** : si la combinaison contient plus de filtres que cette limite, la politique passe automatiquement en `noindex follow`. Exemple : 2 filtres maximum sur les chaussures (couleur + taille indexées, mais pas couleur + taille + matière + saison).
- **Whitelist de valeurs** : IDs de valeurs autorisées (séparés par virgules). Une combinaison contenant uniquement des valeurs de la whitelist est indexable. Exemple : whitelister les couleurs rouge, noir, blanc, bleu — les couleurs rares comme « vert pomme » ne seront pas indexées.
- **Blacklist de valeurs** : l'inverse. Toute combinaison contenant une valeur blacklisée tombe automatiquement en `noindex`.
- **Minimum de produits** : si la combinaison ne retourne pas au moins ce nombre de produits, elle passe en `noindex`. Évite d'indexer des pages presque vides.
- **Priorité** : entier. En cas de conflit entre deux règles du même scope, la priorité la plus haute gagne.

Stratégie recommandée pour démarrer : créez une règle _globale_ avec politique `canonical parent` et maximum 1 filtre indexable, puis ajoutez progressivement des règles plus spécifiques pour ouvrir l'indexation des combinaisons à fort potentiel.

## Landing pages SEO

Les landing pages sont des pages d'atterrissage dédiées à des combinaisons de filtres stratégiques. Elles ont leur propre URL propre, leur propre H1, leurs propres meta, et un contenu rédactionnel par langue.

### Créer une landing page

1. Allez dans _Améliorer → DF Faceted SEO → Landing pages_
2. Cliquez sur **Ajouter**
3. Section **Ciblage** : choisissez la catégorie et éventuellement la marque concernée
4. Section **Affichage** : tri par défaut, direction, activation, indexation, priorité
5. Section **Combinaison de filtres** : ajoutez les filtres qui composent la combinaison (groupe d'attributs et valeurs, feature, ou marque). Exemple : Couleur = Rouge ET Taille = 42.
6. Onglets multilingues : renseignez pour chaque langue le nom interne, le slug d'URL, le H1, le meta title, la meta description, le contenu d'intro et le contenu d'outro.
7. Sauvegardez

### Structure d'URL

L'URL d'une landing page suit le motif :

```
https://votre-domaine.com/landing/votre-slug
https://votre-domaine.com/en/landing/votre-slug
https://votre-domaine.com/fr/landing/votre-slug
```

Le préfixe de langue est automatiquement géré par le routeur PrestaShop dès que les URLs simplifiées sont activées et que plusieurs langues sont actives sur la boutique.

Si vous avez une 404 sur l'URL d'une landing, vérifiez dans cet ordre : URLs simplifiées activées, `.htaccess` régénéré (bouton Sauvegarder en bas de SEO et URLs), cache vidé, landing active dans le formulaire, hook `moduleRoutes` bien attaché au module dans _Modules → Positions_.

### Contenu rédactionnel

Pour chaque langue, vous disposez de deux blocs HTML riches :

- **Intro** : affiché au-dessus de la grille de produits. Idéal pour un paragraphe d'introduction SEO de 150 à 300 mots avec vos mots-clés cibles.
- **Outro** : affiché sous la grille. Idéal pour des éléments de réassurance, des guides d'achat, des FAQ.

### JSON-LD automatique

Chaque landing page injecte automatiquement deux blocs JSON-LD dans la page :

- **BreadcrumbList** : Accueil → Catégorie → Landing
- **Product** : un bloc Product par produit affiché (nom, prix, image, URL, disponibilité)

Vous obtenez automatiquement les rich snippets Google sans configuration supplémentaire.

## Statistiques des combinaisons populaires

Le module enregistre automatiquement, dans la table `ps_dffacetedseo_combination_log`, chaque combinaison de filtres réellement visitée par vos clients : signature, nombre de hits, dernière vue.

### Exploiter les statistiques

1. Allez dans _Améliorer → DF Faceted SEO → Statistiques_
2. Filtrez par catégorie, nombre minimum de hits, limite d'affichage
3. Triez par hits décroissants
4. Repérez les combinaisons à plus de 50 hits par semaine
5. Cliquez sur **Promouvoir** dans la colonne action
6. Le formulaire de landing page s'ouvre **pré-rempli** avec la combinaison de filtres
7. Vous n'avez plus qu'à renseigner le contenu rédactionnel et sauvegarder

### Maintenance

Le bas de la page Statistiques propose un bouton _Purger les anciennes données_ avec un champ « jours à conserver ». Recommandé : purger tous les 90 jours pour éviter une croissance illimitée de la table.

## Paramètres globaux

Le tableau de bord propose 11 paramètres globaux regroupés en 3 sections.

### Indexation

- **Politique par défaut** : politique appliquée quand aucune règle ne matche
- **Maximum de filtres indexables** : valeur globale (peut être surchargée par règle)
- **Minimum de produits par combinaison** : seuil global pour considérer une page indexable

### Performance

- **TTL du cache (secondes)** : durée de vie d'une entrée en cache. Défaut : 3600 (1 heure). Augmentez à 86400 (24 h) en production stable.
- **Masquer les filtres vides** : si activé, les valeurs avec 0 résultat sont cachées dans le panneau de filtres
- **Limite de résultats par page** : pagination produits

### URLs

- **Préfixe des URLs de landings** : par défaut `landing`. Le motif de route est défini en dur dans le hook `moduleRoutes` du module et utilise ce préfixe.

## Canonical intelligent

Sur chaque page facettée, le module calcule le canonical optimal :

- Combinaison qui matche une landing existante : canonical = URL pretty de la landing
- Combinaison indexable selon les règles : canonical = self normalisé (filtres triés et regroupés)
- Combinaison non indexable selon les règles : canonical = catégorie parente
- Page de catégorie sans filtre : canonical = self standard

La normalisation regroupe les valeurs par groupe et trie les groupes par ID. Deux URLs visuellement différentes mais sémantiquement identiques (par exemple ordre des paramètres GET différent) reçoivent le même canonical.

## Moteur de filtres haute performance

Le moteur s'appuie sur la table `ps_dffacetedseo_index` : une ligne par couple (produit, type de filtre, valeur). La recherche se transforme en une intersection d'ensembles d'identifiants produits.

### Cache deux niveaux

- **Niveau 1 : mémoire (in-process)**. Évite de retaper la même requête deux fois dans la même page.
- **Niveau 2 : base de données (table ps_dffacetedseo_cache)**. Persiste les résultats entre les requêtes avec TTL.

### Invalidation automatique

Le module écoute les hooks `actionProductSave`, `actionProductDelete` et `actionCategoryUpdate`. Chaque fois qu'un produit est sauvegardé, son entrée dans l'index est régénérée et toutes les entrées de cache liées à ce produit sont invalidées.

### AJAX et UX

Le panneau de filtres front est entièrement piloté en AJAX :

- Debounce de 250 ms sur les changements de filtres
- `pushState` pour mettre à jour l'URL sans recharger la page
- Mise à jour en temps réel des balises `canonical` et `robots` dans la tête du document
- Scroll fluide vers la grille de produits après mise à jour
- Chips actifs cliquables pour retirer un filtre individuel
- Slider de prix avec champs numériques et bouton Appliquer
- Swatches de couleur visibles sur les attributs de type Couleur

## Multiboutique et multilingue

Le module est nativement multi-boutique et multi-langue :

- Chaque landing page a des traductions par langue (table `ps_dffacetedseo_landing_page_lang`)
- Chaque landing peut être restreinte à une ou plusieurs boutiques (table `ps_dffacetedseo_landing_page_shop`)
- Les règles d'indexation s'appliquent par défaut à toutes les boutiques
- L'index est partitionné par boutique
- Les traductions de l'interface sont fournies en français et en anglais (XLIFF dans `translations/`)

## Architecture technique

### Hooks utilisés

- `displayHeader` : canonical et meta robots dynamiques
- `actionFrontControllerSetMedia` : CSS et JS frontend
- `moduleRoutes` : route propre pour les landing pages
- `displayLeftColumn` : injection du panneau de filtres
- `displayBeforeBodyClosingTag` : JSON-LD sur les landings
- `actionProductSearchProviderRunQuery` : intégration avec le moteur PS
- `actionProductSave` et `actionProductDelete` : réindexation incrémentale
- `actionCategoryUpdate` : invalidation du cache catégorie
- `displayBackOfficeHeader` : CSS et JS admin

### Tables créées

| Table | Rôle |
| --- | --- |
| `dffacetedseo_rule` | Règles d'indexation par scope |
| `dffacetedseo_landing_page` | Landings (données métier) |
| `dffacetedseo_landing_page_lang` | Traductions des landings |
| `dffacetedseo_landing_page_shop` | Liens multi-boutique |
| `dffacetedseo_landing_filter` | Filtres associés aux landings |
| `dffacetedseo_combination_log` | Statistiques de visite |
| `dffacetedseo_cache` | Cache résultats requêtes |
| `dffacetedseo_filter_template` | Templates de filtres réutilisables |
| `dffacetedseo_index` | Index dénormalisé (clé performance) |
| `dffacetedseo_setting` | Paramètres internes |

### Convention d'URL des filtres

```
?attribute_group__{id_group}=v1,v2&feature__{id_feature}=v3&manufacturer__0=5&price=10-50&s=needle
```

Une signature SHA-1 stable est calculée pour comparer les combinaisons (matching landing, clé de cache, log).

## Performance attendue

Mesures réalisées sur un catalogue de référence (50 000 produits, 8 facettes actives) :

| Moteur | Temps moyen |
| --- | --- |
| `ps_facetedsearch` natif | 800 ms à 1,4 s par requête |
| DF Faceted SEO sans cache | 50 à 120 ms |
| DF Faceted SEO avec cache | moins de 10 ms |

Gain typique : **×10 à ×30**

## FAQ technique

### Faut-il désinstaller ps_facetedsearch

Non, le module s'intègre via les hooks officiels. Vous pouvez le tester en parallèle. Une fois validé, désinstallez `ps_facetedsearch` pour éviter la duplication du panneau de filtres.

### Le module est-il compatible HTTPS et URL canoniques absolus

Oui. Le module utilise `Context::getContext()->link->getPageLink()` et `getModuleLink()` qui respectent la configuration HTTPS de PrestaShop.

### Comment ajouter une nouvelle langue côté module

Copiez le fichier `translations/fr-FR.xlf` en `translations/xx-XX.xlf` et traduisez les `trans-unit`. Aucune autre intervention nécessaire.

### Le module supporte-t-il les attributs composés (combinaisons d'attributs)

Oui. L'index dénormalisé indexe les déclinaisons via leurs attributs. Le moteur de recherche filtre sur les produits dont au moins une déclinaison correspond à tous les filtres actifs.

### Comment déboguer une règle qui ne s'applique pas

Activez les logs PrestaShop (_Paramètres avancés → Logs_) et consultez la section `dffacetedseo`. Chaque résolution de directive logge la règle matchée et la raison.

## Dépannage

### Fatal error sur un appel à `getBySlug`

Symptôme : `Call to a member function getBySlug() on false`. Cause : ancien helper `get()` qui retournait `false` au lieu de l'objet service. Corrigé en v1.0.1. Mettez à jour le module.

### 404 sur l'URL d'une landing page

Symptôme : `https://votre-site/en/landing/votre-slug` renvoie 404. Cause typique : le hook `moduleRoutes` n'est pas enregistré ou le cache de routes PrestaShop est obsolète.

1. Vérifiez que _Préférences → SEO et URLs → Activer les URL simplifiées_ est sur OUI
2. Sauvegardez cette page (régénère le `.htaccess`)
3. Videz le cache PrestaShop deux fois
4. Allez dans _Modules → Positions_, vérifiez que `dffacetedseo` est attaché à `moduleRoutes`
5. Fallback de test : `https://votre-site/index.php?fc=module&module=dffacetedseo&controller=landing&slug=votre-slug`

### Le moteur de recherche ne retourne aucun produit

L'index est probablement vide. Allez dans le tableau de bord et cliquez sur **Reconstruire l'index**.

### Les filtres ne s'affichent pas dans la colonne

Vérifiez dans _Modules → Positions_ que `dffacetedseo` est attaché au hook `displayLeftColumn`. Selon votre thème, vous pouvez également l'attacher à `displayRightColumn` ou `displayHome`.

### Performance dégradée après import massif de produits

L'invalidation incrémentale fonctionne bien pour des modifications unitaires. Après un import en masse, il est plus rapide de reconstruire l'index entier depuis le tableau de bord et de vider le cache.

## Mises à jour

Le module suit un cycle de versionnage `MAJEUR.MINEUR.PATCH`. Les correctifs critiques (sécurité, fatal errors) sont fournis sous forme de patch ; les nouvelles fonctionnalités déclenchent un bump mineur. Chaque mise à jour majeure inclut un script `upgrade/upgrade-X.Y.Z.php` qui s'exécute automatiquement à l'installation de la nouvelle version.

## Support

Pour toute question ou rapport de bug, contactez [support@datafirefly.com](mailto:support@datafirefly.com) en précisant la version PrestaShop, la version PHP, la version du module et les logs PHP/PrestaShop.
