Сообщение «до бесплатной доставки осталось 800 ₽» — один из самых дешёвых способов поднять средний чек. Покупатель видит конкретную сумму, до которой не хватает, и часто докладывает в корзину ещё одну мелочь, лишь бы не платить за доставку. Ниже — как сделать это в WooCommerce без плагинов.
Рабочий вариант
Код добавляется в functions.php дочерней темы. Сообщение выводится только в корзине и на странице оформления, сразу в нужном месте, и содержит остаток до порога:
add_action( 'woocommerce_before_cart', 'shop_free_shipping_notice' );
add_action( 'woocommerce_before_checkout_form', 'shop_free_shipping_notice' );
function shop_free_shipping_notice() {
if ( ! WC()->cart || WC()->cart->is_empty() ) {
return;
}
$threshold = 5000; // порог бесплатной доставки
$subtotal = (float) WC()->cart->get_subtotal(); // число, без валюты и HTML
$remaining = $threshold - $subtotal;
if ( $remaining > 0 ) {
wc_print_notice(
sprintf( 'Добавьте товаров ещё на %s — и доставка будет бесплатной.', wc_price( $remaining ) ),
'notice'
);
} else {
wc_print_notice( 'Доставка по этому заказу бесплатная.', 'success' );
}
}
Как это устроено. Хуки woocommerce_before_cart и woocommerce_before_checkout_form срабатывают только на нужных страницах, а wc_print_notice() — в отличие от wc_add_notice() — выводит сообщение сразу, без очереди, поэтому дублей не будет. Функция wc_price() форматирует остаток по настройкам магазина: с нужной валютой, разделителями и количеством знаков.
Какую сумму сравнивать с порогом
Тут есть тонкость. У метода «Бесплатная доставка» в настройках WooCommerce есть переключатель «Применять правило минимальной суммы до скидки по купону». Если он выключен, порог сравнивается с суммой уже после скидок, и в коде стоит брать get_cart_contents_total() вместо get_subtotal(). Иначе сообщение пообещает бесплатную доставку, а система её не даст — или наоборот. Сверьте эти две настройки между собой.
Порог — из настроек, а не из кода
Хардкод «5000» в коде рано или поздно разойдётся с настройкой метода доставки: порог поменяли в админке, а в сообщении осталась старая цифра. Надёжнее читать минимальную сумму прямо из зоны доставки:
function shop_get_free_shipping_threshold() {
foreach ( WC_Shipping_Zones::get_zones() as $zone ) {
foreach ( $zone['shipping_methods'] as $method ) {
if ( 'free_shipping' === $method->id
&& 'yes' === $method->enabled
&& ! empty( $method->min_amount ) ) {
return (float) $method->min_amount;
}
}
}
return 0; // бесплатной доставки по сумме нет
}
Тогда в основной функции строка с порогом становится такой: $threshold = shop_get_free_shipping_threshold(); — и если функция вернула ноль, сообщение выводить не нужно. Одна оговорка: get_zones() не включает зону «Остальные регионы мира»; если бесплатная доставка настроена именно там, её надо проверить отдельно через WC_Shipping_Zones::get_zone( 0 ).
Где ещё показывать
Корзина и чекаут — обязательный минимум. Есть смысл добавить сообщение и в мини-корзину в шапке: там его увидят раньше, ещё в каталоге. Для этого подключите ту же функцию к хуку woocommerce_widget_shopping_cart_before_buttons. Больше трёх мест лучше не делать — навязчивость работает против конверсии.
Если у вас блочная корзина
На новых магазинах корзина и чекаут собраны на блоках, и хуки woocommerce_before_cart и woocommerce_before_checkout_form там не срабатывают — это шаблонные хуки классических страниц на шорткодах. Самый простой обходной путь — обернуть ту же логику в шорткод и поставить его блоком над корзиной в редакторе страницы:
add_shortcode( 'free_shipping_notice', function () {
if ( ! WC()->cart || WC()->cart->is_empty() ) {
return '';
}
$threshold = shop_get_free_shipping_threshold();
if ( ! $threshold ) {
return '';
}
$remaining = $threshold - (float) WC()->cart->get_subtotal();
$text = $remaining > 0
? sprintf( 'Добавьте товаров ещё на %s — и доставка будет бесплатной.', wc_price( $remaining ) )
: 'Доставка по этому заказу бесплатная.';
return '<div class="woocommerce-info">' . $text . '</div>';
} );
Минус варианта в том, что сумма посчитается при загрузке страницы и не обновится, когда покупатель изменит количество в блочной корзине без перезагрузки. Для живого пересчёта нужен уже JavaScript, подписанный на события корзины — или плагин, который это умеет.
Частые ошибки
Брать сумму из «отображаемых» методов. Всё, что называется get_cart_subtotal(), get_cart_total() и похоже на них, возвращает строки для показа. Для арифметики — get_subtotal(), get_cart_contents_total(), get_total( 'edit' ).
Ставить уведомление в очередь. wc_add_notice() нужен, когда сообщение должно пережить редирект — например, после добавления в корзину. Для вывода «здесь и сейчас» — wc_print_notice().
Порог в коде не совпадает с настройкой доставки. Сообщение обещает одно, система считает другое. Читайте порог из зоны.
Не учитывать скидки. Сверьте, до или после купона считается минимальная сумма в методе доставки, и берите ту же базу в коде.
Коротко
Сообщение об остатке до бесплатной доставки — это двадцать строк в дочерней теме: число из get_subtotal(), порог из настроек зоны, вывод через wc_print_notice() в корзине и на чекауте. На блочной корзине те же расчёты заворачиваются в шорткод. Главное — не сравнивать строки с числами и не ставить уведомления в очередь на каждой странице.
Частые вопросы
Потому что этот метод возвращает готовую строку для вывода — с валютой и HTML-разметкой. Для расчётов нужны числовые методы: get_subtotal() или get_cart_contents_total().
wc_add_notice() ставит сообщение в очередь и показывает на ближайшей подходящей странице — его задача пережить редирект. wc_print_notice() выводит сразу в том месте, где вызван, поэтому дублей не бывает.
Прочитать минимальную сумму из метода «Бесплатная доставка» в зоне доставки через WC_Shipping_Zones::get_zones() — свойство min_amount у метода free_shipping. Тогда сообщение всегда совпадает с настройкой.
Хуки классической корзины на блоке не срабатывают. Обходной путь — шорткод с той же логикой, поставленный блоком над корзиной; сумма при этом обновится только после перезагрузки страницы.
Источники
- 1.Free Shipping — документация WooCommercehttps://woocommerce.com/document/free-shipping/
- 2.Setting up Shipping Zones — документация WooCommercehttps://woocommerce.com/document/setting-up-shipping-zones/
- 3.WooCommerce Hooks Referencehttps://woocommerce.github.io/code-reference/hooks/hooks.html


