Сценарий знакомый: товар добавляется в корзину, но мини-корзина в шапке не меняется, счетчик остается старым, а иногда и кнопка Добавить в корзину ведет себя так, будто AJAX вообще не сработал. В WooCommerce это часто не ошибка самого магазина, а конфликт с кэшированием страницы, минификацией скриптов или темой, которая перехватывает стандартные шаблоны.
Ниже — не набор общих советов, а рабочая схема: как быстро локализовать причину, что именно отключать и как проверить, что корзина обновляется корректно после правки.
Что обычно ломает AJAX-корзину
Проблема почти всегда лежит в одном из трех слоев: кэш HTML-страницы, оптимизация JS или кастомизация темы. WooCommerce сам по себе использует AJAX-запросы для обновления фрагментов корзины, и если на пути стоит агрессивный кэш или скрипт-оптимизатор, обновление может перестать доходить до интерфейса.
Типичные симптомы
- товар добавляется в корзину, но мини-корзина в шапке не меняется;
- счетчик товаров в корзине обновляется только после перезагрузки страницы;
- AJAX-запрос уходит, но фрагменты не подставляются в DOM;
- после включения кэш-плагина проблема появляется, после отключения — исчезает;
- на мобильной версии работает иначе, чем на десктопе, из-за другой сборки JS.
Диагностика проблемы: с чего начать
Не начинайте с правки кода. Сначала проверьте, где именно ломается цепочка: запрос, ответ или отрисовка на странице. Это экономит время и помогает не отключить лишнее.
Проверка в браузере
- Откройте страницу магазина в режиме инкогнито.
- Откройте DevTools → вкладка
Network. - Добавьте товар в корзину и посмотрите, уходят ли запросы к
?wc-ajax=add_to_cartи?wc-ajax=get_refreshed_fragments. - Проверьте, нет ли ошибок в
Console.
Если запросы уходят, но интерфейс не обновляется, чаще всего проблема в JS или в том, что кэш отдает старую версию HTML с уже неактуальными фрагментами. Если запросов нет вообще, тема или плагин могли отключить стандартное поведение WooCommerce.
Что проверить на стороне сайта
- кэш-плагин: есть ли исключения для корзины, оформления и аккаунта;
- серверный кэш или CDN: не кэшируются ли страницы магазина целиком;
- оптимизация JS: объединение, отложенная загрузка, перенос скриптов в футер;
- кастомная тема: не переопределены ли шаблоны мини-корзины и кнопок;
- плагины для мини-корзины, sticky cart, quick view и фильтров товаров.
Пошаговое решение
Ниже порядок, который обычно дает результат быстрее всего. Идите сверху вниз и после каждого шага проверяйте корзину заново.
1. Исключите корзину и оформление из кэша
Страницы /cart/, /checkout/ и /my-account/ не должны кэшироваться как обычные публичные страницы. Если кэш-плагин умеет исключения по URL, добавьте их туда. Если используется CDN, проверьте правила bypass для этих адресов.
Для большинства сайтов этого уже достаточно, если проблема была только в полном HTML-кэше. Но мини-корзина в шапке может оставаться проблемной на остальных страницах, потому что фрагменты корзины подмешиваются через AJAX.
2. Отключите агрессивную оптимизацию JavaScript
Если включены объединение, задержка или отложенная загрузка скриптов, временно выключите эти режимы и проверьте результат. Особенно часто ломают корзину:
- defer/async для
woocommerceиwc-cart-fragments; - объединение JS в один файл;
- удаление «неиспользуемых» скриптов на уровне страницы;
- lazy load для inline-скриптов, которые инициализируют мини-корзину.
Если после отключения оптимизации все заработало, включайте настройки обратно по одной. Так вы найдете конкретный режим, который конфликтует с WooCommerce.
3. Проверьте, не отключен ли скрипт фрагментов корзины
Некоторые темы и плагины пытаются «ускорить» сайт и отключают wc-cart-fragments. Это может быть оправдано только если мини-корзина вообще не используется. Если в шапке есть счетчик или выпадающая корзина, отключать этот скрипт нельзя без замены логики обновления.
Если вы хотите принудительно вернуть стандартное поведение, можно убедиться, что скрипт подключается, а затем проверить, не снимает ли его кто-то через фильтры или оптимизатор.
4. Сузьте конфликт до темы или плагина
Переключите тему на стандартную WooCommerce-совместимую и проверьте корзину. Если проблема исчезла, значит, дело в шаблонах темы, в ее JS или в кастомном выводе мини-корзины. Если не исчезла — отключайте плагины по одному, начиная с:
- кэш-плагинов;
- оптимизаторов скорости;
- плагинов мини-корзины;
- плагинов быстрых просмотров и AJAX-фильтров;
- плагинов, которые меняют поведение кнопки
add to cart.
Рабочий код: как принудительно обновлять фрагменты корзины
Иногда проблема не в кэше как таковом, а в том, что тема не получает актуальные фрагменты после добавления товара. В таком случае можно добавить собственный фрагмент через стандартный фильтр WooCommerce. Это не лечит плохой кэш, но помогает корректно обновлять мини-корзину в теме.
<?php
add_filter( 'woocommerce_add_to_cart_fragments', function( $fragments ) {
ob_start();
?>
<span class="header-cart-count">
<?php echo WC()->cart ? WC()->cart->get_cart_contents_count() : 0; ?>
</span>
<?php
$fragments['span.header-cart-count'] = ob_get_clean();
return $fragments;
} );Здесь важно, чтобы в шаблоне темы был элемент с классом header-cart-count. После добавления товара WooCommerce подменит этот фрагмент на актуальное значение.
Если у вас в шапке не только счетчик, но и список товаров, можно обновлять и контейнер мини-корзины целиком. Принцип тот же: выводите HTML в буфер и возвращайте его по CSS-селектору.
Пример для мини-корзины в шапке
<?php
add_filter( 'woocommerce_add_to_cart_fragments', function( $fragments ) {
ob_start();
?>
<div class="header-mini-cart">
<?php woocommerce_mini_cart(); ?>
</div>
<?php
$fragments['div.header-mini-cart'] = ob_get_clean();
return $fragments;
} );Этот вариант полезен, если тема рисует мини-корзину вручную и стандартные фрагменты не совпадают с вашей разметкой. Но не дублируйте один и тот же блок в нескольких местах с разными селекторами — это усложняет отладку.
Сравнение подходов: кэш, код или плагин
| Подход | Когда подходит | Плюсы | Минусы |
|---|---|---|---|
| Исключить страницы из кэша | Если ломаются cart/checkout и мини-корзина | Быстро, безопасно, без кода | Не решает конфликт JS |
| Исправить фрагменты через код | Если тема выводит кастомную корзину | Контролируемо, без лишних плагинов | Нужно поддерживать код в теме или mu-plugin |
| Поставить отдельный плагин для мини-корзины | Если нужна готовая замена интерфейса | Меньше ручной разработки | Риск конфликта с кэшем и лишняя нагрузка |
Если задача только в том, чтобы убрать конфликт с кэшем, обычно достаточно первого варианта. Код нужен тогда, когда тема нестандартно рисует шапку и стандартные фрагменты не совпадают с версткой.
Проверка результата после внедрения
После изменений не ограничивайтесь одним кликом по кнопке Добавить в корзину. Проверьте несколько сценариев, чтобы не пропустить скрытый конфликт.
- добавление товара со страницы каталога;
- добавление товара со страницы товара;
- обновление мини-корзины в шапке без перезагрузки;
- переход в корзину и проверка, что количество совпадает;
- очистка кэша и повторная проверка в инкогнито;
- проверка на мобильной версии, если там отдельная шапка или отдельный JS-бандл.
В DevTools снова откройте Network и убедитесь, что запросы к wc-ajax возвращают ответ без ошибок. Если ответ есть, а интерфейс не меняется, значит, проблема уже на стороне фронтенда: селектор не совпал, скрипт не отработал или другой JS перезаписывает DOM.
Частые ошибки и как их исправить
Кэш исключили только для cart и checkout
Этого иногда недостаточно. Если мини-корзина в шапке находится на обычных страницах, они тоже должны корректно работать с AJAX-фрагментами. Проверьте, не кэширует ли CDN HTML для каталога и карточек товаров слишком агрессивно.
Отключили wc-cart-fragments без замены логики
После такой «оптимизации» счетчик в шапке перестает обновляться. Если скрипт отключен намеренно, нужно либо заменить его собственной логикой обновления, либо вернуть стандартный механизм WooCommerce.
Сломали селектор фрагмента
Если в коде указан span.header-cart-count, а в шаблоне на самом деле div.header-cart-count или вообще другой класс, фрагмент не подменится. Селектор должен совпадать с реальной разметкой.
Минификацию включили обратно целиком
После исправления проблемы часто возвращают все настройки оптимизатора сразу. В итоге ошибка появляется снова, но уже неочевидно, какой именно параметр виноват. Включайте режимы по одному и проверяйте корзину после каждого шага.
Проверяют только авторизованного администратора
У админа кэш и поведение страниц могут отличаться. Тестируйте в инкогнито и без авторизации, иначе можно пропустить проблему, которая видна обычным покупателям.
Безопасность и производительность: что не стоит делать
Не отключайте все кэширование на сайте ради одной корзины. Это плохой компромисс: магазин начнет работать медленнее, а причина поломки останется неясной. Лучше точечно исключить проблемные страницы и аккуратно настроить JS-оптимизацию.
Если правите код, добавляйте его в дочернюю тему или в отдельный mu-plugin, а не в файлы родительской темы. Тогда обновление темы не затрет исправление. Для магазинов с нестабильной шапкой и большим количеством служебных блоков полезно отдельно документировать, какие селекторы участвуют в AJAX-фрагментах.
Если нужен более широкий контроль над дублями, служебными скриптами и мусором в WordPress, иногда проще сначала навести порядок в базовой оптимизации сайта, а уже потом разбирать WooCommerce-специфику. В таких случаях помогает, например, Clearfy Pro, но только как инструмент для аккуратной настройки, а не как замена диагностики.
Короткий чек-лист перед публикацией исправления
- страницы корзины и оформления исключены из кэша;
- JS-оптимизация проверена без объединения и без defer для WooCommerce-скриптов;
- селекторы фрагментов совпадают с реальной версткой;
- проверка выполнена в инкогнито и без авторизации;
- после очистки кэша корзина обновляется стабильно на всех нужных страницах.
Если после всех проверок AJAX-корзина все еще ведет себя нестабильно, проблема почти наверняка в конкретной теме или в одном из плагинов, который вмешивается в фронтенд. В таком случае быстрее всего оставить минимальную конфигурацию, а затем возвращать компоненты по одному, пока не проявится конфликт.