Combien de fonctionnalités d’un LMS complet comme LearnDash ou LifterLMS sont réellement utilisées sur un catalogue de dix à vingt leçons ? Sur un projet client récent dans le secteur de la formation professionnelle, la réponse a été : très peu. Le client avait besoin de trois actions précises — afficher une leçon, la marquer comme terminée, reprendre le parcours là où l’apprenant s’était arrêté — sans les quiz notés, les certificats, les groupes d’apprenants ou les parcours conditionnels que propose un LMS complet, avec le poids et la complexité d’administration que cela implique.
Construire un module léger sur mesure, plutôt que d’installer et de configurer un LMS complet pour n’en utiliser qu’une fraction, s’est révélé plus rapide à livrer et plus simple à maintenir pour un catalogue de cette taille. Ce choix ne convient évidemment pas à tous les projets : au-delà d’une certaine complexité pédagogique (quiz, prérequis conditionnels, certificats), un LMS établi redevient le bon choix.
Structurer le parcours avec un CPT et un champ d’ordre
Le cœur du module repose sur un CPT lecon, hiérarchisé par un champ numérique d’ordre plutôt que par la hiérarchie native des pages, plus rigide à requêter :
register_post_type( 'lecon', [
'label' => 'Leçons',
'public' => true,
'show_in_rest' => true,
'supports' => [ 'title', 'editor', 'thumbnail' ],
'has_archive' => false,
] );
register_post_meta( 'lecon', 'ordre_parcours', [
'type' => 'integer',
'single' => true,
'show_in_rest' => true,
] );
Le champ ordre_parcours permet de récupérer l’ensemble des leçons d’un cours triées dans l’ordre pédagogique voulu, via meta_key et orderby => 'meta_value_num' dans une WP_Query, sans dépendre de l’ordre de création des articles.
Enregistrer la complétion d’une leçon
Le suivi de progression tient dans une seule table personnalisée, associant un utilisateur, une leçon et un horodatage de complétion. Une table dédiée évite d’alourdir wp_usermeta avec des dizaines d’entrées sérialisées difficiles à requêter en masse :

CREATE TABLE {$wpdb->prefix}elearning_progression (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT UNSIGNED NOT NULL,
lecon_id BIGINT UNSIGNED NOT NULL,
terminee_le DATETIME NOT NULL,
UNIQUE KEY user_lecon (user_id, lecon_id)
) {$charset_collate};
La contrainte UNIQUE KEY sur la paire utilisateur/leçon évite les doublons et simplifie la logique d’enregistrement : une requête INSERT ... ON DUPLICATE KEY UPDATE suffit à marquer une leçon terminée, qu’elle l’ait déjà été ou non.
Le point d’entrée AJAX de complétion
La marque de complétion se déclenche depuis le front, via un point d’entrée AJAX authentifié :
add_action( 'wp_ajax_marquer_lecon_terminee', function () {
check_ajax_referer( 'elearning_progression', 'nonce' );
$lecon_id = absint( $_POST['lecon_id'] ?? 0 );
if ( ! $lecon_id || ! get_post( $lecon_id ) ) {
wp_send_json_error( 'Leçon introuvable.' );
}
global $wpdb;
$wpdb->query( $wpdb->prepare(
"INSERT INTO {$wpdb->prefix}elearning_progression (user_id, lecon_id, terminee_le)
VALUES (%d, %d, NOW())
ON DUPLICATE KEY UPDATE terminee_le = NOW()",
get_current_user_id(), $lecon_id
) );
wp_send_json_success();
} );
Calculer un pourcentage de progression global
Le pourcentage affiché à l’apprenant se calcule simplement en comparant le nombre de leçons terminées au nombre total de leçons du cours, sans nécessiter de logique complexe de pondération — sauf si le client demande explicitement des leçons à poids variable, auquel cas un champ poids_lecon supplémentaire suffit :
- Compter les leçons terminées pour l’utilisateur courant via une requête
COUNTsur la table de progression. - Diviser par le nombre total de leçons du cours obtenu via
WP_Query. - Mettre en cache ce calcul dans un transient de courte durée si le module est affiché sur une page à fort trafic.
Reprendre le parcours là où l’apprenant s’est arrêté
La fonctionnalité « reprendre » consiste simplement à identifier, parmi les leçons triées par ordre_parcours, la première qui n’apparaît pas encore dans la table de progression de l’utilisateur. Aucune notion de session complexe n’est nécessaire : la table de progression fait déjà foi.
Sur ce projet, le client avait initialement demandé LearnDash par réflexe, avant de réaliser qu’aucune de ses fonctionnalités de quiz ou de certification n’était utile à son catalogue. Le module sur mesure a coûté moins cher à développer que la configuration seule d’un LMS complet.
En résumé
Un suivi de progression de cours en ligne ne justifie pas systématiquement l’installation d’un LMS complet. Pour un catalogue de leçons linéaires sans quiz noté ni certification, un CPT ordonné, une table de progression dédiée et un point d’entrée AJAX de complétion couvrent l’essentiel du besoin, avec une charge d’administration bien moindre pour l’équipe pédagogique du client.