Douze couleurs, trois tailles, une galerie de huit photos par référence : voilà ce qu’un tourneur sur bois de Haute-Loire exportait depuis Shopify avant de rapatrier son catalogue sur WordPress. Il ne vend pas en ligne pour l’instant — il veut d’abord un site vitrine qui affiche ses pièces avec la même richesse que sa boutique précédente, sans dépendre d’un plugin e-commerce complet pour ça.
L’exercice est intéressant parce qu’il oblige à séparer ce qui relève réellement de la vente (paiement, stock, panier) de ce qui relève de la présentation (variantes visuelles, galerie, caractéristiques). Ce second bloc, on peut le reconstituer entièrement avec l’API Blocks, sans toucher à WooCommerce ni à une extension de fiche produit.
Modéliser la fiche comme un bloc composé
Une fiche produit Shopify exporte typiquement un titre, un prix, une description, des variantes (option/valeur) et une galerie d’images. Plutôt que de tout caser dans un seul bloc dynamique, on construit un bloc parent artisan/fiche-produit qui utilise InnerBlocks pour accueillir des blocs enfants : un bloc artisan/variante répété pour chaque combinaison, et une galerie native de WordPress pour les photos.
Le bloc parent porte les attributs globaux :
{
"attributes": {
"nomProduit": { "type": "string" },
"prixBase": { "type": "number" },
"reference": { "type": "string" },
"matiere": { "type": "string" },
"disponible": { "type": "boolean", "default": true },
"delaiFabrication": { "type": "string" }
}
}
Six attributs suffisent à couvrir l’essentiel : nom, prix, référence interne, matière, disponibilité et délai de fabrication — ce dernier étant propre à un artisan, absent d’un export Shopify standard mais essentiel pour rassurer un visiteur.
Gérer les variantes sans champ répétable natif

Gutenberg ne propose pas de champ « répétable » clé en main dans l’inspecteur : chaque variante devient donc un bloc enfant à part entière, inséré via InnerBlocks avec un template et un allowedBlocks restreint :
const ALLOWED_BLOCKS = [ 'artisan/variante' ];
const TEMPLATE = [
[ 'artisan/variante', { option: 'Couleur', valeur: 'Chêne clair' } ],
];
function Edit( { clientId } ) {
const blockProps = useBlockProps();
return (
<div { ...blockProps }>
<InnerBlocks
allowedBlocks={ ALLOWED_BLOCKS }
template={ TEMPLATE }
templateLock={ false }
/>
</div>
);
}
Chaque bloc artisan/variante reste minimal : deux attributs texte (option, valeur) et éventuellement un attribut image pour associer une photo précise à une variante donnée. L’artisan peut ainsi ajouter, réordonner ou supprimer une variante comme il déplacerait un paragraphe — sans formulaire complexe à comprendre.
La galerie : bloc natif plutôt que réinvention
Inutile de coder un composant galerie personnalisé : le bloc core/gallery couvre déjà l’affichage en grille, le lightbox et le responsive. On l’insère simplement dans le template du bloc parent, à la suite des variantes :
- Le bloc parent verrouille sa structure (
templateLock: "insert") pour empêcher l’ajout de blocs hors périmètre. - La galerie reste éditable librement (ajout, suppression, réordonnancement de photos) puisqu’elle n’est pas concernée par le verrou de structure.
- Le rendu final s’appuie sur
render.phppour un affichage cohérent, la galerie étant simplement délégué au rendu natif decore/galleryà l’intérieur des InnerBlocks.
Un rendu dynamique pour l’affichage final
Le bloc parent est déclaré dynamique dans son block.json, avec un render.php qui assemble l’en-tête (nom, prix, matière, disponibilité) et laisse WordPress restituer le contenu des InnerBlocks :
<article class="fiche-produit">
<header>
<h3><?php echo esc_html( $attributes['nomProduit'] ); ?></h3>
<p class="prix"><?php echo esc_html( number_format_i18n( $attributes['prixBase'], 2 ) ); ?> €</p>
<?php if ( ! $attributes['disponible'] ) : ?>
<p class="rupture">Sur commande — <?php echo esc_html( $attributes['delaiFabrication'] ); ?></p>
<?php endif; ?>
</header>
<?php echo $content; ?>
</article>
La variable $content restitue exactement ce que l’éditeur affichait — variantes et galerie — sans qu’il soit nécessaire de reconstruire manuellement chaque InnerBlock côté PHP.
Ce que cette reconstitution n’a pas vocation à couvrir
Sur ce type de projet, mieux vaut livrer une fiche produit statique impeccable qu’un panier bancal : le paiement viendra plus tard, avec la bonne extension, quand le besoin sera confirmé.
Le paiement, la gestion de stock en temps réel et le tunnel de commande restent hors périmètre de cette reconstitution : ils appellent une solution e-commerce dédiée (WooCommerce ou une passerelle de paiement), pas un empilement de blocs. Vouloir tout faire à la main à ce stade reviendrait à réinventer un panier — ce qui n’est ni l’objectif, ni raisonnable en termes de maintenance.
En résumé
Reconstituer une fiche produit Shopify en blocs natifs tient en une poignée de décisions : un bloc parent porteur des attributs globaux, des blocs enfants pour les variantes, la galerie native pour les photos, et un rendu PHP qui assemble le tout. L’artisan retrouve une fiche aussi riche que celle qu’il avait quittée, sans dépendance à une plateforme tierce ni complexité inutile pour un site qui, pour l’instant, ne vend pas encore en ligne.