PrestaShop headless avec WordPress : API, SEO et panier
PrestaShop

PrestaShop headless avec WordPress : API, SEO et panier

PrestaShop 9 en headless avec WordPress : webservice ou API d'administration, rendu serveur, panier, paiement et coûts. Architectures et limites.

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

ArchitecturePrincipePour quiCoût et risque
1. WordPress éditorial à côté de la boutiqueBlog WordPress sur un sous-dossier ou un sous-domaine, liens vers les fiches PrestaShopLa plupart des boutiques qui veulent publier du contenuFaible : deux sites, aucune synchronisation
2. Blocs produits dans WordPressLes articles affichent des produits lus par le webservice ; le bouton renvoie vers la fiche PrestaShopContenu éditorial riche autour du catalogueMoyen : 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’administrationUn service exporte le catalogue vers un index ou un PIM, que le front interrogeGros 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èreWebservice (historique)API d’administration (PrestaShop 9)
ActivationParamè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
AuthentificationClé en Basic (nom d’utilisateur = clé) ou paramètre ws_keyOAuth 2, flux client_credentials, jeton JWT de 3 600 s par défaut
DroitsMéthodes HTTP par ressource et par cléScopes par client, par exemple product_read
FormatsXML par défaut, JSON avec output_format=JSONJSON
Couverture64 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 :

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.

OptionAvantagesLimites
Bouton vers la fiche produit PrestaShopAucun développement ; modules de paiement intactsChangement visuel entre les deux sites
Lien d’ajout direct au contrôleur panierLe visiteur arrive avec le produit dans son panierLe 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éeLivraison, 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

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

Agence web PrestaShop & WordPress

Agence web spécialisée PrestaShop et WordPress : création, maintenance, sécurité, performance et référencement. Nos tutoriels sont issus de nos interventions sur de vraies boutiques.

L'agence Genisoft → LinkedIn →