WooCommerce

Как автоматически проставить alt и title для картинок товаров в WooCommerce

M
Markabus
·12 января 2019 г.
Фотореалистичный кадр рабочего места контент-менеджера магазина: слева настольный лайтбокс с белыми кроссовками и камера на штативе, справа монитор с медиатекой интернет-магазина — сетка миниатюр товаров и панель с пустым текстовым полем; на столе клавиатура, кофе, бирки и коробка — иллюстрация к статье об автоматическом alt для картинок товаров в WooCommerce

Типичная картина в магазине на WooCommerce: сотни товаров, у каждого по несколько фотографий, и почти у всех атрибут alt пустой. Менеджеры загружают картинки быстро, а поле «Атрибут alt» в медиатеке остаётся незаполненным. В результате поисковик не понимает, что изображено, а пользователи с экранными читалками слышат просто «изображение».

Самое простое решение для каталога — автоматически подставлять в alt название товара. Это не идеальное описание, но для карточки товара оно почти всегда осмысленно: «Кроссовки Nike Air Max 90 белые» говорит о фотографии больше, чем пустота.

Сниппет: подставляем название товара при выводе

Код добавляется в functions.php дочерней темы. Он перехватывает атрибуты каждого изображения в момент вывода и, если картинка относится к товару, подставляет его название:

// Автоматический alt для картинок товаров WooCommerce
add_filter( 'wp_get_attachment_image_attributes', 'shop_product_image_alt', 20, 2 );
function shop_product_image_alt( $attr, $attachment ) {
    // Уважаем alt, заполненный вручную
    if ( ! empty( $attr['alt'] ) ) {
        return $attr;
    }

    // Определяем товар: сначала по родителю картинки, затем по текущему посту
    $product_id = $attachment->post_parent;
    if ( ! $product_id || 'product' !== get_post_type( $product_id ) ) {
        global $post;
        if ( $post && 'product' === $post->post_type ) {
            $product_id = $post->ID;
        }
    }

    if ( $product_id ) {
        $attr['alt'] = get_the_title( $product_id );
    }

    return $attr;
}

Фильтр wp_get_attachment_image_attributes срабатывает везде, где WordPress собирает тег изображения через wp_get_attachment_image(): в главном фото товара, в галерее, в списках каталога и в блоках «похожие товары». Приоритет 20 нужен, чтобы наш код выполнился после стандартных фильтров WooCommerce и его значение осталось последним.

Что здесь важно

Проверка на пустой alt. Самая частая ошибка в подобных сниппетах — безусловная перезапись. Если у части картинок alt уже заполнен вручную или сгенерирован, грубый вариант затрёт эту работу. Проверка ! empty( $attr['alt'] ) оставляет ручные описания нетронутыми и подставляет название только там, где пусто.

Товар определяется по картинке, а не по странице. В блоках «похожие товары» и в каталоге глобальный $post указывает на текущий элемент цикла, и обычно этого достаточно. Но у картинки есть свой родитель — post_parent вложения, и это надёжнее: фото получит название именно того товара, к которому прикреплено. Проверка через $post остаётся запасным вариантом для картинок, загруженных без привязки.

Атрибут title не ставим. Иногда название дублируют ещё и в title. Практической пользы в этом нет: поисковики его не учитывают, экранные читалки по умолчанию не озвучивают, а в браузере он лишь вызывает всплывающую подсказку при наведении, которая на картинках товара скорее раздражает. Если title вам всё же нужен, добавьте одну строку — $attr['title'] = $attr['alt']; — перед return.

Вариант второй: записываем alt при загрузке

У фильтра при выводе есть ограничение: он подставляет alt только в HTML, а в базе поле остаётся пустым. Значит, в XML-карте изображений, в REST API и в любом плагине, который читает alt напрямую из медиатеки, картинка так и будет без описания. Если хочется, чтобы alt был «настоящим», его нужно сохранить в момент загрузки:

// Записываем alt в базу при прикреплении картинки к товару
add_action( 'add_attachment', 'shop_set_product_image_alt_on_upload' );
function shop_set_product_image_alt_on_upload( $attachment_id ) {
    $parent_id = wp_get_post_parent_id( $attachment_id );
    if ( ! $parent_id || 'product' !== get_post_type( $parent_id ) ) {
        return;
    }

    $existing = get_post_meta( $attachment_id, '_wp_attachment_image_alt', true );
    if ( '' === $existing ) {
        update_post_meta( $attachment_id, '_wp_attachment_image_alt', get_the_title( $parent_id ) );
    }
}

Хук add_attachment срабатывает один раз для каждой новой картинки. Alt хранится в мета-поле _wp_attachment_image_alt — это то же самое поле, которое вы видите в медиатеке, поэтому его потом можно править руками. Условие '' === $existing снова защищает от перезаписи.

Оба сниппета совместимы: первый закрывает уже загруженные картинки, второй — все новые. Для старого каталога с тысячами фото можно добавить и разовый проход по медиатеке, но это уже отдельная задача.

Когда названия товара недостаточно

Название описывает товар, а не конкретный кадр. Для галереи из пяти фотографий одной куртки — спереди, сзади, деталь молнии, на модели, в сложенном виде — все пять получат одинаковый alt. Для поиска это допустимо, для доступности — слабо. Если хочется настоящих описаний под каждый кадр, задачу лучше отдать нейросети: мы разбирали это в статье о генерации alt-текста нейросетью для WooCommerce. Сниппет из этой заметки тогда остаётся страховкой на случай, если генерация по какой-то картинке не прошла.

Коротко

Пустой alt у картинок товаров — проблема массовая, и закрывается она пятнадцатью строками кода. Фильтр wp_get_attachment_image_attributes подставляет название товара при выводе, хук add_attachment сохраняет его в базу при загрузке. В обоих случаях главное — не перезаписывать то, что уже заполнено, и не тащить за собой бесполезный title.

Частые вопросы

Q.Почему не стоит ставить атрибут title картинкам товаров?

Поисковики его не учитывают, экранные читалки по умолчанию не озвучивают, а в браузере он лишь показывает всплывающую подсказку при наведении. Для SEO и доступности важен только alt.

Q.Сниппет перезапишет alt, который я заполнил вручную?

Нет. Оба варианта сначала проверяют, пуст ли alt, и подставляют название товара только там, где описания нет. Ручные и сгенерированные описания остаются нетронутыми.

Q.Чем вариант с записью при загрузке лучше фильтра при выводе?

Фильтр подставляет alt только в HTML, а в базе поле остаётся пустым — его не увидят XML-карта изображений, REST API и плагины, читающие медиатеку напрямую. Запись при загрузке сохраняет alt в мета-поле, и он становится «настоящим». Лучше использовать оба.

Q.Подойдёт ли название товара как alt для всей галереи?

Для поиска — допустимо, для доступности — слабо: пять ракурсов одной куртки получат одинаковое описание. Если нужны описания под каждый кадр, их лучше генерировать нейросетью, а сниппет оставить как страховку.

Источники

Предыдущая
Как убрать последний элемент в хлебных крошках Woocommerce
Следующая
Как программно получить категорию товара по его ID

Читайте также