Publié le 24 février 2026 SEO Technique

do_filter WordPress : comprendre et utiliser les filtres WordPress

Sommaire de l'article

Introduction

Contrairement à ce que laisserait penser l’expression do filter WordPress, il n’existe pas de fonction native nommée do_filter dans le cœur de WordPress. En réalité, le système de filtres repose principalement sur deux fonctions clés : apply_filters et add_filter. Ces fonctions permettent de modifier des données à la volée, d’adapter le comportement de WordPress, de vos thèmes et de vos extensions sans toucher directement au code source.

Dans cet article complet, nous allons :

  • expliquer ce qu’est un filtre WordPress et en quoi il diffère d’une action,
  • clarifier la confusion courante autour du terme « do filter wordpress »,
  • montrer comment utiliser concrètement apply_filters et add_filter dans vos projets,
  • présenter des exemples pratiques orientés SEO et performance,
  • et donner les bonnes pratiques pour un usage propre, maintenable et sécurisé des filtres.

L’objectif est de vous offrir une compréhension claire et opérationnelle du système de filtres WordPress, afin de pouvoir améliorer le comportement de votre site, votre référencement naturel et l’intégration de vos plugins, sans casser le cœur de WordPress.

Concepts clés sur les filtres WordPress

Qu’est-ce qu’un filtre dans WordPress ?

Dans WordPress, un filtre est un point d’accroche (hook) qui permet à un développeur de modifier une donnée à un moment précis de l’exécution du code. Cette donnée peutêtre un titre, un contenu d’article, une URL, un nombre de posts, une requête SQL, un champ d’un formulaire, etc.

Le fonctionnement repose sur deuxéléments :

  • une fonction qui déclenche le filtre et passe la donnée à modifier : apply_filters,
  • une ou plusieurs fonctions qui s’accrochent à ce filtre pour modifier la donnée : via add_filter.

Schématiquement :

  • apply_filters( 'nom_du_filtre', $valeur ) déclare « Je rends $valeur modifiable via le filtre nom_du_filtre ».
  • add_filter( 'nom_du_filtre', 'ma_fonction_de_filtre' ) dit « Quand le filtre nom_du_filtre est appelé, exécute ma_fonction_de_filtre et renvoie la valeuréventuellement modifiée ».

« do filter WordPress » vs fonctions réelles : apply_filters et do_action

Le terme « do filter WordPress » est souvent une confusion entre plusieurs fonctions du système de hooks :

  • apply_filters est la fonction qui exécute un filtre et retourne une valeur (potentiellement modifiée).
  • add_filter permet d’enregistrer une fonction de rappel (callback) à un filtre existant.
  • do_action est l’équivalent côté actions (hooks qui ne retournent pas de données, mais déclenchent du code).

Il n’existe donc pas de fonction do_filter dans le cœur de WordPress : lorsque vous lisez ou entendez « do filter wordpress », il s’agit en général de l’idée d’appliquer un filtre via apply_filters ou de définir un filtre personnalisé dans votre code.

Différence entre actions et filtres

WordPress utilise un système d’événements fondé sur deux types de hooks :

  • Actions (via do_action / add_action) : permettent d’exécuter du code à un moment donné, sans obligation de retourner une valeur. Exemple : envoyer un e‑mail après la publication d’un article.
  • Filtres (via apply_filters / add_filter) : permettent de modifier une donnée et de retourner une nouvelle valeur. Exemple : modifier le titre d’un article avant son affichage.

En résumé :

  • Une action « fait quelque chose ».
  • Un filtre « modifie quelque chose ».

Comment WordPress gère-t-il les filtres ?

La fonction apply_filters

La fonction apply_filters est utilisée pour rendre une valeur « filtrable ». Elle suit généralement cette forme :

apply_filters( 'nom_du_filtre', $valeur_a_filtrer, $argument_optionnel_1, $argument_optionnel_2, ... );

Leséléments importants :

  • 'nom_du_filtre' : identifiant unique du filtre, sous forme de chaîne de caractères.
  • $valeur_a_filtrer : variable qui vaêtre transmise aux fonctions de filtre et potentiellement modifiée.
  • Les arguments optionnels peuvent fournir un contexte supplémentaire (ID de post, type de contenu, objet de requête, etc.).

Lorsqu’un filtre est appliqué :

  • WordPress recherche toutes les fonctions enregistrées sur ce hook via add_filter.
  • Les callbacks sont exécutés dans l’ordre de priorité défini.
  • Chaque callback reçoit la valeur courante, la modifieéventuellement, puis la retourne.
  • La valeur finale retournée par apply_filters est utilisée par le reste du code.

La fonction add_filter

add_filter permet d’enregistrer une fonction qui s’exécutera lorsqu’un filtre donné sera appliqué. Sa signature la plus courante est :

add_filter( 'nom_du_filtre', 'nom_de_la_fonction', $priorite, $nb_arguments_acceptes );

Les paramètres principaux :

  • 'nom_du_filtre' : doit correspondre exactement au nom utilisé dans apply_filters.
  • 'nom_de_la_fonction' : nom de la fonction PHP de rappel (callback).
  • $priorite : entier indiquant l’ordre d’exécution (10 par défaut, les plus petits nombres sont exécutés en premier).
  • $nb_arguments_acceptes : nombre d’arguments que votre callback attend (1 par défaut, souvent plus pour les filtres complexes).

Dans le texte initial, le terme « do filter WordPress » était confondu avec le filtrage de backlinks. Il est important de préciser les points suivants :

  • WordPress ne propose pas nativement de système interne de filtrage ou d’analyse des backlinks entrants (liens provenant d’autres sites vers le vôtre).
  • La gestion des backlinks (identification, audit, désaveu) se fait principalement via des outils externes comme Google Search Console, des plateformes spécialisées ou des solutions SEO tierces.
  • Cependant, WordPress permet d’utiliser des plugins SEO qui s’interfacent avec ces outils ou présentent des rapports basés sur leurs données (par exemple via des tableaux de bord, des alertes, des recommandations de contenus, etc.).

Les filtres WordPress, eux, servent à modifier des données internes (contenu, URLs, métadonnées, requêtes) mais ne réalisent pas, en tant que tels, un audit complet de backlinks.

Exemples pratiques de filtres WordPress

Exemple 1 : filtrer le titre d’un article pour le SEO

Supposons que vous souhaitiez ajouter automatiquement le nom de votre marque à la fin de tous les titres d’articles sur le front‑end. Vous pouvez pour cela utiliser le filtre the_title.

Exemple de logique :

  • WordPress appelle apply_filters( 'the_title', $title, $post_id ) avant d’afficher un titre.
  • Vous accrochez une fonction sur 'the_title' avec add_filter.
  • Votre fonction ajoute « | Nom de la marque » au titre, sauf dans l’administration.

Exemple 2 : filtrer le contenu d’un article

Le filtre the_content est l’un des plus utilisés pour modifier le corps d’un article : insertion de bannières, de blocs d’appel à l’action, de tableaux de sommaire, etc. Les constructeurs de pages, les plugins d’affiliation ou de publicité s’appuient massivement sur ce filtre.

Typiquement :

  • WordPress prépare le contenu brut dans une variable $content.
  • Il appelle $content = apply_filters( 'the_content', $content );
  • Tous les plugins et thèmes qui se sont accrochés via add_filter( 'the_content', 'ma_fonction' ) peuvent alors enrichir ou altérer ce contenu.

Exemple 3 : filtrer le nombre d’articles par page (requêtes)

Les filtres ne se limitent pas au contenu textuel. Par exemple, le filtre pre_get_posts permet de modifier la requête principale de WordPress avant son exécution : changer le nombre d’articles par page, exclure une catégorie, personnaliser l’archive de blog, etc.

Scénario courant :

  • Sur la page d’accueil du blog, vous souhaitez afficher 5 articles au lieu de la valeur par défaut.
  • Vous utilisez un callback accroché à pre_get_posts pour modifier la propriété posts_per_page de la requête principale.

Ce type de filtre est très utile pour le SEO, par exemple pour structurer correctement vos archives, éviter le contenu dupliqué ou contrôler la profondeur d’exploration des robots.

Exemple 4 : filtrer les métadonnées et les URLs

De nombreux plugins SEO s’appuient sur des filtres pour personnaliser :

  • les balises </code> et <code>meta description</code>,</li> <li>les balises <code>og:</code> (Open Graph) et <code>twitter:</code>,</li> <li>les URLs canoniques,</li> <li>certainséléments du plan de site XML.</li> </ul> <p>En exposant des filtres comme <code>wpseo_title</code> ouéquivalents, ces extensions permettent à des développeurs avancés de surcharger le comportement par défaut, par exemple pour intégrer des logiques métier plus complexes ou des règles multilingues très spécifiques.</p> <h2 id="bonnes-pratiques-seo-avec-les-filtres-wordpress">Bonnes pratiques SEO avec les filtres WordPress</h2> <h3 id="utiliser-les-filtres-pour-ameliorer-le-maillage-interne">Utiliser les filtres pour améliorer le maillage interne</h3> <p>Les filtres peuvent contribuer indirectement au <strong>maillage interne</strong>, donc au SEO :</p> <ul> <li>vous pouvez injecter automatiquement des liens internes contextuels dans <code>the_content</code>,</li> <li>ajouter des blocs de contenus recommandés (articles populaires, contenus similaires),</li> <li>adapter les ancres de liens selon la taxonomie de l’article.</li> </ul> <p>En agissant à travers des filtres, vousévitez de modifier manuellement chaque article et vous centralisez la logique SEO dans quelques fonctions réutilisables.</p> <h3 id="preserver-les-performances-et-la-lisibilite-du-code">Préserver les performances et la lisibilité du code</h3> <p>Un usage abusif des filtres peut rendre un site difficile à maintenir et ralentir légèrement certaines pages. Pour une utilisation saine :</p> <ul> <li>évitez d’empiler trop de callbacks sur un même hook pour des opérations lourdes,</li> <li>privilégiez des fonctions de rappel <strong>simples, documentées et testées</strong>,</li> <li>limitez l’exécution de vos filtres au contexte nécessaire (par exemple vérifier <code>is_admin</code>, <code>is_single</code>, <code>is_page</code>, etc.),</li> <li>soyez attentif à la compatibilité avec les mises à jour de WordPress et des plugins tiers.</li> </ul> <h3 id="compatibilite-avec-les-extensions-seo">Compatibilité avec les extensions SEO</h3> <p>Les principaux plugins SEO modernes (comme ceux qui gèrent les balises méta, les plans de site, les données structurées) exposent de nombreux filtres pour affiner les réglages. Pour une intégration propre :</p> <ul> <li>utilisez les filtres publiquement documentés plutôt que de surcharger des fichiers internes du plugin,</li> <li>testez les changements sur un environnement de préproduction,</li> <li>vérifiez toujours l’impact sur les balises de sortie via le code source HTML, les outils de test de données structurées et les rapports des moteurs de recherche.</li> </ul> <h2 id="filtres-backlinks-et-securite">Filtres, backlinks et sécurité</h2> <h3 id="filtrer-les-donnees-entrantes-pour-limiter-les-risques">Filtrer les données entrantes pour limiter les risques</h3> <p>Les filtres WordPress ne concernent pas uniquement le SEO, ils sont aussi un outil important pour la <strong>sécurité</strong>. Vous pouvez par exemple :</p> <ul> <li>filtrer certaines entrées utilisateur (commentaires, champs de formulaires) pour supprimer des liens indésirables,</li> <li>restreindre l’affichage de certaines URL ou paramètres,</li> <li>normaliser des données avant enregistrement en base (par exemple via des filtres spécifiques de plugins).</li> </ul> <p>Cette approche permet de réduire le risque d’injection de contenus indésirables (comme des liens spam dans les commentaires) et de garder le contrôle sur ce qui est rendu public.</p> <h3 id="backlinks-toxiques-nbsp-ce-que-wordpress-ne-fait-pas-nativement">Backlinks toxiques : ce que WordPress ne fait pas nativement</h3> <p>Il est important de distinguer :</p> <ul> <li>les <strong>filtres WordPress</strong>, qui agissent sur les données internes du site (contenu, requêtes, sorties),</li> <li>la <strong>gestion des backlinks externes</strong>, qui dépend principalement de l’écosystème de référencement web global et d’outils spécialisés.</li> </ul> <p>WordPress ne détecte pas de lui‑même les <strong>backlinks toxiques</strong> qui pointent vers votre site. Pour cela, vous utiliserez :</p> <ul> <li>Google Search Console pour obtenir la liste des sites qui vous lient,</li> <li>des outils d’audit SEO pour qualifier ces liens et identifier les risques potentiels,</li> <li>la fonctionnalité de désaveu de liens de Google lorsque c’est nécessaire.</li> </ul> <p>Les filtres WordPress peuvent toutefois vous aider indirectement, par exemple pour gérer des redirections, afficher des messages ou bloquer certaines requêtes malveillantes, mais ils ne remplacent pas un outil d’audit de backlinks.</p> <h2 id="creer-vos-propres-filtres-personnalises">Créer vos propres filtres personnalisés</h2> <h3 id="pourquoi-creer-un-filtre-personnalise-nbsp">Pourquoi créer un filtre personnalisé ?</h3> <p>Créer vos propres filtres est une excellente pratique lorsque vous développez un thème ou un plugin destiné àêtre extensible. Au lieu de figer un comportement, vous offrez la possibilité à d’autres développeurs (ou à vous‑même, plus tard) de <strong>modifier ce comportement sanséditer votre code source de base</strong>.</p> <p>Par exemple, si votre plugin génère un message dans le pied de page, vous pouvez rendre ce message filtrable :</p> <ul> <li>vous appelez <code>apply_filters</code> sur la chaîne de texte par défaut,</li> <li>d’autres développeurs peuvent ensuite la modifier depuis leur propre code via <code>add_filter</code>.</li> </ul> <h3 id="etapes-pour-creer-un-filtre">Étapes pour créer un filtre</h3> <p>Pour mettre en place un filtre personnalisé dans un thème ou un plugin :</p> <ul> <li>Identifiez la donnée que vous souhaitez rendre modifiable (texte, nombre, tableau, objet).</li> <li>Choisissez un nom de filtre unique et cohérent, souvent préfixé par le nom de votre thème ou plugin.</li> <li>Entourez la valeur par un appel à <code>apply_filters</code>.</li> <li>Documentez le filtre (nom, paramètres, type de valeur retournée) pour les futurs utilisateurs.</li> </ul> <p>Exemple de logique : une fonction qui prépare une valeur, l’envoie à <code>apply_filters</code>, puis retourne la valeur filtrée. N’importe quel autre code qui appelle <code>add_filter</code> sur ce hook pourra ajuster le résultat final.</p> <h2 id="organisation-du-code-et-maintenance">Organisation du code et maintenance</h2> <h3 id="structurer-vos-filtres-dans-un-theme-enfant-ou-un-plugin-dedie">Structurer vos filtres dans un thème enfant ou un plugin dédié</h3> <p>Pouréviter de perdre vos personnalisations lors d’une mise à jour de thème ou de plugin, il est recommandé de :</p> <ul> <li>regrouper vos modifications de filtres dans un <strong>plugin personnalisé</strong> dédié à votre site, ou</li> <li>les placer dans un <strong>thème enfant</strong> plutôt que dans le thème parent.</li> </ul> <p>Cela permet :</p> <ul> <li>de mettre à jour en toute sécurité les thèmes et extensions tiers,</li> <li>de garder une trace claire de toutes vos personnalisations,</li> <li>de désactiver facilement vos filtres en cas de problème (en désactivant le plugin dédié).</li> </ul> <h3 id="documenter-vos-filtres-et-callbacks">Documenter vos filtres et callbacks</h3> <p>Au fil du temps, un site WordPress peut utiliser des dizaines de filtres différents. Sans documentation, il devient vite difficile de comprendre quelles modifications sont appliquées et pourquoi. Pour rester efficace :</p> <ul> <li>ajoutez des commentaires au-dessus de chaque <code>add_filter</code> pour expliquer son objectif,</li> <li>nommez clairement vos fonctions de rappel (par exemple en incluant le nom du filtre dans le nom de fonction),</li> <li>notez les dépendanceséventuelles avec des plugins précis (filtre utilisé uniquement si un plugin particulier est actif).</li> </ul> <h2 id="faq-sur-les-filtres-wordpress-et-le-terme-nbsp-do-filter-wordpress-nbsp">FAQ sur les filtres WordPress et le terme « do filter wordpress »</h2> <h3 id="existe-t-il-une-fonction-do-filter-dans-wordpress-nbsp">Existe-t-il une fonction <code>do_filter</code> dans WordPress ?</h3> <p>Non. Le cœur de WordPress ne contient pas de fonction <code>do_filter</code>. Pour déclencher un filtre, on utilise <code>apply_filters</code>. Pour déclencher une action, on utilise <code>do_action</code>. L’expression « do filter wordpress » renvoie généralement à l’idée d’<strong>appliquer un filtre</strong> avec <code>apply_filters</code> ou d’utiliser le système de filtres en général.</p> <h3 id="wordpress-filtre-t-il-automatiquement-les-backlinks-toxiques-nbsp">WordPress filtre-t-il automatiquement les backlinks toxiques ?</h3> <p>Non. WordPress ne dispose pas d’un module natif qui analyserait vos backlinks externes pour déterminer s’ils sont toxiques ou non. La détection et le désaveu de backlinks toxiques se font via des outils SEO spécialisés et via les consoles des moteurs de recherche. En revanche, WordPress peut, grâce aux filtres, vous aider à gérer ce que vous affichez, comment vous structurez vos liens internes, ou comment vous nettoyez certains contenus soumis par les utilisateurs.</p> <h3 id="les-filtres-influencent-ils-directement-le-referencement-naturel-nbsp">Les filtres influencent-ils directement le référencement naturel ?</h3> <p>Les filtres n’agissent pas directement sur l’algorithme des moteurs de recherche, mais ils vous permettent de <strong>contrôler finement les contenus et les métadonnées</strong> renvoyés par votre site. En ce sens, ils sont un levier technique important pour :</p> <ul> <li>optimiser les titres, descriptions et balises sociales,</li> <li>améliorer le maillage interne et la structure des pages,</li> <li>personnaliser les pages de catégories, d’archives, de résultats de recherche,</li> <li>adapter le comportement de plugins SEO tiers.</li> </ul> <h3 id="peut-on-abuser-des-filtres-nbsp">Peut-on abuser des filtres ?</h3> <p>Oui. Même si un ou deux filtres bien utilisés sont généralement très légers en termes de performances, multiplier les callbacks complexes sur des hooks très fréquemment appelés (comme <code>the_content</code> ou <code>init</code>) peut ralentir légèrement le site ou créer des comportements difficiles à déboguer. Il est donc important de les utiliser avec mesure, de tester systématiquement et de surveiller les performances globales.</p> <h3 id="que-faire-si-un-filtre-d-un-plugin-tiers-me-gene-nbsp">Que faire si un filtre d’un plugin tiers me gêne ?</h3> <p>Si un plugin modifie une donnée via un filtre et que ce comportement vous dérange, plusieurs approches sont possibles :</p> <ul> <li>consulter la documentation du plugin pour voir s’il existe une option de configuration permettant de désactiver ce comportement,</li> <li>identifier le hook et la fonction de callback utilisés, puis, dans certains cas, retirer le filtre avec <code>remove_filter</code> si cela ne casse rien,</li> <li>remplacer ou surcharger le comportement par un autre filtre, en ajustant la priorité,</li> <li>si nécessaire, contacter l’éditeur du plugin pour demander un hook supplémentaire ou un ajustement.</li> </ul> <h2 id="conclusion-generale">Conclusion générale</h2> <p>Le système de filtres de WordPress, souventévoqué à travers des termes flous comme « do filter wordpress », repose en réalité sur un mécanisme structuré et puissant centré sur <code>apply_filters</code> et <code>add_filter</code>. Bien utilisés, les filtres vous permettent de :</p> <ul> <li>adapter en profondeur le comportement de WordPress sans modifier son cœur,</li> <li>rendre vos thèmes et plugins plus flexibles et extensibles,</li> <li>affiner votre stratégie SEO en contrôlant métadonnées, contenu et structure,</li> <li>améliorer la sécurité et la qualité des données manipulées par votre site.</li> </ul> <p>En maîtrisant ces concepts et en appliquant les bonnes pratiques décrites dans cet article, vous disposerez d’un levier technique puissant pour optimiser votre site WordPress à la fois sur le plan fonctionnel et sur le plan du référencement naturel.</p> </div> <!-- Articles similaires --> <div class="mt-12 pt-8 border-t border-gray-200"> <h2 class="text-2xl font-bold text-gray-900 mb-6 flex items-center gap-2"> <i class="fas fa-newspaper text-purple-600"></i> Articles similaires </h2> <div class="grid gap-4"> <a href="/blog/avant-wordpress-comprendre-le-web-d-hier-pour-mieux-utiliser-le-web-d-aujourd-hui/" class="block p-4 bg-white rounded-lg border border-gray-200 hover:border-purple-300 hover:shadow-md transition"> <span class="text-purple-600 font-semibold hover:text-purple-800">Avant WordPress : comprendre le web d’hier pour mieux utiliser le web d’aujourd’hui</span> </a> <a href="/blog/pourquoi-utiliser-wordpress/" class="block p-4 bg-white rounded-lg border border-gray-200 hover:border-purple-300 hover:shadow-md transition"> <span class="text-purple-600 font-semibold hover:text-purple-800">Pourquoi utiliser WordPress</span> </a> <a href="/blog/comment-utiliser-wordpress-en-local-guide-complet/" class="block p-4 bg-white rounded-lg border border-gray-200 hover:border-purple-300 hover:shadow-md transition"> <span class="text-purple-600 font-semibold hover:text-purple-800">Comment utiliser WordPress en local : guide complet</span> </a> </div> </div> <!-- CTA Section --> <div class="mt-12 pt-8 border-t border-gray-200"> <div class="bg-gradient-to-r from-purple-600 to-blue-600 rounded-xl p-8 text-center text-white"> <h3 class="text-2xl font-bold mb-4">Besoin d'aide avec votre SEO ?</h3> <p class="mb-6 text-purple-100">Notreéquipe d'experts peut vous aider à optimiser votre site e-commerce</p> <div class="flex flex-col sm:flex-row gap-4 justify-center"> <a href="/seo-ecommerce" class="bg-white text-purple-600 px-8 py-3 rounded-lg font-semibold hover:bg-purple-50 transition inline-block"> Découvrir nos services SEO </a> <a href="/#contact" class="bg-purple-800 text-white px-8 py-3 rounded-lg font-semibold hover:bg-purple-900 transition inline-block"> Nous contacter </a> </div> </div> </div> </article> <!-- Section Commentaires --> <div class="mt-12 max-w-4xl mx-auto bg-white rounded-2xl shadow-xl p-8 md:p-12"> <h2 class="text-3xl font-bold text-gray-900 mb-6 flex items-center gap-3"> <i class="fas fa-comments text-purple-600"></i> Commentaires </h2> <!-- Liste des commentaires approuvés --> <div id="comments-list" class="mb-8 space-y-6"> <!-- Les commentaires approuvés seront chargés ici via JavaScript --> </div> <!-- Formulaire de commentaire --> <div class="border-t border-gray-200 pt-8"> <h3 class="text-xl font-semibold text-gray-900 mb-4">Laisser un commentaire</h3> <form id="comment-form" class="space-y-4"> <input type="hidden" id="article-slug" value="do-filter-wordpress-comprendre-et-utiliser-les-filtres-wordpress"> <div class="grid md:grid-cols-2 gap-4"> <div> <label for="comment-name" class="block text-sm font-medium text-gray-700 mb-2">Nom *</label> <input type="text" id="comment-name" name="name" required class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-600 focus:border-transparent"> </div> <div> <label for="comment-email" class="block text-sm font-medium text-gray-700 mb-2">Email *</label> <input type="email" id="comment-email" name="email" required class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-600 focus:border-transparent"> </div> </div> <div> <label for="comment-message" class="block text-sm font-medium text-gray-700 mb-2">Message *</label> <textarea id="comment-message" name="message" rows="5" required class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-600 focus:border-transparent"></textarea> </div> <div class="text-sm text-gray-600"> <i class="fas fa-info-circle text-purple-600"></i> Votre commentaire sera soumis à modération avant publication. </div> <button type="submit" class="bg-gradient-to-r from-purple-600 to-blue-600 text-white px-8 py-3 rounded-lg font-semibold hover:from-purple-700 hover:to-blue-700 transition inline-flex items-center gap-2"> <i class="fas fa-paper-plane"></i> Publier le commentaire </button> </form> <div id="comment-status" class="mt-4 hidden"></div> </div> </div> <!-- Navigation Articles --> <div class="mt-12 max-w-4xl mx-auto"> <a href="/blog" class="inline-flex items-center gap-2 text-purple-600 hover:text-purple-800 transition font-semibold"> <i class="fas fa-arrow-left"></i> Retour au blog </a> </div> </div> </section> <!-- Script pour les commentaires --> <script> const articleSlug = 'do-filter-wordpress-comprendre-et-utiliser-les-filtres-wordpress'; // Charger les commentaires approuvés async function loadComments() { try { const response = await fetch(`/gestion-commentaires/get-comments.php?slug=${articleSlug}`); const data = await response.json(); const commentsList = document.getElementById('comments-list'); if (data.success && data.comments.length > 0) { commentsList.innerHTML = data.comments.map(comment => ` <div class="border-l-4 border-purple-600 pl-4 py-2"> <div class="flex items-center gap-2 mb-2"> <strong class="text-gray-900">${comment.name}</strong> <span class="text-sm text-gray-500">•</span> <span class="text-sm text-gray-500">${new Date(comment.date).toLocaleDateString('fr-FR')}</span> </div> <p class="text-gray-700">${comment.message}</p> </div> `).join(''); } else { commentsList.innerHTML = '<p class="text-gray-500 italic">Aucun commentaire pour le moment. Soyez le premier à commenter !</p>'; } } catch (error) { console.error('Erreur lors du chargement des commentaires:', error); } } // Gérer la soumission du formulaire document.getElementById('comment-form').addEventListener('submit', async function(e) { e.preventDefault(); const formData = { slug: articleSlug, name: document.getElementById('comment-name').value, email: document.getElementById('comment-email').value, message: document.getElementById('comment-message').value }; const submitBtn = this.querySelector('button[type="submit"]'); const originalText = submitBtn.innerHTML; submitBtn.disabled = true; submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Envoi en cours...'; try { const response = await fetch('/gestion-commentaires/submit-comment.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(formData) }); const result = await response.json(); const messageDiv = document.getElementById('comment-status'); if (result.success) { messageDiv.className = 'mt-4 p-4 bg-green-100 border border-green-400 text-green-700 rounded-lg'; messageDiv.textContent = 'Merci ! Votre commentaire aété soumis et sera publié après modération.'; messageDiv.classList.remove('hidden'); this.reset(); } else { messageDiv.className = 'mt-4 p-4 bg-red-100 border border-red-400 text-red-700 rounded-lg'; messageDiv.textContent = result.message || 'Une erreur est survenue. Veuillez réessayer.'; messageDiv.classList.remove('hidden'); } } catch (error) { const messageDiv = document.getElementById('comment-status'); messageDiv.className = 'mt-4 p-4 bg-red-100 border border-red-400 text-red-700 rounded-lg'; messageDiv.textContent = 'Erreur de connexion. Veuillez réessayer plus tard.'; messageDiv.classList.remove('hidden'); } finally { submitBtn.disabled = false; submitBtn.innerHTML = originalText; } }); // Charger les commentaires au chargement de la page loadComments(); </script> <footer class="bg-gray-950 text-gray-400 py-12"> <div class="container mx-auto px-6"> <div class="flex flex-col md:flex-row justify-between items-center"> <div class="mb-6 md:mb-0 flex items-start gap-4"> <img src="/images/logo.png" alt="Logo VRAIVEX" class="h-32 w-32 md:h-40 md:w-40 object-contain"> <div> <a href="#" class="text-2xl font-bold block"> <span class="gradient-text">VRAIVEX</span> </a> <p class="mt-2 text-sm">Automatisation, IA et SEO au service de la performance e-commerce</p> </div> </div> <div class="flex flex-col items-center md:items-end"> <div class="grid grid-cols-2 md:flex md:flex-wrap gap-3 md:space-x-6 mb-4 text-center md:text-right"> <a href="/#about" class="hover:text-white transition text-sm">À propos</a> <a href="/#services" class="hover:text-white transition text-sm">Services</a> <a href="/#prestations" class="hover:text-white transition text-sm">Prestations</a> <a href="/#bestsellers" class="hover:text-white transition text-sm">Best Sellers</a> <a href="/#realisations" class="hover:text-white transition text-sm">Réalisations</a> <a href="/#brands" class="hover:text-white transition text-sm">Nos Sites</a> <a href="/creation-site-ecommerce" class="hover:text-white transition text-sm">Création Sites</a> <a href="/seo-ecommerce" class="hover:text-white transition text-sm">SEO E-commerce</a> <a href="/partenaires" class="hover:text-white transition text-sm">Partenaires</a> <a href="/#contact" class="hover:text-white transition text-sm">Contact</a> </div> <p class="text-sm text-center md:text-right">© 2026 VRAIVEX. Tous droits réservés.</p> </div> </div> </div> </footer> <!-- Back to Top Button --> <button id="backToTop" class="fixed bottom-8 right-8 bg-gradient-to-r from-purple-600 to-blue-600 text-white p-4 rounded-full shadow-lg hover:shadow-xl transform hover:scale-110 transition-all duration-300 z-50 hidden"> <i class="fas fa-arrow-up text-xl"></i> </button> <script> // Header scroll effect window.addEventListener('scroll', function() { const header = document.getElementById('header'); if (window.scrollY > 100) { header.classList.add('header-scrolled'); } else { header.classList.remove('header-scrolled'); } }); // Smooth scrolling for anchor links document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); document.querySelector(this.getAttribute('href')).scrollIntoView({ behavior: 'smooth' }); }); }); // Mobile menu toggle const mobileMenuButton = document.getElementById('mobileMenuButton'); const mobileMenu = document.getElementById('mobileMenu'); const menuIcon = document.getElementById('menuIcon'); if (mobileMenuButton && mobileMenu) { mobileMenuButton.addEventListener('click', function() { mobileMenu.classList.toggle('hidden'); // Toggle icon between bars and times if (mobileMenu.classList.contains('hidden')) { menuIcon.classList.remove('fa-times'); menuIcon.classList.add('fa-bars'); } else { menuIcon.classList.remove('fa-bars'); menuIcon.classList.add('fa-times'); } }); // Close menu when clicking on a link const mobileLinks = mobileMenu.querySelectorAll('a'); mobileLinks.forEach(link => { link.addEventListener('click', function() { mobileMenu.classList.add('hidden'); menuIcon.classList.remove('fa-times'); menuIcon.classList.add('fa-bars'); }); }); } // Brands Carousel const brandsCarousel = document.getElementById('brandsCarousel'); const brandsContainer = document.getElementById('brandsContainer'); const brandsPrevBtn = document.getElementById('brandsPrevBtn'); const brandsNextBtn = document.getElementById('brandsNextBtn'); const brandsPrevBtnMobile = document.getElementById('brandsPrevBtnMobile'); const brandsNextBtnMobile = document.getElementById('brandsNextBtnMobile'); if (brandsContainer && brandsCarousel) { let currentIndex = 0; const cards = brandsContainer.querySelectorAll('.brand-card'); const gap = 24; const cardsPerView = { mobile: 1, tablet: 2, desktop: 3, large: 4 }; function getCardsPerView() { const w = window.innerWidth; if (w >= 1280) return cardsPerView.large; if (w >= 1024) return cardsPerView.desktop; if (w >= 768) return cardsPerView.tablet; return cardsPerView.mobile; } function getCardWidth() { const cpv = getCardsPerView(); const cw = brandsCarousel.offsetWidth; return (cw - gap * (cpv - 1)) / cpv; } function updateCarousel() { const cpv = getCardsPerView(); const cardW = getCardWidth(); const maxIdx = Math.max(0, cards.length - cpv); currentIndex = Math.min(currentIndex, maxIdx); const offset = currentIndex * (cardW + gap); brandsContainer.style.transform = `translateX(-${offset}px)`; const atStart = currentIndex === 0; const atEnd = currentIndex >= maxIdx; [brandsPrevBtn, brandsPrevBtnMobile].forEach(function(btn) { if (btn) { btn.style.opacity = atStart ? '0.4' : '1'; btn.style.pointerEvents = atStart ? 'none' : 'auto'; } }); [brandsNextBtn, brandsNextBtnMobile].forEach(function(btn) { if (btn) { btn.style.opacity = atEnd ? '0.4' : '1'; btn.style.pointerEvents = atEnd ? 'none' : 'auto'; } }); if (document.getElementById('brandsCounter')) { document.getElementById('brandsCounter').textContent = (currentIndex + 1) + ' / ' + (maxIdx + 1); } } function nextSlide() { const cpv = getCardsPerView(); const maxIdx = Math.max(0, cards.length - cpv); if (currentIndex < maxIdx) { currentIndex++; updateCarousel(); } } function prevSlide() { if (currentIndex > 0) { currentIndex--; updateCarousel(); } } if (brandsNextBtn) brandsNextBtn.addEventListener('click', nextSlide); if (brandsPrevBtn) brandsPrevBtn.addEventListener('click', prevSlide); if (brandsNextBtnMobile) brandsNextBtnMobile.addEventListener('click', nextSlide); if (brandsPrevBtnMobile) brandsPrevBtnMobile.addEventListener('click', prevSlide); function setCardWidths() { const cardW = getCardWidth(); cards.forEach(function(card) { card.style.width = cardW + 'px'; card.style.minWidth = cardW + 'px'; card.style.flexShrink = '0'; }); } let touchStartX = 0; let touchEndX = 0; brandsCarousel.addEventListener('touchstart', function(e) { touchStartX = e.changedTouches[0].screenX; }, { passive: true }); brandsCarousel.addEventListener('touchend', function(e) { touchEndX = e.changedTouches[0].screenX; const diff = touchStartX - touchEndX; if (Math.abs(diff) > 50) { diff > 0 ? nextSlide() : prevSlide(); } }, { passive: true }); setCardWidths(); updateCarousel(); let resizeTimeout; window.addEventListener('resize', function() { clearTimeout(resizeTimeout); resizeTimeout = setTimeout(function() { setCardWidths(); currentIndex = 0; updateCarousel(); }, 250); }); } </script> <script> // Header scroll effect window.addEventListener('scroll', function() { const header = document.getElementById('header'); if (window.scrollY > 50) { header.classList.add('header-scrolled'); } else { header.classList.remove('header-scrolled'); } }); // Scroll animations const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }; const observer = new IntersectionObserver(function(entries) { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('visible'); } }); }, observerOptions); // Observe all fade-in-up elements document.querySelectorAll('.fade-in-up').forEach(el => { observer.observe(el); }); // Smooth scroll for anchor links document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if (target) { target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); // Counter animation for stats function animateCounter(element, target, duration = 2000) { let start = 0; const increment = target / (duration / 16); const timer = setInterval(() => { start += increment; if (start >= target) { element.textContent = target + (element.textContent.includes('+') ? '+' : '') + (element.textContent.includes('K') ? 'K€' : ''); clearInterval(timer); } else { element.textContent = Math.floor(start) + (element.textContent.includes('+') ? '+' : '') + (element.textContent.includes('K') ? 'K€' : ''); } }, 16); } // Observe stats section const statsObserver = new IntersectionObserver(function(entries) { entries.forEach(entry => { if (entry.isIntersecting && !entry.target.classList.contains('animated')) { entry.target.classList.add('animated'); const statsCards = entry.target.querySelectorAll('.stats-card'); statsCards.forEach((card, index) => { setTimeout(() => { card.style.opacity = '0'; card.style.transform = 'translateY(20px)'; setTimeout(() => { card.style.transition = 'all 0.6s ease'; card.style.opacity = '1'; card.style.transform = 'translateY(0)'; }, 100); }, index * 100); }); } }); }, { threshold: 0.3 }); const statsSection = document.querySelector('section.bg-gradient-to-r'); if (statsSection) { statsObserver.observe(statsSection); } </script> <script> // Gestion du formulaire de contact const contactForm = document.getElementById('contact-form'); const formMessage = document.getElementById('form-message'); const submitBtn = document.getElementById('submit-btn'); if (contactForm) { contactForm.addEventListener('submit', async function(e) { e.preventDefault(); // Désactiver le bouton pendant l'envoi submitBtn.disabled = true; submitBtn.textContent = 'Envoi en cours...'; // Récupérer les données du formulaire const formData = new FormData(contactForm); try { // Vérifier que les données sont bien dans le FormData const formDataObj = { name: formData.get('name'), email: formData.get('email'), subject: formData.get('subject'), message: formData.get('message') }; console.log('Données du formulaire:', formDataObj); // Vérifier que tous les champs sont remplis if (!formDataObj.name || !formDataObj.email || !formDataObj.subject || !formDataObj.message) { formMessage.classList.remove('hidden'); formMessage.className = 'mb-6 p-4 rounded-lg bg-red-600 text-white'; formMessage.textContent = 'Veuillez remplir tous les champs du formulaire.'; submitBtn.disabled = false; submitBtn.textContent = 'Envoyer le message'; return; } // Essayer d'abord avec JSON (plus fiable) // Siça ne fonctionne pas, on essaiera avec FormData let response; try { // Méthode 1 : Envoyer en JSON (plus fiable selon les forums) response = await fetch('gestion-formulaire-contact/send-email-json.php', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(formDataObj) }); } catch (jsonError) { console.warn('Erreur avec JSON, essai avec FormData:', jsonError); // Méthode 2 : Fallback avec FormData response = await fetch('send-email.php', { method: 'POST', body: formData }); } // Lire le texte de la réponse d'abord pour déboguer const responseText = await response.text(); console.log('Réponse serveur:', responseText.substring(0, 500)); // Vérifier si la réponse est OK if (!response.ok) { // Essayer de parser le JSON d'erreur try { const errorResult = JSON.parse(responseText); // Afficher le message d'erreur du serveur directement à l'utilisateur formMessage.classList.remove('hidden'); formMessage.className = 'mb-6 p-4 rounded-lg bg-red-600 text-white'; formMessage.textContent = errorResult.message || `Erreur ${response.status}: ${response.statusText}`; submitBtn.disabled = false; submitBtn.textContent = 'Envoyer le message'; return; // Sortir de la fonction pour ne pas continuer } catch (e) { throw new Error(`Erreur HTTP ${response.status}: ${response.statusText}. Réponse: ${responseText.substring(0, 200)}`); } } // Vérifier si PHP n'est pas exécuté (le serveur renvoie le code PHP brut) if (responseText.trim().startsWith('<?php') || responseText.includes('<?php')) { console.error('ERREUR: PHP n\'est pas exécuté par le serveur. Le code PHP est renvoyé brut.'); console.error('Le serveur web n\'est pas configuré pour exécuter PHP.'); // Utiliser la solution de secours : sauvegarder dans localStorage const messageData = { name: formData.get('name'), email: formData.get('email'), subject: formData.get('subject'), message: formData.get('message'), timestamp: new Date().toISOString() }; // Sauvegarder dans localStorage comme solution de secours const savedMessages = JSON.parse(localStorage.getItem('vraivex_messages') || '[]'); savedMessages.push(messageData); localStorage.setItem('vraivex_messages', JSON.stringify(savedMessages)); // Afficher un message spécial formMessage.classList.remove('hidden'); formMessage.className = 'mb-6 p-4 rounded-lg bg-yellow-600 text-white'; formMessage.innerHTML = '⚠️ PHP n\'est pas configuré sur le serveur. Votre message aété sauvegardé localement. <br>Veuillez nous contacter directement à <strong>contact@vraivex.fr</strong> ou consulter les messages sauvegardés dans la console du navigateur.'; // Afficher les messages sauvegardés dans la console console.log('Messages sauvegardés localement:', savedMessages); console.log('Pour consulter les messages, tapez dans la console: JSON.parse(localStorage.getItem("vraivex_messages"))'); return; // Sortir de la fonction } // Essayer de parser le JSON let result; try { result = JSON.parse(responseText); } catch (parseError) { console.error('Erreur de parsing JSON:', parseError); console.error('Réponse reçue:', responseText.substring(0, 500)); throw new Error('Le serveur a renvoyé une réponse invalide. Vérifiez la console pour plus de détails.'); } // Afficher le message de résultat formMessage.classList.remove('hidden'); if (result.success) { formMessage.className = 'mb-6 p-4 rounded-lg bg-green-600 text-white'; formMessage.textContent = 'Message envoyé avec succès ! Nous vous répondrons dans les plus brefs délais.'; contactForm.reset(); } else { formMessage.className = 'mb-6 p-4 rounded-lg bg-red-600 text-white'; let errorMsg = result.message || 'Une erreur est survenue. Veuillez réessayer.'; // Afficher le message de debug en développement (à retirer en production) if (result.debug) { console.error('Erreur détaillée:', result.debug); } formMessage.textContent = errorMsg; } } catch (error) { formMessage.classList.remove('hidden'); formMessage.className = 'mb-6 p-4 rounded-lg bg-red-600 text-white'; // Message d'erreur plus détaillé pour le débogage let errorMsg = 'Une erreur est survenue lors de la communication avec le serveur. '; errorMsg += 'Veuillez réessayer plus tard ou nous contacter directement à contact@vraivex.fr'; // En mode développement, afficher plus de détails if (error.message) { console.error('Erreur détaillée:', error); console.error('Message:', error.message); console.error('Stack:', error.stack); } formMessage.textContent = errorMsg; } finally { // Réactiver le bouton submitBtn.disabled = false; submitBtn.textContent = 'Envoyer le message'; // Masquer le message après 5 secondes setTimeout(() => { formMessage.classList.add('hidden'); }, 5000); } }); } // Back to Top Button functionality const backToTopButton = document.getElementById('backToTop'); // Show/hide button based on scroll position window.addEventListener('scroll', () => { if (window.pageYOffset > 300) { backToTopButton.classList.remove('hidden'); } else { backToTopButton.classList.add('hidden'); } }); // Smooth scroll to top when clicked backToTopButton.addEventListener('click', () => { window.scrollTo({ top: 0, behavior: 'smooth' }); }); </script> </body> </html>