WooCommerce hooks дозволяють змінити майже будь-яку частину магазину, не чіпаючи файли плагіна. Клієнт просить «додати рядок про доставку під кнопкою» або «прибрати поле Компанія з оформлення замовлення», і перша думка зазвичай про плагін. Але здебільшого вистачає 5–10 рядків коду.
Нижче те, чим я користуюся в проєктах: як влаштовані хуки, WooCommerce single product hooks з пріоритетами, хуки кошика й сторінки магазину, найкорисніші фільтри, шість робочих прикладів і кілька помилок, на яких я сам колись втрачав час.
Table of Contents
Action і filter: у чому різниця
Хук — це місце в коді, де WordPress або WooCommerce дозволяє вам щось втрутитись. Їх два види.
Action — «зроби щось у цьому місці». Наприклад, вивести блок тексту. Він нічого не повертає, просто виконується.
Filter — «ось значення, змін його і поверни». Наприклад, текст кнопки або список полів форми. Фільтр обов’язково має повертати значення, інакше воно зникне.
Для обох працює той самий принцип: add_action() або add_filter() з назвою хука, вашою функцією і пріоритетом. Чим менше число пріоритету, тим раніше спрацює функція. За замовчуванням це 10.
Куди писати код
Не в основну тему і не в плагін WooCommerce, бо після оновлення все зникне. Є три нормальні варіанти:
- дочірня тема (файл
functions.php); - власний невеликий плагін на один файл;
- плагін на кшталт Code Snippets, якщо код потрібен лише на одному сайті і ви не хочете створювати файли.
Для клієнтських сайтів я роблю окремий плагін. Тоді код не залежить від теми, і якщо тему змінять, магазин не зламається.
Хуки сторінки товару (WooCommerce single product hooks)
Сторінка окремого товару збирається з кількох хуків. Ось ті, що потрібні найчастіше, разом з тим, що WooCommerce вішає на них за замовчуванням:
| Хук | Пріоритет | Що виводиться |
|---|---|---|
woocommerce_before_single_product_summary | 10 / 20 | Мітка знижки / галерея |
woocommerce_single_product_summary | 5 | Назва |
woocommerce_single_product_summary | 10 | Рейтинг, ціна |
woocommerce_single_product_summary | 20 | Короткий опис |
woocommerce_single_product_summary | 30 | Кнопка «Додати в кошик» |
woocommerce_single_product_summary | 40 | Артикул, категорії, мітки |
woocommerce_single_product_summary | 50 | Хук для кнопок «поділитися» (за замовчуванням порожній) |
woocommerce_after_single_product_summary | 10 / 15 / 20 | Вкладки / апсейли / схожі товари |
Також корисні woocommerce_before_add_to_cart_button і woocommerce_after_add_to_cart_button: вони стоять просто навколо кнопки.
Те саме у вигляді схеми, у порядку, в якому збирається сторінка:
woocommerce_before_single_product
├─ woocommerce_before_single_product_summary
│ 10 мітка знижки · 20 галерея
├─ woocommerce_single_product_summary
│ 5 назва · 10 рейтинг · 10 ціна · 20 короткий опис
│ 30 додати в кошик · 40 метадані · 50 «поділитися»
├─ woocommerce_after_single_product_summary
│ 10 вкладки · 15 апсейли · 20 схожі товари
└─ woocommerce_after_single_product
Одна деталь, про яку часто забувають. Якщо у вас блокова тема і шаблон товару зібраний з блоків (а не з класичного шаблону WooCommerce), частина цих хуків просто не спрацює, бо блоки їх не викликають. Це легко перевірити: додайте тестовий echo на хук і подивіться на сторінці. Якщо нічого не з’явилось, або використовуйте блок «Classic Template» у шаблоні, або змінюйте вивід через фільтр render_block.
Приклад 1. Рядок про доставку під кнопкою
Пріоритет 35 стоїть між кнопкою (30) і метаданими (40), тож рядок з’явиться одразу під кнопкою.
add_action( 'woocommerce_single_product_summary', 'dd_delivery_note', 35 );
function dd_delivery_note() {
echo '<p class="delivery-note">Відправляємо Новою поштою в день замовлення до 15:00.</p>';
}
Якщо текст має бути різним для різних товарів, візьміть його з власного поля товару через get_post_meta() і додайте перевірку, що воно не порожнє.
Приклад 2. Перенести блок в інше місце
Короткий опис за замовчуванням іде над кнопкою. Щоб показати його нижче за метадані, треба зняти стандартний хук і повісити його з новим пріоритетом.
add_action( 'init', 'dd_move_excerpt' );
function dd_move_excerpt() {
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_excerpt', 20 );
add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_excerpt', 45 );
}
Важливо: remove_action має використовувати те саме ім’я функції і той самий пріоритет, що й оригінальний add_action. Інакше нічого не станеться, і помилки ви не побачите. Саме тому я зазвичай запускаю його на init, коли WooCommerce вже зареєстрував свої хуки.
Хуки кошика (WooCommerce cart page hooks)
На сторінці кошика хуків менше, але їх вистачає для типових задач: повідомлення над таблицею, примітка біля підсумку, текст перед кнопкою оформлення.
| Хук | Що виводиться |
|---|---|
woocommerce_before_cart | Перед усією формою кошика |
woocommerce_before_cart_table | Над таблицею товарів |
woocommerce_after_cart_table | Під таблицею товарів |
woocommerce_cart_collaterals | Cross-sell і блок підсумку |
woocommerce_before_cart_totals | Над підсумком |
woocommerce_proceed_to_checkout | Кнопка оформлення (пріоритет 20) |
woocommerce_after_cart | Після всього кошика |
Приклад 3. Примітка над кнопкою оформлення
add_action( 'woocommerce_proceed_to_checkout', 'dd_cart_note', 5 );
function dd_cart_note() {
echo '<p class="cart-note">Безкоштовна доставка від 2000 грн.</p>';
}
Сама кнопка висить із пріоритетом 20, тому пріоритет 5 ставить примітку над нею. Це працює для класичного кошика (шорткод). Якщо на сторінці кошика стоїть блок Cart, ці хуки не діють, тому спершу перевірте, що саме у вас.
Хуки сторінки магазину (WooCommerce shop page hooks)
Сторінки магазину й категорій працюють через цикл: однаковий набір хуків виконується для кожної картки товару. Тому зміни тут впливають на всі товари у списку.
| Хук | Пріоритет | Що виводиться |
|---|---|---|
woocommerce_before_main_content | 10 / 20 | Початок обгортки / хлібні крихти |
woocommerce_archive_description | 10 | Опис категорії |
woocommerce_before_shop_loop | 20 / 30 | Кількість результатів / сортування |
woocommerce_before_shop_loop_item | 10 | Відкриває посилання товару |
woocommerce_shop_loop_item_title | 10 | Назва товару |
woocommerce_after_shop_loop_item_title | 5 / 10 | Рейтинг / ціна |
woocommerce_after_shop_loop_item | 5 / 10 | Закриває посилання / кнопка «Додати в кошик» |
woocommerce_after_shop_loop | 10 | Пагінація |
Приклад 4. Примітка про наявність під ціною в каталозі
add_action( 'woocommerce_after_shop_loop_item_title', 'dd_loop_stock_note', 15 );
function dd_loop_stock_note() {
global $product;
if ( $product->is_in_stock() ) {
echo '<span class="stock-note">В наявності, відправка сьогодні</span>';
}
}
Ціна виводиться з пріоритетом 10, тому 15 ставить примітку одразу під нею.
Фільтри WooCommerce (WooCommerce filter hooks)
Фільтри змінюють значення: текст, HTML, масиви. Ось ті, які я використовую найчастіше:
| Фільтр | Що змінює |
|---|---|
woocommerce_get_price_html | HTML ціни |
woocommerce_product_single_add_to_cart_text | Текст кнопки на сторінці товару |
woocommerce_product_add_to_cart_text | Текст кнопки в каталозі й категоріях |
woocommerce_product_tabs | Вкладки товару: додати, прибрати, змінити порядок |
woocommerce_checkout_fields | Поля форми оформлення (класичний checkout) |
Приклад 5. Змінити текст кнопки
add_filter( 'woocommerce_product_single_add_to_cart_text', 'dd_add_to_cart_text', 10, 2 );
function dd_add_to_cart_text( $text, $product ) {
if ( $product->is_type( 'simple' ) ) {
return 'Купити';
}
return $text;
}
Третій аргумент 10 — пріоритет, четвертий 2 — скільки параметрів функція приймає. Без нього $product не буде передано.
Так само працює і з вкладками. Наприклад, щоб прибрати вкладку «Відгуки»:
add_filter( 'woocommerce_product_tabs', 'dd_remove_reviews_tab', 98 );
function dd_remove_reviews_tab( $tabs ) {
unset( $tabs['reviews'] );
return $tabs;
}
Приклад 6. Прибрати зайві поля на checkout
Для українського магазину поля «Компанія» і «Адреса 2» зазвичай не потрібні. Індекс теж часто лишній, якщо доставка Новою поштою.
add_filter( 'woocommerce_checkout_fields', 'dd_checkout_fields' );
function dd_checkout_fields( $fields ) {
unset( $fields['billing']['billing_company'] );
unset( $fields['billing']['billing_address_2'] );
unset( $fields['billing']['billing_postcode'] );
return $fields;
}
Два застереження. По-перше, якщо ви рахуєте податки чи доставку за індексом, його прибирати не можна. По-друге, цей фільтр працює для класичного оформлення замовлення (шорткод). У нових магазинах WooCommerce за замовчуванням ставить блок Checkout, і там поля змінюються інакше, через власний API блоку. Перед тим як писати код, відкрийте сторінку оформлення і подивіться, яка в вас версія.
Як знайти потрібні WooCommerce hooks
Вгадувати назви не треба.
- Встановіть плагін Query Monitor. У ньому є вкладка «Hooks & Actions», де видно, які хуки спрацювали на поточній сторінці і які функції на них висять.
- Відкрийте файл шаблону в папці
woocommerce/templates/і пошукайтеdo_action(. Це і є всі місця, де можна втрутитись. - Для довідки є офіційний перелік хуків WooCommerce у code reference.
Помилки, яких варто уникати
- Код у файлах плагіна WooCommerce або в основній темі. Після оновлення він зникне.
- Не той пріоритет. Якщо блок з’являється не там, де очікували, майже завжди проблема в числі.
echoу фільтрі. Фільтр повинен повертати значення черезreturn, а не виводити його.- Вивід без екранування. Якщо текст береться з поля чи з користувача, використовуйте
esc_html()абоwp_kses_post(). - Перевірка тільки у своєму браузері. Закешована сторінка може показувати стару версію. Очистіть кеш і перевірте без входу в адмінку.
- Правки без бекапу. Помилка в
functions.phpможе покласти сайт, тож майте свіжу копію і будьте готові прибрати сніпет через FTP.
Підсумок
WooCommerce hooks — найпростіший спосіб змінити магазин без зайвих плагінів: менше коду, менше навантаження, менше ризиків при оновленнях. Якщо вам потрібна доробка магазину або створення інтернет-магазину з нуля, дивіться як я роблю інтернет-магазини на WooCommerce. А як блокова тема змінює підхід до шаблонів, описано в гайді про Full Site Editing.