Если AJAX-запросы в админке или на витрине внезапно начинают возвращать 404, чаще всего проблема не в самом JavaScript, а в том, как сервер отдает /wp-admin/admin-ajax.php. В WordPress и WooCommerce это ломает фильтры, корзину, поиск, автосохранение и любые формы, которые завязаны на AJAX.
Ниже — рабочий порядок проверки: сначала быстро локализуем источник 404, потом правим конфигурацию, и только после этого трогаем код темы или плагинов.
Как выглядит проблема и где искать источник 404
Симптом обычно один из трех:
- в консоли браузера запрос к
admin-ajax.phpуходит, но в ответ приходит 404; - в WooCommerce не обновляется корзина или не работают вариации товара;
- в админке перестают работать метабоксы, автосохранение или загрузка некоторых полей.
Сначала откройте DevTools → Network и найдите запрос к admin-ajax.php. Важно понять, кто именно возвращает 404:
- сам WordPress;
- nginx/Apache;
- кэширующий слой или CDN;
- плагин безопасности, который режет запрос до WordPress.
Если в ответе видна HTML-страница 404 от темы или сервера, это почти всегда серверная маршрутизация или правила доступа. Если ответ похож на JSON с ошибкой приложения, тогда уже смотрим PHP и хук-обработчик.
Диагностика: что проверить в первую очередь
1. Доступен ли сам файл admin-ajax.php
Проверьте URL напрямую в браузере:
https://example.com/wp-admin/admin-ajax.phpОжидаемое поведение — не 404. Обычно без параметров WordPress отвечает строкой 0 или пустым ответом, но сам файл должен открываться. Если уже здесь 404, проблема не в JS.
2. Не переписывает ли сервер путь к wp-admin
На некоторых хостингах или после ручной правки конфигурации могут ломаться правила для /wp-admin/. Проверьте:
- не стоит ли редирект с
/wp-admin/на другой URL; - не блокирует ли WAF запросы к
admin-ajax.php; - не включен ли агрессивный кэш для всего сайта, включая POST-запросы.
Для Apache убедитесь, что стандартные правила WordPress в .htaccess не повреждены. Для nginx проверьте, что запросы к PHP в /wp-admin/ обрабатываются тем же PHP-FPM, что и фронтенд.
3. Не подменяет ли ответ кэш
AJAX-запросы часто ломаются, если кэш-плагин или CDN пытается кэшировать admin-ajax.php. Это особенно заметно в WooCommerce: корзина и фильтры начинают вести себя как будто данные “залипли”.
Проверьте заголовки ответа в Network. Если видите признаки кэша на POST-запросе или на admin-ajax.php, этот путь нужно исключить из кэширования.
Пошаговое решение
Шаг 1. Исключите admin-ajax.php из кэша и оптимизации
В настройках кэш-плагина добавьте исключение для:
/wp-admin/admin-ajax.php/wp-json/, если у вас рядом ломаются REST-запросы;- страниц корзины, оформления заказа и личного кабинета в WooCommerce.
Если используете серверный кэш или CDN, проверьте отдельные правила для POST и для URL с query string. admin-ajax.php не должен обслуживаться как статическая страница.
Шаг 2. Проверьте корректность AJAX-URL в теме или плагине
Частая ошибка — в JS жестко прописан неправильный URL, например без HTTPS, с другим доменом или с лишним слешем. В WordPress правильнее передавать URL через wp_localize_script() или wp_add_inline_script().
add_action('wp_enqueue_scripts', function () {
wp_enqueue_script(
'theme-ajax',
get_stylesheet_directory_uri() . '/assets/js/theme-ajax.js',
array('jquery'),
'1.0.0',
true
);
wp_localize_script('theme-ajax', 'themeAjax', array(
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('theme_ajax_nonce'),
));
});В JS используйте именно переданный URL:
jQuery(function ($) {
$.post(themeAjax.ajaxUrl, {
action: 'theme_check_stock',
nonce: themeAjax.nonce,
product_id: 123
})
.done(function (response) {
console.log(response);
})
.fail(function (xhr) {
console.error('AJAX failed', xhr.status, xhr.responseText);
});
});Шаг 3. Убедитесь, что обработчик зарегистрирован для обеих сторон
Если запрос идет из фронтенда, а зарегистрирован только хук для авторизованных пользователей, WordPress не найдет обработчик. Это не всегда выглядит как 404, но в реальных проектах такие ошибки часто маскируются под “не работает AJAX”.
add_action('wp_ajax_theme_check_stock', 'theme_check_stock_handler');
add_action('wp_ajax_nopriv_theme_check_stock', 'theme_check_stock_handler');
function theme_check_stock_handler() {
check_ajax_referer('theme_ajax_nonce', 'nonce');
$product_id = isset($_POST['product_id']) ? absint($_POST['product_id']) : 0;
if (!$product_id) {
wp_send_json_error(array('message' => 'Некорректный product_id'), 400);
}
wp_send_json_success(array(
'product_id' => $product_id,
'in_stock' => true,
));
}Шаг 4. Проверьте плагины безопасности и ограничения доступа
Некоторые security-плагины и WAF режут admin-ajax.php, если видят частые запросы, подозрительный referer или отсутствие nonce. Это полезно для защиты, но легко ломает фронтенд.
Что делать:
- временно отключить защитный плагин и повторить запрос;
- посмотреть его логи блокировок;
- добавить исключение для конкретного action, если плагин это поддерживает;
- не отключать защиту целиком на продакшене без замены на точечное правило.
Сравнение подходов: что быстрее помогает
| Подход | Когда применять | Плюсы | Минусы |
|---|---|---|---|
| Исключение из кэша | Если 404/ошибка появляется только на фронтенде | Быстро снимает конфликт с CDN и кэшем | Не лечит неверный URL в коде |
| Проверка конфигурации сервера | Если admin-ajax.php не открывается напрямую | Устраняет корень проблемы | Нужен доступ к nginx/Apache |
| Исправление JS и хуков | Если файл доступен, но action не срабатывает | Решает проблему в теме или плагине | Требует проверки кода |
Проверка результата после исправления
После изменений не ограничивайтесь обновлением страницы. Проверьте три уровня:
- Откройте
/wp-admin/admin-ajax.phpнапрямую — 404 быть не должно. - Повторите проблемный сценарий в браузере и посмотрите Network: запрос должен получать ответ от WordPress, а не от кэша или страницы ошибки.
- Если это WooCommerce, проверьте корзину, вариации товара, фильтры и обновление мини-корзины.
Для быстрой проверки можно временно добавить лог в обработчик:
function theme_check_stock_handler() {
error_log('theme_check_stock_handler fired');
check_ajax_referer('theme_ajax_nonce', 'nonce');
wp_send_json_success(array('ok' => true));
}Если запись появляется в debug.log, значит запрос доходит до WordPress и проблема уже не на уровне маршрутизации.
Частые ошибки и как их исправить
- Жестко прописан старый домен в JS. Исправьте на
admin_url('admin-ajax.php')и пересоберите ассеты. - Кэшируется POST-запрос. Исключите
admin-ajax.phpиз кэша на уровне плагина, сервера и CDN. - Нет
wp_ajax_nopriv_*для публичного запроса. Добавьте отдельный хук для неавторизованных пользователей. - Nonce проверяется, но не передается. Сверьте имя поля в JS и PHP:
nonceдолжен совпадать. - Плагин безопасности блокирует action. Посмотрите логи и добавьте точечное исключение, а не отключайте защиту целиком.
Что важно для безопасности и производительности
AJAX-обработчики часто пишут как “быстрый костыль”, а потом они становятся точкой атаки. Минимальный набор защиты:
- проверяйте nonce через
check_ajax_referer(); - валидируйте входные данные через
absint(),sanitize_text_field()и похожие функции; - не возвращайте лишние данные в JSON;
- не делайте тяжелые запросы к базе на каждый клик, если можно кэшировать результат на короткое время.
Если проблема повторяется на нескольких сайтах, имеет смысл проверить не только тему, но и набор типовых оптимизаций. Например, в Clearfy Pro есть функции для чистки лишних элементов и снижения конфликтов на фронтенде, но любые такие инструменты нужно настраивать аккуратно, чтобы не задеть рабочие AJAX-эндпоинты.
Если после всех проверок admin-ajax.php по-прежнему отдает 404, уже стоит смотреть логи веб-сервера и правила виртуального хоста. На этом этапе проблема обычно не в WordPress, а в маршрутизации на уровне хостинга.