Publié le 6 janvier 2026 SEO Technique

Meta Title SEO : Guide complet d'optimisation du titre méta

Introduction

Le meta title, ou titre méta en français, est unélément clé du SEO (Search Engine Optimization) qui joue un rôle crucial dans la visibilité et le positionnement des pages web sur les moteurs de recherche. Bien que souvent sous-estimé par les débutants en marketing digital, l'optimisation du titre méta peut avoir un impact significatif sur les résultats de recherche et le taux de clic (CTR).

Contrairement aux idées reçues, le meta title n'est pas uniquement unélément technique : c'est l'une des premières impressions que vos visiteurs potentiels auront de votre contenu dans les résultats de recherche. Une mauvaise optimisation peut entraîner un faible taux de clics et affecter négativement votre positionnement global. Dans ce guide complet et professionnel, nous allons explorer en profondeur le concept du meta title SEO, ses bonnes pratiques d'optimisation ainsi que les outils nécessaires pour améliorer votre stratégie SEO.

Qu'est-ce qu'un titre méta ?

Le titre méta est une balise HTML (</strong>) qui apparaît dans le code source d'une page web. Elle sert à décrire de manière concise le contenu de la page pour les moteurs de recherche et les utilisateurs finaux. Le titre méta est visible dans plusieurs contextes :</p> <ul> <li>Dans les résultats des moteurs de recherche (SERP - Search Engine Results Pages)</li> <li>Dans l'onglet du navigateur lorsque l'utilisateur ouvre la page</li> <li>Dans les favoris ou signets de l'utilisateur</li> <li>Lors du partage sur les réseaux sociaux (dans certains cas)</li> <li>Dans les historiques de navigation</li> </ul> <p><strong>Exemple concret :</strong><br> Si vous avez une page web intitulée « Meilleures recettes de gâteaux au chocolat », votre balise title pourraitêtre structurée ainsi :</p> <code></code> <p>Cette structure simple mais efficace contient le mot-clé principal, une séparation claire avec la marque, et reste concise pour une affichage optimal sur les moteurs de recherche.</p> <h2 id="role-strategique-du-titre-meta-dans-le-seo">Rôle stratégique du titre méta dans le SEO</h2> <p>Le titre méta est l'un des facteurs les plus importants pour le positionnement d'une page sur les moteurs de recherche. Ses principales fonctions incluent :</p> <ul> <li><strong>Amélioration du CTR (Click Through Rate) :</strong> Un titre attractif et pertinent attire plus de clics des utilisateurs, ce qui est un signal positif pour les moteurs de recherche.</li> <li><strong>Aide à la compréhension pour les moteurs de recherche :</strong> Les robots des moteurs de recherche utilisent le titre méta pour comprendre le thème et le contexte de la page.</li> <li><strong>Expérience utilisateur optimale :</strong> Un titre clair et précis informe l'utilisateur de ce qu'il trouvera sur la page avant même de cliquer.</li> <li><strong>Facteur de classement direct :</strong> Le titre méta influence directement le classement d'une page dans les résultats de recherche.</li> </ul> <p>Lorsqu'une page apparaît dans les résultats de recherche, le titre méta est l'un des premierséléments que voient les utilisateurs. Une mauvaise optimisation peut conduire à un faible CTR, à une augmentation du taux de rebond et à un mauvais positionnement dans les SERP.</p> <h2 id="longueur-optimale-du-titre-meta">Longueur optimale du titre méta</h2> <p>L'une des questions les plus fréquemment posées par les spécialistes SEO concerne la longueur idéale du titre méta. Cette question a une réponse précise basée sur l'affichage réel dans les moteurs de recherche.</p> <h3 id="la-longueur-en-caracteres">La longueur en caractères</h3> <p>La longueur recommandée pour un titre méta est de <strong>50à 60 caractères</strong>. Cette plage garantit que le titre s'affiche complètement dans les résultats de recherche Google sur les appareils de bureau sansêtre tronqué avec des points de suspension.</p> <h3 id="la-longueur-en-pixels">La longueur en pixels</h3> <p>Techniquement, Google affiche les titres sur une zone de <strong>environ 600 pixels de large</strong>. Cependant, puisque chaque caractère n'occupe pas la même largeur (un « W » occupe plus d'espace qu'un « i »), il est plus fiable de se fier au nombre de caractères qu'à une mesure en pixels.</p> <h3 id="que-se-passe-t-il-si-le-titre-est-trop-long">Que se passe-t-il si le titre est trop long ?</h3> <p>Si votre titre dépasse 60 caractères, Google risque de le couper et d'afficher une ellipsis (...) à la fin. Cela réduit significativement le CTR car :</p> <ul> <li>L'information importante est cachée ou incomplète</li> <li>L'expérience utilisateur est dégradée</li> <li>Le message clé ne passe pas</li> <li>Les mots-clés situés en fin de titre deviennent invisibles</li> </ul> <h3 id="cas-speciaux-mobile-et-affichages-personnalises">Cas spéciaux : mobile et affichages personnalisés</h3> <p>Sur les appareils mobiles, l'espace disponible est souvent plus limité. Google affiche généralement les titres sur une largeur inférieure sur mobile, ce qui peut entraîner une troncature plus précoce. Pour le référencement mobile, il est recommandé de maintenir les titres à moins de 45 caractères pour une sécurité maximale.</p> <p>Il est important de noter que Google réécrit automatiquement certains titres méta s'il estime que votre titre ne correspond pas à l'intention de recherche ou s'il peut proposer une meilleure version. Cette pratique s'est intensifiée en 2024-2025.</p> <h2 id="structure-et-contenu-d-un-titre-meta-efficace">Structure et contenu d'un titre méta efficace</h2> <h3 id="les-meilleures-structures-pour-un-titre-meta">Les meilleures structures pour un titre méta</h3> <p>Il n'existe pas une seule structure universelle pour tous les sites, mais quelques formuleséprouvées fonctionnent particulièrement bien :</p> <p><strong>Structure 1 : Mot-clé + Bénéfice | Marque</strong></p> <code></code> <p><strong>Structure 2 : Mot-clé | Description de marque</strong></p> <code></code> <p><strong>Structure 3 : Mot-clé – Type de contenu | Marque</strong></p> <code></code> <h3 id="placement-du-mot-cle-principal">Placement du mot-clé principal</h3> <p>Le <strong>mot-clé principal doitêtre placé en début de titre</strong>, autant que possible. Cette position accorde plus de poids SEO au mot-clé et aide les moteurs de recherche à comprendre immédiatement le sujet de la page. Un utilisateur scannant rapidement la SERP remarquera aussi plus facilement votre mot-clé s'il est en début de titre.</p> <p>Cependant, le placement du mot-clé doit rester naturel et lisible. Ne sacrifiez jamais la qualité rédactionnelle pour positionner un mot-clé.</p> <h3 id="utilisation-des-mots-cles-et-eviter-le-keyword-stuffing">Utilisation des mots-clés etéviter le keyword stuffing</h3> <p>L'une des erreurs les plus courantes est de remplir le titre avec trop de mots-clés (keyword stuffing). Google pénalise cette pratique. Voici les bonnes pratiques :</p> <ul> <li>Inclure uniquement un mot-clé principal pertinent</li> <li>Utiliser au maximum un mot-clé principal et une variante ou synonyme</li> <li>Ajouter des mots-clés de longue traîne si cela ne compromet pas la clarté</li> <li>Privilégier l'expérience utilisateur à l'optimisation keyword</li> <li>Éviter de répéter le même terme plusieurs fois</li> </ul> <h3 id="exemple-de-bon-et-mauvais-titre-meta">Exemple de bon et mauvais titre méta</h3> <table border="1" cellpadding="10" cellspacing="0"> <tr> <th><strong>Bon titre méta</strong></th> <th><strong>Mauvais titre méta</strong></th> </tr> <tr> <td>« Meilleures recettes de gâteaux au chocolat | Blog Cuisine »</td> <td>« Recettes gâteaux chocolat recettes desserts chocolat »</td> </tr> <tr> <td>« Agence SEO Paris – Experts en référencement »</td> <td>« Page d'accueil »</td> </tr> <tr> <td>« Guide complet du SEO 2025 | Marketing Digital »</td> <td>« Bienvenue sur notre site »</td> </tr> </table> <h2 id="bonnes-pratiques-d-optimisation-du-titre-meta">Bonnes pratiques d'optimisation du titre méta</h2> <h3 id="principes-fondamentaux-a-respecter">Principes fondamentaux à respecter</h3> <p>Pour créer un titre méta vraiment efficace qui génère des clics et améliore votre classement, respectez ces principes :</p> <p><strong>1. Être précis et descriptif</strong><br> Votre titre doit clairement indiquer le sujet de la page. Évitez les termes vagues ou trop génériques qui ne distinguent pas votre contenu de celui de vos concurrents.</p> <p><strong>2. Inclure une proposition de valeur</strong><br> Si possible, ajoutez un bénéfice ou une promesse : « Apprendre », « Découvrir », « Guide gratuit », « Solutions », etc. Les verbes d'action augmentent le CTR.</p> <p><strong>3. Respecter l'unicité</strong><br> Chaque page de votre site doit avoir un titre méta unique. Les titres dupliqués peuvent confondre les moteurs de recherche et réduire l'efficacité globale de votre site.</p> <p><strong>4. Adapter à l'intention de recherche</strong><br> Votre titre doit correspondre à l'intention de l'utilisateur qui tape sa requête. Si quelqu'un cherche « comment optimiser un titre méta », un titre qui répond directement à cette question aura un meilleur CTR.</p> <p><strong>5. Utiliser des caractères spéciaux avec parcimonie</strong><br> Des symboles comme « | », « – », ou « » peuvent améliorer la lisibilité, mais ne les abusez pas. Un titre avec trop de symboles devient difficile à lire.</p> <h3 id="inclusion-de-la-marque-dans-le-titre-meta">Inclusion de la marque dans le titre méta</h3> <p>La plupart des sites SEO recommandent d'ajouter le nom de la marque ou du site à la fin du titre méta. Cela serve plusieurs objectifs :</p> <ul> <li>Renforce la reconnaissance de marque</li> <li>Aide les utilisateurs à identifier rapidement la source</li> <li>Évite les malentendus avec les pages concurrentes</li> <li>Crée une cohérence visuelle sur tous les résultats de recherche</li> </ul> <p>Cependant, placez la marque à la fin pour ne pas sacrifier l'espace précieux destiné au mot-clé et à la proposition de valeur.</p> <h2 id="strategie-de-gestion-des-titres-meta">Stratégie de gestion des titres méta</h2> <h3 id="audit-initial-des-titres-meta-existants">Audit initial des titres méta existants</h3> <p>Avant d'optimiser vos titres, effectuez un audit complet :</p> <ul> <li>Identifiez tous les titres dupliqués</li> <li>Repérez les titres trop courts ou trop longs</li> <li>Vérifiez que chaque titre contient un mot-clé principal</li> <li>Évaluez la qualité et la pertinence de chaque titre</li> <li>Analysez les titres des pages à fort potentiel (actuellement bien classées ou moyennement bien classées)</li> </ul> <h3 id="priorisation-des-pages-a-optimiser">Priorisation des pages à optimiser</h3> <p>Ne réécrivez pas tous vos titres méta d'un coup. Privilégiez :</p> <ul> <li>Les pages de destination (landing pages) générant du trafic</li> <li>Les pages classées entre la position 5 et 20 (zone critique)</li> <li>Les pages avec un CTR faible malgré un bon classement</li> <li>Les pages avec des mots-clés à fort potentiel de conversion</li> </ul> <h3 id="mise-a-jour-reguliere-des-titres-meta">Mise à jour régulière des titres méta</h3> <p>Google Search Console indique que vous devriez revoir vos titres méta régulièrement :</p> <ul> <li>Tous les 3à 6 mois pour les pages importantes</li> <li>Après chaque mise à jour majeure du contenu</li> <li>Quand vous remarquez une baisse du CTR</li> <li>Lors de l'ajout de nouvelles pages au site</li> <li>En réponse auxévolutions des tendances de recherche</li> </ul> <h2 id="outils-pour-optimiser-vos-titres-meta">Outils pour optimiser vos titres méta</h2> <h3 id="google-search-console">Google Search Console</h3> <p>Google Search Console est l'outil le plus important pour monitorer vos titres méta :</p> <ul> <li>Voir comment vos titres apparaissent réellement dans les résultats de recherche</li> <li>Identifier les cas où Google réécrit votre titre</li> <li>Analyser le CTR de chaque page</li> <li>Repérer les erreurs d'indexation</li> <li>Recevoir des suggestions d'amélioration</li> </ul> <h3 id="extensions-wordpress-pour-l-optimisation-seo">Extensions WordPress pour l'optimisation SEO</h3> <p><strong>Yoast SEO</strong> et <strong>Rank Math</strong> sont deux extensions populaires qui permettent :</p> <ul> <li>De personnaliser facilement chaque titre méta</li> <li>De vérifier la longueur en temps réel</li> <li>D'obtenir des suggestions d'amélioration</li> <li>De voir un aperçu du titre tel qu'il apparaîtra sur Google</li> <li>D'identifier les mots-clés et d'analyser leur pertinence</li> </ul> <h3 id="autres-outils-utiles">Autres outils utiles</h3> <p><strong>Screaming Frog :</strong> Un audit complet de tous les titres méta de votre site en quelques secondes. Idéal pour identifier les doublons et les titres manquants.</p> <p><strong>SEMrush :</strong> Analysez les titres méta de vos concurrents pour identifier les opportunités d'optimisation.</p> <p><strong>Ahrefs :</strong> Examinez la performance des titres méta sur des pages classées et apprenez ce qui fonctionne dans votre secteur.</p> <p><strong>Google Analytics :</strong> Croisez les données de Google Search Console avec Google Analytics pour voir comment les modifications de titre impactent le trafic et les conversions.</p> <h2 id="erreurs-courantes-a-eviter">Erreurs courantes àéviter</h2> <h3 id="les-pieges-les-plus-frequents">Les pièges les plus fréquents</h3> <p><strong>Titres dupliqués :</strong> Utiliser le même titre pour plusieurs pages confond les moteurs de recherche et dilue votre potentiel SEO.</p> <p><strong>Oublier le mot-clé principal :</strong> Un titre sans mot-clé pertinent ne sera pas optimal pour le classement.</p> <p><strong>Dépasser 60 caractères :</strong> Cela risque une troncature et réduit le CTR.</p> <p><strong>Rédiger uniquement pour Google :</strong> Un titre doit d'abordêtre attractif et pertinent pour un humain qui le lit dans les résultats de recherche.</p> <p><strong>Ne pas mettre à jour après un changement de stratégie :</strong> Vos titres doiventévoluer avec votre contenu et vos objectifs business.</p> <p><strong>Utiliser des caractères spéciaux inappropriés :</strong> Certains caractères peuvent ne pas s'afficher correctement sur tous les appareils.</p> <p><strong>Ignorer l'intention de recherche :</strong> Un titre doit répondre précisément à ce que cherche l'utilisateur, pas à ce que vous voulez vendre.</p> <h2 id="impact-du-titre-meta-sur-le-ctr-et-le-classement">Impact du titre méta sur le CTR et le classement</h2> <p>Il existe une corrélation directe entre la qualité du titre méta et le taux de clic. Une amélioration du CTR envoie un signal positif à Google, qui peut améliorer votre classement au fil du temps.</p> <p>Inversement, un titre méta faible entraîne un CTR bas, ce qui peut progressivement réduire votre visibilité dans les résultats de recherche même si votre contenu est excellent.</p> <p>C'est pourquoi l'optimisation du titre méta devrait faire partie de votre stratégie SEO continue. Testez, mesurez, et itérez pour trouver les formules qui génèrent le meilleur CTR pour votre audience spécifique.</p> <h2 id="cas-d-usage-specifiques">Cas d'usage spécifiques</h2> <h3 id="titre-meta-pour-les-pages-d-accueil">Titre méta pour les pages d'accueil</h3> <p>Pour la page d'accueil, privilégiez la marque et une description claire :</p> <code></code> <h3 id="titre-meta-pour-les-articles-de-blog">Titre méta pour les articles de blog</h3> <p>Pour les articles, incluez le sujet spécifique et le type de contenu :</p> <code></code> <h3 id="titre-meta-pour-les-pages-produits">Titre méta pour les pages produits</h3> <p>Pour l'e-commerce, mentionnez le produit et une caractéristique clé :</p> <code></code> <h2 id="conclusion">Conclusion</h2> <p>Le titre méta reste l'un deséléments les plus importants du SEO on-page. Bien que Google devienne plus sophistiqué chaque année et récrive parfois les titres, optimiser vos titres méta reste une pratique fondamentale et efficace.</p> <p>Résumez votre stratégie en quelques points clés : un mot-clé pertinent en début de titre, une longueur entre 50 et 60 caractères, une proposition de valeur claire, et l'unicité pour chaque page. Ces principes simples appliqués systématiquement auront un impact mesurable sur votre trafic organique.</p> <p>Utilisez les outils recommandés pour monitorer régulièrement vos titres, testez des variantes, et continuez d'améliorer votre approche. Le SEO est un processus d'amélioration continue, et le titre méta en est une composante essentielle.</p> </body> </html> ``` </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/balise-titre-seo-guide-complet-de-la-balise-title-html-pour-un-seo-on-page-performant/" 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">Balise titre SEO : guide complet de la balise title HTML pour un SEO on-page performant</span> </a> <a href="/blog/balise-title-seo-guide-complet-d-optimisation-pour-augmenter-votre-visibilite-en-2025/" 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">Balise Title SEO : Guide complet d'optimisation pour augmenter votre visibilité en 2025</span> </a> <a href="/blog/optimisation-seo-wikipedia/" 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">Optimisation SEO Wikipedia</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="meta-title-seo-guide-complet-d-optimisation-du-titre-meta"> <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 = 'meta-title-seo-guide-complet-d-optimisation-du-titre-meta'; // 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>