Chapitre 1120 minDébutant
Faire évoluer un site avec les données de l'organisation
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- formuler un besoin en récits utilisateurs et critères d'acceptation ;
- choisir entre import de fichier, API et accès à une base ;
- lire une extension WordPress qui importe des données ;
- protéger les données internes et personnelles exploitées par le site.
3 exercices corrigés1 schéma
Faire évoluer un site exploitant les données de l'organisation, c'est lui ajouter une fonction qui s'appuie sur les informations que l'organisation gère déjà ailleurs : un catalogue alimenté par le logiciel de stock, un agenda tiré de la base des animations, une prise de rendez-vous reliée au planning, des horaires mis à jour depuis une source unique. C'est la troisième activité de la compétence « présence en ligne » du référentiel. Ce chapitre suit un projet complet à la Cyclerie, de l'expression du besoin à la mesure du résultat, et compare les façons techniques de relier un site aux données de l'organisation sans les mettre en danger.
Ce que demande le référentiel
L'activité s'intitule « participer à l'évolution d'un site Web exploitant les données de l'organisation », et l'indicateur correspondant est que « le site a évolué conformément au besoin exprimé ». Trois mots comptent :
- participer : tu n'as pas à tout faire seul, mais ta contribution doit être identifiable ;
- exploitant les données de l'organisation : il ne s'agit pas de changer une couleur ou d'ajouter une page de texte, mais d'afficher ou de collecter des données qui ont une existence dans le système d'information ;
- conformément au besoin exprimé : il faut un besoin formulé au départ, et une preuve qu'il est satisfait à l'arrivée.
| Exemple d'évolution | Données exploitées | Plutôt SLAM | Plutôt SISR |
|---|---|---|---|
| Catalogue des vélos d'occasion | Stock du logiciel de caisse | Développer l'extension qui importe et affiche les vélos | Mettre en place l'échange sécurisé, la tâche planifiée, la supervision |
| Agenda des animations d'une médiathèque | Base des animations | Page alimentée par la base, filtres par public | Hébergement, sauvegarde, sous-domaine et certificat |
| Prise de rendez-vous en ligne | Planning de l'atelier | Formulaire relié au planning, confirmation par courriel | Configuration de l'outil, messagerie (SPF, DKIM), droits des utilisateurs |
| Carte des points de collecte d'une collectivité | Fichier des points tenu par un service | Import et affichage sur une carte accessible | Automatisation de l'import, contrôle des données |
| Annuaire des professionnels d'un réseau | Base des adhérents | Recherche et fiches, en ne publiant que les données autorisées | Gestion des comptes, sauvegardes, journalisation |
De la demande à la mise en production
Une évolution de site est un petit projet (travailler en mode projet). À la rentrée de sa deuxième année, la gérante confie à Ondine le catalogue des vélos d'occasion qu'elle avait évoqué lors du choix du CMS (chapitre 3). Léo suit les étapes suivantes.
1. Recueillir et formuler le besoin. La gérante explique : « Les clients appellent sans arrêt pour savoir si on a un vélo d'occasion à leur taille. Je voudrais qu'ils voient sur le site ce qu'on a en magasin, sans que la vendeuse ressaisisse tout. » Léo reformule par écrit et fait valider : afficher sur le site les vélos d'occasion en vente, à partir du logiciel de caisse et de stock, mis à jour automatiquement, sans ressaisie.
2. Écrire les récits utilisateurs et les critères d'acceptation. Un récit utilisateur (user story) décrit un besoin du point de vue de celui qui utilise le site ; les critères d'acceptation disent comment on vérifiera qu'il est satisfait.
| Récit utilisateur | Critères d'acceptation |
|---|---|
| En tant que client, je veux voir les vélos d'occasion disponibles pour savoir si ça vaut le déplacement | La page /velos-occasion/ liste tous les vélos au statut « en vente » dans le stock ; chaque fiche montre la photo, le type, la taille de cadre, l'année, l'état et le prix ; un vélo vendu disparaît du site dans l'heure |
| En tant que client, je veux filtrer par taille et par type pour trouver vite un vélo qui me convient | Filtres « taille » et « type » utilisables au clavier ; le nombre de résultats s'affiche |
| En tant que vendeuse, je ne veux rien ressaisir | Aucune saisie dans WordPress : un vélo ajouté dans le logiciel de stock apparaît sur le site dans l'heure |
| En tant que gérante, je veux qu'aucune information interne ne soit publiée | Le prix d'achat, le nom du déposant et les notes internes n'apparaissent ni sur le site, ni dans la base WordPress |
3. Analyser l'existant. Le logiciel de caisse de la Cyclerie, en SaaS, propose une API REST en lecture : on peut lui demander, en HTTPS et avec une clé, la liste des articles d'une catégorie.
4. Maquetter la page dans le respect de la charte graphique (chapitre 5), et la faire valider.
5. Développer et tester sur la préproduction, avec un cahier de recette qui reprend chaque critère d'acceptation (cours tests).
6. Faire la recette avec la gérante, corriger, obtenir sa validation écrite (recette et procès-verbal).
7. Mettre en production, documenter (fonctionnement, procédure en cas de panne de l'import), former la vendeuse.
8. Mesurer l'effet (chapitre 7).
Trois façons de relier le site aux données
| Approche | Principe | Avantages | Limites |
|---|---|---|---|
| Import d'un fichier | Le logiciel exporte un fichier (CSV, JSON) déposé sur le serveur par SFTP ; une tâche planifiée l'importe | Simple, marche avec presque tout logiciel, découple les deux systèmes | Données à jour seulement à chaque export ; format à surveiller |
| Appel d'une API | Le site interroge une API du logiciel, côté serveur, et met le résultat en cache ou en base | Données fraîches, format documenté, accès limité par une clé | Il faut que le logiciel propose une API ; gérer les pannes et les quotas |
| Accès direct à la base | Le site se connecte directement à la base du logiciel métier | Données en temps réel | À éviter depuis Internet : la base du système d'information exposée au serveur web, un seul défaut et toutes les données sont en danger |
Dans les trois cas, une règle : le visiteur du site ne touche jamais le système de l'organisation. C'est le serveur du site qui récupère les données, les filtre, et ne garde que ce qui doit être publié.
Léo retient l'API, déjà proposée par le logiciel, avec une clé en lecture seule limitée à la catégorie « occasion ». Il demande au support de l'éditeur de configurer la réponse pour qu'elle ne contienne que les champs publics : c'est la minimisation des données à la source.
Le catalogue, côté WordPress
Le développement tient dans une petite extension WordPress, écrite par Léo et relue par son tuteur. Elle déclare un type de contenu dédié, velo_occasion, pour que les vélos aient leurs propres fiches, leur adresse (/velos-occasion/…) et leur page de liste :
<?php
/**
* Plugin Name: Cyclerie – Vélos d'occasion
* Description: Publie les vélos d'occasion du logiciel de stock.
*/
function cyclerie_cpt() {
register_post_type( 'velo_occasion', array(
'labels' => array(
'name' => "Vélos d'occasion",
'singular_name' => "Vélo d'occasion",
),
'public' => true,
'has_archive' => true,
'rewrite' => array( 'slug' => 'velos-occasion' ),
'supports' => array( 'title', 'editor', 'thumbnail' ),
'show_in_rest' => true,
) );
}
add_action( 'init', 'cyclerie_cpt' );
L'import, déclenché toutes les heures par le planificateur de WordPress, appelle l'API et crée ou met à jour une fiche par vélo :
function cyclerie_importer_velos() {
$reponse = wp_remote_get( CYCLERIE_STOCK_URL . '/articles?categorie=occasion&statut=en_vente', array(
'headers' => array( 'Authorization' => 'Bearer ' . CYCLERIE_STOCK_CLE ),
'timeout' => 15,
) );
// En cas d'erreur, on garde le catalogue actuel et on le note dans le journal
if ( is_wp_error( $reponse ) || 200 !== wp_remote_retrieve_response_code( $reponse ) ) {
error_log( 'Cyclerie : import des vélos impossible' );
return;
}
$velos = json_decode( wp_remote_retrieve_body( $reponse ), true );
if ( ! is_array( $velos ) ) {
error_log( 'Cyclerie : réponse de l\'API illisible' );
return;
}
$references_en_vente = array();
foreach ( $velos as $velo ) {
$reference = sanitize_text_field( $velo['reference'] ?? '' );
if ( '' === $reference ) {
continue;
}
$references_en_vente[] = $reference;
$existants = get_posts( array(
'post_type' => 'velo_occasion',
'post_status' => 'any',
'meta_key' => 'reference',
'meta_value' => $reference,
'numberposts' => 1,
'fields' => 'ids',
) );
$fiche = array(
'post_type' => 'velo_occasion',
'post_status' => 'publish',
'post_title' => sanitize_text_field( $velo['designation'] ?? '' ),
'meta_input' => array(
'reference' => $reference,
'type' => sanitize_text_field( $velo['type'] ?? '' ),
'taille' => sanitize_text_field( $velo['taille_cadre'] ?? '' ),
'annee' => absint( $velo['annee'] ?? 0 ),
'etat' => sanitize_text_field( $velo['etat'] ?? '' ),
'prix' => round( (float) ( $velo['prix_vente'] ?? 0 ), 2 ),
),
);
if ( $existants ) {
$fiche['ID'] = $existants[0];
}
wp_insert_post( $fiche );
}
// Les vélos absents de la réponse ont été vendus : on retire leur fiche du site
$publies = get_posts( array(
'post_type' => 'velo_occasion',
'post_status' => 'publish',
'numberposts' => -1,
'fields' => 'ids',
) );
foreach ( $publies as $id ) {
if ( ! in_array( get_post_meta( $id, 'reference', true ), $references_en_vente, true ) ) {
wp_update_post( array( 'ID' => $id, 'post_status' => 'draft' ) );
}
}
}
add_action( 'cyclerie_import_horaire', 'cyclerie_importer_velos' );
register_activation_hook( __FILE__, function () {
if ( ! wp_next_scheduled( 'cyclerie_import_horaire' ) ) {
wp_schedule_event( time(), 'hourly', 'cyclerie_import_horaire' );
}
// Déclare le type de contenu puis régénère les adresses : sans cela, /velos-occasion/ renvoie une 404
cyclerie_cpt();
flush_rewrite_rules();
} );
register_deactivation_hook( __FILE__, function () {
wp_clear_scheduled_hook( 'cyclerie_import_horaire' );
unregister_post_type( 'velo_occasion' );
flush_rewrite_rules();
} );
L'import des photos (téléchargement de l'image et rattachement à la fiche) est omis ici pour garder l'exemple lisible ; il suit le même principe.
Quelques choix à savoir justifier devant un jury :
- l'adresse de l'API et la clé sont des constantes définies dans
wp-config.php(CYCLERIE_STOCK_URL,CYCLERIE_STOCK_CLE), pas dans le code de l'extension, qui pourrait se retrouver dans un dépôt Git ; - chaque valeur reçue est nettoyée (
sanitize_text_field,absint, conversion en nombre) avant d'être enregistrée : on ne fait jamais confiance à une source externe, même interne à l'organisation ; - si l'API ne répond pas, l'import s'arrête sans rien supprimer : le site garde le catalogue de l'heure précédente plutôt que d'afficher une page vide ;
- à l'activation, l'extension déclare le type de contenu et régénère les règles d'adresses (
flush_rewrite_rules), sinon/velos-occasion/renvoie une 404 tant que personne n'a réenregistré les permaliens ; à la désactivation, elle supprime sa tâche planifiée (wp_clear_scheduled_hook) et retire ses adresses, pour ne laisser ni import orphelin ni règle inutile ; - les vélos vendus passent en brouillon plutôt que d'être supprimés, ce qui garde un historique et permet de les republier s'ils reviennent en stock ;
- à l'affichage, le thème échappe chaque valeur (
esc_html,esc_url) pour empêcher qu'un contenu inattendu soit interprété comme du code dans la page (faille XSS).
Pour le référencement, chaque fiche reçoit un titre et une description générés à partir de ses données (« VTC électrique taille M, 2023, très bon état – 1 290 € »), et des données structurées Product avec une offre (Offer) au prix et à la disponibilité réels (chapitre 6).
Sécurité et données personnelles
Exploiter les données de l'organisation sur un site public impose quelques garde-fous :
| Risque | Garde-fou |
|---|---|
| Publier une donnée interne (prix d'achat, marge, note interne) | Minimisation à la source (l'API ne renvoie que les champs publics) et dans le code (on n'enregistre que les champs prévus) |
| Publier une donnée personnelle (nom du déposant d'un vélo en dépôt-vente) | Ne jamais l'importer ; vérifier la réponse de l'API pendant la recette |
| Vol de la clé d'API | Clé en lecture seule, limitée à une catégorie, stockée hors du code, renouvelée si un doute existe |
| Injection ou affichage de code malveillant | Nettoyage à l'entrée, échappement à la sortie, requêtes préparées si on interroge une base (cours SQL) |
| Indisponibilité du logiciel source | Import qui conserve les dernières données, alerte en cas d'échecs répétés |
| Formulaire qui collecte des données (rendez-vous, réservation) | Information des personnes, durée de conservation, accès limité (chapitre 9) |
Mesurer le résultat
Le besoin exprimé par la gérante était de réduire les appels et de faire venir les clients. Trois mois après la mise en ligne, Léo relève : 1 380 visites de la page /velos-occasion/, la page la plus consultée après l'accueil ; 46 clics sur le bouton « Réserver un essai » ; et, selon la vendeuse, nettement moins d'appels pour demander « ce que vous avez en taille M ». Le délai moyen entre la mise en stock et la vente d'un vélo d'occasion, tiré du logiciel de caisse, est passé de 24 à 17 jours. C'est ce genre de résultat, chiffré et relié au besoin, qui prouve que « le site a évolué conformément au besoin exprimé ».
Exercices
Exercice 1 sur 3 Écrire des critères d'acceptation Réussi À revoir
Une médiathèque veut que son agenda en ligne soit alimenté par la base des animations tenue par les bibliothécaires. Écris un récit utilisateur pour un usager et un pour une bibliothécaire, avec deux critères d'acceptation chacun.
Voir la réponseMasquer la réponse de l'exercice 1
Une proposition :
- En tant qu'usager, je veux voir les animations à venir pour choisir celles qui m'intéressent. Critères : la page « Agenda » liste les animations dont la date est postérieure à aujourd'hui, triées par date ; chaque animation affiche le titre, la date, l'horaire, le public visé et le lieu ; une animation passée disparaît de la liste le lendemain.
- En tant que bibliothécaire, je veux saisir une animation une seule fois. Critères : une animation créée dans la base des animations apparaît sur le site sans autre saisie, dans un délai annoncé (par exemple une heure) ; une animation annulée dans la base est retirée du site ou affichée « annulée » dans le même délai.
Un bon critère est vérifiable pendant la recette : « rapide » ou « joli » ne le sont pas, « dans l'heure » ou « utilisable au clavier » le sont.
Tu avais trouvé ?
Exercice 2 sur 3 Choisir l'approche technique Réussi À revoir
Pour chaque situation, choisis entre import de fichier, appel d'API et accès direct à la base, et justifie.
- Un club sportif tient la liste de ses créneaux dans un tableur partagé, mis à jour une fois par mois.
- Une entreprise de location de salles utilise un logiciel de réservation en SaaS qui propose une API documentée ; le site doit afficher les disponibilités du jour.
- Un stagiaire propose de connecter directement le site public à la base MySQL de l'ERP de l'entreprise « pour que ce soit en temps réel ».
Voir la réponseMasquer la réponse de l'exercice 2
- Import de fichier : un export CSV mensuel, importé par une tâche planifiée ou même manuellement, suffit. Une API serait disproportionnée pour des données qui changent une fois par mois.
- Appel d'API côté serveur, avec un cache de quelques minutes : les données doivent être fraîches et l'éditeur prévoit cet usage.
- Refuser l'accès direct : il exposerait la base de l'ERP (clients, factures, salaires peut-être) au serveur web public ; une faille du site deviendrait une fuite de tout le système d'information. Proposer à la place une API en lecture seule qui n'expose que les données à publier, ou un export filtré.
Tu avais trouvé ?
Exercice 3 sur 3 Repérer la fuite Réussi À revoir
Pendant la recette, Léo affiche la réponse brute de l'API pour un vélo :
{
"reference": "OCC-2026-041",
"designation": "VTC électrique taille M",
"type": "VTC électrique",
"taille_cadre": "M",
"annee": 2023,
"etat": "Très bon état",
"prix_vente": 1290.00,
"prix_achat": 850.00,
"deposant": "Mme Lefort, 06 12 34 56 78",
"note_interne": "batterie à 82 %, à signaler au client"
}
- Quels champs ne doivent jamais arriver sur le site ?
- Le code de l'extension montré plus haut les publie-t-il ?
- Que fait Léo quand même, et pourquoi ?
Voir la réponseMasquer la réponse de l'exercice 3
prix_achat(information commerciale interne),deposant(donnée personnelle d'une cliente en dépôt-vente : nom et téléphone) etnote_interne. Remarque : l'information sur la batterie doit être donnée au client, mais rédigée par la vendeuse dans la description, pas recopiée d'une note interne.- Non : l'extension n'enregistre que les champs listés dans
meta_input(référence, type, taille, année, état, prix de vente). C'est la minimisation dans le code. - Il demande à l'éditeur du logiciel de retirer ces champs de la réponse de l'API pour la clé du site (minimisation à la source). Tant qu'ils sont transmis, ils circulent jusqu'au serveur web : en cas de compromission du site, de journalisation trop bavarde ou d'une future modification du code, ils pourraient fuiter. Il note le point dans le cahier de recette.
Tu avais trouvé ?