Le déclic : -73% de trafic organique en 3 mois
En juin 2024, un client e-commerce suisse a vu son trafic Google s’effondrer de 73%. Diagnostic : Core Web Vitals en rouge depuis la mise à jour de l’algorithme de mai.
Métriques avant intervention
- LCP (Largest Contentful Paint) : 4.2s
- FID (First Input Delay) : 180ms
- CLS (Cumulative Layout Shift) : 0.28
- PageSpeed Score : 31/100 mobile
Après 2 semaines d’optimisations
- LCP : 0.8s (-81%)
- FID : 45ms (-75%)
- CLS : 0.02 (-93%)
- PageSpeed Score : 94/100 mobile
- Trafic organique : +127% en 6 semaines
Voici exactement ce que j’ai fait.
LCP : Largest Contentful Paint (< 2.5s)
Problème #1 : Images non optimisées
Avant
<img src="/hero.jpg" alt="Hero">
<!-- 2.8MB JPEG, 4000x3000px -->
Après
<picture>
<source
srcset="/hero-800.webp 800w, /hero-1200.webp 1200w, /hero-1600.webp 1600w"
type="image/webp"
>
<img
src="/hero-1200.jpg"
alt="Hero"
width="1200"
height="600"
loading="eager"
fetchpriority="high"
>
</picture>
<!-- 85KB WebP, dimensions correctes -->
Gain LCP : -1.8s
Script de conversion automatique
# Installer sharp
npm install sharp-cli -g
# Convertir toutes les images hero
for img in public/images/hero-*.jpg; do
sharp -i "$img" -o "${img%.jpg}.webp" --webp quality=85
sharp -i "$img" --resize 800 -o "${img%.jpg}-800.webp"
sharp -i "$img" --resize 1200 -o "${img%.jpg}-1200.webp"
sharp -i "$img" --resize 1600 -o "${img%.jpg}-1600.webp"
done
Problème #2 : Fonts bloquantes
Avant
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
<!-- Bloque le render pendant ~400ms -->
Après
<!-- 1. Preconnect -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- 2. Font display swap -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
<!-- 3. Mieux : self-host -->
<link rel="preload" href="/fonts/inter-var.woff2" as="font" type="font/woff2" crossorigin>
<style>
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-var.woff2') format('woff2');
font-display: swap;
}
</style>
Gain LCP : -600ms
Problème #3 : CSS bloquant
Avant : 1 fichier CSS de 280KB chargé en <head>
Après : Critical CSS inline + CSS asynchrone
<head>
<!-- Critical CSS inline (< 14KB) -->
<style>
/* Styles above-the-fold uniquement */
body { margin: 0; font-family: Inter, sans-serif; }
.hero { height: 600px; background: #1a1a1a; }
/* ... */
</style>
<!-- CSS complet en async -->
<link rel="preload" href="/style.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/style.css"></noscript>
</head>
Outil pour extraire le critical CSS
npm install critical -g
critical index.html --base ./ --inline --minify \
--width 1920 --height 1080 \
> critical.css
Gain LCP : -800ms
FID : First Input Delay (< 100ms)
Problème : JavaScript bloque le main thread
Audit
// Dans Chrome DevTools > Performance
// Identifier les Long Tasks (> 50ms)
Solution : Code splitting + lazy loading
Avant
import Analytics from './analytics';
import ChatWidget from './chat-widget';
import VideoPlayer from './video-player';
// Tout chargé au démarrage → 340KB JS
Après
// Charger uniquement le nécessaire
const loadAnalytics = () => import('./analytics');
const loadChat = () => import('./chat-widget');
const loadVideo = () => import('./video-player');
// Analytics : après 3s
setTimeout(loadAnalytics, 3000);
// Chat : au scroll
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) loadChat();
});
observer.observe(document.querySelector('.chat-trigger'));
// Video : au clic
document.querySelector('.play-btn').addEventListener('click', async () => {
const { default: VideoPlayer } = await loadVideo();
new VideoPlayer().play();
});
Gain FID : -95ms
CLS : Cumulative Layout Shift (< 0.1)
Problème #1 : Images sans dimensions
Avant
<img src="/product.jpg" alt="Product">
<!-- Le navigateur ne connaît pas la taille → layout shift quand l'image charge -->
Après
<img
src="/product.jpg"
alt="Product"
width="600"
height="400"
style="aspect-ratio: 600/400; max-width: 100%; height: auto;"
>
<!-- Espace réservé → pas de layout shift -->
Problème #2 : Fonts qui changent la mise en page
Solution : font-size-adjust
body {
font-family: 'Inter', Arial, sans-serif;
font-size-adjust: 0.5; /* Évite le FOUT */
}
Problème #3 : Bannières/alertes dynamiques
Avant
// Bannière cookie ajoutée après chargement
setTimeout(() => {
document.body.insertAdjacentHTML('afterbegin', '<div class="cookie-banner">...</div>');
}, 1000);
// → CLS de 0.15
Après
<!-- Réserver l'espace dès le HTML -->
<div class="cookie-banner-placeholder" style="height: 60px;"></div>
<script>
// Remplacer le placeholder
document.querySelector('.cookie-banner-placeholder').outerHTML = '...';
</script>
Gain CLS : -0.18
Checklist d’optimisation (30 minutes)
Mesurer (PageSpeed Insights)
[ ] Desktop + Mobile
[ ] Noter LCP, FID, CLS actuels
Images
[ ] Formats next-gen (WebP/AVIF)
[ ] Dimensions explicites (width/height)
[ ] Lazy loading (sauf hero)
[ ] Responsive images (srcset)
Fonts
[ ] Preconnect aux CDN
[ ] font-display: swap
[ ] Envisager self-hosting
CSS
[ ] Critical CSS inline
[ ] CSS non-critique async
[ ] Minification
JavaScript
[ ] Code splitting
[ ] Lazy load non-essentiel
[ ] Defer scripts tiers
Re-mesurer
[ ] Valider gains
[ ] Tester sur vraie 3G/4G
Outils indispensables
- PageSpeed Insights : https://pagespeed.web.dev/
- WebPageTest : Test sur vraie connexion mobile
- Chrome DevTools : Performance tab
- Lighthouse CI : Intégrer dans CI/CD
- Cloudflare : CDN + auto-optimisations
Résultats business
E-commerce suisse (6 semaines après optimisations)
- Trafic organique : +127%
- Taux de rebond : -34%
- Conversions mobiles : +41%
- Position moyenne Google : +12 places
ROI : ~8,500 CHF investis, +87,000 CHF de CA additionnel sur 3 mois.
Quand optimiser ?
Priorité haute si :
- PageSpeed Score < 50
- Trafic mobile > 60%
- E-commerce
- Taux de rebond > 55%
Fréquence : audit tous les 3-6 mois (nouvelles features dégradent souvent les métriques).
Besoin d’un audit de performance ? Contactez-moi pour un diagnostic gratuit de vos Core Web Vitals.