
📝 Додавання приміток до замовлення WooCommerce в лист: повний посібник
Клієнт зробив замовлення, а ви залишили примітку в адмінці, уточнили термін доставки, додали трек-номер або просто написали «зателефонувати перед відправкою». Але клієнт цього не бачить. Примітки до замовлення WooCommerce за замовчуванням живуть лише в адмінці, на боковій панелі редагування замовлення. У листах, які йдуть покупцю, їх немає.
Проблема вирішується одним сніпетом у functions.php. Без плагінів, без правки шаблонів, чистий хук, який виводить примітки в тіло листа. На практиці ми використовуємо цей підхід на клієнтських магазинах уже кілька років, жодного збою після оновлень WooCommerce. У цьому посібнику розберемо, як WooCommerce зберігає нотатки до замовлень, який хук використовувати і як кастомізувати вивід під свої завдання.
💡 Швидкий огляд:
- Як WooCommerce зберігає примітки до замовлень: тип коментаря
order_noteі функціяwc_get_order_notes() - Два підходи до кастомізації листів: перевизначення шаблонів або хуки, який і коли вибирати
- Готовий сніпет для виводу приміток у лист про виконання замовлення з розбором кожного рядка
- Кастомізація: стилізація списку, фільтрація лише клієнтських заміток, підтримка plain-text листів
- Тестування через попередній перегляд листів в адмінці, без спаму реальним клієнтам
Крок 1: Як WooCommerce зберігає примітки до замовлень
WooCommerce зберігає примітки як коментарі WordPress типу order_note. Кожна дія із замовленням, зміна статусу, refund, примітка адміністратора або повідомлення клієнту, записується в таблицю wp_comments з прапором comment_type = 'order_note'.
Різниця між внутрішніми і клієнтськими замітками визначається мета-полем is_customer_note. Якщо чекбокс «Visible in My Account» увімкнено при додаванні замітки, WooCommerce ставить is_customer_note = true, і покупець бачить її в особистому кабінеті. Звичайні внутрішні замітки (is_customer_note = false) клієнту не показуються ніде.
З виходом High Performance Order Storage (HPOS) у WooCommerce 8.2+ замітки потрапили в окрему таблицю wp_wc_order_notes. Прямі SQL-запити до wp_comments з увімкненим HPOS можуть повертати порожній результат. Тому замість get_comments() краще використовувати wc_get_order_notes(), вона працює коректно за будь-якого режиму зберігання.
Крок 2: Шаблони або хуки, який підхід вибрати
У WooCommerce два шляхи для кастомізації листів: перевизначення шаблонів і використання екшен-хуків. У кожного, свій сценарій.
Перевизначення шаблонів. Ви копіюєте файл з woocommerce/templates/emails/ у yourtheme/woocommerce/emails/ і правите HTML напряму. Плюс, повний контроль над розміткою. Мінус, при великих оновленнях WooCommerce ваш шаблон може розійтися з актуальною версією, і листи почнуть ламатися. Документація зі структури шаблонів тепер на woocommerce.com, а не на старому docs.woothemes.com.
Хуки. Ви вішаєте callback на дію woocommerce_email_order_meta, і WooCommerce сам викликає вашу функцію в потрібному місці листа. Плюс, не залежить від версій шаблонів, працює «з коробки» після оновлень ядра. Мінус, ви обмежені позицією хука (він спрацьовує в блоці метаданих замовлення, після таблиці з товарами).
Критерій | Шаблони | Хуки |
|---|---|---|
Контроль над розміткою | Повний | У межах позиції хука |
Стійкість до оновлень | Низька | Висока |
Складність впровадження | Вища | Нижча |
Підходить для | Капітальної переробки листа | Додавання одного блоку |
Для нашого завдання, виводу приміток, хука більш ніж достатньо. Якщо вам потрібно повністю перекроїти дизайн листів, беріть шаблони і закладайте час на їх актуалізацію раз на півроку.
Крок 3: Додаємо код у functions.php
Хук woocommerce_email_order_meta спрацьовує в усіх транзакційних листах WooCommerce: підтвердження замовлення, виконання, скасування, рахунок та інші. У callback передаються чотири параметри: об'єкт замовлення $order, прапор $sent_to_admin, прапор $plain_text і об'єкт листа $email.
Розмістіть цей код у functions.php активної теми (або через плагін Code Snippets, безпечніше, не злетить при зміні теми):
1 add_action( 'woocommerce_email_order_meta', 'sd_add_order_notes_to_email', 10, 4 ); 2 3 function sd_add_order_notes_to_email( $order, $sent_to_admin, $plain_text, $email ) { 4 // Не ломаем plain-text версию письма 5 if ( $plain_text ) { 6 echo "\n\n" . esc_html__( 'Order Notes:', 'woocommerce' ) . "\n"; 7 8 $notes = wc_get_order_notes( array( 9 'order_id' => $order->get_id(), 10 'type' => 'customer', 11 ) ); 12 13 if ( empty( $notes ) ) { 14 echo esc_html__( 'No notes for this order.', 'woocommerce' ) . "\n"; 15 return; 16 } 17 18 foreach ( $notes as $note ) { 19 echo '- ' . wp_strip_all_tags( $note->content ) . "\n"; 20 } 21 return; 22 } 23 24 // HTML-версия: получаем только клиентские заметки 25 $notes = wc_get_order_notes( array( 26 'order_id' => $order->get_id(), 27 'type' => 'customer', 28 ) ); 29 30 if ( empty( $notes ) ) { 31 return; 32 } 33 34 echo '<h2>' . esc_html__( 'Order Notes', 'woocommerce' ) . '</h2>'; 35 echo '<ul class="order-notes-list" style="list-style:none;padding:0;margin:0 0 24px;">'; 36 37 foreach ( $notes as $note ) { 38 $note_date = sprintf( 39 '%1$s в %2$s', 40 date_i18n( get_option( 'date_format' ), strtotime( $note->date_created ) ), 41 date_i18n( get_option( 'time_format' ), strtotime( $note->date_created ) ) 42 ); 43 44 printf( 45 '<li style="background:#f9f9f9;border-left:4px solid #7f54b3;padding:12px 16px;margin-bottom:10px;border-radius:0 4px 4px 0;">' 46 . '<div style="margin-bottom:4px;">%s</div>' 47 . '<small style="color:#888;">%s</small>' 48 . '</li>', 49 wp_kses_post( nl2br( $note->content ) ), 50 esc_html( $note_date ) 51 ); 52 } 53 54 echo '</ul>'; 55 }
Що тут відбувається по рядках:
- Рядок 1. Реєструємо хук з пріоритетом 10 і приймаємо всі 4 параметри. Без
10, 4WooCommerce передасть лише перший аргумент, отримаєте помилку. - Рядки 5-20. Обробка plain-text листів. Деякі листи йдуть у текстовому форматі, виводимо замітки списком з дефісами, без HTML.
- Рядки 24-28.
wc_get_order_notes()запитує лише клієнтські замітки (type => 'customer'). Прибрати фільтр, показати всі замітки, включно з внутрішніми (зміна статусу, refund). Масив порожній → нічого не виводимо, лист не захаращуємо. - Рядки 34-38. Форматуємо дату через
date_i18n(), поважає локаль сайту і налаштування формату дати/часу. - Рядки 40-48.
printf()виводить кожну замітку в стилізованому блоці: фіолетова смуга зліва, світлий фон, дата знизу сірим.
Код не використовує зовнішніх залежностей і сумісний з WooCommerce 3.2+ (функція wc_get_order_notes з'явилася саме в цій версії) і HPOS (нативна підтримка з 8.2+).
Крок 4: Тестуємо без спаму клієнтам
Після додавання коду не чекайте реальне замовлення для перевірки. WooCommerce дає вбудований попередній перегляд листів: WooCommerce → Налаштування → Emails → натисніть на будь-який лист → кнопка «Preview» внизу. Ви побачите лист у HTML і plain-text, зі справжнім замовленням (береться останнє існуюче). Якщо замовлень немає, створіть тестове вручну.
Що перевірити:
- Клієнтська замітка з увімкненим «Visible in My Account» відображається в листі;
- Внутрішня замітка (без галочки) не відображається (якщо залишили
type => 'customer'); - Plain-text версія листа не зламана (перемкніться за посиланням під попереднім переглядом);
- Блок із замітками не дублюється в листах адміністратору (додайте перевірку
if ( $sent_to_admin ) return;якщо потрібно).
Якщо користуєтеся Code Snippets, достатньо деактивувати сніпет для відкату. Якщо правили functions.php, закоментуйте або видаліть код. Жодних слідів у базі не залишається.
⁉️🤔 Часті запитання
Чи можна виводити ВСІ примітки, а не лише клієнтські?
Так. Замініть
'type' => 'customer'на'type' => 'internal', отримаєте лише внутрішні замітки. Приберіть параметрtypeзовсім, отримаєте всі замітки поспіль. Враховуйте, що внутрішні замітки можуть містити службову інформацію (ID refund, суми), яку клієнту бачити ні до чого. Більшості магазинів достатньо'type' => 'customer'. Якщо хочете розділити вивід, зробіть два блоки: спочатку клієнтські замітки із заголовком «Коментарі до замовлення», потім внутрішні під заголовком «Деталі виконання» (це вже для листів адміністратору, прапор$sent_to_admin).
Код працює для конкретного листа чи для всіх одразу?
Хук
woocommerce_email_order_metaспрацьовує в усіх транзакційних листах: Completed Order, Processing Order, Order on Hold, Customer Invoice і так далі. Якщо потрібно обмежити вивід лише листом про виконання замовлення, оберніть код у перевірку:
1 if ( 'customer_completed_order' !== $email->id ) { 2 return; 3 }
Список усіх ID листів доступний у документації WooCommerce: customer_completed_order · customer_processing_order · customer_on_hold_order · customer_invoice · customer_refunded_order · customer_new_account · new_order · cancelled_order · failed_order.
Чи безпечно правити functions.php на робочому сайті?
Правка
functions.phpнапряму, ризикований шлях. Помилка в синтаксисі (зайва дужка, незакрита лапка) кладе весь сайт у білий екран. Безпечніше використовувати плагін Code Snippets, він дозволяє додавати PHP-сніпети через адмінку і автоматично вимикає код з фатальною помилкою. Альтернатива: WPCode (безкоштовна версія на wordpress.org), той самий функціонал плюс умовна логіка (лише для адмінів, лише на певних сторінках). Якщо все ж правитеfunctions.php, зробіть бекап файлу і тримайте під рукою FTP-доступ. Білий екран лікується заміноюfunctions.phpна оригінал з бекапу.
Примітки дублюються в листах, що я зробив не так?
Дві ймовірні причини. Перша: ви одночасно додали код і в
functions.php, і через плагін сніпетів, хук спрацьовує двічі. Залиште щось одне. Друга: тема або інший плагін уже вішають callback на цей самий хук. Перевірте через пошук по коду проекту (grep -r "woocommerce_email_order_meta" wp-content/). Якщо дублювання йде від плагіна, достатньо прибрати ваш код. Якщо від теми, оберніть свій callback уremove_action()передadd_action(), щоб гарантовано виконувався лише один обробник.
Що в підсумку: чи варто додавати примітки в листи клієнтам
Прозорість комунікації, один із найдешевших способів знизити навантаження на підтримку. Коли клієнт бачить у листі «Трек-номер: X123456789, доставка 15 червня», він не йде писати в чат «а де моє замовлення?». Один сніпет, нуль плагінів, п'ять хвилин на впровадження, а ефект вимірюється десятками зекономлених тікетів на місяць.
Якщо листи вже кастомізовані через шаблони, вбудуйте вивід замітки прямо в шаблон, а не хук. Якщо користуєтеся плагіном кастомізації листів (Kadence, YayMail, ShopMagic), у кожного з них є свій механізм додавання динамічних блоків, використовуйте його замість коду.
Спробуйте з одним типом листів (Completed Order), перевірте на тестовому замовленні і через тиждень оцініть, чи стало менше однотипних питань від клієнтів. Майже напевно, так.



