Mis à jour le 1er novembre 2026. L’ancienne version proposait un module qui appelait une IA à chaque enregistrement de produit et écrivait le même texte, en français, dans toutes les langues de la boutique. La méthode ci-dessous la remplace : génération par lots, langue par langue, relecture dans un tableur, puis import contrôlé. Ajouts : les obligations d’accessibilité depuis juin 2025 et une FAQ.
Les textes alternatifs vides sont fréquents sur les catalogues PrestaShop. Les compléter n’est pas une opération de remplissage de mots-clés : un bon texte alternatif décrit ce que montre l’image, pour une personne qui ne la voit pas. L’IA peut préparer un premier jet à grande échelle, à condition de garder une relecture humaine avant toute publication.
Pourquoi les textes alternatifs comptent
- Accessibilité : les lecteurs d’écran lisent ce texte aux personnes aveugles ou malvoyantes. Depuis le 28 juin 2025, la directive européenne sur l’accessibilité s’applique aux services de commerce électronique ; en France, le référentiel technique est le RGAA. La directive exempte les microentreprises qui fournissent des services (moins de 10 personnes et un chiffre d’affaires ou un bilan annuel ne dépassant pas 2 millions d’euros). Faites vérifier votre situation exacte par un professionnel.
- Google Images : Google utilise le texte alternatif, avec le contenu de la page, pour comprendre une image. Ses bonnes pratiques pour les images demandent un texte utile et descriptif, sans bourrage de mots-clés.
- Secours : quand une image ne se charge pas, le navigateur affiche ce texte à sa place.
Où se trouve le texte alternatif dans PrestaShop
C’est le champ Légende de chaque image, dans l’onglet Images de la fiche produit, à remplir pour chaque langue (128 caractères au plus). Si la légende est vide, PrestaShop la remplace par le titre meta du produit, ou à défaut par son nom (vérifié dans le code de PrestaShop 9.2) : toutes les photos d’un produit portent alors le même texte, ce qui n’aide personne.
Étape 1 : faire l’état des lieux
Cette requête compte les légendes vides par langue (adaptez le préfixe ps_) :
SELECT l.iso_code AS langue,
COUNT(*) AS images,
SUM(il.legend IS NULL OR il.legend = '') AS sans_texte,
ROUND(100 * SUM(il.legend IS NULL OR il.legend = '') / COUNT(*), 1) AS pourcentage_vide
FROM ps_image_lang il
JOIN ps_lang l ON l.id_lang = il.id_lang
GROUP BY l.iso_code;
Commencez par les produits qui comptent : meilleures ventes, produits qui reçoivent du trafic de Google Images (visible dans la Search Console, filtre « Type de recherche : Image »).
Étape 2 : préparer les propositions avec l’IA, sans toucher à la boutique
Le script ci-dessous lit les images sans légende dans une langue, envoie chaque photo à un modèle d’IA capable d’analyser des images, et écrit les propositions dans un fichier CSV. Il n’écrit rien dans la boutique. Deux choix importants :
- l’image est lue sur le disque et envoyée directement au modèle : le script fonctionne aussi sur une copie de test ou un site protégé, que le fournisseur d’IA ne pourrait pas télécharger ;
- le modèle et la clé d’API viennent de variables d’environnement : vous changez de modèle sans modifier le code.
<?php
// alt-proposer.php — à placer hors du dossier public, lancer en ligne de commande :
// AI_API_KEY=... AI_MODEL=... php alt-proposer.php /chemin/vers/boutique fr 50
[$script, $shopRoot, $iso, $limit] = $argv + [null, null, 'fr', 50];
require $shopRoot . '/config/config.inc.php';
$idLang = (int) Language::getIdByIso($iso);
$rows = Db::getInstance()->executeS('
SELECT i.id_image, pl.name, cl.name AS category
FROM ' . _DB_PREFIX_ . 'image i
JOIN ' . _DB_PREFIX_ . 'image_lang il ON il.id_image = i.id_image AND il.id_lang = ' . $idLang . '
JOIN ' . _DB_PREFIX_ . 'product p ON p.id_product = i.id_product AND p.active = 1
JOIN ' . _DB_PREFIX_ . 'product_lang pl ON pl.id_product = i.id_product AND pl.id_lang = ' . $idLang . ' AND pl.id_shop = ' . (int) Configuration::get('PS_SHOP_DEFAULT') . '
LEFT JOIN ' . _DB_PREFIX_ . 'category_lang cl ON cl.id_category = p.id_category_default AND cl.id_lang = ' . $idLang . ' AND cl.id_shop = pl.id_shop
WHERE il.legend IS NULL OR il.legend = ""
LIMIT ' . (int) $limit);
$out = fopen("propositions-alt-$iso.csv", 'w');
fputcsv($out, ['id_image', 'langue', 'produit', 'proposition']);
foreach ($rows as $row) {
$file = _PS_PROD_IMG_DIR_ . Image::getImgFolderStatic($row['id_image']) . $row['id_image'] . '-large_default.jpg';
if (!is_file($file)) {
continue;
}
$prompt = "Écris en langue « $iso » le texte alternatif de cette photo de produit e-commerce.\n"
. "Produit : {$row['name']}. Catégorie : {$row['category']}.\n"
. "Décris ce que l'on voit (couleur, matière visible, angle de vue, mise en situation), en 125 caractères au plus.\n"
. "Ne commence pas par « image de » ou « photo de ». N'invente aucune caractéristique invisible sur la photo.\n"
. "Réponds uniquement par le texte.";
$payload = [
'model' => getenv('AI_MODEL'),
'messages' => [[
'role' => 'user',
'content' => [
['type' => 'text', 'text' => $prompt],
['type' => 'image_url', 'image_url' => ['url' => 'data:image/jpeg;base64,' . base64_encode(file_get_contents($file))]],
],
]],
'max_tokens' => 120,
];
$ch = curl_init(getenv('AI_API_URL') ?: 'https://api.openai.com/v1/chat/completions');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer ' . getenv('AI_API_KEY')],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_TIMEOUT => 60,
]);
$response = json_decode((string) curl_exec($ch), true);
$alt = trim($response['choices'][0]['message']['content'] ?? '');
if ($alt !== '') {
fputcsv($out, [$row['id_image'], $iso, $row['name'], mb_substr($alt, 0, 128)]);
}
usleep(300000); // ménager les limites de l'API
}
fclose($out);
echo "Propositions écrites dans propositions-alt-$iso.csv\n";
L’exemple utilise le format d’API de type OpenAI, que proposent plusieurs fournisseurs ; adaptez l’adresse (AI_API_URL) et le format si le vôtre diffère. Lancez-le une fois par langue : chaque langue obtient un texte écrit dans sa langue, pas une copie du français.
Étape 3 : relire dans un tableur
Ouvrez le CSV, comparez avec les photos et corrigez. Les questions à se poser :
- Le texte décrit-il ce que l’on voit réellement ? Une IA peut se tromper de couleur ou confondre une variante.
- Les photos d’un même produit ont-elles des textes différents (face, dos, détail, porté) ?
- Le texte reste-t-il naturel, sans liste de mots-clés ni argument commercial (« meilleur prix », « livraison offerte ») ?
- Une image décorative (fond, motif) n’a pas besoin de description.
Supprimez les lignes que vous ne validez pas : seules les lignes restantes seront importées.
Étape 4 : importer les textes validés
Ce second script lit le CSV relu et remplit la légende seulement si elle est encore vide, langue par langue. Sauvegardez la base avant de le lancer.
<?php
// alt-import.php — php alt-import.php /chemin/vers/boutique propositions-alt-fr.csv
[$script, $shopRoot, $csv] = $argv;
require $shopRoot . '/config/config.inc.php';
$in = fopen($csv, 'r');
fgetcsv($in); // en-tête
$updated = 0;
while (($line = fgetcsv($in)) !== false) {
[$idImage, $iso, , $alt] = $line;
$idLang = (int) Language::getIdByIso($iso);
$image = new Image((int) $idImage);
if (!Validate::isLoadedObject($image) || !$idLang || trim((string) $image->legend[$idLang]) !== '') {
continue; // image absente ou texte déjà rempli : on ne touche à rien
}
$image->legend[$idLang] = mb_substr(trim($alt), 0, 128);
if ($image->update()) {
++$updated;
}
}
echo "$updated textes alternatifs importés\n";
Testez les deux scripts sur une copie avant la boutique en ligne, puis traitez le catalogue par lots (une catégorie à la fois).
Coût et rythme
Le coût dépend du fournisseur, du modèle, de la résolution envoyée et de ses tarifs du moment : ne vous fiez pas à un barème publié ailleurs. Mesurez sur un échantillon de 50 images le coût réel, le taux de propositions acceptées sans correction et le temps de relecture, puis décidez du rythme.
Et ensuite
Les nouvelles photos arrivent sans texte : intégrez la légende à votre procédure d’ajout de produit, ou relancez le script chaque semaine sur les images récentes. Pour le reste de l’optimisation (formats WebP et AVIF, tailles, chargement), voir Images WebP et AVIF sur PrestaShop : automatiser l’optimisation.
Questions fréquentes
Le texte alternatif doit-il contenir le nom du produit ?
Pas obligatoirement. Il doit décrire l’image ; le nom du produit y figure souvent naturellement, mais le répéter sur chaque photo n’apporte rien. Mieux vaut préciser ce qui distingue chaque vue.
Quelle longueur viser ?
Une phrase courte, souvent entre 50 et 125 caractères. PrestaShop limite la légende à 128 caractères.
Pourquoi ne pas générer le texte automatiquement à chaque enregistrement de produit ?
Parce que l’appel à l’IA ralentit l’enregistrement, peut échouer et publie un texte sans relecture. Une génération par lots, relue avant import, est plus sûre et moins coûteuse.
Faut-il un texte pour chaque langue ?
Oui. Chaque langue a son propre champ Légende. Un texte en français sur une fiche anglaise gêne les lecteurs d’écran et n’aide pas le référencement dans cette langue.
Pour aller plus loin
- Images WebP et AVIF sur PrestaShop : automatiser l’optimisation
- IA et SEO produit PrestaShop : la méthode en 5 étapes
- Référencer une boutique PrestaShop : 10 actions en 2026