Проблема массовой отправки URL из WooCommerce в IndexNow
При большом каталоге товаров в WooCommerce возникает задача эффективно отправлять URL в IndexNow для быстрой индексации. Массовые изменения остатков, цен или статусов значительно увеличивают количество URL, которые нужно отправить. Простая отправка всех URL разом может привести к превышению лимитов API, ошибкам из-за таймаутов или блокировкам со стороны поисковых систем.
Диагностика проблемы
- Проверить логи ошибок сервера и плагинов на предмет таймаутов или отказов при отправке URL.
- Отследить HTTP-ответы от IndexNow (статусы 429, 503 и прочие)
- Выявить пики нагрузки при массовых изменениях товаров или цен
- Оценить, сколько URL отправляется в одном запросе и частоту запросов
Оптимальное решение: очередь с пакетной обработкой и отложенной отправкой
Реализация собственной очереди URL для отправки в IndexNow позволяет контролировать скорость и объем запросов, избегать блокировок и ошибок, а также распределять нагрузку по времени.
Шаг 1. Создаём таблицу для очереди URL
CREATE TABLE wp_indexnow_queue ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, url VARCHAR(255) NOT NULL, status ENUM('pending','sent','error') DEFAULT 'pending', attempts INT DEFAULT 0, last_attempt DATETIME DEFAULT NULL, PRIMARY KEY(id), INDEX(status) );Шаг 2. Добавляем URL в очередь при изменениях товаров
Используем хуки WooCommerce для отслеживания изменений и записи URL в очередь:
add_action('woocommerce_update_product', 'enqueue_indexnow_url', 10, 1);function enqueue_indexnow_url($product_id) { $url = get_permalink($product_id); global $wpdb; $table = $wpdb->prefix . 'indexnow_queue'; $exists = $wpdb->get_var($wpdb->prepare("SELECT id FROM $table WHERE url = %s AND status = 'pending'", $url)); if (!$exists) { $wpdb->insert($table, ['url' => $url, 'status' => 'pending', 'attempts' => 0]); }}Шаг 3. Пакетная отправка URL в IndexNow через WP-Cron
Создаем задачу, которая раз в 5 минут отправляет пакеты по 10 URL:
add_action('indexnow_send_batch', 'send_indexnow_batch');function send_indexnow_batch() { global $wpdb; $table = $wpdb->prefix . 'indexnow_queue'; $batch_size = 10; $urls = $wpdb->get_results("SELECT * FROM $table WHERE status = 'pending' ORDER BY id ASC LIMIT $batch_size"); if (empty($urls)) { return; } $url_list = array_column($urls, 'url'); $api_key = 'ваш_ключ_IndexNow'; $endpoint = 'https://api.indexnow.org/indexnow?url=' . implode('&url=', $url_list) . '&key=' . $api_key; $response = wp_remote_get($endpoint, ['timeout' => 10]); foreach ($urls as $url_entry) { $status = is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200 ? 'error' : 'sent'; $attempts = $url_entry->attempts + 1; $wpdb->update( $table, ['status' => $status, 'attempts' => $attempts, 'last_attempt' => current_time('mysql')], ['id' => $url_entry->id] ); }}Запускаем крон событие при инициализации:
if (!wp_next_scheduled('indexnow_send_batch')) { wp_schedule_event(time(), 'five_minutes', 'indexnow_send_batch');}Для добавления интервала 'five_minutes' добавьте фильтр:
add_filter('cron_schedules', function($schedules) { $schedules['five_minutes'] = ['interval' => 300, 'display' => 'Every 5 Minutes']; return $schedules;});Проверка результата после внедрения
- Отслеживайте таблицу
wp_indexnow_queue: статус URL должен меняться наsent. - Проверяйте логи сервера и плагина на отсутствие ошибок отправки.
- Используйте инструменты IndexNow для проверки принятых URL.
- Следите за уменьшением ошибок 429 и 503 в логах.
Частые ошибки и как их исправить
- Ошибка 429 (Too Many Requests): Уменьшите размер пакета и увеличьте интервал отправки.
- Повторные попытки без удаления URL: Добавьте ограничение по количеству попыток (например, 3), после чего отмечайте URL как
errorи исключайте из очереди. - Отправка URL с неправильным протоколом или без www: Используйте
get_permalinkс проверкой и нормализацией URL перед вставкой в очередь. - Отсутствие задачи WP-Cron: Проверьте, что WP-Cron включён и работает на сервере (например, с помощью плагина WP Crontrol).
Практические советы по безопасности и производительности
- Храните ключ API IndexNow в
wp-config.phpили безопасном хранилище, не в коде плагина. - Ограничивайте количество попыток отправки URL, чтобы не создавать нагрузку и не попадать в блокировки.
- Используйте транзиенты или кэш для предотвращения дублирующего добавления URL.
- Мониторьте нагрузку на базу и сервер при массовых обновлениях товаров, распределяйте задачи.
Сравнение вариантов реализации очереди
| Метод | Преимущества | Недостатки | Пример |
|---|---|---|---|
| Прямое отправление при изменении | Простота, мгновенная отправка | Риск таймаутов, блокировок, перегрузка сервера | Хук woocommerce_update_product + wp_remote_get |
| Очередь с WP-Cron и пакетной обработкой | Контроль нагрузки, надежность, масштабируемость | Сложнее в реализации, требует дополнительной таблицы | Реализация в статье |
| Использование сторонних плагинов | Готовые решения, поддержка | Могут быть избыточны, не всегда гибкие | Плагины с IndexNow поддержкой |