Skip to content
Learni
View all tutorials
Développement Backend

Comment implémenter le lead scoring en 2026

Introduction

Le lead scoring est une technique essentielle en marketing automation qui attribue un score numérique à chaque prospect (lead) en fonction de son comportement et de ses caractéristiques. Cela permet de prioriser les leads 'chauds' prêts à convertir, optimisant ainsi les efforts des équipes ventes. Imaginez un entonnoir où seuls les meilleurs leads remontent automatiquement : c'est exactement ce que fait le lead scoring.

Dans ce tutoriel beginner, nous implémentons un système complet avec Node.js, Express et TypeScript. Nous calculerons des scores basés sur des critères concrets : présence d'un email professionnel (+10 pts), nombre de pages visitées (+5 pts par page), ouverture d'emails (+15 pts) et téléchargement de ressources (+25 pts). Le résultat ? Une API REST qui stocke les leads en mémoire et les classe par score.

Pourquoi 2026 ? Avec l'essor de l'IA, les bases solides comme celle-ci restent cruciales avant d'ajouter du machine learning. Ce tutoriel est actionnable : copiez-collez le code et testez en 15 minutes. Idéal pour freelances ou startups en growth hacking. (142 mots)

Prérequis

  • Node.js 20+ installé (téléchargez ici)
  • Connaissances basiques en JavaScript/TypeScript
  • Un éditeur comme VS Code
  • Terminal (bash ou PowerShell)
  • 5 minutes pour l'installation

Initialiser le projet

terminal
mkdir lead-scoring-app
cd lead-scoring-app
npm init -y
npm install express typescript @types/express @types/node ts-node
dev: npm install -D nodemon
npm pkg set type="module"
npx tsc --init
mkdir src

Cette commande initialise un projet Node.js moderne avec TypeScript et Express. Le flag --init -y crée package.json rapidement, ts-node permet d'exécuter TS directement, et nodemon recharge le serveur en dev. Évitez les erreurs ESM en settant 'type=module'.

Définir les types Lead

Avant le code, structurons nos données. Un lead aura un ID, email, pages visitées, emails ouverts et ressources téléchargées. Le score sera calculé dynamiquement.

Types et interface Lead

src/types.ts
export interface Lead {
  id: string;
  email: string;
  pagesVisited: number;
  emailsOpened: number;
  resourcesDownloaded: number;
  score?: number;
}

export type Leads = Lead[]; 

Cette interface définit un lead avec ses propriétés clés. score est optionnel car calculé à la volée. Utilisez-la partout pour un typage strict, évitant les erreurs runtime comme un pagesVisited négatif.

Fonction de calcul de score

src/scoring.ts
import { Lead } from './types.js';

export function calculateScore(lead: Lead): number {
  let score = 0;

  // Email professionnel (+10)
  if (/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.(com|fr|io)$/i.test(lead.email) && !lead.email.includes('gmail.com') && !lead.email.includes('yahoo.com')) {
    score += 10;
  }

  // Pages visitées (+5 par page, max 50)
  score += Math.min(lead.pagesVisited * 5, 50);

  // Emails ouverts (+15 par ouverture, max 45)
  score += Math.min(lead.emailsOpened * 15, 45);

  // Ressources (+25 par téléchargement, max 75)
  score += Math.min(lead.resourcesDownloaded * 25, 75);

  return score;
}

export function scoreAllLeads(leads: Lead[]): Lead[] {
  return leads.map(lead => ({ ...lead, score: calculateScore(lead) }));
}

La fonction calculateScore applique des règles métier concrètes avec des seuils pour éviter l'inflation. Regex pour email pro, multiplicateurs limités. scoreAllLeads met à jour une liste entière. Testez-la isolément avant intégration.

Mettre en place le serveur

Nous créons un serveur Express minimaliste avec CORS pour tester depuis un navigateur. Les leads sont stockés en mémoire (array global) pour simplicité beginner.

Serveur Express principal

src/server.ts
import express from 'express';
import cors from 'cors';
import { Lead, Leads } from './types.js';
import { calculateScore, scoreAllLeads } from './scoring.js';

const app = express();
const PORT = 3000;
let leads: Leads = [];

app.use(cors());
app.use(express.json());

app.get('/leads', (req, res) => {
  const scoredLeads = scoreAllLeads(leads);
  scoredLeads.sort((a, b) => (b.score || 0) - (a.score || 0));
  res.json(scoredLeads);
});

app.post('/leads', (req, res) => {
  const newLead: Lead = {
    id: Date.now().toString(),
    ...req.body
  };
  leads.push(newLead);
  res.status(201).json({ message: 'Lead ajouté', lead: newLead });
});

app.listen(PORT, () => {
  console.log(`Serveur lead scoring sur http://localhost:${PORT}`);
});

Ce serveur expose deux routes : GET /leads (liste triée par score descendant) et POST /leads (ajout). scoreAllLeads recalcule à chaque requête pour fraîcheur. Tri décroissant priorise les meilleurs leads. Lancez avec npx ts-node src/server.ts.

Configuration TypeScript

tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "allowJs": true,
    "strict": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "ts-node": {
    "esm": true
  }
}

Ce tsconfig active ESM, strict mode et transpilation. ts-node.esm permet d'exécuter TS nativement. Copiez-collez pour éviter les erreurs de module comme 'Cannot use import statement'.

Script de package.json

package.json
{
  "name": "lead-scoring-app",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "nodemon --exec ts-node src/server.ts",
    "start": "ts-node src/server.ts"
  },
  "dependencies": {
    "express": "^4.19.2",
    "typescript": "^5.6.2",
    "@types/express": "^4.17.21",
    "@types/node": "^22.5.5",
    "ts-node": "^10.9.2",
    "cors": "^2.8.5"
  },
  "devDependencies": {
    "nodemon": "^3.1.4"
  }
}

Mettez à jour package.json avec ces scripts et deps. npm run dev lance en watch mode. Ajout de cors pour tests frontend. Installez avec npm install après.

Tester l'API

Démarrez le serveur : npm run dev.

Utilisez curl ou Postman :

  • POST : curl -X POST http://localhost:3000/leads -H "Content-Type: application/json" -d '{"email":"pro@entreprise.fr","pagesVisited":4,"emailsOpened":2,"resourcesDownloaded":1}'
  • GET : curl http://localhost:3000/leads

Score exemple : 10 (email pro) + 20 (4 pages) + 30 (2 emails) + 25 (1 ressource) = 85 pts.

Client de test HTML/JS

test-client.html
<!DOCTYPE html>
<html>
<head><title>Test Lead Scoring</title></head>
<body>
  <button onclick="addLead()">Ajouter Lead</button>
  <button onclick="getLeads()">Lister Leads</button>
  <pre id="output"></pre>

  <script>
    async function addLead() {
      const response = await fetch('http://localhost:3000/leads', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({
          email: 'test@pro.fr',
          pagesVisited: 5,
          emailsOpened: 1,
          resourcesDownloaded: 0
        })
      });
      const data = await response.json();
      document.getElementById('output').textContent += JSON.stringify(data, null, 2) + '\n';
    }

    async function getLeads() {
      const response = await fetch('http://localhost:3000/leads');
      const leads = await response.json();
      document.getElementById('output').textContent = JSON.stringify(leads, null, 2);
    }
  </script>
</body>
</html>

Ouvrez ce fichier HTML dans un navigateur pour tester interactivement. Ajoute des leads et liste-les triés. Vérifiez les scores recalculés. Parfait pour démo sans outil externe.

Bonnes pratiques

  • Pondérez dynamiquement : Ajustez les coefficients via config JSON pour A/B tests.
  • Persistance : Migrez vers SQLite/Prisma pour prod (remplacez l'array par DB).
  • Validation : Ajoutez Zod pour valider inputs (ex: pagesVisited >=0).
  • Seuils d'alerte : Notifiez Slack si score >80 (intégrez webhooks).
  • Logs : Utilisez Winston pour tracer les calculs de score.

Erreurs courantes à éviter

  • Pas de seuils : Sans Math.min, un lead avec 100 pages score 500+ (irréaliste).
  • Oubli du tri : Toujours sorter descending pour prioriser.
  • Mémoire infinie : Limitez leads à 1000, archivez les anciens.
  • CORS manquant : Erreur frontend sans app.use(cors()).

Pour aller plus loin