Проблема массовых изменений остатков товаров и индексации
В крупных WooCommerce-магазинах часто возникают ситуации, когда происходит массовое обновление остатков товаров (например, после синхронизации с 1С или обновления склада). Без корректной настройки интеграции с IndexNow эти изменения не всегда своевременно отражаются в поисковой выдаче, что снижает актуальность отображаемой информации и может повлиять на продажи.
Обычно штатные хуки WordPress и WooCommerce вызываются при сохранении отдельного товара (save_post, woocommerce_update_product), но при массовом обновлении (bulk edit, импорт, API) они могут не срабатывать или срабатывать слишком часто, что приводит к проблемам с производительностью и лимитами API IndexNow.
Диагностика проблемы: как понять, что изменения не отправляются
- Отсутствие новых URL в логах IndexNow (если ведется логирование отправок).
- Длительный период, когда в поисковиках отображаются устаревшие остатки товаров.
- Высокая нагрузка на сервер при массовом обновлении из-за множественных вызовов отправки URL.
Для точной диагностики можно включить логирование отправок через функцию-обертку:
function indexnow_send_url_with_log( $url ) {
error_log('IndexNow send URL: ' . $url);
// Здесь вызывается реальная функция отправки URL
}Если в логе нет новых URL после обновления, значит автоматизация не работает.
Пошаговое решение: оптимальная автоматизация отправки URL при массовом обновлении остатков
1. Отслеживаем массовое обновление остатков
При массовом обновлении через стандартный импорт или API обычно вызывается функция, которая обновляет мета-поля товаров с остатками (_stock). Чтобы отследить изменения, используем хук updated_post_meta с проверкой конкретного мета-ключа:
add_action('updated_post_meta', 'indexnow_wc_stock_updated', 10, 4);
function indexnow_wc_stock_updated( $meta_id, $post_id, $meta_key, $meta_value ) {
if ( $meta_key === '_stock' && get_post_type($post_id) === 'product' ) {
// Добавляем ID товара в очередь на отправку
indexnow_wc_add_to_queue( $post_id );
}
}2. Организуем очередь для пакетной отправки URL
Чтобы избежать множественных API-вызовов, создаём transient с массивом ID товаров, которые нужно отправить. Отправка будет запускаться через Cron с интервалом 5 минут.
function indexnow_wc_add_to_queue( $product_id ) {
$queue = get_transient('indexnow_wc_queue') ?: [];
if ( ! in_array( $product_id, $queue, true ) ) {
$queue[] = $product_id;
set_transient('indexnow_wc_queue', $queue, 10 * MINUTE_IN_SECONDS);
}
}
// Регистрируем событие Cron
if ( ! wp_next_scheduled( 'indexnow_wc_send_queue_event' ) ) {
wp_schedule_event( time(), 'five_minutes', 'indexnow_wc_send_queue_event' );
}
add_action( 'indexnow_wc_send_queue_event', 'indexnow_wc_send_queue' );
function indexnow_wc_send_queue() {
$queue = get_transient('indexnow_wc_queue');
if ( empty($queue) ) {
return;
}
$urls = [];
foreach ( $queue as $product_id ) {
$permalink = get_permalink( $product_id );
if ( $permalink ) {
$urls[] = $permalink;
}
}
// Отправляем пакет URL в IndexNow (реализуйте реальный вызов API)
$result = indexnow_send_urls_batch( $urls );
if ( $result ) {
delete_transient('indexnow_wc_queue');
}
}
// Добавляем интервал 5 минут для Cron
add_filter('cron_schedules', function($schedules){
$schedules['five_minutes'] = [
'interval' => 300,
'display' => 'Every 5 Minutes'
];
return $schedules;
});3. Реализация функции отправки URL в IndexNow
Пример функции для отправки пакета URL в IndexNow через API. В реальном проекте замените $api_key и URL на ваши значения.
function indexnow_send_urls_batch( array $urls ): bool {
$api_key = 'ВАШ_КЛЮЧ_API_INDEXNOW';
$host = 'https://api.indexnow.org/indexnow';
$payload = [
'host' => parse_url( home_url(), PHP_URL_HOST ),
'key' => $api_key,
'keyLocation' => home_url('/indexnow-key.txt'),
'urlList' => $urls
];
$args = [
'body' => wp_json_encode( $payload ),
'headers' => [ 'Content-Type' => 'application/json' ],
'timeout' => 10,
'redirection' => 5,
'method' => 'POST'
];
$response = wp_remote_post( $host, $args );
if ( is_wp_error( $response ) ) {
error_log( 'IndexNow API Error: ' . $response->get_error_message() );
return false;
}
$code = wp_remote_retrieve_response_code( $response );
return $code === 200;
}Проверка результата после внедрения
- Обновите остаток нескольких товаров массово (через импорт или админку).
- Проверьте, что ID товаров добавляются в transient
indexnow_wc_queue(через var_dump или в базе). - Дождитесь срабатывания Cron (или запустите вручную с помощью
do_action('indexnow_wc_send_queue_event')). - Проверьте логи на предмет успешной отправки URL (error_log или мониторинг сервера).
- Убедитесь, что в панели IndexNow (если есть) отображаются последние отправленные URL.
Частые ошибки и как их исправить
- Отсутствие запуска Cron: Убедитесь, что WP-Cron работает корректно. Для теста вызовите вручную
do_action('indexnow_wc_send_queue_event'). - Повторная отправка одних и тех же URL: Очистка transient после успешной отправки обязательна.
- Неправильный мета-ключ: В WooCommerce остаток хранится в
_stock. Иногда используется_stock_status, но для отправки URL достаточно использовать изменение_stock. - Ошибка при отправке API: Проверьте корректность ключа и доступность URL
indexnow-key.txtна сайте.
Практические советы по безопасности и производительности
- Хранение ключа API: Не храните ключ в коде напрямую. Используйте константы в
wp-config.phpили настройки в админке с защитой. - Ограничение частоты: Пакетная отправка через очередь и Cron снижает нагрузку и риски блокировок.
- Логирование: Логируйте ошибки, но не сохраняйте в логи чувствительные данные.
- Кэширование: Отключайте кэширование для URL
/indexnow-key.txt, чтобы ключ всегда был доступен поисковикам.
Сравнение вариантов реализации автоматической отправки URL при массовом обновлении WooCommerce
| Вариант | Плюсы | Минусы | Рекомендации |
|---|---|---|---|
Обработка в save_post (при сохранении товара) | Простота реализации | Не срабатывает при массовом обновлении, высокая нагрузка при массовом редактировании | Подходит для малых магазинов с редкими изменениями |
Отслеживание updated_post_meta для _stock + очередь + Cron | Оптимальная нагрузка, надежная работа при массовом обновлении | Сложнее в реализации, нужна очередь и Cron | Рекомендуется для крупных магазинов |
| Использование сторонних плагинов для интеграции IndexNow | Быстрая настройка, поддержка разработчиков | Может быть избыточным, нагрузка и ограничения плагина | Подходит, если нет ресурсов для кастомной реализации |