Introduction
L'A/B Testing UX est une méthode scientifique pour comparer deux versions d'une interface utilisateur (variante A et B) et déterminer laquelle performe le mieux en termes de conversions, clics ou temps passé. En 2026, avec la maturité des outils frontend, implémenter un test A/B ne nécessite plus de services payants complexes : un simple script JavaScript suffit pour randomiser l'expérience utilisateur et tracker les métriques clés.
Ce tutoriel beginner vous guide pas à pas pour créer un A/B test sur une landing page fictive d'inscription newsletter. Nous testerons deux boutons CTA : un vert optimiste (variante A) vs un bleu confiant (variante B). Imaginez comme un laboratoire : 50% des visiteurs voient A, 50% B ; on mesure les clics pour décider du gagnant.
Pourquoi c'est crucial ? Un bouton mal choisi peut diviser vos inscriptions par 2. À la fin, vous aurez un prototype fonctionnel, localStorage pour persister le variant, et un tracker basique affichant les stats en console. Prêt à booster votre UX data-driven ? (128 mots)
Prérequis
- Connaissances de base en HTML, CSS et JavaScript (niveau débutant).
- Un éditeur de code comme VS Code.
- Un navigateur moderne (Chrome/Firefox) avec console devtools (F12).
- Pas de serveur requis : ouvrez simplement
index.htmlen local.
Étape 1 : Page HTML de base
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>A/B Testing UX - Newsletter</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<h1>Inscrivez-vous à notre newsletter</h1>
<p>Recevez des astuces UX hebdomadaires.</p>
<form id="newsletter-form">
<input type="email" id="email" placeholder="Votre email" required>
<button type="submit" id="cta-button">S'inscrire</button>
</form>
<p id="stats"></p>
</div>
<script src="script.js"></script>
</body>
</html>Ce fichier HTML crée une landing page minimaliste avec un formulaire d'inscription. Le bouton #cta-button sera modifié dynamiquement par JS selon le variant A/B. Le paragraphe #stats affichera les métriques en temps réel. Copiez-collez tel quel pour démarrer.
Étape 1 : Comprendre la structure HTML
Cette structure est responsive et accessible : viewport meta pour mobile, required sur input pour validation native, et IDs clairs pour cibler en JS. Analogie : c'est le squelette de votre test, neutre pour ne biaiser aucun variant. Ouvrez index.html dans votre navigateur pour vérifier.
Étape 2 : Styles CSS pour les variants
body {
font-family: Arial, sans-serif;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
}
.container {
background: white;
padding: 2rem;
border-radius: 10px;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
text-align: center;
max-width: 400px;
}
h1 { color: #333; margin-bottom: 1rem; }
#email {
width: 100%;
padding: 0.75rem;
margin-bottom: 1rem;
border: 1px solid #ddd;
border-radius: 5px;
box-sizing: border-box;
}
#cta-button {
width: 100%;
padding: 0.75rem;
border: none;
border-radius: 5px;
font-size: 1rem;
cursor: pointer;
transition: transform 0.2s;
}
#cta-button:hover { transform: scale(1.02); }
#cta-button.variant-a {
background: #4CAF50;
color: white;
}
#cta-button.variant-b {
background: #2196F3;
color: white;
}
#stats { margin-top: 1rem; font-size: 0.9rem; color: #666; }Les styles de base rendent la page attractive et mobile-first. Les classes .variant-a (vert) et .variant-b (bleu) définissent les deux looks UX à tester : vert pour urgence positive, bleu pour confiance. Le hover ajoute du feedback interactif sans JS.
Étape 2 : Pourquoi ces styles UX ?
Le gradient background crée une ambiance moderne ; le shadow donne de la profondeur comme un carte Material Design. Les variants testent la psychologie des couleurs : vert = action rapide (A), bleu = fiabilité (B). Rechargez la page : le bouton est neutre pour l'instant.
Étape 3 : JS pour assigner le variant
(function() {
// Fonction pour assigner variant A ou B (50/50)
function assignVariant() {
if (localStorage.getItem('ab_variant')) {
return localStorage.getItem('ab_variant');
}
const variant = Math.random() < 0.5 ? 'a' : 'b';
localStorage.setItem('ab_variant', variant);
return variant;
}
const variant = assignVariant();
document.getElementById('cta-button').classList.add(`variant-${variant}`);
console.log(`Variant assigné: ${variant.toUpperCase()}`);
// Initialiser stats
let clicksA = 0;
let clicksB = 0;
updateStats();
function updateStats() {
document.getElementById('stats').textContent =
`Stats: A=${clicksA} clics, B=${clicksB} clics`;
}
})();Ce script utilise localStorage pour persister le variant par utilisateur (évite flicker sur refresh). Math.random() assure 50/50 split. Applique la classe CSS immédiatement au DOM. updateStats() prépare le tracking. Testez en hard refresh (Ctrl+F5) : variant fixe par session.
Étape 3 : Logique de randomisation
Comme un pile ou face digital, le split 50/50 est fair. LocalStorage simule un cookie user-ID : même visiteur voit toujours le même variant. Ouvrez la console (F12) : vous verrez 'Variant assigné: A' ou 'B'. Parfait pour tests cohérents.
Étape 4 : Tracker les clics
// Ajoutez ceci après updateStats() dans script.js
document.getElementById('cta-button').addEventListener('click', function(e) {
e.preventDefault();
const email = document.getElementById('email').value;
if (!email) {
alert('Email requis !');
return;
}
const variant = localStorage.getItem('ab_variant');
if (variant === 'a') {
clicksA++;
} else {
clicksB++;
}
updateStats();
console.log(`Clic sur variant ${variant.toUpperCase()} - Email: ${email}`);
// Ici, envoyez à un backend: fetch('/track', {method: 'POST', body: JSON.stringify({variant, event: 'click'})});
alert('Inscription simulée ! Merci.');
});L'event listener tracke les clics réels, incrémente le bon compteur, et valide l'email. preventDefault() évite submit réel pour test local. Console logge tout ; remplacez par fetch pour prod. C'est actionnable : cliquez plusieurs fois pour voir stats live.
Étape 4 : Mesurer l'impact
Les stats s'affichent sous le formulaire en temps réel. Testez avec plusieurs onglets : chaque a son variant. Taux de clic = clics / visites ; ici, simulez visites en refresh. Variante B gagne souvent car bleu = confiance (psycho UX).
Étape 5 : Reset et analyse
// Ajoutez ces fonctions à la fin de script.js
function resetTest() {
localStorage.removeItem('ab_variant');
clicksA = 0;
clicksB = 0;
updateStats();
location.reload();
}
// Bouton reset (ajoutez dans HTML: <button onclick="resetTest()">Reset Test</button>)
console.log('Test A/B actif. Pour reset: localStorage.clear() ou bouton.');
// Export stats pour CSV
console.table({ 'Variant A': clicksA, 'Variant B': clicksB, 'Taux A': clicksA / (clicksA + clicksB) * 100 || 0, 'Taux B': clicksB / (clicksA + clicksB) * 100 || 0 });Ajoutez un bouton reset dans HTML pour simuler nouveaux users. console.table donne un tableau analysable avec taux %. Copiez le script complet : il est maintenant 100% fonctionnel. Analysez : si A > B de 10%, déployez A !
Étape 5 : Finaliser et scaler
Votre A/B test est live ! Testez 20-50 'visites' (refresh + clic). Pour prod, remplacez console par Google Analytics : gtag('event', 'ab_click', {variant}). Scalable à 100 variants avec Math.random() buckets.
Étape 6 : Version avec fetch backend simu
// Remplacez le console.log par ceci (simule API)
async function trackClick(variant, email) {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
body: JSON.stringify({ variant, email, event: 'ab_click', timestamp: Date.now() }),
headers: { 'Content-Type': 'application/json' }
});
console.log('Tracké:', await response.json());
} catch (e) {
console.error('Tracking échoué:', e);
}
}
// Dans click handler: await trackClick(variant, email);Utilise JSONPlaceholder comme mock API pour persister clics. async/await gère erreurs sans bloquer UX. En prod, pointez vers votre endpoint. Testez : clics s'"envoient" ; inspectez Network tab.
Bonnes pratiques
- Split échantillon : Toujours 50/50 ou segments (ex: mobile/desktop) pour stats fiables.
- Persistance : LocalStorage + user-agent hash pour cross-device.
- Métriques multiples : Trackez clics + scroll + temps (IntersectionObserver).
- Significativité : Min 100 clics/variant ; utilisez Evan Miller calculator.
- No-flicker : Appliquez variant avant
paintavecdocument.documentElement.classList.
Erreurs courantes à éviter
- Oublier persistance : Refresh change variant → stats biaisées (utilisez localStorage).
- Pas de validation : Clics sans email gonflent métriques (ajoutez
if (!email)). - Échantillon trop petit : 10 clics = variance haute ; attendez 100+.
- Flicker UX : JS lent → variante clignote (chargez script dans
avecdefer).
Pour aller plus loin
- Intégrez PostHog ou Amplitude pour dashboards auto.
- Lisez "Trustworthy Online Controlled Experiments" de Kohavi.
- Testez avec Optimizely JS SDK.
- Découvrez nos formations Learni sur UX Data-Driven.
- Repo GitHub exemple : github.com/learni-dev/ab-testing-ux.