Mis à jour le 1er novembre 2026. Article réécrit à partir du code de PrestaShop 9.2.0 : paramètres du webservice vérifiés (format JSON, champs, filtres, prix calculés, langue), fonctionnement de la nouvelle API d’administration, comportement du panier pour un visiteur venu de WordPress, recommandations de Google sur le rendu JavaScript.
Une architecture headless sépare le moteur e-commerce de la couche de présentation. PrestaShop reste la source de vérité pour les produits, les prix, les stocks et les commandes ; un autre système, ici WordPress, construit les pages. Ce découpage répond à des besoins précis, mais il ajoute un second système à héberger, à sécuriser et à mettre à jour. Il ne rend pas un site plus rapide par lui-même.
Cet article compare les architectures possibles, les deux API de PrestaShop 9, les conséquences pour le SEO et pour le tunnel de commande.
Quatre architectures, du plus simple au plus lourd
| Architecture | Principe | Pour qui | Coût et risque |
|---|---|---|---|
| 1. WordPress éditorial à côté de la boutique | Blog WordPress sur un sous-dossier ou un sous-domaine, liens vers les fiches PrestaShop | La plupart des boutiques qui veulent publier du contenu | Faible : deux sites, aucune synchronisation |
| 2. Blocs produits dans WordPress | Les articles affichent des produits lus par le webservice ; le bouton renvoie vers la fiche PrestaShop | Contenu éditorial riche autour du catalogue | Moyen : cache et cohérence des prix |
| 3. Front entièrement séparé | WordPress, ou un framework rendu côté serveur, sert toutes les pages ; le paiement reste sur PrestaShop | Équipe de développement dédiée, besoins multicanaux | Élevé : SEO, redirections, double maintenance |
| 4. Synchronisation par l’API d’administration | Un service exporte le catalogue vers un index ou un PIM, que le front interroge | Gros catalogues, ERP, recherche externe | Élevé : un service de plus à exploiter |
Pour une boutique de taille modeste, l’architecture 1 couvre l’essentiel du besoin : WordPress pour les guides et le blog, le thème PrestaShop pour le catalogue et la commande. Les architectures 3 et 4 se justifient quand les mêmes données alimentent plusieurs canaux (site, application, bornes) ou quand l’équipe front doit livrer indépendamment du thème.
Les deux API de PrestaShop 9
PrestaShop 9 propose deux interfaces. Leur comparaison, vérifiée dans le code de la version 9.2.0 :
| Critère | Webservice (historique) | API d’administration (PrestaShop 9) |
|---|---|---|
| Activation | Paramètres avancés > Webservice, « Activer le service web » | Paramètres avancés > API d’administration ; renvoie 404 si elle est désactivée |
| Point d’entrée | /api/, réécrit vers webservice/dispatcher.php | /admin-api/, dossier séparé à la racine |
| Authentification | Clé en Basic (nom d’utilisateur = clé) ou paramètre ws_key | OAuth 2, flux client_credentials, jeton JWT de 3 600 s par défaut |
| Droits | Méthodes HTTP par ressource et par clé | Scopes par client, par exemple product_read |
| Formats | XML par défaut, JSON avec output_format=JSON | JSON |
| Couverture | 64 ressources dans le cœur (produits, déclinaisons, stocks, paniers, commandes…) | Ressources fournies par le module ps_apiresources (0.9.0 dans la 9.2) |
L’API d’administration repose sur API Platform. Elle impose HTTPS en TLS 1.2 minimum, sauf option réservée au mode debug, et renvoie 404 en multiboutique tant que l’option expérimentale correspondante n’est pas activée. Son nom le dit : elle sert à administrer la boutique depuis un ERP, un PIM ou un script. Les ressources que nous avons trouvées dans la 9.2 ne couvrent pas un panier de visiteur ; elle ne remplace donc pas le webservice pour un front public. L’équipe PrestaShop a annoncé en 2024 qu’elle remplacerait à terme le webservice, sans calendrier.
Mettre en place le webservice
Une clé à permissions minimales
Créez une clé par application et laissez PrestaShop générer la valeur. Pour un affichage public, la lecture (GET) suffit sur products, categories, images, manufacturers, combinations et stock_availables. N’ajoutez des écritures sur carts, customers ou orders que pour un besoin précis, relu séparément. Conservez la clé dans wp-config.php ou un gestionnaire de secrets, jamais dans le dépôt de code.
Préférez l’en-tête Basic au paramètre ws_key : une clé passée dans l’URL finit dans les journaux du serveur et des proxys.
Tester l’accès
curl -g -u "VOTRE_CLE_API:" \
"https://boutique.example.fr/api/products?output_format=JSON&display=[id,name,price]&language=1&limit=0,3"
Les paramètres display, filter[champ], sort, limit et language sont lus par le code du webservice 9.2. Avec une seule langue demandée, un champ multilingue comme name est renvoyé sous forme de texte ; avec plusieurs, sous forme de liste d’objets id et value. L’option -g empêche cURL d’interpréter les crochets.
Afficher un prix exact
Le champ price d’un produit est le prix de base hors taxe : il ignore les prix spécifiques, les groupes et les réductions. Le webservice accepte un champ calculé, nommé par vous, avec les paramètres price[nom][use_tax], group, country, currency, quantity ou product_attribute. Le code le calcule avec la même fonction que la boutique.
Interroger le webservice depuis WordPress
Le webservice n’envoie aucune notification : WordPress interroge l’API et met les réponses en cache. Ces fonctions sont à placer dans une extension dédiée.
<?php
// Dans wp-config.php :
// define( 'PRESTASHOP_API_URL', 'https://boutique.example.fr/api/' );
// define( 'PRESTASHOP_API_KEY', 'CLE_GENEREE_PAR_PRESTASHOP' );
function prestashop_get( $resource, array $params = array() ) {
$query = http_build_query( array_merge( array( 'output_format' => 'JSON' ), $params ) );
$url = trailingslashit( PRESTASHOP_API_URL ) . ltrim( $resource, '/' ) . '?' . $query;
$response = wp_remote_get( $url, array(
'timeout' => 10,
'headers' => array( 'Authorization' => 'Basic ' . base64_encode( PRESTASHOP_API_KEY . ':' ) ),
) );
if ( is_wp_error( $response ) ) {
return $response;
}
if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
return new WP_Error( 'prestashop_http', 'Code HTTP ' . wp_remote_retrieve_response_code( $response ) );
}
$data = json_decode( wp_remote_retrieve_body( $response ), true );
return is_array( $data ) ? $data : new WP_Error( 'prestashop_json', 'Réponse invalide.' );
}
function prestashop_get_cached( $resource, array $params = array(), $ttl = 900 ) {
$key = 'ps_' . md5( $resource . wp_json_encode( $params ) );
$cached = get_transient( $key );
if ( false === $cached ) {
$cached = prestashop_get( $resource, $params );
if ( ! is_wp_error( $cached ) ) {
set_transient( $key, $cached, $ttl );
}
}
return $cached;
}
L’affichage d’une liste, avec un prix TTC calculé par PrestaShop :
<?php
$result = prestashop_get_cached( 'products', array(
'display' => '[id,name,link_rewrite,prix_ttc]',
'filter[active]' => '1',
'language' => '1',
'limit' => '0,12',
'price[prix_ttc][use_tax]' => '1',
) );
if ( is_wp_error( $result ) || empty( $result['products'] ) ) {
echo '<p>Produits indisponibles pour le moment.</p>';
return;
}
echo '<ul class="produits">';
foreach ( $result['products'] as $p ) {
$price = number_format( (float) $p['prix_ttc'], 2, ',', ' ' ) . ' € TTC';
echo '<li><h3>' . esc_html( $p['name'] ) . '</h3><p>' . esc_html( $price ) . '</p></li>';
}
echo '</ul>';
Le champ calculé doit figurer dans display : le code du webservice l’autorise explicitement. N’insérez pas d’URL d’image de l’API dans le HTML, car une balise img ne peut pas envoyer l’authentification ; utilisez l’URL publique de l’image sur la boutique ou copiez l’image dans la médiathèque. Pour le cache côté PrestaShop, voir notre guide Valkey ou Redis.
Tester l’API d’administration
Créez un client dans Paramètres avancés > API d’administration, avec le seul scope nécessaire. Le secret n’est affiché qu’une fois.
TOKEN=$(curl -s -X POST "https://boutique.example.fr/admin-api/access_token" \
-d grant_type=client_credentials -d client_id=synchro-catalogue \
-d client_secret="$SECRET" -d "scope[]=product_read" | jq -r .access_token)
curl -s -H "Authorization: Bearer $TOKEN" "https://boutique.example.fr/admin-api/products"
Le jeton se demande et s’utilise uniquement côté serveur. Ce flux ne connaît pas de visiteur : il identifie une application.
SEO du rendu
Google traite les pages JavaScript en trois phases (exploration, rendu, indexation) et indique qu’une page peut rester en file d’attente de rendu plus que quelques secondes. Il recommande toujours le rendu côté serveur ou le pré-rendu, plus rapides pour les visiteurs comme pour les robots. Le rendu dynamique, qui sert une version différente aux robots, est présenté comme un contournement non recommandé. En pratique :
- Rendu : le nom, le prix, la disponibilité et les liens doivent figurer dans le HTML renvoyé par le serveur. Un WordPress classique le fait ; un front JavaScript doit être rendu côté serveur.
- Une seule URL par produit : si WordPress affiche une fiche et que PrestaShop garde la sienne, choisissez la version indexable et pointez la canonical de l’autre vers elle. Dans PrestaShop 9, la règle par défaut est
{id}{-:id_product_attribute}-{rewrite}.html; une migration vers d’autres URL exige des 301 pour chaque ancienne adresse. - Données structurées : le bloc
Productdoit reprendre le prix affiché et la disponibilité réelle, donc les mêmes données que la page. - Produits supprimés : un produit désactivé doit renvoyer un 404 ou un 410 côté WordPress, sans quoi des pages vides restent indexables. Ce contrôle est à coder, l’API ne le signale pas.
- Sitemaps : un sitemap par système, sans doublon entre les deux.
Pour le reste du référencement technique de la boutique, voir notre guide avancé PrestaShop et la gestion des facettes et de la pagination.
Panier et paiement
C’est la part la plus lourde d’un projet headless.
| Option | Avantages | Limites |
|---|---|---|
| Bouton vers la fiche produit PrestaShop | Aucun développement ; modules de paiement intacts | Changement visuel entre les deux sites |
| Lien d’ajout direct au contrôleur panier | Le visiteur arrive avec le produit dans son panier | Le code de la 9.2 exige un jeton pour un client connecté (si la protection est active) et ignore les robots |
Panier reconstruit par l’API (carts, orders) | Expérience unifiée | Livraison, taxes, bons de réduction et paiement à réimplémenter ; la plupart des modules de paiement passent par le front de PrestaShop |
Le lien d’ajout direct (index.php?controller=cart&add=1&id_product=12&qty=1) fonctionne dans le code pour un visiteur anonyme. Pour un client connecté, PrestaShop attend un jeton calculé à partir de son compte, que WordPress ne connaît pas, et le renvoie vers l’accueil. Le bouton vers la fiche produit reste le choix le plus sûr. Les deux sites sur le même domaine, par exemple la boutique à la racine et WordPress sous /blog/, évitent aussi les problèmes de cookies entre domaines.
Coûts et limites
- Synchronisation : un TTL de quinze minutes convient à un catalogue stable, pas à un stock limité ou à une promotion courte. Une purge à la modification suppose un module PrestaShop qui notifie WordPress : le webservice ne le fait pas.
- Surface d’attaque : chaque API ouvre une porte. Restreignez
/webservice/et/admin-api/par adresse IP au niveau du serveur, comme le montre notre guide de sécurisation du back-office, et appliquez les mises à jour de PHP, dont celles du 21 octobre 2026. - Modules front : sliders, pop-ups et widgets de vente sont à réimplémenter ; les modules de gestion (stock, logistique, ERP) continuent de fonctionner.
- Double maintenance : deux systèmes, deux cycles de mise à jour, des compétences en PHP, en API et en SEO technique.
- Mesure : aucun gain n’est acquis d’avance. Mesurez LCP, INP et CLS avant et après, comme le décrit notre guide des Core Web Vitals PrestaShop.
Questions fréquentes
Une petite boutique a-t-elle intérêt à passer en headless ?
Généralement non. Un blog WordPress à côté d’un thème PrestaShop bien configuré couvre la plupart des besoins, sans synchronisation ni double tunnel de commande.
Faut-il utiliser le webservice ou l’API d’administration ?
Pour un front public, le webservice reste l’interface adaptée dans la 9.2. L’API d’administration convient aux synchronisations entre la boutique et un ERP, un PIM ou un index, avec des scopes limités.
Le headless améliore-t-il automatiquement la vitesse ?
Non. Le front attend les réponses de PrestaShop ou de son cache, et le cache introduit un décalage. Mesurez les Core Web Vitals avant et après.
Peut-on exposer la clé du webservice dans le navigateur ?
Non. Les appels partent uniquement du serveur WordPress. Une clé visible dans le code client donne à n’importe qui les permissions accordées.
Sources
- Code de PrestaShop 9.2.0 (lecture locale) :
classes/webservice/WebserviceRequest.php,WebserviceOutputJSON.php,WebserviceOutputBuilder.php,webservice/dispatcher.php,controllers/front/CartController.php,src/PrestaShopBundle/EventListener/API/AdminAPIFeatureListener.php, moduleps_apiresources0.9.0. - PrestaShop Devdocs : webservice (9.x)
- PrestaShop Devdocs : Admin API
- PrestaShop Devdocs : utiliser l’Admin API
- PrestaShop Build : Meet the PrestaShop 9 API (6 juin 2024)
- Google Search Central : principes de base du SEO pour JavaScript
- Google Search Central : le rendu dynamique, une solution de contournement