Le symptôme : vous installez un plugin de minification HTML/CSS/JS (le nôtre, ou un autre), tout va bien côté visiteurs. Puis vous ouvrez l'éditeur Elementor d'une page existante, et BAM : "There has been a critical error on this website", impossible d'éditer quoi que ce soit. Désactivez le plugin, ça remarche. Réactivez, ça recasse. Voici pourquoi, et comment on l'a définitivement réglé.
Le décor : SiteGround, Cloudflare, et un proxy SSL pas vu
Mi-mai 2026, un client testait Alesta AI v1.3.0 sur un site WordPress hébergé chez SiteGround, avec Elementor Pro 3.21. Il active le module Cache & Minification, passe sur le front : parfait, page en 1,2 s au lieu de 2,8 s. Il retourne dans l'admin pour modifier une section dans Elementor… écran blanc. Critical error.
Première hypothèse classique : un conflit JS. On ouvre la console navigateur. Pas d'erreur JavaScript. À la place, une douzaine de lignes rouges qui disent toutes la même chose :
Mixed Content: The page at 'https://exemple.fr/wp-admin/post.php?post=42&action=elementor'
was loaded over HTTPS, but requested an insecure stylesheet
'http://exemple.fr/wp-content/cache/alesta/min-abc123.css'.
This request has been blocked; the content must be served over HTTPS.
Voilà le coupable. Le serveur génère des URLs en http:// pour les fichiers
minifiés, le navigateur les refuse parce que la page mère est en https://,
Elementor n'arrive plus à charger ses dépendances CSS, et son éditeur React part en sucette.
Pourquoi l'URL sort en HTTP alors que le site est en HTTPS ?
C'est là que ça devient intéressant. Le site est bien en HTTPS partout : siteurl
et home dans wp_options commencent par https://.
Pourtant, WP_CONTENT_URL évalué au moment où notre module est instancié
renvoie une URL HTTP.
La raison : chez SiteGround (et chez la plupart des hébergeurs qui terminent SSL au
niveau proxy NGINX), Apache reçoit la requête en http:// et c'est un en-tête
X-Forwarded-Proto: https qui dit à WordPress qu'il faut considérer la connexion
comme sécurisée. WordPress lit cet en-tête… mais après que certaines constantes
ont été figées. Si votre plugin construit ses URLs trop tôt dans le cycle, vous récupérez
l'URL HTTP brute.
Le serveur est convaincu d'être en HTTP. Le navigateur est convaincu d'être en HTTPS. Tout le monde a raison de son point de vue. Et l'utilisateur a un écran blanc.
Pourquoi ça casse Elementor en particulier ?
Sur le front public, Mixed Content génère juste un warning console et une feuille de style manquante : visuellement laid, mais pas bloquant. Dans l'éditeur Elementor, c'est différent. L'éditeur tourne dans une iframe en HTTPS strict, et il fait du polling JS sur les feuilles de style. Quand il en attend une qui ne charge pas, il lève une exception non-catchée dans son boundary React.
Résultat affiché à l'utilisateur : "There has been a critical error on this website. Please check your site admin email inbox for instructions." Le mail en question contient une stack trace PHP qui n'a rien à voir avec le vrai problème, ce qui fait perdre des jours à chercher dans la mauvaise direction.
Le fix que nous avons codé dans Alesta AI v1.3.5
Le réflexe naïf serait de remplacer toutes les occurrences de http:// par
https:// dans la sortie HTML. Mauvaise idée : ça casse les liens externes
légitimes vers des ressources HTTP, et ça ne règle pas le fond du problème.
Le bon fix tient en trois lignes : ne jamais figer l'URL du cache au moment de l'init du plugin, mais la recalculer dynamiquement à chaque utilisation, en respectant le schéma réellement perçu par WordPress :
private function cache_url() {
$url = trailingslashit( WP_CONTENT_URL ) . 'cache/alesta/';
return set_url_scheme( $url, is_ssl() ? 'https' : 'http' );
}
Trois choses se passent ici. D'abord, on n'utilise plus de constante CACHE_URL
figée au chargement ; on évalue à chaque appel. Ensuite, is_ssl() de
WordPress lit correctement X-Forwarded-Proto (à condition d'avoir le bon
SERVER_PORT dans wp-config.php, ce qu'on rappelle dans notre
documentation d'installation). Enfin, set_url_scheme() reconstruit l'URL en
respectant le schéma demandé, sans toucher au reste.
Tant qu'on y est : la même règle pour le préchargement
Notre module de préchargement (echo_preload_link()) émettait aussi des
<link rel="preload"> avec des URLs HTTP. Pareil, même fix :
- Passer toutes les URLs émises par le plugin à travers
set_url_scheme(). - Ajouter
?ver=avec un hash de contenu pour invalider le cache navigateur quand un fichier change. - Détecter le contexte page-builder (Elementor, Beaver, Divi, Bricks, Oxygen) via
is_page_builder_context()pour désactiver la minification quand on est dans un de leurs éditeurs. La minification n'a aucun intérêt côté admin, et elle est systématiquement source de conflits.
Ce qu'il faut vérifier de votre côté
Si vous tombez sur ce bug avec un autre plugin de cache/minification, voici la checklist rapide que vous pouvez appliquer :
- Dans la console DevTools, onglet Console : cherchez les lignes "Mixed Content". Si vous en voyez, vous tenez votre coupable.
- Ajoutez dans
wp-config.php, avant la lignerequire_once ABSPATH . 'wp-settings.php';:
Ça suffit pour la majorité des cas SiteGround / Kinsta / WP Engine derrière proxy SSL.if ( ! empty( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ) { $_SERVER['HTTPS'] = 'on'; } - Désactivez la minification HTML dans les contextes admin : c'est la règle d'or. Aucun visiteur ne voit l'admin, l'économie de poids est nulle, et vous évitez 90 % des conflits avec les page builders.
- Si votre plugin de cache n'expose pas cette option, ouvrez un ticket. C'est un défaut de conception, pas une demande de feature.
Pourquoi ça nous a pris deux semaines
Honnêtement : parce qu'aucun de nos environnements de dev ne reproduisait le bug. En local sur MAMP, pas de proxy SSL, donc pas de Mixed Content. Sur notre staging, on testait le front en navigation publique, jamais l'éditeur Elementor. Le bug ne s'est révélé que chez un client en production, et il a fallu reproduire son setup exact (SiteGround + Cloudflare proxy + Elementor Pro) pour le voir.
Leçon retenue : notre nouveau pipeline de test automatisé via SSH sur staging active désormais tous les modules et charge systématiquement l'éditeur Elementor d'une page complexe pour vérifier qu'il s'ouvre sans erreur console. Ce test n'existait pas en v1.3.0. Il existe en v1.3.5.