Publié le 17 janvier 2026 SEO Technique

On-Page SEO : Balises meta etéléments HTML essentiels

Sommaire de l'article

Introduction

Le SEO (Search Engine Optimization) est une discipline essentielle pour améliorer le positionnement d'un site web dans les résultats des moteurs de recherche. Parmi les nombreux facteurs qui influencent le classement d'une page web figurent les balises HTML et, en particulier, les balises meta. Ceséléments jouent un rôle central dans l’optimisation on-page, car ils aident les moteurs de recherche à comprendre le contenu, le contexte et l’objectif de chaque page.

Dans cet article complet et professionnel consacré au thème « On-Page SEO : balise meta, balise title etéléments HTML », nous explorerons en profondeur les concepts clés liés aux balises meta SEO. Nous aborderonségalement les bonnes pratiques d’optimisation, des exemples concrets de code HTML, ainsi que des recommandationséditoriales pour améliorer votre visibilité et augmenter votre taux de clic (CTR) dans les pages de résultats.

Si vous souhaitez comprendre comment les balises meta, la balise title et d’autreséléments HTML structurants peuvent booster votre visibilité sur Internet et attirer davantage de trafic qualifié vers votre site web, ce guide détaillé est fait pour vous.

Concepts clés

Qu'est-ce qu'une balise meta ?

Une balise meta est unélément HTML placé dans l’en-tête d’une page web (la section ) qui fournit des informations sur cette page aux moteurs de recherche et aux navigateurs web. Ces informations, appelées métadonnées, ne sont pas directement visibles par l’internaute dans le contenu principal, mais elles influencent la façon dont la page est indexée, affichée et parfois interprétée dans les résultats de recherche.

Toutes les balises meta n’ont pas un impact direct sur le classement, mais certaines influencent fortement la compréhension du contenu (par exemple la balise description) et la façon dont la page apparaît dans les résultats. Une bonne maîtrise de ces balises est donc indispensable pour une stratégie d’on-page SEO efficace.

Les balises meta sont toujours situées dans la section du document HTML :

     

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

Balise title et balise meta : bien faire la différence

En SEO, on parle souvent de balise title (ou titre SEO) et de balises meta. La balise </code> n’est pas techniquement une balise <code><meta></code>, mais on la regroupe fréquemment avec les balises meta car elle se trouve dans le <code><head></code> et joue un rôle déterminant dans l’<strong>affichage dans les résultats de recherche</strong>.</p> <ul> <li><strong>Balise title</strong> : définit le titre de la page tel qu’il apparaît dans les onglets de navigateur et, surtout, dans les résultats des moteurs de recherche.</li> <li><strong>Balise meta description</strong> : fournit un résumé du contenu de la page, souvent affiché comme extrait sous le titre dans les résultats de recherche.</li> <li><strong>Balise meta robots</strong> : indique aux moteurs de recherche si la page peutêtre indexée et si les liens doiventêtre suivis.</li> <li><strong>Balise meta viewport</strong> : contrôle l’affichage de la page sur les appareils mobiles.</li> </ul> <p>Il est fondamental de ne pas confondre la balise <code><title></code> avec la balise <code><h1></code>. La première est unélément technique utilisé par les moteurs de recherche et les navigateurs, tandis que la seconde est un titre visible par l’utilisateur dans le corps de la page.</p> <h3 id="principaux-types-de-balises-meta-utilisees-en-seo">Principaux types de balises meta utilisées en SEO</h3> <p>Les principales balises meta etéléments associés utilisés dans une stratégie SEO on-page sont les suivants :</p> <ul> <li><strong>Balise title (titre SEO)</strong> : élément HTML <code><title></code> qui définit le titre de la page dans l’onglet du navigateur et dans les résultats de recherche.</li> <li><strong>Balise meta description</strong> : balise <code></code> qui décrit le contenu de la page.</li> <li><strong>Balise meta robots</strong> : balise <code></code> qui indique aux robots d’exploration ce qu’ils peuvent faire.</li> <li><strong>Balise meta viewport</strong> : balise <code></code> qui adapte la page auxécrans mobiles.</li> <li><strong>Balises Open Graph et Twitter Cards</strong> : balises <code></code> et <code></code> utilisées pour optimiser l’affichage lors du partage sur les réseaux sociaux (impact indirect sur le SEO via la visibilité et le trafic).</li> </ul> <h2 id="balise-title-un-pilier-de-l-optimisation-on-page">Balise title : un pilier de l’optimisation on-page</h2> <h3 id="role-de-la-balise-title">Rôle de la balise title</h3> <p>La <strong>balise title</strong> est l’un deséléments les plus importants pour l’optimisation SEO on-page. Elle s’affiche :</p> <ul> <li>en haut de l’onglet du navigateur ;</li> <li>comme titre cliquable dans les résultats des moteurs de recherche ;</li> <li>souvent comme titre de base lors du partage de la page sur d’autres plateformes.</li> </ul> <p>Une balise title bien optimisée aide les moteurs de recherche à comprendre le sujet principal de la page et incite l’internaute à cliquer. Elle influence donc à la fois la <strong>pertinence perçue</strong> de la page et son <strong>taux de clic (CTR)</strong>.</p> <h3 id="exemple-de-balise-title-optimisee">Exemple de balise title optimisée</h3> <pre></pre> <h3 id="longueur-et-bonnes-pratiques-pour-la-balise-title">Longueur et bonnes pratiques pour la balise title</h3> <p>Les moteurs de recherche n’utilisent pas une limite stricte en nombre de caractères, mais une largeur maximale en pixels (environ 600 pixels sur desktop). Dans la pratique, il est recommandé de viser une balise title :</p> <ul> <li>d’une longueur d’environ <strong>45à 65 caractères</strong>, espaces compris ;</li> <li>qui reste lisible sur mobile, où l’affichage est souvent tronqué après environ 40à 55 caractères ;</li> <li>qui contient le <strong>mot-clé principal</strong> de la page, de préférence le plus tôt possible dans le titre sans sacrifier la lisibilité.</li> </ul> <p>Quelques conseils concrets pour optimiser votre balise title :</p> <ul> <li>Intégrer le mot-clé principal de manière naturelle.</li> <li>Éviter les titres génériques du type « Accueil » ou « Page sans titre ».</li> <li>Créer un titre unique pour chaque page de votre site.</li> <li>Ajouter unélément incitatif (<em>bénéfice, promesse, précision</em>) pour encourager le clic.</li> </ul> <h2 id="balise-meta-description">Balise meta description</h2> <h3 id="definition-et-role">Définition et rôle</h3> <p>La <strong>balise meta description</strong> fournit un résumé textuel du contenu de la page. Elle est généralement affichée sous le titre dans les résultats de recherche, sous forme de petit paragraphe (extrait).</p> <p>Cette balise n’est pas un <em>facteur de classement direct</em> dans les principaux moteurs de recherche, mais elle a un impact majeur sur le <strong>taux de clic</strong>. Une description claire, pertinente et attractive incite davantage les internautes à sélectionner votre résultat plutôt que celui d’un concurrent.</p> <h3 id="exemple-de-balise-meta-description">Exemple de balise meta description</h3> <pre></pre> <h3 id="longueur-recommandee-et-bonnes-pratiques">Longueur recommandée et bonnes pratiques</h3> <p>Les moteurs de recherche n’imposent pas une limite fixe en nombre de caractères. En pratique, pour maximiser les chances que votre description soit affichée intégralement, il est recommandé de viser :</p> <ul> <li>un minimum d’environ <strong>90 caractères</strong> pour donner suffisamment de contexte ;</li> <li>une longueur située généralement entre <strong>150 et 200 caractères</strong>, espaces compris, selon la langue et la structure de la phrase.</li> </ul> <p>Quelques recommandations pour rédiger une meta description efficace :</p> <ul> <li>Inclure au moins une fois le <strong>mot-clé principal</strong> de la page, dans un contexte naturel.</li> <li>Résumer en une ou deux phrases claires la <strong>proposition de valeur</strong> de la page.</li> <li>Utiliser un langage orienté bénéfice : ce que l’utilisateur va apprendre, obtenir ou résoudre.</li> <li>Éviter le bourrage de mots-clés et les formulations artificielles.</li> <li>Créer une description <strong>unique</strong> pour chaque page importante.</li> </ul> <p>Il estégalement important de savoir que les moteurs de recherche peuvent parfois ignorer votre meta description et générer eux-mêmes un extrait à partir du contenu de la page, notamment lorsque ils estiment qu’un autre passage est plus pertinent pour la requête de l’utilisateur. Cela renforce la nécessité d’un <strong>contenuéditorial de qualité</strong> sur l’ensemble de la page.</p> <h2 id="balise-meta-robots">Balise meta robots</h2> <h3 id="fonction-de-la-balise-meta-robots">Fonction de la balise meta robots</h3> <p>La <strong>balise meta robots</strong> indique aux moteurs de recherche comment traiter une page lors de l’exploration et de l’indexation. Elle se présente en général sous la forme suivante :</p> <pre></pre> <p>Cette balise est placée dans le <code><head></code>. Lorsqu’elle est absente, la plupart des moteurs de recherche considèrent par défaut que la page est <em>indexable</em> et que les liens peuventêtre suivis.</p> <h3 id="principales-valeurs-de-la-balise-meta-robots">Principales valeurs de la balise meta robots</h3> <ul> <li><strong>index,follow</strong> : autorise l’indexation de la page et le suivi des liens. C’est le comportement souhaité pour la majorité des pages publiques.</li> <li><strong>noindex,follow</strong> : empêche l’indexation de la page, mais autorise le suivi des liens présents sur celle-ci. Utile pouréviter qu’une page soit affichée dans les résultats de recherche tout en conservant la transmission de popularité aux pages liées.</li> <li><strong>noindex,nofollow</strong> : empêche à la fois l’indexation et le suivi des liens. À utiliser avec prudence, par exemple pour des pages techniques ou des contenus strictement privés déj à protégés d’une autre façon.</li> <li><strong>index,nofollow</strong> : autorise l’indexation de la page, mais empêche le suivi des liens. Cette configuration est plus rare et doitêtre utilisée de manière réfléchie, car elle coupe la circulation du « jus de lien » vers les autres pages.</li> </ul> <p>Il estégalement possible de cibler des robots spécifiques (par exemple <code>googlebot</code>) en remplaçant <code>name="robots"</code> par <code>name="googlebot"</code>, ou d’ajouter d’autres directives comme <code>noarchive</code>, <code>nosnippet</code> ou <code>max-snippet</code> pour contrôler finement l’affichage dans les résultats.</p> <h2 id="balise-meta-viewport-et-optimisation-mobile">Balise meta viewport et optimisation mobile</h2> <h3 id="pourquoi-la-balise-viewport-est-essentielle">Pourquoi la balise viewport est essentielle</h3> <p>La <strong>balise meta viewport</strong> contrôle la manière dont une page web s’affiche sur les appareils mobiles. Elle définit notamment la largeur de la zone d’affichage (viewport) et le niveau de zoom initial. Dans un contexte où la grande majorité des utilisateurs accèdent au web via un smartphone, une configuration correcte de cette balise est indispensable.</p> <p>Les moteurs de recherche accordent une importance croissante à l’<strong>ergonomie mobile</strong>. Une page difficile à consulter sur un téléphone (texte trop petit, zoom manuel obligatoire, éléments débordants) risque de fournir une mauvaise expérience utilisateur, ce qui peut à terme nuire à sa visibilité, en particulier sur mobile.</p> <h3 id="exemple-de-balise-meta-viewport-recommandee">Exemple de balise meta viewport recommandée</h3> <pre></pre> <p>Cette configuration ajuste la largeur de la page à la largeur de l’écran du périphérique et définit un niveau de zoom initial adapté. Elle constitue un point de départ fiable pour la plupart des sites responsive.</p> <h2 id="autres-balises-meta-et-elements-lies-au-seo-on-page">Autres balises meta etéléments liés au SEO on-page</h2> <h3 id="balises-open-graph-et-twitter-cards">Balises Open Graph et Twitter Cards</h3> <p>Bien qu’elles ne soient pas des balises SEO directes au sens strict, les balises <strong>Open Graph</strong> (utilisées notamment par Facebook, LinkedIn, etc.) et les <strong>Twitter Cards</strong> enrichissent l’affichage des pages lorsqu’elles sont partagées sur les réseaux sociaux. Cela peut augmenter la visibilité, les interactions et, indirectement, le trafic organique.</p> <p>Exemple de balises Open Graph :</p> <pre> </pre> <h3 id="attribut-alt-des-images">Attribut Alt des images</h3> <p>L’attribut <strong>alt</strong> n’est pas une balise meta, mais il joue un rôle important pour le SEO on-page et l’accessibilité. Il fournit une description textuelle du contenu d’une image pour les lecteurs d’écran et lorsque l’image ne peut pasêtre chargée.</p> <p>Quelques bonnes pratiques :</p> <ul> <li>Utiliser une description courte et précise du visuel.</li> <li>Intégrer des mots-clés pertinents lorsque cela est naturel et cohérent.</li> <li>Éviter de surcharger l’attribut alt avec une liste de mots-clés.</li> </ul> <p>Exemple :</p> <pre><img src="balises-meta-exemple.png" alt="Schéma expliquant la balise title et la meta description pour le SEO"></pre> <h2 id="bonnes-pratiques-d-optimisation-on-page-avec-les-balises-meta">Bonnes pratiques d’optimisation on-page avec les balises meta</h2> <h3 id="1-alignement-entre-balise-title-meta-description-et-contenu">1. Alignement entre balise title, meta description et contenu</h3> <p>Pour obtenir un bon positionnement SEO, il est indispensable que les balises meta et le contenu réel de la page soient cohérents. Les moteurs de recherche accordent une grande importance à la <strong>pertinence globale</strong> de la page par rapport à l’intention de recherche.</p> <ul> <li>Le <strong>mot-clé principal</strong> doit apparaître dans la balise title, dans la meta description et dans le contenu.</li> <li>Les sous-titres <code><h2 id="et-le-corps-du-texte-doivent-developper-les-sujets-annonces-dans-les-balises-eviter-tout-decalage-tr"></code>, <code><h3></code> et le corps du texte doivent développer les sujets annoncés dans les balises.</li> <li>Éviter tout décalage trompeur entre ce qui est promis dans la balise description et ce qui est réellement proposé dans l’article.</li> </ul> <h3>2. Intégration naturelle des mots-clés</h3> <p>L’intégration des mots-clés doit se faire de manière naturelle et fluide. Le <strong>bourrage de mots-clés</strong> (keyword stuffing) est à proscrire, car il nuit à la lisibilité et peutêtre identifié comme une pratique de faible qualité.</p> <ul> <li>Utiliser le mot-clé principal dans la balise title, la meta description, l’introduction et au moins un sous-titre.</li> <li>Enrichir le champ lexical avec des synonymes et des expressions proches.</li> <li>Rédiger avant tout pour l’utilisateur, puis affiner pour les moteurs de recherche.</li> </ul> <h3 id="3-contenu-unique-pertinent-et-suffisamment-developpe">3. Contenu unique, pertinent et suffisamment développé</h3> <p>Les balises meta ne suffisent pas à elles seules à bien se positionner. Elles doivent s’appuyer sur un <strong>contenuéditorial solide</strong> : unique, utile et suffisamment détaillé pour répondre à l’intention de recherche de l’utilisateur.</p> <ul> <li>Éviter le contenu dupliqué (y compris entre différentes pages de votre propre site).</li> <li>Développer les sujets de manière complète avec des exemples, des explications et des cas concrets.</li> <li>Structurer le texte avec des titres et sous-titres clairs.</li> </ul> <h3 id="4-structuration-html-claire-et-hierarchisee">4. Structuration HTML claire et hiérarchisée</h3> <p>Une bonne structure HTML facilite la compréhension du contenu par les moteurs de recherche et améliore l’expérience utilisateur. Les balises meta font partie de cet ensemble, mais elles doiventêtre complétées par une structure bien hiérarchisée dans le <code><body></code>.</p> <ul> <li>Un seul <code><h1></code> par page, décrivant le sujet principal.</li> <li>Des <code><h2 id="pour-les-grandes-sections-puis-des-pour-les-sous-parties-etc-des-paragraphes-relativement-courts-pou"></code> pour les grandes sections, puis des <code><h3></code> pour les sous-parties, etc.</li> <li>Des paragraphes <code><p></code> relativement courts pour une meilleure lisibilité.</li> <li>Des listes <code><ul></code> ou <code><ol></code> pour présenter des points clés.</li> </ul> <h3>5. Prise en compte du mobile et de la vitesse de chargement</h3> <p>Les balises meta ne remplacent pas les autres aspects techniques du SEO, mais elles s’y intègrent. En particulier :</p> <ul> <li>Une balise viewport correctement configurée doitêtre accompagnée d’un design responsive.</li> <li>Les images décrites par un attribut alt pertinent doiventêtre optimisées en taille et en poids.</li> <li>Les scripts et feuilles de style doiventêtre gérés de façon à ne pas ralentir excessivement le chargement.</li> </ul> <h2 id="exemples-concrets-de-configuration-de-balises-meta">Exemples concrets de configuration de balises meta</h2> <h3 id="exemple-complet-pour-une-page-d-article-de-blog-seo">Exemple complet pour une page d’article de blog SEO</h3> <pre><head> </head></pre> <h3 id="exemple-pour-une-page-a-ne-pas-indexer">Exemple pour une page à ne pas indexer</h3> <p>Pour certaines pages (par exemple des pages de test, des pages internes ou des contenus très temporaires), il peutêtre pertinent de demander explicitement aux moteurs de recherche de ne <strong>pas indexer</strong> la page.</p> <pre><head> </head></pre> <h2 id="erreurs-frequentes-a-eviter-avec-les-balises-meta">Erreurs fréquentes àéviter avec les balises meta</h2> <h3 id="1-titre-manquant-duplique-ou-hors-sujet">1. Titre manquant, dupliqué ou hors sujet</h3> <p>Une balise title vide, identique sur de nombreuses pages ou sans rapport avec le contenu est un signal négatif. Cela complique la compréhension du site par les moteurs de recherche et peut réduire le CTR.</p> <h3 id="2-meta-descriptions-identiques-sur-de-nombreuses-pages">2. Meta descriptions identiques sur de nombreuses pages</h3> <p>Utiliser la même description générique sur des dizaines de pages empêche les moteurs de recherche de différencier clairement les contenus. Chaque page importante mérite une description adaptée à son sujet et à son intention de recherche.</p> <h3 id="3-utilisation-inappropriee-de-noindex-ou-nofollow">3. Utilisation inappropriée de noindex ou nofollow</h3> <p>Appliquer <code>noindex</code> par erreur à des pages stratégiques peut les faire disparaître des résultats de recherche. De même, un usage abusif de <code>nofollow</code> peut perturber la circulation interne de la popularité entre vos pages. Il est essentiel de vérifier régulièrement la cohérence de vos directives robots.</p> <h3 id="4-bourrage-de-mots-cles-dans-les-balises-meta">4. Bourrage de mots-clés dans les balises meta</h3> <p>Répéter le même mot-clé de manière non naturelle dans la balise title ou la meta description n’apporte pas de bénéfice et peut détériorer l’image de votre site auprès des utilisateurs. Privilégiez des formulations lisibles, crédibles et orientées solutions.</p> <h2 id="mettre-en-uvre-une-strategie-on-page-seo-centree-sur-les-balises-meta">Mettre en œuvre une stratégie on-page SEO centrée sur les balises meta</h2> <h3 id="etapes-pratiques-pour-optimiser-vos-pages">Étapes pratiques pour optimiser vos pages</h3> <p>Pour tirer pleinement parti des balises meta et de la balise title, vous pouvez suivre une démarche structurée :</p> <ul> <li>Identifier pour chaque page un <strong>mot-clé principal</strong> et quelques expressions associées.</li> <li>Rédiger une balise title unique qui inclut le mot-clé et apporte une promesse claire.</li> <li>Écrire une meta description qui résume le contenu, met en avant les bénéfices et incite au clic.</li> <li>Vérifier la présence d’une balise viewport adaptée aux mobiles.</li> <li>Contrôler la directive de la balise meta robots pouréviter les erreurs d’indexation.</li> <li>Structurer le corps du contenu avec des titres hiérarchisés et un texte lisible.</li> </ul> <h3 id="suivi-et-amelioration-continue">Suivi et amélioration continue</h3> <p>Le travail sur les balises meta et la balise title n’est pas figé. Il est utile d’analyser régulièrement les performances de vos pages (impressions, positions moyennes, CTR) et d’ajuster vos titres ou descriptions lorsque certaines pages affichent un faible taux de clic malgré une bonne position.</p> <p>En testant différentes formulations, en mettant à jour les informations pour rester à jour et en affinant vos messages, vous pouvez progressivement améliorer la visibilité et la rentabilité de votre trafic organique.</p> <h2 id="resume-des-points-essentiels">Résumé des points essentiels</h2> <p>Les <strong>balises meta</strong> et la <strong>balise title</strong> sont deséléments HTML stratégiques pour le SEO on-page. Bien qu’elles ne remplacent pas un contenu de haute qualité, elles influencent fortement la manière dont vos pages sont comprises, indexées et affichées dans les résultats de recherche. En respectant les bonnes pratiques présentées dans ce guide – longueur raisonnable, intégration naturelle des mots-clés, cohérence avec le contenu, directives robots pertinentes et expérience mobile optimisée – vous renforcez les fondations techniques etéditoriales de votre 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/on-page-seo-twitter-meta-tags-guide-complet-des-balises-twitter-et-elements-html/" 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">On-Page SEO Twitter Meta Tags : Guide Complet des Balises Twitter etÉléments HTML</span> </a> <a href="/blog/on-page-seo-balises-open-graph-et-elements-html-essentiels/" 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">On-Page SEO : Balises Open Graph etÉléments HTML Essentiels</span> </a> <a href="/blog/meta-description-seo-on-page-guide-complet-de-la-balise-html-description/" 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">Meta description SEO on-page : guide complet de la balise HTML description</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="on-page-seo-balises-meta-et-elements-html-essentiels"> <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 = 'on-page-seo-balises-meta-et-elements-html-essentiels'; // 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="/#brands" class="hover:text-white transition text-sm">Nos marques</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">© 2025 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 cardsPerView = { mobile: 1, tablet: 2, desktop: 3, large: 4 }; function getCardsPerView() { const width = window.innerWidth; if (width >= 1280) return cardsPerView.large; if (width >= 1024) return cardsPerView.desktop; if (width >= 768) return cardsPerView.tablet; return cardsPerView.mobile; } function updateCarousel() { const cardsPerViewCount = getCardsPerView(); const containerWidth = brandsCarousel.offsetWidth; const cardWidth = containerWidth / cardsPerViewCount; const maxIndex = Math.max(0, cards.length - cardsPerViewCount); currentIndex = Math.min(currentIndex, maxIndex); brandsContainer.style.transform = `translateX(-${currentIndex * cardWidth}px)`; // Update button states const isAtStart = currentIndex === 0; const isAtEnd = currentIndex >= maxIndex; if (brandsPrevBtn) { brandsPrevBtn.style.opacity = isAtStart ? '0.5' : '1'; brandsPrevBtn.style.cursor = isAtStart ? 'not-allowed' : 'pointer'; } if (brandsNextBtn) { brandsNextBtn.style.opacity = isAtEnd ? '0.5' : '1'; brandsNextBtn.style.cursor = isAtEnd ? 'not-allowed' : 'pointer'; } if (brandsPrevBtnMobile) { brandsPrevBtnMobile.style.opacity = isAtStart ? '0.5' : '1'; brandsPrevBtnMobile.style.cursor = isAtStart ? 'not-allowed' : 'pointer'; } if (brandsNextBtnMobile) { brandsNextBtnMobile.style.opacity = isAtEnd ? '0.5' : '1'; brandsNextBtnMobile.style.cursor = isAtEnd ? 'not-allowed' : 'pointer'; } } function nextSlide() { const cardsPerViewCount = getCardsPerView(); const maxIndex = Math.max(0, cards.length - cardsPerViewCount); if (currentIndex < maxIndex) { currentIndex++; updateCarousel(); } } function prevSlide() { if (currentIndex > 0) { currentIndex--; updateCarousel(); } } // Event listeners if (brandsNextBtn) brandsNextBtn.addEventListener('click', nextSlide); if (brandsPrevBtn) brandsPrevBtn.addEventListener('click', prevSlide); if (brandsNextBtnMobile) brandsNextBtnMobile.addEventListener('click', nextSlide); if (brandsPrevBtnMobile) brandsPrevBtnMobile.addEventListener('click', prevSlide); // Set responsive width for cards function setCardWidths() { const cardsPerViewCount = getCardsPerView(); const containerWidth = brandsCarousel.offsetWidth; const gap = 24; // 24px gap const cardWidth = (containerWidth - (gap * (cardsPerViewCount - 1))) / cardsPerViewCount; cards.forEach(card => { card.style.width = `${cardWidth}px`; card.style.flexShrink = '0'; }); } // Initialize setCardWidths(); updateCarousel(); // Update on resize 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>