Article SEO SEO Technique

Comment migrer un site WordPress de local en ligne (guide complet)

Sommaire de l'article

Introduction

Migrer un site WordPress de l'environnement local vers un hébergement en ligne peut paraître complexe pour les débutants. Pourtant, cette étape est indispensable pour rendre votre site accessible au public, sécuriser vos données et optimiser votre référencement naturel. Dans ce guide complet, vous allez découvrir pas à pas comment migrer un site WordPress local en ligne, aussi bien avec une méthode manuelle qu’avec des extensions spécialisées. Vous verrez également quelles bonnes pratiques appliquer avant, pendant et après la migration pour améliorer les performances et la visibilité de votre site.

L’objectif de cet article est de vous proposer une procédure claire, structurée et réaliste, que vous utilisiez XAMPP, MAMP, WAMP ou un autre environnement local, et que votre hébergement soit chez OVH, Hostinger, o2switch ou tout autre fournisseur. En suivant les étapes décrites ci-dessous, vous serez capable de mettre en ligne votre site WordPress sans perte de données et en limitant les risques d’erreurs techniques.

Concepts clés avant la migration

Avant de commencer la migration de votre site WordPress de local en ligne, il est important de bien comprendre quelques notions fondamentales.

  • L’environnement local : c’est l’espace de travail où vous développez et testez votre site WordPress sur votre ordinateur. Il est généralement composé :
    • d’un serveur web local (Apache ou Nginx dans la majorité des cas) ;
    • d’un moteur PHP ;
    • d’un serveur de base de données MySQL ou MariaDB.

    Les solutions les plus répandues sont XAMPP, WAMP, MAMP, Local ou encore Laragon. Le principe reste identique : votre site n’est visible que sur votre machine, via une adresse du type http://localhost/ ou http://localhost:8888/.

  • L’hébergement en ligne : c’est le serveur (ou l’infrastructure cloud) sur lequel votre site WordPress sera stocké pour être accessible via Internet, en utilisant un nom de domaine comme votresite.fr. Vous avez besoin :
    • d’un nom de domaine enregistré (par exemple monsite.com) ;
    • d’un hébergement web (mutualisé, VPS, dédié, cloud, etc.) ;
    • des accès FTP ou SFTP et des identifiants de base de données fournis par votre hébergeur.

    Sur de nombreux hébergeurs, le répertoire racine où placer les fichiers WordPress se nomme public_html ou www.

  • La base de données : WordPress s’appuie sur une base de données MySQL ou MariaDB pour stocker les contenus (articles, pages, menus), les utilisateurs, les réglages du site, les options des thèmes et des extensions. Lors de la migration, il faut :
    • exporter la base de données locale dans un fichier .sql ;
    • créer une base de données vide sur l’hébergement en ligne ;
    • importer le fichier .sql dans cette nouvelle base.
  • Les fichiers du site : il s’agit de l’ensemble du dossier WordPress, qui contient notamment :
    • wp-admin (interface d’administration) ;
    • wp-includes (fichiers du cœur de WordPress) ;
    • wp-content (thèmes, extensions, uploads) ;
    • les fichiers à la racine (wp-config.php, index.php, etc.).

    Lors d’une migration manuelle, vous devez transférer tous ces fichiers, et non pas uniquement le dossier wp-content.

En résumé, une migration complète implique deux éléments indissociables : les fichiers WordPress et la base de données. Sans l’un des deux, votre site ne pourra pas fonctionner correctement.

Préparatifs avant de migrer un site WordPress local en ligne

Une migration réussie commence toujours par une bonne préparation. Avant de déplacer votre site WordPress vers votre hébergement en ligne, prenez le temps de suivre ces étapes.

Sauvegarder le site local

Même si votre site est encore en local, il est fortement conseillé d’effectuer une sauvegarde complète avant toute manipulation :

  • Copiez l’intégralité du dossier WordPress de votre environnement local (par exemple le dossier situé dans htdocs pour XAMPP/MAMP) vers un emplacement sécurisé sur votre ordinateur ou un disque externe.
  • Exportez la base de données locale au format .sql via phpMyAdmin ou un outil équivalent, et conservez ce fichier dans un dossier dédié à vos sauvegardes.

En cas de problème lors de la migration, vous pourrez revenir à cette version sans repartir de zéro.

Vérifier la configuration de l’hébergement

Assurez-vous que votre hébergement en ligne est prêt à accueillir WordPress :

  • Vérifiez la version de PHP (une version moderne et supportée, comme PHP 8.x, est recommandée).
  • Confirmez la taille maximale de téléversement de fichiers, surtout si vous prévoyez une migration via un plugin (certains hébergeurs limitent l’upload à 64 Mo ou 128 Mo par défaut).
  • Créez une base de données MySQL ou MariaDB vide, avec :
    • un nom de base de données ;
    • un nom d’utilisateur ;
    • un mot de passe ;
    • un hôte de base de données (souvent localhost sur les hébergements mutualisés, mais certains hébergeurs utilisent un nom spécifique).

Optimiser le contenu avant la mise en ligne

La migration est un moment idéal pour améliorer la qualité éditoriale et choisir une structure adaptée au SEO :

  • Relisez vos pages et articles pour corriger les fautes, clarifier les titres et supprimer les contenus dupliqués ou obsolètes.
  • Optimisez les images : compressez-les avec des outils en ligne ou des logiciels dédiés afin de réduire leur poids sans perte de qualité visible. Des images légères améliorent la vitesse de chargement.
  • Soignez les titres et les meta-descriptions : rédigez des balises </code> et des meta-descriptions attractives et pertinentes contenant vos principaux mots-clés ciblés.</li> </ul> <h2 id="methode-1-migrer-un-site-wordpress-de-local-en-ligne-manuellement">Méthode 1 : migrer un site WordPress de local en ligne manuellement</h2> <p>La méthode manuelle est la plus universelle, car elle ne dépend d’aucune extension spécifique. Elle convient particulièrement si :</p> <ul> <li>vous souhaitez garder un contrôle total sur chaque étape ;</li> <li>votre site est volumineux ;</li> <li>les limitations d’upload de votre hébergeur rendent les plugins de migration moins pratiques.</li> </ul> <h3 id="etape-1-transferer-les-fichiers-wordpress-par-ftp">Étape 1 : transférer les fichiers WordPress par FTP</h3> <ol> <li>Installez un client FTP ou SFTP (par exemple FileZilla ou Cyberduck) sur votre ordinateur.</li> <li>Récupérez vos identifiants FTP ou SFTP dans le panneau d’administration de votre hébergeur (hôte, nom d’utilisateur, mot de passe, port).</li> <li>Connectez-vous au serveur distant avec votre client FTP.</li> <li>Placez-vous dans le répertoire racine du site, généralement <code>public_html</code> ou <code>www</code> selon l’hébergeur.</li> <li>Sur votre ordinateur, ouvrez le dossier qui contient votre site WordPress local (par exemple dans <code>htdocs/nomdusite</code>).</li> <li>Sélectionnez l’ensemble des fichiers et dossiers WordPress (y compris <code>wp-admin</code>, <code>wp-includes</code>, <code>wp-content</code> et tous les fichiers à la racine) puis transférez-les vers le serveur dans le répertoire racine du domaine choisi.</li> </ol> <p>Le transfert peut prendre plusieurs minutes en fonction de la taille de votre site et de la vitesse de votre connexion. Patientez jusqu’à la fin de l’envoi de tous les fichiers.</p> <h3 id="etape-2-exporter-la-base-de-donnees-locale">Étape 2 : exporter la base de données locale</h3> <ol> <li>Accédez à l’interface phpMyAdmin de votre environnement local (par exemple <code>http://localhost/phpmyadmin</code> ou une adresse spécifique fournie par XAMPP, MAMP ou WAMP).</li> <li>Sélectionnez la base de données utilisée par votre site WordPress dans le menu de gauche.</li> <li>Cliquez sur l’onglet « Exporter ».</li> <li>Choisissez l’option d’exportation rapide au format <code>SQL</code> (suffisant dans la majorité des cas).</li> <li>Lancez l’export et enregistrez le fichier <code>.sql</code> généré sur votre ordinateur. Conservez ce fichier dans un endroit sûr, car il contient tout le contenu de votre site.</li> </ol> <h3 id="etape-3-importer-la-base-de-donnees-sur-le-serveur-en-ligne">Étape 3 : importer la base de données sur le serveur en ligne</h3> <ol> <li>Connectez-vous au panneau d’administration de votre hébergeur.</li> <li>Accédez à l’outil de gestion des bases de données (phpMyAdmin ou équivalent).</li> <li>Sélectionnez la base de données vide que vous avez créée pour le site.</li> <li>Cliquez sur l’onglet « Importer ».</li> <li>Choisissez le fichier <code>.sql</code> exporté précédemment depuis votre environnement local.</li> <li>Lancez l’import et attendez le message de confirmation indiquant que l’opération s’est déroulée avec succès.</li> </ol> <h3 id="etape-4-mettre-a-jour-les-urls-dans-la-base-de-donnees">Étape 4 : mettre à jour les URLs dans la base de données</h3> <p>Lorsque vous développez en local, l’adresse de votre site ressemble souvent à <code>http://localhost/nomdusite</code>. En ligne, votre site sera par exemple accessible à l’adresse <code>https://www.monsite.fr</code>. Il est donc nécessaire d’indiquer cette nouvelle URL dans la base de données pour éviter les liens cassés et les redirections incorrectes.</p> <p>Vous devez au minimum modifier les deux valeurs suivantes dans la table des options de WordPress (par défaut <code>wp_options</code>, sauf si vous avez changé le préfixe des tables) :</p> <ul> <li><strong>siteurl</strong> : URL d’installation de WordPress ;</li> <li><strong>home</strong> : URL principale du site.</li> </ul> <p>Pour cela :</p> <ol> <li>Dans phpMyAdmin côté hébergeur, ouvrez la base de données de votre site en ligne.</li> <li>Cliquez sur la table des options (par exemple <code>wp_options</code>).</li> <li>Recherchez les lignes <code>siteurl</code> et <code>home</code>.</li> <li>Remplacez l’ancienne adresse locale par l’URL définitive de votre site, sans slash final (par exemple <code>https://www.monsite.fr</code>).</li> <li>Enregistrez les modifications.</li> </ol> <p>Si votre site contient de nombreux liens internes absolus (intégrant l’ancienne URL locale), il peut être utile d’utiliser un script de recherche/remplacement ou une extension spécialisée après la mise en ligne pour remplacer l’ancienne URL par la nouvelle dans l’ensemble des contenus. Faites toutefois très attention en effectuant des remplacements dans la base de données : une sauvegarde préalable est indispensable.</p> <h3 id="etape-5-configurer-le-fichier-wp-config-php">Étape 5 : configurer le fichier wp-config.php</h3> <p>Le fichier <code>wp-config.php</code> contient les informations de connexion à la base de données. Après la migration, vous devez l’adapter à votre hébergement en ligne.</p> <p>Sur le serveur distant, ouvrez le fichier <code>wp-config.php</code> à la racine de votre installation WordPress et modifiez les constantes suivantes en fonction des informations fournies par votre hébergeur :</p> <ul> <li><code>DB_NAME</code> : nom de la base de données en ligne ;</li> <li><code>DB_USER</code> : nom d’utilisateur de la base de données ;</li> <li><code>DB_PASSWORD</code> : mot de passe de la base de données ;</li> <li><code>DB_HOST</code> : hôte de la base de données (souvent <code>localhost</code> sur les hébergements mutualisés, sauf instruction contraire de l’hébergeur).</li> </ul> <p>Enregistrez le fichier modifié puis renvoyez-le sur le serveur s’il n’est pas déjà édité en direct. Sans cette mise à jour, WordPress ne pourra pas se connecter à la base de données et affichera une erreur.</p> <h3 id="etape-6-verifier-la-mise-en-ligne-et-regenerer-les-permaliens">Étape 6 : vérifier la mise en ligne et régénérer les permaliens</h3> <p>Une fois les fichiers transférés, la base de données importée et le fichier <code>wp-config.php</code> correctement configuré, vous pouvez tester votre site en vous rendant à l’adresse de votre nom de domaine.</p> <p>Connectez-vous ensuite à l’interface d’administration WordPress (<code>/wp-admin</code>) puis :</p> <ul> <li>allez dans « Réglages > Permaliens » ;</li> <li>vérifiez que la structure d’URL est celle que vous souhaitez ;</li> <li>cliquez simplement sur « Enregistrer les modifications » pour régénérer les permaliens.</li> </ul> <p>Cette étape permet de recréer le fichier <code>.htaccess</code> si nécessaire et de s’assurer que toutes les URLs internes fonctionnent correctement.</p> <h2 id="methode-2-migrer-un-site-wordpress-de-local-en-ligne-avec-un-plugin">Méthode 2 : migrer un site WordPress de local en ligne avec un plugin</h2> <p>Si vous préférez une approche simplifiée, il est possible d’utiliser des extensions dédiées à la migration. Ces outils automatisent une grande partie du processus en prenant en charge à la fois les fichiers et la base de données.</p> <h3 id="all-in-one-wp-migration">All-in-One WP Migration</h3> <p>All-in-One WP Migration est une extension très populaire pour migrer un site WordPress. Le principe est de :</p> <ul> <li>créer un fichier d’export à partir du site local ;</li> <li>installer WordPress sur l’hébergement en ligne ;</li> <li>installer la même extension sur le site en ligne ;</li> <li>importer le fichier généré précédemment.</li> </ul> <p>Sur votre site WordPress local :</p> <ol> <li>Installez et activez l’extension All-in-One WP Migration depuis le répertoire officiel des plugins.</li> <li>Accédez au menu dédié de l’extension, puis choisissez l’option d’export (par exemple « Exporter vers un fichier »).</li> <li>Laissez l’extension générer le fichier d’export contenant les fichiers et la base de données.</li> <li>Téléchargez ce fichier sur votre ordinateur.</li> </ol> <p>Sur votre hébergement en ligne :</p> <ol> <li>Installez WordPress sur le domaine souhaité (même de manière minimale).</li> <li>Connectez-vous à l’administration de ce site vide.</li> <li>Installez et activez l’extension All-in-One WP Migration.</li> <li>Utilisez la fonction d’import pour téléverser le fichier d’export créé sur votre machine locale.</li> <li>Laissez le plugin remplacer les fichiers et la base de données du site en ligne par ceux issus de votre site local.</li> </ol> <p>Selon la taille de votre site, la version gratuite du plugin peut imposer une limite de taille de fichier. Au-delà d’un certain poids, il peut être nécessaire de recourir à une version payante ou à une méthode alternative.</p> <h3 id="duplicator">Duplicator</h3> <p>Duplicator est une autre extension très utilisée pour migrer des sites WordPress, cloner des installations ou créer des sauvegardes complètes.</p> <p>Sur le site local :</p> <ol> <li>Installez et activez le plugin Duplicator.</li> <li>Créez un nouveau « package » en suivant l’assistant : le plugin va analyser le site, préparer une archive et un script d’installation.</li> <li>Téléchargez l’archive générée (fichier compressé) ainsi que le script <code>installer.php</code>.</li> </ol> <p>Sur le serveur en ligne :</p> <ol> <li>Transférez par FTP l’archive et le fichier <code>installer.php</code> dans le répertoire racine du site (par exemple <code>public_html</code> ou <code>www</code>).</li> <li>Assurez-vous que la base de données cible a bien été créée et qu’elle est vide.</li> <li>Lancez le script d’installation en accédant à <code>https://votredomaine.fr/installer.php</code> dans votre navigateur.</li> <li>Renseignez les informations de connexion à la base de données en ligne (nom, utilisateur, mot de passe, hôte).</li> <li>Laissez l’assistant importer les données, configurer le site et mettre à jour les URLs.</li> </ol> <p>À la fin du processus, Duplicator propose généralement de supprimer les fichiers d’installation restants pour des raisons de sécurité. Veillez à effectuer cette étape.</p> <h3 id="autres-plugins-utiles">Autres plugins utiles</h3> <p>Il existe d’autres extensions permettant de gérer des migrations ou des sauvegardes, parmi lesquelles :</p> <ul> <li>des extensions de sauvegarde complètes (par exemple des solutions capables de sauvegarder fichiers + base de données et de les restaurer sur un autre hébergement) ;</li> <li>des outils spécialisés dans l’export/import de bases de données WordPress ;</li> <li>des solutions de sauvegarde cloud qui peuvent aussi servir pour migrer d’un serveur à un autre.</li> </ul> <p>Le choix dépendra de la taille de votre site, des limitations de votre hébergeur et de vos préférences en matière de gestion des sauvegardes.</p> <h2 id="bonnes-pratiques-seo-avant-et-apres-la-migration">Bonnes pratiques SEO avant et après la migration</h2> <p>Une migration technique réussie ne suffit pas : pour que votre site soit visible et performant, il est essentiel de travailler son référencement naturel avant, pendant et après la mise en ligne.</p> <h3 id="optimiser-le-contenu-avant-la-migration">Optimiser le contenu avant la migration</h3> <ul> <li><em>Améliorez la structure éditoriale</em> : utilisez une hiérarchie de titres claire (<code><h1></code>, <code><h2 id="etc-pour-chaque-page-importante-le-titre-principal-doit-etre-unique-et-descriptif-integrez-des-mots-"></code>, <code><h3></code>, etc.) pour chaque page importante. Le titre principal doit être unique et descriptif.</li> <li><em>Intégrez des mots-clés pertinents</em> dans les titres, les sous-titres et le corps du texte, sans sur-optimiser. Préférez les expressions naturelles et proches de ce que votre audience recherche réellement.</li> <li><em>Optimisez les images</em> en définissant des attributs <code>alt</code> descriptifs, afin d’améliorer l’accessibilité et d’aider les moteurs de recherche à comprendre le contenu visuel.</li> </ul> <h3>Améliorer la structure du site</h2> <ul> <li><em>Organisez vos URLs</em> : choisissez une structure de permaliens claire, par exemple basée sur le nom de l’article. Évitez les URLs trop longues, remplies de paramètres ou de chiffres inutiles.</li> <li><em>Créez un maillage interne logique</em> : reliez vos pages entre elles de manière cohérente pour faciliter la navigation des utilisateurs et le crawl des moteurs de recherche.</li> <li><em>Générez un sitemap XML</em> à l’aide d’une extension SEO, puis soumettez-le à votre outil d’analyse des performances de recherche pour accélérer l’indexation.</li> </ul> <h3 id="creer-du-contenu-de-qualite-apres-la-mise-en-ligne">Créer du contenu de qualité après la mise en ligne</h3> <ul> <li><em>Publiez régulièrement</em> des articles, guides, études de cas ou actualités pertinentes pour votre audience. La régularité envoie un signal positif aux moteurs de recherche.</li> <li><em>Variez les formats</em> : intégrez des vidéos, des infographies, des podcasts ou des images de qualité pour enrichir l’expérience utilisateur.</li> <li><em>Travaillez les intentions de recherche</em> : ciblez des expressions précises correspondant à des questions ou des besoins spécifiques, afin d’attirer un trafic qualifié.</li> </ul> <h2 id="outils-indispensables-pour-une-migration-wordpress-reussie">Outils indispensables pour une migration WordPress réussie</h2> <h3 id="outils-pour-la-migration-wordpress">Outils pour la migration WordPress</h3> <ul> <li><strong>Extensions de migration</strong> : des plugins comme All-in-One WP Migration ou Duplicator permettent d’exporter et d’importer facilement vos fichiers et votre base de données, en automatisant la plupart des opérations techniques.</li> <li><strong>Clients FTP / SFTP</strong> : des logiciels comme FileZilla ou Cyberduck sont indispensables pour transférer les fichiers de votre ordinateur vers votre hébergement en ligne, surtout si vous optez pour une migration manuelle.</li> <li><strong>phpMyAdmin ou équivalent</strong> : cet outil, généralement fourni par votre hébergeur, permet d’exporter et d’importer les bases de données MySQL ou MariaDB, ainsi que d’effectuer des vérifications et des ajustements ciblés.</li> </ul> <h3 id="outils-pour-analyser-et-ameliorer-le-site-apres-migration">Outils pour analyser et améliorer le site après migration</h3> <ul> <li><strong>Outils d’analyse de performances</strong> : des services comme des analyseurs de vitesse de page vous donnent des recommandations précises pour réduire les temps de chargement, optimiser les images, configurer la mise en cache et améliorer l’expérience utilisateur.</li> <li><strong>Outils d’audit technique</strong> : des crawlers SEO permettent de parcourir votre site comme un moteur de recherche afin de détecter les liens cassés, les redirections en chaîne, les pages orphelines ou les problèmes de balisage HTML.</li> <li><strong>Plateformes d’analyse de mots-clés et de concurrence</strong> : ces outils vous aident à identifier de nouvelles opportunités de contenu, à comprendre comment se positionnent vos concurrents et à ajuster votre stratégie éditoriale.</li> </ul> <h2 id="etapes-de-verification-apres-la-migration">Étapes de vérification après la migration</h2> <p>Une fois votre site en ligne, prenez le temps de contrôler les points suivants pour vous assurer que tout fonctionne correctement.</p> <h3 id="controles-techniques">Contrôles techniques</h3> <ul> <li>Testez plusieurs pages clés du site (accueil, catégories, articles principaux, formulaire de contact) pour vérifier qu’aucune erreur critique ne s’affiche.</li> <li>Assurez-vous que les formulaires, les recherches internes, les systèmes de commentaires et les fonctionnalités des extensions fonctionnent comme prévu.</li> <li>Vérifiez que le site est bien accessible en HTTPS si vous disposez d’un certificat SSL, et mettez en place des redirections de HTTP vers HTTPS si nécessaire.</li> </ul> <h3 id="controles-de-contenu-et-de-liens">Contrôles de contenu et de liens</h3> <ul> <li>Parcourez votre site à la recherche de liens pointant encore vers les anciennes adresses locales. Remplacez-les par les nouvelles URLs du site en ligne.</li> <li>Vérifiez que les médias (images, vidéos, fichiers à télécharger) sont correctement affichés et accessibles.</li> <li>Contrôlez la cohérence des menus, des catégories et des étiquettes, afin de garantir une navigation fluide.</li> </ul> <h3 id="suivi-de-la-performance-et-du-trafic">Suivi de la performance et du trafic</h3> <ul> <li>Installez un outil d’analyse de trafic pour suivre le nombre de visiteurs, les pages les plus consultées et les sources de trafic.</li> <li>Surveillez l’évolution du positionnement de vos pages sur vos principaux mots-clés afin de détecter d’éventuelles baisses après la migration.</li> <li>Analysez les rapports d’erreurs et les statistiques de crawl fournis par votre outil de suivi de recherche pour corriger rapidement les problèmes détectés.</li> </ul> <h2 id="conseils-supplementaires-pour-une-migration-wordpress-sereine">Conseils supplémentaires pour une migration WordPress sereine</h2> <ul> <li><strong>Planifiez la migration à un moment calme</strong> : si votre site est déjà visible (par exemple dans le cadre d’une refonte), privilégiez un créneau de faible affluence pour limiter l’impact sur les visiteurs.</li> <li><strong>Gardez un environnement local fonctionnel</strong> : ne supprimez pas immédiatement votre installation locale après la mise en ligne. Elle peut servir de solution de secours ou d’espace de test pour de futures évolutions.</li> <li><strong>Documentez vos étapes</strong> : notez les réglages importants (version de PHP, structure des permaliens, extensions essentielles). Ces informations vous seront utiles lors de prochaines migrations ou lors de la résolution de problèmes ultérieurs.</li> <li><strong>Testez régulièrement vos sauvegardes</strong> : une sauvegarde n’est réellement utile que si elle peut être restaurée. Vérifiez ponctuellement que vous êtes capable de restaurer votre site à partir d’une sauvegarde complète.</li> </ul> <p>En appliquant ces méthodes et bonnes pratiques, vous disposerez d’un processus fiable pour migrer votre site WordPress de local en ligne, tout en préservant vos données, vos performances et vos efforts de référencement.</p> </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="comment-migrer-un-site-wordpress-de-local-en-ligne-guide-complet"> <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 = 'comment-migrer-un-site-wordpress-de-local-en-ligne-guide-complet'; // 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>