Retour au blog
Boutiques en ligne

Magento 2 + Hyvä : 15 boutiques, 9 langues, un cas réel

Capture d'écran de Loviux, e-commerce Magento 2 avec Hyvä développé par Kiwop

Faire tourner un e-commerce Magento 2 à 15 boutiques et 9 langues sur une seule instance n'est pas un exercice théorique. C'est un projet réel que nous avons mené pour Loviux, une e-commerce spécialisé dans le bien-être intime qui opère dans toute l'Europe. Cet article retrace les décisions techniques, les obstacles rencontrés et les solutions mises en place.

Si vous travaillez avec Magento à grande échelle — en tant que CTO, lead technique ou développeur senior — vous trouverez ici ce que nous avons appris en migrant de Luma vers Hyvä, en construisant un checkout sur mesure sans frameworks lourds, en automatisant la génération de contenu pour plus de 9 000 produits et en maintenant une infrastructure de production qui ne bronche pas au moment du déploiement.

Pourquoi migrer de Luma vers Hyvä (et ce que cela change concrètement)

Luma a été le frontend par défaut de Magento 2 pendant des années. Et pendant des années, il en a aussi été le principal handicap technique.

Le coût réel du maintien de Luma

La stack de Luma repose sur RequireJS pour le chargement de modules et Knockout.js pour le data binding. Ce sont des technologies de 2013 que Magento a héritées sans jamais les moderniser. Le constat sur un projet à 15 boutiques :

  • RequireJS génère une cascade de requêtes HTTP qui bloque le rendu. Sur un catalogue de milliers de produits, chaque page chargeait entre 40 et 60 fichiers JS avant d'être interactive.
  • Knockout.js ajoute du poids sans apporter de valeur. Pour un e-commerce où l'interactivité réelle se limite au panier, aux filtres et au checkout, embarquer un framework complet de data binding relève de la surindénierie.
  • Le CSS de Luma pèse environ 300 Ko non compressé. Chaque personnalisation empile des couches de LESS que personne n'ose refactoriser.

Dans nos mesures, une page catégorie sous Luma affichait un LCP de 4,2 secondes (Largest Contentful Paint) sur mobile. Inacceptable pour un e-commerce où chaque seconde de chargement supplémentaire réduit la conversion de 7 % selon les données de Google.

Ce que Hyvä + Tailwind CSS apportent

Hyvä remplace l'intégralité du frontend de Luma par une architecture moderne : Alpine.js pour l'interactivité, Tailwind CSS pour les styles et zéro dépendance legacy.

Les chiffres après migration :

Ce n'est pas une amélioration incrémentale. C'est un changement d'ordre de grandeur. Et dans un multi-store à 15 boutiques, cette différence se démultiplie : moins de ressources serveur par requête, un cache plus efficace, une meilleure expérience dans chacune des 9 langues.

La migration n'a pas été anodine. Chaque module tiers qui s'appuyait sur Luma (nous en avions plus de 30) a nécessité un module de compatibilité Hyvä ou un remplacement pur et simple. Nous avons documenté chaque dépendance avant de commencer et priorisé par impact métier. Les modules limités à l'admin n'ont pas demandé de changements ; ceux qui embarquaient des templates .phtml côté frontend, si.

Multi-store à l'échelle : 15 boutiques, 9 langues, une seule instance

Magento gère le multi-store nativement, mais la réalité de l'exploitation à grande échelle est tout autre.

Architecture websites, stores et store views

Le setup de Loviux s'articule sur 3 niveaux :

  • Websites : regroupent les boutiques par zone tarifaire et fiscale (UE sud, UE nord, Royaume-Uni)
  • Stores : un par pays (France, Allemagne, Espagne, Italie, Pays-Bas, Portugal, Pologne, Autriche, Suisse, Belgique, Royaume-Uni, et variantes)
  • Store views : la couche linguistique. Un store peut avoir plusieurs vues (la Suisse en compte 3 : DE, FR, IT ; la Belgique en a 2 : NL, FR)

Au total, 15 store views servant du contenu dans 9 langues : français, anglais, espagnol, portugais, allemand, italien, néerlandais, polonais et les variantes régionales.

Système de fallback linguistique sur mesure

C'est ici que nous avons rencontré le premier véritable défi. Magento dispose d'un fallback de traductions basique, mais il ne résout pas le problème du contenu catalogue.

Le problème : lorsqu'un produit n'a pas de description traduite en allemand d'Autriche (de_AT), Magento affiche un champ vide. Il ne retombe pas automatiquement sur l'allemand standard (de_DE). Sans système de fallback, il faudrait traduire chaque produit individuellement pour chaque locale, y compris les variantes qui partagent la même langue.

Notre solution : nous avons développé un plugin qui intercepte le chargement des attributs localisés et applique une chaîne de fallback configurable :

Le résultat : les variantes de pays héritent automatiquement du contenu de la langue principale. Il suffit de traduire une seule fois par langue, et les spécificités régionales (prix, disponibilité, mentions légales) se gèrent au niveau du store sans dupliquer l'intégralité du catalogue.

Ce mécanisme a réduit l'effort de traduction de 65 % et éliminé le risque de laisser des milliers de produits avec des champs vides dans les boutiques secondaires.

Checkout sur mesure avec Magewire et Alpine.js

Le checkout est le point névralgique d'un e-commerce. Le checkout par défaut de Magento 2 (basé sur Knockout.js + UI Components) fonctionne mais reste lourd, lent et difficile à personnaliser.

Pourquoi nous avons écarté React et Knockout

Nous avons évalué trois pistes :

  1. Checkout Luma stock : écarté car nous migrions vers Hyvä et conserver Knockout uniquement pour le checkout aurait été incohérent.
  2. Checkout avec React (comme Hyvä Checkout) : ajoute une dépendance supplémentaire d'environ 130 Ko et un pipeline de build séparé. Pour un formulaire en 3 étapes, c'est disproportionné.
  3. Magewire + Alpine.js : même stack que le reste de Hyvä. Aucune dépendance supplémentaire, aucun pipeline de build additionnel, aucun conflit d'état entre frameworks.

Nous avons retenu Magewire. Il s'agit d'un portage de Laravel Livewire pour Magento qui permet de construire des composants interactifs avec PHP côté serveur et Alpine.js côté client. Le résultat : un checkout qui pèse moins de 15 Ko de JS (hors Alpine, déjà chargé globalement).

Architecture en 3 colonnes

Nous avons conçu le checkout sous forme de 3 colonnes en desktop :

  • Colonne gauche : adresse de livraison et informations client
  • Colonne centrale : modes de livraison et de paiement
  • Colonne droite : récapitulatif de commande, coupons, totaux

Les trois panneaux sont rendus côté serveur par Magewire et actualisés via AJAX lorsque l'utilisateur modifie ses données. Pas de SPA, pas de routeur côté client, pas d'état partagé à gérer entre frameworks. Chaque composant Magewire est autonome et communique directement avec le backend.

Sur mobile, les colonnes passent en flux vertical avec des accordéons. Le même code, sans duplication ni media queries de mise en page complexes.

Résultat : le checkout se charge en 1,1 seconde sur mobile (LCP) et le taux d'abandon à l'étape de paiement a diminué de 12 % par rapport au checkout précédent sous Luma.

Catalogue de +60 000 produits avec recherche avancée

Un catalogue de cette taille exige davantage que la recherche native de Magento (MySQL FULLTEXT). Il faut une recherche facettée rapide et pertinente. Il suffit de parcourir leur catalogue de vibrateurs pour mesurer l'échelle.

SmileElasticSuite avec OpenSearch

Nous avons déployé SmileElasticSuite, la solution de recherche open source la plus aboutie pour Magento, connectée à OpenSearch 2.x comme moteur d'indexation.

Points de configuration clés :

  • Recherche facettée avec filtres dynamiques par catégorie : les filtres disponibles s'adaptent à la catégorie en cours (taille, couleur, matière, marque, fourchette de prix)
  • Autocomplétion avec suggestions de produits, de catégories et de termes de recherche
  • Synonymes par langue : configurés par store view pour que des termes équivalents renvoient les mêmes résultats
  • Pertinence ajustée : boost des produits en stock, avec image et avec avis au-dessus des autres

La réindexation complète du catalogue (60 000+ produits x 9 langues) prend 8 minutes via un cron dédié. Les mises à jour incrémentales (prix, stock) sont traitées en moins de 30 secondes.

Synchronisation des stocks avec les fournisseurs

Loviux travaille avec plusieurs fournisseurs qui transmettent leurs flux de stock dans des formats hétérogènes : XML, CSV et, dans un cas, un endpoint JSON propriétaire.

Nous avons construit un système d'importation modulaire :

  1. Parsers par fournisseur : chaque fournisseur dispose d'un adaptateur qui normalise son flux au format interne (SKU, quantité, prix d'achat, délai)
  2. Exécution quotidienne programmée : un cron Magento lance la synchronisation chaque nuit à 3h00 (créneau de trafic minimal)
  3. Logs et alertes : si un fournisseur ne transmet pas son flux ou si le format change, l'équipe est notifiée par email
  4. Stock agrégé : pour les produits en dropship, le stock affiché est la somme de tous les fournisseurs qui les distribuent

Ce système traite environ 15 000 lignes de stock chaque nuit sans impact sur les performances du frontend.

Pipeline de contenu par IA : 9 000 produits en 9 langues

C'est sans doute le volet le plus marquant du projet. Avec plus de 9 000 produits nécessitant une description dans 9 langues, nous parlons de 81 000 textes produit. Les rédiger manuellement n'est viable ni économiquement ni en termes de délais.

Le pipeline en 4 étapes

Nous avons conçu un pipeline automatisé avec GPT-4o-mini (choisi pour son rapport coût/qualité en génération massive) :

Étape 1 — Extraction des caractéristiques : lecture des fiches techniques fabricant (nom, composition, volume, type de produit, spécificités) et structuration en JSON normalisé.

Étape 2 — Génération native par langue : au lieu de générer en une langue puis de traduire, nous produisons directement dans chaque langue cible. La différence est nette : un texte généré nativement en français sonne naturel ; un texte traduit de l'espagnol sonne comme une traduction. Le prompt intègre le contexte de marque, le ton éditorial et les contraintes réglementaires du marché cible.

Étape 3 — Nettoyage : suppression des formulations génériques répétitives, correction des incohérences entre langues (un produit ne peut pas être "150 ml" dans un pays et "5 oz" dans un autre si toute l'Europe vend en ml) et application des règles de style.

Étape 4 — Validation automatique : chaque texte passe par des contrôles de longueur min/max, présence de mots-clés produit, absence d'hallucinations (ingrédients inventés, caractéristiques fictives) et conformité du format HTML pour Magento.

Les chiffres du pipeline

  • Coût total : environ 420 euros en tokens d'API pour les 81 000 textes
  • Durée de traitement : 14 heures pour la génération complète
  • Taux d'approbation automatique : 87 % des textes ont passé la validation sans intervention manuelle
  • Révision manuelle : les 13 % restants ont nécessité des ajustements mineurs (principalement des produits aux caractéristiques spéciales non couvertes par les fiches fabricant)

Comparé à la traduction professionnelle (estimée à plus de 120 000 euros et 4 à 6 mois de travail), le pipeline IA a représenté une économie de 99,6 % sur le coût et de 95 % sur les délais. La qualité n'atteint pas celle d'un rédacteur senior, mais pour des descriptions produit fonctionnelles et optimisées pour le SEO, elle est largement suffisante.

Stack de performance : Varnish, Redis, OPcache et PHP 8.4

Le résultat parle de lui-même : PageSpeed Insights 100 sur mobile pour un Magento 2 avec 15 store views et plus de 60 000 produits. FCP de 1,4 seconde, LCP de 1,5 seconde, TBT de 30 ms et CLS de 0. Ces chiffres sont exceptionnels pour tout e-commerce, et encore plus pour un site construit sur Magento.

PageSpeed Insights 100 pour Loviux : Magento 2 avec Hyvä, FCP 1,4s, LCP 1,5s, CLS 0
PageSpeed Insights : score de 100 sur mobile pour Loviux (Magento 2 + Hyvä)

La performance d'un e-commerce n'est pas un luxe. Un site lent perd des ventes. Avec 15 boutiques servant du trafic depuis toute l'Europe, l'infrastructure doit être solide.

Architecture de cache

La configuration de développement Magento que nous avons mise en place pour Loviux suit une hiérarchie à 4 niveaux :

  1. Varnish 7.x en reverse proxy : met en cache les pages complètes. Un hit Varnish sert une page en moins de 10 ms sans solliciter PHP. Nous avons configuré un VCL personnalisé pour le purge sélectif par store view, catégorie et produit.
  2. Redis pour le cache applicatif et les sessions : supprime les accès disque. Deux instances distinctes : une pour le cache de configuration et de blocs (DB 0), une autre pour les sessions (DB 2).
  3. OPcache de PHP 8.4 : précompile les quelque 40 000 fichiers PHP de Magento. Avec opcache.jit=tracing activé, les fonctions du chemin critique sont compilées en code machine natif.
  4. Cache full page de Magento en fallback pour les requêtes qui contournent Varnish (utilisateurs connectés, panier non vide).

CSS bloquant : un choix contre-intuitif pour un CLS à 0

La recommandation habituelle consiste à charger le CSS de manière asynchrone et à extraire le critical CSS en inline. Nous avons fait l'inverse. L'intégralité du CSS se charge de manière bloquante dans le <head>.

Pourquoi ? Parce qu'avec Hyvä + Tailwind, le CSS total pèse environ 35 Ko (gzippé : ~8 Ko). Le charger de manière bloquante ajoute quelques millisecondes au First Contentful Paint, mais garantit que la mise en page ne bouge jamais après le premier rendu. Le résultat : un CLS (Cumulative Layout Shift) à 0,000 de façon constante sur toutes les pages.

Sur un projet comportant des dizaines de templates différents (accueil, catégorie, produit, checkout, pages CMS x 15 boutiques), maintenir un système de critical CSS synchronisé serait un cauchemar de maintenance. Avec 8 Ko de CSS bloquant, le compromis n'en vaut pas la peine.

Le déploiement en production suit un processus qui exclut toute interruption de service :

  1. Build dans un répertoire temporaire (/var/www/releases/YYYYMMDD-HHMMSS/)
  2. composer install --no-dev, bin/magento setup:di:compile, bin/magento setup:static-content:deploy pour les 9 langues
  3. Préchauffage du cache : exécution de requêtes sur les pages clés pour alimenter Varnish
  4. Permutation atomique du symlink : ln -sfn fait pointer /var/www/current vers le nouveau release
  5. php-fpm reload pour que les workers chargent le nouveau code
  6. Purge sélectif de Varnish

En cas de problème, le rollback consiste à repositionner le symlink sur le release précédent. Temps d'indisponibilité : 0 seconde.

Le setup:static-content:deploy pour 9 langues prend environ 12 minutes. C'est l'étape la plus longue du pipeline, mais comme elle s'exécute avant la permutation, elle n'affecte pas le trafic en cours.

SEO technique multilingue

Un e-commerce à 15 boutiques et 9 langues est un champ de mines en matière de SEO technique. Google doit comprendre quelle page correspond à quel pays et à quelle langue, sans confondre les variantes.

Hreflang sur chaque page

Chaque page inclut des balises hreflang pointant vers toutes ses variantes :

Cela représente 14 hreflangs par page. Avec un catalogue de 60 000 produits, on arrive à 168 000 déclarations hreflang rien que pour les fiches produit. Cette génération est dynamique, via un module qui interroge les URL rewrites de Magento par store view.

Données structurées complètes

Nous avons implémenté le balisage Schema.org en JSON-LD sur toutes les pages pertinentes :

  • Product : avec offers, aggregateRating, brand, sku, gtin13 lorsqu'il est disponible. Google affiche des rich snippets avec prix et disponibilité.
  • CollectionPage : sur les pages catégorie, avec numberOfItems et fil d'Ariane.
  • BreadcrumbList : navigation hiérarchique complète (Accueil, catégorie, sous-catégorie, produit).
  • Organization : données de l'entreprise sur la page d'accueil et les pages de contact.
  • FAQPage : sur les pages catégorie comportant des questions fréquentes relatives aux produits.

L'ensemble est validé avec le Rich Results Test de Google et exempt d'erreurs dans la Search Console.

Sitemaps distincts par boutique

Un sitemap unique pour 15 boutiques dépasserait la limite des 50 000 URLs. Nous générons des sitemaps individuels par store view :

  • loviux.fr/sitemap.xml renvoie vers un sitemap index qui pointe vers sitemap-products.xml, sitemap-categories.xml, sitemap-cms.xml
  • Même logique pour chaque domaine (.es, .de, .it, .nl, .pt, .pl, .co.uk, .at, .ch, .be, .com)

Chaque sitemap est régénéré quotidiennement à 5h00 et inclut un <lastmod> basé sur la dernière modification réelle du contenu, et non sur la date de génération. Google apprécie l'honnêteté des timestamps.

Intégrations clés

Brevo pour l'email marketing

Nous avons connecté Magento à Brevo (anciennement Sendinblue) pour l'automatisation des emails transactionnels et marketing :

  • Synchronisation bidirectionnelle des contacts (inscription, achat, abandon)
  • Emails transactionnels (confirmation de commande, expédition, facture) servis depuis Brevo pour une meilleure délivrabilité
  • Workflows d'abandon de panier segmentés par boutique et par langue

GA4 Enhanced Ecommerce

Nous avons implémenté le tracking complet GA4 Enhanced Ecommerce avec 10 événements standard :

view_item, view_item_list, add_to_cart, remove_from_cart, view_cart, begin_checkout, add_shipping_info, add_payment_info, purchase et refund.

Chaque événement inclut la dimension store view pour permettre la segmentation des performances par pays et par langue dans les rapports.

Cloudflare Turnstile

Nous avons remplacé reCAPTCHA par Cloudflare Turnstile sur l'ensemble des formulaires : inscription, connexion, contact, newsletter et checkout en tant qu'invité. Turnstile ne présente aucun challenge visible à l'utilisateur (il est invisible par défaut) et affiche un meilleur taux d'acceptation que reCAPTCHA v3. Sur un e-commerce, chaque friction supplémentaire dans le tunnel de paiement est une vente en moins.

Ce que nous retenons de ce projet

Après des mois de développement, de tests et d'optimisation, voici les enseignements qui ont eu le plus d'impact :

  1. Hyvä n'est plus une option pour un nouveau projet Magento 2. Démarrer avec Luma aujourd'hui, c'est démarrer avec de la dette technique. L'écart de performance est trop important.
  1. Le fallback linguistique se conçoit avant de charger le premier produit. Le mettre en place après coup avec 60 000 produits déjà en base aurait été un enfer de migrations de données.
  1. Magewire est la bonne réponse pour le checkout sous Hyvä. Même paradigme que le reste du frontend, sans dépendance supplémentaire. Laravel Livewire a prouvé le concept ; Magewire l'adapte à Magento.
  1. L'IA pour le contenu produit ne remplace pas les rédacteurs, mais elle passe à l'échelle là où ils ne peuvent pas. 81 000 textes en 9 langues pour 420 euros, c'est une équation qui se passe de commentaire. La relecture humaine reste indispensable pour les 10 à 15 % de cas particuliers.
  1. Le CSS bloquant avec Hyvä a plus de sens que le critical CSS. Quand votre CSS total pèse moins qu'un avatar, la complexité d'un système de critical CSS ne se justifie pas.
  1. Le deploy zero-downtime est une obligation, pas un bonus. Avec 15 boutiques et du trafic 24h/24 depuis plusieurs fuseaux horaires, il n'existe pas de créneau de maintenance sûr.

Si votre entreprise a besoin de faire monter en charge un e-commerce Magento 2 — qu'il s'agisse d'une migration vers Hyvä, d'un setup multi-store ou d'intégrations avancées — contactez notre équipe. Nous concevons des solutions e-commerce performantes à grande échelle depuis plus de 15 ans.

Besoin de faire évoluer votre e-commerce Magento ?

Chez Kiwop, nous développons des boutiques Magento 2 + Hyvä optimisées pour la performance, le multilingue et la conversion.

Découvrez notre service de Développement Magento

Audit
technique initial.

IA, sécurité et performance. Diagnostic avec proposition par phases.

NDA disponible
Réponse <24h
Proposition par phases

Votre premier rendez-vous est avec un Architecte Solutions, pas un commercial.

Demander un diagnostic