Article SEO SEO Technique

Structure des titres Headings en SEO On-Page

On-Page SEO Heading Structure : structure des titres et concept

Introduction

La structure des titres joue un rôle crucial dans l’optimisation pour les moteurs de recherche et dans l’exp érience utilisateur. Une bonne on-page SEO heading structure, c’est-à-dire une structure des titres claire et coh érente, aide les moteurs à comprendre le sujet principal de la page, la hi érarchie des informations et les relations entre les diff érentes sections. En parall èle, elle permet aux internautes de parcourir rapidement le contenu, d’identifier les parties qui les int éressent et de rester plus longtemps sur la page, ce qui contribue indirectement au r éf érencement.

Dans ce guide, nous allons d étailler le concept de structure des titres appliqu é au SEO on-page, en expliquant comment utiliser efficacement les balises H1 à H6. Nous verrons comment une architecture de titres bien pens ée améliore la pertinence per çue par les moteurs de recherche, renforce le th ème principal de la page et soutient la strat égie de mots-cl és. Nous aborderons également les meilleures pratiques de r éf érencement, des exemples concrets, ainsi que des outils pour auditer et optimiser vos titres. Enfin, une FAQ r épondra aux questions les plus fr équentes sur la structure des titres et son impact r éel sur le SEO. L’objectif est de vous donner une m éthodologie claire et op érationnelle pour structurer vos contenus de manière professionnelle et orient ée performance.

Concepts cl és de la structure des titres en on-page SEO

Les balises de titre HTML, de H1 à H6, servent à organiser logiquement le contenu d’une page. Le H1 correspond au titre principal de la page, les H2 d élimitent les grandes sections, les H3 structurent les sous-parties, et ainsi de suite jusqu’à H6 pour les niveaux les plus fins. Cette hi érarchie n’a pas qu’une fonction visuelle : elle fournit aux moteurs de recherche un signal clair sur l’architecture de l’information et les th ématiques abord ées. Dans une logique de r éf érencement, une page bien structur ée améliore la compr éhension du contenu, la capacit é de crawl et, in fine, les performances SEO.

Concr ètement, la balise H1 doit r ésumer le sujet central de la page. Elle agit comme un point d’entr ée s émantique fort pour les moteurs de recherche et pour les utilisateurs. Les H2 repr ésentent les grandes parties qui d étaillent ce sujet : par exemple, introduction, concepts cl és, bonnes pratiques, outils ou FAQ. Chaque H2 peut être subdivis é en H3 pour pr éciser certains aspects : d éfinitions, listes d’ étapes, explications techniques, etc. Le recours à H4, H5 et H6 est en g én éral r éserv é aux contenus tr ès riches ou techniques, lorsqu’un niveau de granularit é suppl émentaire est n écessaire. L’essentiel est de conserver une hi érarchie coh érente, sans sauter de niveaux de manière d ésordonn ée.

Une bonne on-page SEO heading structure repose donc sur trois piliers : une hi érarchie logique, un choix de libell és align és avec les mots-cl és strat égiques, et une r édaction centr ée sur l’intention de recherche. Le r ôle des titres n’est pas seulement de contenir des mots-cl és : ils doivent refl éter précisément le contenu des sections qu’ils introduisent, afin de r épondre aux attentes des visiteurs et d’ éviter tout d écalage entre promesse et r éalit é. Cela contribue à r éduire le taux de rebond, à am éliorer la lisibilit é et à renforcer la pertinence globale de la page aux yeux des moteurs.

Hi érarchie H1 à H6 et importance SEO

Dans une page correctement structur ée, la balise H1 est unique et d ésigne le sujet principal. Techniquement, HTML5 autorise l’utilisation de plusieurs H1 dans des contextes distincts (par exemple avec des balises de section), mais dans la pratique SEO, il est pr éf érable de conserver un seul H1 par URL pour limiter les ambiguït és et clarifier la th ématique. Le H1 doit int égrer le mot-cl é principal de la page de manière naturelle, idéalement vers le d ébut du titre, tout en restant lisible et attrayant pour l’internaute.

Les balises H2 structurent les sections majeures autour de ce th ème principal. Elles peuvent contenir le mot-cl é principal ou des variantes s émantiquement proches et des mots-cl és secondaires. Les H3, quant à eux, viennent d étailler les H2 : par exemple, un H2 “Bonnes pratiques” peut être suivi de plusieurs H3 correspondants à chaque conseil. Les balises H4, H5 et H6 sont moins courantes mais peuvent être utiles sur des pages longues, des guides complets ou des documentations techniques o ù plusieurs niveaux de d étail sont n écessaires. Le plus important est de ne pas utiliser ces balises pour de simples effets de style graphique : leur fonction est sémantique et structurante.

Sur le plan du r éf érencement, la hi érarchie des titres aide les moteurs à construire une carte mentale de votre contenu. Un encha înement logique H1 → H2 → H3 facilite la d étection des sujets trait és, des relations entre les sections et de la profondeur d’analyse. Une page sans structure claire, ou utilisant les titres de manière al éatoire, complique le travail des robots d’indexation et peut diluer la pertinence sémantique. À l’inverse, une structure des titres propre, coh érente et richement d évelopp ée renforce votre positionnement sur vos requêtes cibles tout en améliorant l’accessibilit é et la navigation.

Bonnes pratiques pour une structure de titres optimis ée

Pour tirer pleinement parti de la on-page SEO heading structure, certaines bonnes pratiques sont incontournables. D’abord, utilisez un H1 unique par page, clairement align é avec l’objectif du contenu et contenant le mot-cl é principal. Ce H1 doit être diff érent de la balise du document HTML, même si les deux peuvent être proches : le <title> vise principalement l’affichage dans les r ésultats de recherche et dans l’onglet du navigateur, tandis que le H1 s’adresse à l’utilisateur sur la page. Les deux doivent rester coh érents, mais il est utile de les diff érencier l ég èrement pour multiplier les formulations et optimiser à la fois le clic et la lecture.</p> <p>Ensuite, d éfinissez des <strong>H2</strong> qui repr ésentent les grandes parties de votre article : introduction, concepts, bonnes pratiques, outils, FAQ, conclusion, etc. Chaque H2 devrait r ésumer en quelques mots la section qu’il introduit et idéalement contenir soit une variante de votre mot-cl é principal, soit un mot-cl é secondaire li é à votre thématique de r éf érencement. Les <strong>H3</strong> d étailent ces parties : par exemple, au sein d’un H2 sur les bonnes pratiques, vous pouvez cr éer un H3 pour l’optimisation du H1, un autre pour la r édaction des H2/H3, un autre pour les erreurs à éviter, et ainsi de suite. Cette granularit é rend la page plus digeste et plus facile à parcourir.</p> <p>La longueur des titres doit rester <strong>concise et descriptive</strong>. Il n’existe pas de limite stricte en nombre de caract ères pour les balises H1, H2 ou H3, mais un titre trop long perd en impact et en lisibilit é. De manière pratique, viser entre une cinquantaine et une soixantaine de caract ères pour les H1 est souvent un bon compromis, alors que les H2 et H3 peuvent être l ég èrement plus courts ou plus longs selon le contexte. L’essentiel est que le titre refl ète fidèlement le contenu de la section et suscite l’int érêt du lecteur sans tomber dans le bourrage de mots-cl és.</p> <p>L’<strong>int égration des mots-cl és</strong> doit rester naturelle. Placez le mot-cl é principal dans le H1, et r épandez des variantes et expressions associ ées dans certains H2 et H3 lorsque c’est pertinent. Il ne s’agit pas de forcer un mot-cl é dans chaque titre, mais de couvrir intelligemment le champ sémantique de votre sujet. Une page sur la “structure des titres” pourra ainsi utiliser des formulations comme “on-page SEO heading structure”, “hi érarchie H1 à H6”, “optimisation des balises de titre”, “structure des titres et r éf érencement”, etc. Cette vari ét é enrichit le contenu tout en restant centr ée sur le besoin de l’utilisateur.</p> <h2 id="erreurs-frequentes-a-eviter-dans-la-structure-des-titres">Erreurs fréquentes à éviter dans la structure des titres</h2> <p>De nombreuses pages souffrent de probl èmes de titres qui nuisent à leur <strong>r éf érencement</strong>. Une erreur courante consiste à utiliser plusieurs <strong>H1</strong> pour des raisons purement esth étiques, par exemple pour mettre en avant plusieurs blocs de texte. Même si les navigateurs interpr ètent cela sans erreur technique majeure, d’un point de vue SEO, cela peut brouiller la compr éhension du th ème central de la page. Pr éf érez un seul H1 et utilisez des H2 ou H3 pour les autres blocs importants, en adaptant le style via les feuilles de style CSS plut ôt que via des niveaux de titre inappropri és.</p> <p>Une autre erreur fr équente est la <strong>rupture de hi érarchie</strong>, comme passer directement d’un H1 à un H3, ou utiliser des H4 pour des sections qui devraient être en H2. Cette d éstructuration complique la lecture, notamment pour les technologies d’assistance (lecteurs d’ écran) et pour les robots des moteurs de recherche. De même, certains r édacteurs emploient des balises de titres juste pour grossir le texte, sans logique sémantique : par exemple, mettre un bouton ou un appel à l’action en H2. Ces pratiques diluent les signaux importants pour le SEO et peuvent affaiblir la coh érence globale de la page.</p> <p>Le <strong>bourrage de mots-cl és</strong> dans les titres constitue également une mauvaise pratique. R ép éter plusieurs fois la même expression exacte dans diff érents H2 ou H3, sans valeur ajout ée pour le lecteur, peut être per çu comme une tentative de manipulation. Privil égiez plutôt des formulations naturelles, en vous concentrant sur la clart é, la pertinence et l’intention de recherche. Enfin, n’ oubliez pas que la structure des titres doit rester coh érente avec le contenu : promettre quelque chose dans un titre, puis ne pas fournir l’information dans la section correspondante, d éçoit les internautes et d égrade les signaux comportementaux (temps pass é, taux de rebond, etc.).</p> <h2 id="exemples-concrets-de-structure-de-titres-optimis-ee">Exemples concrets de structure de titres optimis ée</h2> <p>Pour illustrer le concept d’<strong>on-page SEO heading structure</strong>, prenons l’exemple d’un guide complet sur la structure des titres et le r éf érencement. Le H1 pourrait être : “On-Page SEO Heading Structure : structure des titres et concept”. Les H2 viendraient ensuite découper logiquement le contenu : “Introduction”, “Concepts cl és”, “Hi érarchie H1 à H6”, “Bonnes pratiques”, “Erreurs fréquentes”, “Outils et ressources”, “FAQ”, “Conclusion”. Chaque H2 introduit un volet clair du sujet global et simplifie la navigation à la fois pour le lecteur et pour les moteurs.</p> <p>Sous le H2 “Bonnes pratiques”, des <strong>H3</strong> peuvent détailler chaque recommandation, par exemple : “Utiliser un H1 unique et pertinent”, “Structurer les sections avec des H2 coh érents”, “Optimiser les H3 pour le d étail”, “Rester naturel dans l’int égration des mots-cl és”, “Aligner les titres avec l’intention de recherche”. Dans chaque sous-section, le texte d éveloppe le conseil, donne un exemple et rappelle le lien avec le r éf érencement. Cette granularit é permet à l’utilisateur de passer directement à la partie qui l’int éresse, tout en offrant aux moteurs une vision claire de la profondeur du traitement du sujet.</p> <p>Ce type de structure peut être adapt é à n’importe quel th ème SEO ou non-SEO. L’essentiel est de définir un <strong>H1</strong> repr ésentatif, des <strong>H2</strong> qui segmentent logiquement le contenu, et des <strong>H3/H4</strong> pour affiner lorsque n écessaire. Sur des pages plus courtes, il est tout à fait possible de se limiter à un H1 et quelques H2, sans H3, tant que la hi érarchie reste stable. L’important est de mettre la structure des titres au service du lecteur : un internaute qui comprend instantan ément comment la page est organis ée aura plus de chances de consommer le contenu en profondeur, ce qui est un atout indirect pour le r éf érencement naturel.</p> <h2 id="outils-et-ressources-pour-analyser-la-structure-des-titres">Outils et ressources pour analyser la structure des titres</h2> <p>Plusieurs outils permettent de contr ôler et d’optimiser votre <strong>structure des titres</strong>. Les crawlers SEO comme Screaming Frog, Sitebulb ou d’autres solutions similaires peuvent analyser l’ensemble de votre site et g én érer un rapport pr écis sur l’usage des H1, H2, H3, la pr ésence de doublons, les pages sans H1 ou avec des hi érarchies incoh érentes. Ces outils facilitent l’identification rapide des probl èmes et la planification des corrections à grande échelle, surtout sur les sites volumineux.</p> <p>Les extensions de navigateurs et certains plugins d’ éditeur de contenu permettent aussi de visualiser en un clic la structure des titres d’une page. Des outils d’audit on-page int ègrent fréquemment un module d’ analyse des balises d’en-tête, qui signale par exemple les H1 manquants, les H1 dupliqu és ou les H2 excessifs. Du c ôté des CMS, des plugins de r éf érencement comme Yoast SEO ou Rank Math proposent des recommandations de base sur la r édaction des titres et la pr ésence du mot-cl é principal dans le H1, ce qui peut être utile pour les r édacteurs moins techniques.</p> <p>Les outils d’analyse de performance comme Google Analytics et les solutions de suivi de position permettent de mesurer indirectement l’impact de vos am éliorations de structure de titres. En suivant l’ évolution du trafic organique, du temps pass é sur les pages ou du taux de rebond après une refonte de la hi érarchie H1–H6, vous pouvez valoriser le r ôle de cette optimisation dans votre strat égie globale de r éf érencement. Il est souvent int éressant de coupler cette analyse à des tests A/B sur les formulations de titres pour identifier celles qui g én èrent le plus d’engagement.</p> <h2 id="int-egration-de-la-structure-des-titres-dans-une-strat-egie-de-contenu">Int égration de la structure des titres dans une strat égie de contenu</h2> <p>La <strong>on-page SEO heading structure</strong> ne doit pas être consid ér ée comme un élément isol é, mais comme une composante à part entière de votre strat égie de contenu et de r éf érencement. D ès la phase de planification éditoriale, il est utile de d éfinir une trame de titres : un H1 ciblant le mot-cl é principal, des H2 correspondant aux grandes questions ou sous-th ématiques à traiter, et, si besoin, des H3 pr évus pour d évelopper certains points. Cette pr éparation en amont facilite la r édaction, assure la coh érence de la page et vous aide à couvrir de manière structur ée l’intention de recherche vis ée.</p> <p>Lors de la r édaction, gardez à l’esprit que la structure des titres doit rester au service de la clart é. Même si l’objectif est d’optimiser le r éf érencement, le lecteur reste prioritaire. Chaque titre doit répondre à une logique de question-r éponse ou de progression pédagogique : pourquoi ce point est-il important ? que va apprendre l’internaute dans cette section ? Comment ce paragraphe s’inscrit-il dans l’ensemble du guide ? En combinant cette approche centr ée sur l’utilisateur avec une int égration intelligente de vos mots-cl és, vous obtenez des pages à la fois performantes en SEO et agr éables à consulter.</p> <h2 id="faq-sur-la-structure-des-titres-et-le-seo-on-page">FAQ sur la structure des titres et le SEO on-page</h2> <h3 id="faut-il-absolument-un-seul-h1-par-page-nbsp">Faut-il absolument un seul H1 par page ?</h3> <p>Sur le plan technique, HTML5 autorise plusieurs H1 dans certains cas, mais dans une optique de <strong>r éf érencement</strong> et de clart é, il est fortement recommand é de n’utiliser qu’un seul H1 par page. Cela évite les ambiguït és sur le sujet principal et simplifie l’analyse par les moteurs et les utilisateurs.</p> <h3 id="la-longueur-du-h1-a-t-elle-une-limite-pr-ecise-nbsp">La longueur du H1 a-t-elle une limite pr écise ?</h3> <p>Il n’existe pas de limite officielle en nombre de caract ères pour un H1. En pratique, un H1 compris autour de quelques dizaines de caract ères est g én éralement plus lisible. L’objectif est de rester suffisamment descriptif tout en évitant les formulations trop longues ou surchargees en mots-cl és. La priorit é doit être la clart é pour le lecteur.</p> <h3 id="google-p-enalise-t-il-les-pages-sans-h2-nbsp">Google p énalise-t-il les pages sans H2 ?</h3> <p>Google ne p énalise pas directement une page qui ne comporte pas de H2. Cependant, l’absence de structure claire peut rendre le contenu plus difficile à comprendre pour les moteurs et pour les internautes. Utiliser des H2 logiques et bien r éd ig és am éliore la lisibilit é, la navigation et, indirectement, vos performances en SEO on-page.</p> <h3 id="dois-je-mettre-mon-mot-cl-e-principal-dans-tous-les-titres-nbsp">Dois-je mettre mon mot-cl é principal dans tous les titres ?</h3> <p>Non, il n’est pas n écessaire ni souhaitable de r ép éter le mot-cl é principal dans tous les titres. Il est recommand é de le placer dans le H1 et dans au moins un H2, puis d’utiliser des variantes et termes associ és dans les autres titres. L’objectif est de couvrir le champ sémantique du sujet sans tomber dans le bourrage de mots-cl és.</p> <h3 id="la-structure-des-titres-suffit-elle-a-bien-r-ef-erencer-une-page-nbsp">La structure des titres suffit-elle à bien r éf érencer une page ?</h3> <p>La structure des titres est un pilier important de l’<strong>on-page SEO</strong>, mais elle ne suffit pas à elle seule. Le contenu doit être de qualit é, r épondre clairement à l’intention de recherche, s’appuyer sur une recherche de mots-cl és pertinente, b én éficier d’un maillage interne solide et d’une bonne performance technique du site. Les titres constituent un levier puissant, mais ils doivent s’inscrire dans une strat égie SEO globale.</p> <h3 id="a-quelle-fr-equence-mettre-a-jour-la-structure-des-titres-nbsp">À quelle fr équence mettre à jour la structure des titres ?</h3> <p>Il n’y a pas de fr équence fixe, mais il est pertinent de r éexaminer la structure des titres lors des mises à jour majeures du contenu, lors d’une refonte du site ou lorsque vous constatez des baisses de performances SEO. Une mise à jour ponctuelle permet d’aligner les titres avec les nouvelles attentes des utilisateurs, l’ évolution de votre offre et les tendances de recherche.</p> <h2 id="conclusion">Conclusion</h2> <p>La <strong>on-page SEO heading structure</strong>, ou structure des titres, constitue un levier strat égique pour am éliorer à la fois la lisibilit é de vos contenus et leurs performances en r éf érencement naturel. En d éfinissant un H1 unique, clair et orient é mot-cl é principal, en organisant vos sections avec des H2 coh érents et des H3 pertinents, et en évitant les erreurs classiques de hi érarchie et de bourrage de mots-cl és, vous offrez aux moteurs de recherche comme aux internautes une vision nette de votre contenu et de sa valeur.</p> <p>Int égr ée à une strat égie de contenu globale, la structure des titres vous aide à mieux r épondre aux intentions de recherche, à guider vos lecteurs tout au long de la page et à renforcer la pertinence de votre site sur vos th ématiques cl és de r éf érencement. Prenez le temps d’auditer vos pages existantes, d’identifier les am éliorations possibles et d’appliquer progressivement ces bonnes pratiques. À terme, une architecture de titres bien pens ée deviendra un reflexe dans votre processus de r édaction et un atout durable pour la performance de votre site.</p> </body> </html> </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="structure-des-titres-headings-en-seo-on-page"> <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 = 'structure-des-titres-headings-en-seo-on-page'; // 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>