Сценарий узкий, но в магазинах он встречается регулярно: заказ меняет статус, а вместе с ним меняется набор данных, который виден в личном кабинете клиента, в админке или в связанных страницах. Если у вас есть кастомные шаблоны заказов, страницы благодарности, документы, трекинг-страницы или отдельные записи для логистики, имеет смысл отправлять в IndexNow не только товары, но и URL, которые реально обновились после смены статуса.
Важно сразу зафиксировать границу: сам WooCommerce не публикует заказ в публичный индекс как обычную запись, и не каждый URL заказа вообще должен попадать в поисковую выдачу. Поэтому задача здесь не в том, чтобы индексировать все подряд, а в том, чтобы корректно реагировать на изменение статуса и отправлять только те адреса, которые действительно стали другими или получили новый контент.
Когда это нужно и когда не нужно
Если у вас обычный магазин без публичных страниц заказов, то отправка URL заказа в IndexNow не даст пользы. Такие страницы обычно закрыты от индексации, и это правильно. Но есть несколько рабочих кейсов, где автоматизация оправдана:
- страница заказа доступна клиенту по публичному URL и содержит обновляемые блоки: статус, трекинг, состав доставки;
- после смены статуса обновляется отдельная страница в пользовательском кабинете, которая индексируется;
- вы генерируете публичную страницу подтверждения или сервисную страницу, завязанную на заказ;
- при смене статуса меняются связанные записи: например, статья базы знаний, страница доставки, FAQ по заказу или карточка сервиса.
Если же заказ закрыт, доступен только после авторизации и закрыт от индексации, лучше вообще не отправлять его URL. В этом случае IndexNow не решает задачу, а только добавляет лишние запросы.
Диагностика проблемы: что именно не обновляется
Перед кодом стоит понять, какой URL должен уходить в IndexNow. Частая ошибка — отправлять URL самого заказа, хотя поисковику он не нужен. Сначала проверьте, что именно меняется при смене статуса:
- меняется ли публичная страница;
- есть ли у нее канонический URL;
- не закрыта ли она через
noindexили robots.txt; - не кэшируется ли она агрессивно без сброса при обновлении статуса;
- не дублируется ли изменение через другой механизм, например через sitemap или ручную отправку.
Если страница меняется, но в индексе остается старая версия, обычно проблема не в IndexNow как таковом, а в том, что:
- URL не отправляется в момент изменения;
- отправляется не тот адрес;
- страница отдает старый HTML из кэша;
- каноникал указывает на другой URL;
- страница закрыта от индексации, и поисковик ее игнорирует.
Какой хук WooCommerce использовать
Для смены статуса заказа в WooCommerce удобно использовать хук woocommerce_order_status_changed. Он срабатывает после перехода заказа из одного статуса в другой и дает доступ к ID заказа, старому статусу, новому статусу и объекту заказа.
Это лучше, чем пытаться ловить все через обновление поста, потому что статус заказа — отдельная бизнес-событие, а не просто изменение записи.
Базовая отправка URL при смене статуса
Ниже пример, который отправляет в IndexNow URL страницы заказа только для выбранных статусов. Это безопаснее, чем слать запрос на каждый переход, включая служебные статусы.
add_action('woocommerce_order_status_changed', function($order_id, $old_status, $new_status, $order) {
if (! $order instanceof WC_Order) {
$order = wc_get_order($order_id);
}
if (! $order) {
return;
}
// Отправляем только при финальных статусах.
$allowed_statuses = array('processing', 'completed');
if (! in_array($new_status, $allowed_statuses, true)) {
return;
}
$url = get_permalink($order_id);
if (! $url) {
return;
}
$payload = array(
'host' => wp_parse_url(home_url(), PHP_URL_HOST),
'key' => 'YOUR_INDEXNOW_KEY',
'keyLocation' => home_url('/YOUR_INDEXNOW_KEY.txt'),
'urlList' => array($url),
);
$response = wp_remote_post('https://api.indexnow.org/indexnow', array(
'timeout' => 10,
'headers' => array('Content-Type' => 'application/json; charset=utf-8'),
'body' => wp_json_encode($payload),
));
if (is_wp_error($response)) {
error_log('IndexNow error for order ' . $order_id . ': ' . $response->get_error_message());
return;
}
$code = wp_remote_retrieve_response_code($response);
if ($code < 200 || $code >= 300) {
error_log('IndexNow HTTP ' . $code . ' for order ' . $order_id);
}
}, 10, 4);Здесь есть важный момент: get_permalink($order_id) сработает только если у вас действительно есть публичная запись с этим ID. Для стандартного заказа WooCommerce это обычно не тот URL, который нужен для индексации. Поэтому в реальном проекте чаще отправляют не страницу заказа, а кастомный URL, который вы сами строите.
Если URL заказа кастомный
Допустим, у вас есть публичная страница вида /order-tracking/{order_key}/ или отдельный шаблон в кабинете клиента. Тогда лучше формировать адрес явно, а не полагаться на permalink заказа.
add_action('woocommerce_order_status_changed', function($order_id, $old_status, $new_status, $order) {
if (! $order instanceof WC_Order) {
$order = wc_get_order($order_id);
}
if (! $order) {
return;
}
if ($new_status !== 'completed') {
return;
}
$order_key = $order->get_order_key();
$url = home_url('/order-tracking/' . rawurlencode($order_key) . '/');
$payload = array(
'host' => wp_parse_url(home_url(), PHP_URL_HOST),
'key' => 'YOUR_INDEXNOW_KEY',
'keyLocation' => home_url('/YOUR_INDEXNOW_KEY.txt'),
'urlList' => array($url),
);
wp_remote_post('https://api.indexnow.org/indexnow', array(
'timeout' => 10,
'headers' => array('Content-Type' => 'application/json; charset=utf-8'),
'body' => wp_json_encode($payload),
));
}, 10, 4);Такой вариант уже ближе к реальной задаче: вы отправляете именно тот URL, который меняется после завершения заказа и который имеет смысл для поисковика.
Пошаговое решение без лишней магии
- Определите, какой публичный URL должен обновляться при смене статуса.
- Проверьте, что он не закрыт от индексации и отдает 200 OK.
- Добавьте обработчик на
woocommerce_order_status_changed. - Сформируйте список только из нужных URL, без внутренних и приватных адресов.
- Отправляйте запрос в IndexNow через
wp_remote_post(). - Логируйте ошибки, чтобы видеть, что именно не ушло.
- Если URL много, не отправляйте их по одному в бесконечном цикле — лучше собирать пакет и отправлять один запрос с массивом URL.
Проверка результата после внедрения
Проверять нужно не только факт HTTP-запроса, но и то, что изменившийся URL реально доступен и не блокируется. Минимальный чек:
- смените статус тестового заказа в админке WooCommerce;
- посмотрите error log или лог плагина, если вы его добавили;
- проверьте, что запрос ушел на
https://api.indexnow.org/indexnowи получил 2xx; - откройте URL в браузере и убедитесь, что страница отдает актуальный контент;
- проверьте заголовки ответа и канонический URL;
- если страница должна индексироваться, убедитесь, что на ней нет
noindex.
Если у вас есть доступ к логам сервера, полезно отдельно проверить, не режет ли хостинг исходящие запросы. На некоторых конфигурациях PHP-FPM или firewall запрос уходит с задержкой или не уходит вовсе, и это выглядит как проблема IndexNow, хотя на деле блокируется HTTP-клиент WordPress.
Сравнение подходов
| Подход | Когда подходит | Плюсы | Минусы |
|---|---|---|---|
| Хук в functions.php | Быстрый тест или небольшой проект | Минимум кода, быстро проверить гипотезу | Сложнее сопровождать, риск потерять код при смене темы |
| Отдельный мини-плагин | Продакшн и несколько сценариев отправки | Удобно логировать, отключать и обновлять | Нужно чуть больше времени на структуру |
| Через очередь и cron | Много заказов и частые изменения статусов | Снижает нагрузку, проще батчить URL | Нужна дополнительная обработка очереди |
Для магазина с небольшим потоком заказов обычно достаточно мини-плагина. Если заказов много, лучше не отправлять запрос прямо в момент смены статуса, а складывать URL в очередь и отправлять пакетами по cron.
Частые ошибки и как их исправить
Отправляют URL, который закрыт от индексации
Это самая бесполезная ошибка. Если страница заказа закрыта через noindex или robots.txt, поисковик ее все равно не будет использовать. Решение простое: отправляйте только публичные страницы.
Используют неправильный URL
В WooCommerce легко перепутать ID заказа, permalink записи и реальный URL кабинета клиента. Проверяйте итоговый адрес вручную до отправки.
Шлют запрос на каждый промежуточный статус
Если заказ проходит через pending, on-hold, processing, completed, нет смысла отправлять все подряд. Обычно достаточно одного-двух финальных статусов.
Не учитывают кэш
Если страница заказа или связанный публичный URL кэшируется, IndexNow может получить сигнал об обновлении, а пользователь и бот увидят старую версию. В таком случае сначала сбрасывайте кэш страницы, потом отправляйте URL.
Нет логирования ошибок
Без логов вы не поймете, это проблема сети, ключа, ответа API или неверного URL. Минимум — писать в error_log(), лучше — в отдельный лог плагина.
Безопасность и производительность
Ключ IndexNow не должен лежать в публичном репозитории. Если делаете мини-плагин, храните ключ в конфиге или в настройках, а не в открытом коде темы. Сам файл ключа должен быть доступен по keyLocation, но только в том виде, который требует протокол.
Для производительности есть два практических правила:
- не отправляйте запрос синхронно, если статус меняется массово;
- не отправляйте один и тот же URL много раз подряд без необходимости.
Если у вас массовые обновления заказов из интеграции с CRM или складом, лучше собрать URL в массив и отправить одним запросом. Это уменьшает количество HTTP-вызовов и делает поведение предсказуемее.
Мини-плагин вместо правки темы
Если хотите не привязываться к теме, вынесите логику в отдельный плагин. Это особенно полезно, если проект живет долго и тема может меняться. Для таких служебных задач это стандартная практика: код остается на месте, а не теряется после обновления шаблона.
Если вам нужно еще и чистить дубли, закрывать лишние URL или убирать мусорные страницы магазина, можно посмотреть в сторону инструментов вроде Clearfy Pro: https://wpshop.ru/plugins/clearfy. Но саму отправку в IndexNow для специфики заказа все равно лучше держать в своем коде, потому что бизнес-логика у магазинов обычно разная.
Если коротко: сначала определите, какой публичный URL реально меняется при смене статуса, потом привяжите отправку к woocommerce_order_status_changed, затем проверьте ответ API и доступность страницы. В этой задаче выигрывает не самый сложный код, а тот, который отправляет ровно нужный адрес и не шумит лишними запросами.