Balises ALT PrestaShop : audit, méthode et génération assistée par IA
PrestaShop

Balises ALT PrestaShop : audit, méthode et génération assistée par IA

Auditer les textes alternatifs des images PrestaShop, les préparer par IA langue par langue, les relire puis les importer sans risque. Scripts pour PrestaShop 8 et 9.

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

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 :

<?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 :

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

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 →