WordPress regorge d’APIs natives souvent méconnues, et l’API Shape Detection en fait partie. Elle permet d’analyser des images directement dans le navigateur — détection de visages, de codes-barres, de texte — sans installer la moindre librairie externe. On va voir ensemble comment l’intégrer dans un bloc Gutenberg, avec ses possibilités réelles… et ses limitations à ne pas ignorer.
L’API Shape Detection : c’est quoi exactement ?
Avant de plonger dans l’intégration avec Gutenberg, on a besoin de bien comprendre ce qu’est l’API Shape Detection — et surtout ce qu’elle n’est pas. Parce que oui, le nom peut prêter à confusion au premier abord.
Une API navigateur native, pas une librairie
L’API Shape Detection est une spécification du W3C, portée par le groupe WICG (Web Incubator Community Group). Concrètement, elle s’intègre directement dans le navigateur, au même titre que la Geolocation API ou la Clipboard API. Pas de npm install, pas de yarn add, pas de bundle à charger : tout est déjà là, dans le moteur du navigateur.
C’est exactement ce qui la rend intéressante pour WordPress. On n’alourdit pas le site avec une dépendance externe (adieu les 200 Ko de TensorFlow.js pour un simple scan de QR code !). La logique de détection s’exécute côté client, souvent en s’appuyant sur les capacités matérielles de l’appareil. Résultat : des performances bien meilleures que ce qu’on obtiendrait avec une librairie JavaScript pure.
Bon, « expérimental » ne veut pas dire « inutilisable ». Ça veut dire qu’il faut gérer la compatibilité avec soin — on y revient juste après.
Les trois détecteurs disponibles : visages, codes-barres, texte
L’API expose trois interfaces principales, chacune ciblant un type de détection spécifique :
FaceDetector: détecte les visages humains dans une image. Pratique pour des fonctionnalités de recadrage automatique ou de validation de photo de profil dans un formulaire Gutenberg.BarcodeDetector: probablement le détecteur le plus utile en pratique. Il supporte une vingtaine de formats (QR code, EAN-13, Code 128, Data Matrix, etc.) et fonctionne à une vitesse impressionnante.TextDetector: reconnaît et extrait du texte présent dans une image (OCR basique). Son support est plus limité que les deux autres, mais il peut dépanner pour des cas simples.
Chaque interface suit le même pattern : on instancie le détecteur, on lui passe une image (ou un élément <canvas>, <img>, ImageBitmap…), et il retourne une Promise avec les résultats. Simple et cohérent.
Compatibilité et support navigateur en 2026
C’est le point sur lequel il faut être honnête : l’API Shape Detection n’est pas encore universelle. Voici l’état du support en 2026 :
| Navigateur | Support |
|---|---|
| Chrome 70+ | ✅ Complet (FaceDetector, BarcodeDetector, TextDetector) |
| Edge 79+ (Chromium) | ✅ Complet |
| Firefox | ⚠️ Partiel — nécessite d’activer un flag dans about:config |
| Safari | ❌ Non supporté |
Concrètement, on couvre environ 65-70% des utilisateurs desktop avec Chrome et Edge seuls. Ce n’est pas parfait, mais pour un outil d’administration WordPress (où Chrome domine largement), c’est tout à fait acceptable.
La bonne pratique, c’est de toujours tester la disponibilité de l’API avant de l’utiliser. Un simple check suffit :
if ('FaceDetector' in window) {
// L'API est disponible, on peut l'utiliser
} else {
// Fallback ou message d'information
console.warn('Shape Detection API non supportée sur ce navigateur.');
}
Vous pouvez consulter le tableau de compatibilité complet sur Can I Use ou sur MDN Web Docs. Et pensez à toujours prévoir un fallback — ça fait partie des bonnes pratiques, quelle que soit l’API utilisée.
Intégrer l’API Shape Detection dans un bloc Gutenberg
On attaque maintenant le cœur du sujet : construire un bloc Gutenberg fonctionnel qui exploite BarcodeDetector pour analyser une image directement dans l’éditeur. Tout se passe côté client — pas de PHP, pas de requête serveur, juste du JavaScript dans l’éditeur. C’est là que c’est intéressant !
Créer un bloc personnalisé avec @wordpress/create-block
La première étape, c’est de scaffolder le bloc avec l’outil officiel de WordPress :
npx @wordpress/create-block shape-detection-block
cd shape-detection-block
npm start
Cette commande génère une structure propre et prête à l’emploi. Les fichiers qui nous intéressent sont :
src/edit.js: le composant React affiché dans l’éditeur Gutenberg (c’est ici que tout se passe)src/save.js: le rendu statique enregistré en base de donnéesblock.json: les métadonnées du bloc (nom, attributs, supports…)
Dans block.json, on va déclarer les attributs dont on a besoin :
{
"attributes": {
"imageUrl": { "type": "string", "default": "" },
"imageId": { "type": "number", "default": 0 },
"detectedValues": { "type": "array", "default": [] }
}
}
Simple et efficace. On stocke l’URL de l’image, son ID dans la médiathèque, et les résultats de détection.
Charger et analyser une image dans l’éditeur côté client
Dans edit.js, on utilise MediaUpload de @wordpress/block-editor pour permettre à l’utilisateur de choisir une image depuis la médiathèque WordPress. Voici un snippet complet et commenté :
import { useState, useRef } from '@wordpress/element';
import { MediaUpload, MediaUploadCheck } from '@wordpress/block-editor';
import { Button } from '@wordpress/components';
export default function Edit({ attributes, setAttributes }) {
const { imageUrl, detectedValues } = attributes;
const [isDetecting, setIsDetecting] = useState(false);
const imgRef = useRef(null);
// Analyse de l'image avec BarcodeDetector
const runDetection = async () => {
// Vérification du support navigateur (voir section suivante)
if (!('BarcodeDetector' in window)) return;
setIsDetecting(true);
try {
// On crée l'instance en précisant les formats souhaités
const detector = new BarcodeDetector({
formats: ['qr_code', 'ean_13', 'code_128'],
});
// imgRef.current pointe vers l'élément <img> rendu dans le bloc
const results = await detector.detect(imgRef.current);
// On stocke les résultats dans les attributs du bloc
setAttributes({
detectedValues: results.map((r) => ({
rawValue: r.rawValue,
format: r.format,
boundingBox: {
x: Math.round(r.boundingBox.x),
y: Math.round(r.boundingBox.y),
width: Math.round(r.boundingBox.width),
height: Math.round(r.boundingBox.height),
},
})),
});
} catch (err) {
console.error('Erreur lors de la détection :', err);
} finally {
setIsDetecting(false);
}
};
return (
<div>
<MediaUploadCheck>
<MediaUpload
onSelect={(media) =>
setAttributes({ imageUrl: media.url, imageId: media.id })
}
allowedTypes={['image']}
render={({ open }) => (
<Button onClick={open} variant="secondary">
{imageUrl ? 'Changer l\'image' : 'Choisir une image'}
</Button>
)}
/>
</MediaUploadCheck>
{imageUrl && (
<>
{/* L'élément img est passé à BarcodeDetector via la ref */}
<img
ref={imgRef}
src={imageUrl}
alt="Image à analyser"
style={{ maxWidth: '100%' }}
crossOrigin="anonymous"
/>
<Button
onClick={runDetection}
variant="primary"
isBusy={isDetecting}
style={{ marginTop: '12px' }}
>
{isDetecting ? 'Analyse en cours...' : 'Détecter les codes-barres'}
</Button>
</>
)}
</div>
);
}
Un point important : l’attribut crossOrigin="anonymous" sur l’élément <img> est indispensable si l’image provient d’un domaine différent (CDN, par exemple). Sans ça, BarcodeDetector peut lever une erreur de sécurité liée au canvas taint.
Afficher les résultats de détection dans le bloc
detector.detect() retourne une Promise qui résout avec un tableau d’objets. Chaque objet contient notamment :
rawValue: la valeur brute décodée (contenu du QR code, numéro EAN, etc.)format: le format détecté ('qr_code','ean_13'…)boundingBox: unDOMRectReadOnlyavec les coordonnées de la zone détectée dans l’image
Pour afficher ces résultats dans le bloc, on complète le JSX retourné par Edit :
{detectedValues.length > 0 && (
<ul style={{ marginTop: '16px' }}>
{detectedValues.map((item, index) => (
<li key={index}>
<strong>Format :</strong> {item.format} —{' '}
<strong>Valeur :</strong> {item.rawValue}{' '}
<em>
(position : x={item.boundingBox.x}, y={item.boundingBox.y})
</em>
</li>
))}
</ul>
)}
{imageUrl && detectedValues.length === 0 && !isDetecting && (
<p style={{ color: '#757575', marginTop: '8px' }}>
Aucun code-barres détecté pour le moment.
</p>
)}
Et côté save.js, on restitue simplement les valeurs stockées dans les attributs — puisque la détection a eu lieu dans l’éditeur, le résultat est déjà persisté :
export default function Save({ attributes }) {
const { imageUrl, detectedValues } = attributes;
return (
<div>
{imageUrl && <img src={imageUrl} alt="Image analysée" />}
{detectedValues.length > 0 && (
<ul>
{detectedValues.map((item, index) => (
<li key={index}>
{item.format} : {item.rawValue}
</li>
))}
</ul>
)}
</div>
);
}
Gérer les erreurs et les cas de non-support navigateur
On l’a vu dans la première section : BarcodeDetector n’est pas disponible partout. Donc, avant toute chose, on vérifie sa présence dans window. Mais plutôt que de simplement bloquer l’exécution en silence, on informe l’utilisateur dans l’éditeur.
Voici comment intégrer un message conditionnel avec Notice de @wordpress/components :
import { Notice } from '@wordpress/components';
// Dans le JSX du composant Edit :
{!('BarcodeDetector' in window) && (
<Notice status="warning" isDismissible={false}>
Votre navigateur ne supporte pas l'API Shape Detection.
La détection de codes-barres n'est pas disponible.
Utilisez Chrome ou Edge pour accéder à cette fonctionnalité.
</Notice>
)}
On peut aussi désactiver le bouton de détection si l’API est absente :
<Button
onClick={runDetection}
variant="primary"
disabled={!('BarcodeDetector' in window)}
>
Détecter les codes-barres
</Button>
Par contre, attention à un cas particulier : même quand BarcodeDetector est présent dans window, la méthode statique BarcodeDetector.getSupportedFormats() peut retourner un tableau vide sur certaines configurations (notamment dans des contextes sécurisés restreints). Un double contrôle ne fait pas de mal :
const supported = await BarcodeDetector.getSupportedFormats();
if (supported.length === 0) {
// Fallback ou message d'avertissement
}
Bref, toute cette logique vit entièrement dans le JavaScript de l’éditeur. Pas de PHP impliqué, pas d’appel AJAX, pas de traitement serveur. L’analyse se fait en local, dans le navigateur de l’utilisateur, au moment où il édite le contenu. C’est justement ça qui rend l’API Shape Detection intéressante dans ce contexte.
Cas d’usage concrets et limitations à connaître
Bon, maintenant qu’on a vu comment implémenter tout ça techniquement, parlons de ce qu’on peut vraiment en faire dans un contexte WordPress réel. Parce que la technologie c’est bien, mais si on ne sait pas à quoi elle sert concrètement, ça reste un beau jouet de développeur.
Ce qu’on peut faire avec dans WordPress
Les cas d’usage sont plus variés qu’on ne le pense au premier abord. Voici ceux qui ont le plus de sens dans un contexte éditorial ou e-commerce :
- Détection automatique de QR codes dans une image uploadée via la médiathèque : on récupère le
rawValueet on peut proposer à l’éditeur de créer automatiquement un lien ou une redirection. Très pratique pour les blocs « événement » ou « campagne marketing ». - Lecture de codes-barres produits dans un bloc WooCommerce : l’éditeur photographie ou uploade une image du produit, et le bloc récupère l’EAN-13 ou l’UPC pour pré-remplir le champ « référence produit ». Un gain de temps réel en saisie.
- Détection de texte avec
TextDetectordans des images scannées ou des captures d’écran : on peut extraire le texte visible pour l’ajouter enaria-labelou en texte alternatif, ce qui améliore à la fois l’accessibilité et les signaux d’indexation pour les moteurs de recherche.
Ces trois scénarios ont un point commun : ils enrichissent l’expérience dans l’éditeur Gutenberg sans ajouter un seul octet à votre bundle JS côté front.
Quand cette API ne suffit pas
Soyons honnêtes : l’API Shape Detection ne remplace pas tout. Il y a des situations où une librairie spécialisée reste incontournable.
Si vous avez besoin de détecter des objets complexes dans des images (voitures, animaux, produits génériques), TensorFlow.js sera bien plus adapté. L’API native se limite à des formes très spécifiques (visages, codes-barres, texte brut) et n’a pas vocation à faire de la classification générale.
Pour l’OCR avancé — comprendre la mise en page d’un document, gérer plusieurs langues, extraire des tableaux — Tesseract.js reste la référence. TextDetector détecte la présence de texte, mais ne fait pas d’analyse sémantique poussée.
Les limitations à avoir en tête
C’est là que ça se corse un peu, et je préfère être transparent plutôt que de vous laisser découvrir les problèmes en production.
Le statut expérimental de l’API est probablement la limitation la plus importante : la spécification est portée par le WICG et peut évoluer (ou régresser) sans préavis. On n’est pas sur une API aussi stable que fetch ou IntersectionObserver.
La couverture navigateur reste partielle. Firefox et Safari ne supportent pas l’API nativement (voir section 1). Ces deux navigateurs représentent une part de marché cumulée significative — autour de 30 à 35 % selon les audiences. C’est trop pour se permettre de l’ignorer, d’où l’importance du fallback qu’on a mis en place.
Impossible de l’utiliser côté serveur. L’API est 100 % navigateur : pas de Node.js, pas de WP-CLI, pas de REST API. Si vous voulez déclencher une analyse depuis un webhook ou un traitement batch côté serveur, il faudra passer par une autre approche (une API externe, une librairie Python, etc.).
Pas de persistance automatique. Les résultats de la détection vivent dans le navigateur au moment de l’analyse. Si vous voulez stocker les codes-barres détectés en base de données (pour les afficher côté front, les indexer, les réutiliser), il faut coder explicitement un appel wp.apiFetch() vers l’API REST WordPress. Ce n’est pas compliqué, mais ce n’est pas magique non plus.
Une API qui a de l’avenir dans l’écosystème WordPress
Malgré ces limitations, je reste convaincu que l’API Shape Detection a sa place dans une boîte à outils WordPress moderne. Elle est parfaite pour enrichir l’expérience éditeur dans Gutenberg — là où le navigateur est maître — sans alourdir le bundle JS d’une seule librairie externe. Et avec l’adoption croissante de Chromium comme moteur de base (Chrome, Edge, Opera, Brave…), la couverture va mécaniquement augmenter avec le temps.
C’est le genre d’investissement technique qui paye sur le long terme : on code une fois, on repose sur le navigateur, et on profite des améliorations natives sans effort de mise à jour.
