Jak tworzyć niestandardowe powiadomienia e-mail WooCommerce

dowiedz się

Niestandardowe powiadomienia e-mail w WooCommerce pozwalają dostarczać bardziej trafne komunikaty, skracać czas obsługi zamówień i budować spójny wizerunek marki. W tym przewodniku przejdziesz od bezpiecznych, szybkich modyfikacji gotowych szablonów po pełne tworzenie własnego typu powiadomienia z klasą WC_Email, rejestracją w panelu i warunkowym wyzwalaniem. Po drodze dotkniesz hooki, filtry, pracę na plikach szablonów oraz podstawy PHP i HTML, a na końcu skonfigurujesz SMTP, wykonasz testy i skuteczne debugowanie.

Architektura powiadomień i przygotowanie środowiska

Jak działa system wiadomości w WooCommerce

WooCommerce opiera wysyłkę na klasach dziedziczących po WC_Email. Każda klasa definiuje identyfikator, domyślne treści (temat, nagłówek), ścieżki do szablonów HTML/tekst oraz mechanizm triggerowania. Silnik e-maili uruchamia się przez WC()->mailer(), który zbiera dostępne klasy, ładuje ustawienia i renderuje treść, przekazując dane zamówienia i odbiorców.

Wbudowane powiadomienia (np. “Nowe zamówienie” do administratora czy “Zamówienie w realizacji” do klienta) mają szablony w katalogu wtyczki: wp-content/plugins/woocommerce/templates/emails/. Modyfikacje wykonuje się, kopiując pliki do motywu potomnego w ścieżce yourtheme/woocommerce/emails/ i edytując kopię, nie oryginał.

Motyw potomny i struktura plików

Przed startem utwórz motyw potomny, aby aktualizacje motywu głównego nie nadpisywały zmian. Minimalnie potrzebujesz style.css i functions.php w katalogu child theme. Następnie przygotuj katalog yourtheme/woocommerce/emails/, gdzie będziesz umieszczać nadpisywane pliki i własne szablony. Dla powiadomień tekstowych możesz dodać też wersje “plain”: emails/plain/.

Panel ustawień i szybkie orientowanie się

W WooCommerce → Ustawienia → E-maile zobaczysz listę włączonych powiadomień i możliwość edycji: włącz/wyłącz, odbiorcy (dla e-maili administracyjnych), temat, nagłówek i dodatkowa treść. Własne typy, które dodasz filtrem, pojawią się tu automatycznie, jeśli ich klasa poprawnie zadeklaruje pola konfiguracyjne.

Bezpieczne środowisko: staging, backup, kontrola wersji

Pracuj na środowisku testowym (staging) lub lokalnym. Zrób kopię bazy i plików, włącz kontrolę wersji (Git), a do testów wysyłek skonfiguruj tymczasową skrzynkę lub przechwytywacz poczty (MailHog/Mailpit). Dzięki temu unikniesz przypadkowego wysłania wiadomości do prawdziwych klientów podczas eksperymentów.

Minimalny zestaw narzędzi

  • Edytor kodu (np. VS Code), dostęp FTP/SSH do serwera lub repozytorium Git.
  • Wtyczka do logowania poczty (np. WP Mail Logging) i inspekcji (Query Monitor).
  • Testowa skrzynka oraz SMTP (np. WP Mail SMTP) do realistycznych prób.

Szybkie modyfikacje istniejących e-maili bez tworzenia nowej klasy

Nadpisanie szablonu w motywie potomnym

Skopiuj plik z: wp-content/plugins/woocommerce/templates/emails/customer-processing-order.php do: wp-content/themes/yourchild/woocommerce/emails/customer-processing-order.php. Edytuj tę kopię, aby zmienić nagłówki, dodać sekcje, grafiki inline, bloki warunkowe (np. tylko dla danego sposobu wysyłki). Pamiętaj, aby po aktualizacjach WooCommerce sprawdzać tablicę “Outdated templates” w WooCommerce → Status.

Zmiana tematu, nagłówka i odbiorców przez filtry

Popularne filtry:

  • woocommerce_email_subject_{id} – zmienia temat wiadomości.
  • woocommerce_email_heading_{id} – zmienia nagłówek w treści.
  • woocommerce_email_recipient_{id} – pozwala dodać/zmienić odbiorców dla e-maili administracyjnych.
  • woocommerce_email_headers – dodanie CC/BCC lub nagłówków bezpieczeństwa.

Przykład: doprecyzowanie tematu i dodatkowy adres działu hurtowego dla “New Order” wysyłanego do admina:

get_order_number(), $order->get_formatted_billing_full_name());
}, 10, 2);

add_filter(’woocommerce_email_recipient_new_order’, function($recipient, $order){
if (!$order instanceof WC_Order) return $recipient;
foreach ($order->get_items() as $item) {
$product = $item->get_product();
if ($product && has_term(’hurt’, 'product_cat’, $product->get_id())) {
$recipient .= ’, dzial.hurtu@twojsklep.pl’;
break;
}
}
return $recipient;
}, 10, 2);
?>

Wstrzykiwanie dodatkowych treści do istniejących e-maili

Skorzystaj z akcji renderujących fragmenty w standardowych miejscach:

  • woocommerce_email_before_order_table
  • woocommerce_email_order_meta
  • woocommerce_email_after_order_table

Przykład: instrukcja dla odbioru osobistego, tylko przy metodzie Local pickup:

get_shipping_methods(), 'method_id’);
if (in_array(’local_pickup’, $shipping_methods, true)) {
echo ’

Odbiór osobisty: Poczekaj na potwierdzenie gotowości. Punkt czynny: pn-pt 9:00–17:00.

’;
}
}, 10, 4);
?>

Załączniki i dokumenty warunkowe

Możesz dołączyć pliki PDF (regulamin, karta gwarancyjna) lub fakturę wygenerowaną przez inną wtyczkę:

Stylowanie i grafika w wiadomościach

Domyślne style generuje plik email-styles.php. Możesz:

  • Nadpisać emails/email-styles.php w motywie i dopisać własne reguły.
  • Użyć filtra woocommerce_email_styles do wstrzyknięcia prostych reguł CSS.

Tłumaczenia i wielojęzyczność

Stosuj funkcje i18n: __(), _x(), esc_html__() z własną domeną tekstową. W projektach wielojęzycznych (WPML/Polylang) trzymaj stałe teksty w szablonach i klasach e-mail możliwe do przetłumaczenia, a dynamiczne elementy (np. nazwy produktów) wyciągaj z WooCommerce w języku kontekstu.

Tworzenie własnego powiadomienia: od klasy WC_Email po szablon

Scenariusz: “Zamówienie gotowe do odbioru” dla Local pickup

Założenie: po oznaczeniu zamówienia jako “Zrealizowane” (completed) i gdy metoda wysyłki to Local pickup, wyślemy klientowi dedykowany e-mail z instrukcją odbioru. Zrobimy to jako osobny typ powiadomienia, widoczny w ustawieniach WooCommerce, z możliwością edycji tematu/nagłówka.

Struktura wtyczki i rejestracja klasy

Najlepiej umieścić logikę w małej wtyczce (wp-content/plugins/custom-wc-emails/):

  • custom-wc-emails.php – plik główny wtyczki.
  • includes/class-wc-email-ready-pickup.php – nasza klasa WC_Email.
  • templates/emails/ready-pickup.php – szablon HTML.
  • templates/emails/plain/ready-pickup.php – szablon tekstowy.

Plik główny (fragmenty):

get_shipping_methods(), 'method_id’);
if (!in_array(’local_pickup’, $shipping_methods, true)) return;

$mailer = WC()->mailer();
$emails = $mailer->get_emails();
if (isset($emails[’WC_Email_Ready_Pickup’])) {
$emails[’WC_Email_Ready_Pickup’]->trigger($order_id);
}
});
?>

Implementacja klasy WC_Email_Ready_Pickup

id = 'ready_pickup’;
$this->title = __(’Zamówienie gotowe do odbioru’, 'custom-wc-emails’);
$this->description = __(’E-mail dla klientów odbierających zamówienie osobiście.’, 'custom-wc-emails’);
$this->customer_email = true;

$this->template_html = ’emails/ready-pickup.php’;
$this->template_plain = ’emails/plain/ready-pickup.php’;

$this->placeholders = array(
'{order_number}’ => ”,
'{pickup_point}’ => ”,
'{order_date}’ => ”,
'{site_title}’ => $this->get_blogname(),
);

$this->init_form_fields();
$this->init_settings();

$this->subject = $this->get_option(’subject’, $this->get_default_subject());
$this->heading = $this->get_option(’heading’, $this->get_default_heading());

add_action(’woocommerce_update_options_email_’ . $this->id, array($this, 'process_admin_options’));

parent::__construct();
}

public function init_form_fields() {
$this->form_fields = array(
'enabled’ => array(
'title’ => __(’Włącz/wyłącz’, 'custom-wc-emails’),
'type’ => 'checkbox’,
'label’ => __(’Włącz ten e-mail’, 'custom-wc-emails’),
'default’ => 'yes’,
),
'subject’ => array(
'title’ => __(’Temat’, 'custom-wc-emails’),
'type’ => 'text’,
'description’ => __(’Możesz użyć: {order_number}, {site_title}’, 'custom-wc-emails’),
'placeholder’ => ”,
'default’ => $this->get_default_subject(),
),
'heading’ => array(
'title’ => __(’Nagłówek’, 'custom-wc-emails’),
'type’ => 'text’,
'description’ => __(’Możesz użyć: {order_number}’, 'custom-wc-emails’),
'placeholder’ => ”,
'default’ => $this->get_default_heading(),
),
'additional_content’ => array(
'title’ => __(’Dodatkowa treść’, 'custom-wc-emails’),
'description’ => __(’Pojawi się pod główną treścią wiadomości.’, 'custom-wc-emails’),
'css’ => 'width:400px; height: 75px;’,
'placeholder’ => __(’Napisz instrukcję odbioru lub kontakt.’, 'custom-wc-emails’),
'type’ => 'textarea’,
'default’ => __(’Pamiętaj o dowodzie zakupu przy odbiorze.’, 'custom-wc-emails’),
'desc_tip’ => true,
),
);
}

public function get_default_subject() {
return sprintf(__('[%s] Zamówienie #{order_number} gotowe do odbioru’, 'custom-wc-emails’), $this->get_blogname());
}

public function get_default_heading() {
return __(’Twoje zamówienie jest gotowe!’, 'custom-wc-emails’);
}

public function trigger($order_id) {
if ($order_id) {
$this->object = wc_get_order($order_id);
$this->setup_locale();

$this->placeholders['{order_number}’] = $this->object->get_order_number();
$this->placeholders['{order_date}’] = wc_format_datetime($this->object->get_date_created());
$this->placeholders['{pickup_point}’] = get_option(’pickup_point_address’, 'Punkt odbioru: ul. Przykładowa 1, Miasto’);

$this->recipient = $this->object->get_billing_email();
}

if (!$this->is_enabled() || !$this->get_recipient()) {
return;
}

$this->send($this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments());

$this->restore_locale();
}

public function get_content_html() {
return wc_get_template_html(
$this->template_html,
array(
'order’ => $this->object,
’email_heading’ => $this->get_heading(),
'sent_to_admin’ => false,
'plain_text’ => false,
’email’ => $this,
),
”,
plugin_dir_path(__FILE__) . ’../templates/’
);
}

public function get_content_plain() {
return wc_get_template_html(
$this->template_plain,
array(
'order’ => $this->object,
’email_heading’ => $this->get_heading(),
'sent_to_admin’ => false,
'plain_text’ => true,
’email’ => $this,
),
”,
plugin_dir_path(__FILE__) . ’../templates/’
);
}
}
endif;
?>

Szablon HTML i wersja tekstowa

Plik templates/emails/ready-pickup.php (fragment):

Dzień dobry,

Zamówienie #get_order_number()); ?> jest gotowe do odbioru.

get_subject()) ); ?>

Punkt odbioru:

get_additional_content()) {
echo wp_kses_post( wpautop( wptexturize( $additional_content ) ) );
}

do_action(’woocommerce_email_footer’, $email);
?>

Wersja plain (templates/emails/plain/ready-pickup.php) może zawierać tylko podstawowy tekst i listę pozycji zamówienia bez HTML.

Wyświetlenie w ustawieniach i test wysyłki

Po aktywacji wtyczki wejdź do WooCommerce → Ustawienia → E-maile. Powinieneś zobaczyć “Zamówienie gotowe do odbioru”. Skonfiguruj temat i nagłówek (obsługiwane placeholdery: {order_number}, {site_title}). Aby wykonać test, ustaw zamówienie z Local pickup i zmień jego status na “Zrealizowane”. Zobaczysz wpis w logu poczty oraz otrzymasz e-mail testowy do skrzynki klienta.

Warianty wyzwalania i segmentacja

  • Inny status: podłącz do akcji woocommerce_order_status_processing lub do własnego statusu (po zarejestrowaniu go).
  • Wybrane kategorie: warunkuj trigger has_term(’preorder’, 'product_cat’, $product_id) dla pozycji w zamówieniu.
  • Minimalna wartość koszyka: if ((float)$order->get_total() >= 500) wysyłaj specjalny e-mail z rabatem na kolejne zakupy.

Testowanie, dostarczalność, utrzymanie i dobre praktyki

Testy funkcjonalne i wizualne

  • Podgląd szablonu: w WooCommerce → Status → Narzędzia znajdziesz generator podglądu “Email template”. To szybka weryfikacja wyglądu bazowego.
  • Logowanie wysyłek: WP Mail Logging pozwoli sprawdzić temat, odbiorcę, nagłówki i treść każdej wysyłki.
  • Środowisko lokalne: MailHog/Mailpit przechwyci pocztę i pokaże różnice między HTML a plain text.
  • RWD i ciemny tryb: przetestuj na Gmail, Outlook, Apple Mail i webmailach, uwzględniając dark mode (kontrast, odwracane kolory).

Dostarczalność: DNS, reputacja i SMTP

  • SPF: dodaj rekord, który uprawnia Twojego nadawcę (np. serwer SMTP) do wysyłania w imieniu domeny.
  • DKIM: podpisuj wiadomości kryptograficznie, aby klienci poczty mogli zweryfikować nadawcę.
  • DMARC: określa politykę traktowania podejrzanych wiadomości; skonfiguruj raportowanie (ruf/rua).
  • SMTP: skonfiguruj wtyczkę do wysyłki przez zewnętrzny serwer transakcyjny (np. SendGrid, Mailgun, Amazon SES) zamiast PHP mail().

Diagnostyka i debugowanie problemów

  • Włącz WP_DEBUG_LOG i sprawdź wp-content/debug.log, gdy e-maile nie są renderowane lub generują ostrzeżenia w szablonie.
  • Używaj wc_get_logger(): wc_get_logger()->info(’Wysłano e-mail gotowości’, array(’source’ => 'wc-email’)); aby śledzić przebieg triggerów.
  • Sprawdź kolejkę Action Scheduler: Narzędzia → Scheduled Actions; niektóre wtyczki wysyłają pocztę asynchronicznie.
  • Błędy kodowania polskich znaków: pamiętaj o UTF-8 bez BOM i właściwych nagłówkach Content-Type.
  • Załączniki: upewnij się, że ścieżki są absolutne i plik istnieje; w przeciwnym razie PHPMailer przerwie wysyłkę.

Bezpieczeństwo i zgodność

  • Sanityzuj i eskapuj: esc_html(), esc_url(), wp_kses_post() w szablonach, by nie wstrzyknąć niebezpiecznego HTML w e-mail.
  • Dane osobowe: nie dołączaj nadmiarowych informacji (np. pełny adres w CC do zewnętrznych działów).
  • Nie edytuj plików wtyczki WooCommerce bezpośrednio; zawsze korzystaj z motywu potomnego lub własnych wtyczek.
  • Wersjonowanie szablonów: kontroluj zgodność z wersją WooCommerce; po aktualizacji sprawdź “Outdated templates”.

Utrzymanie i rozwój: wzorce i checklisty

Checklist przed wdrożeniem:

  • Czy klasa e-mail wyświetla się w panelu i ma ustawienia? (Enabled, Subject, Heading, Additional content)
  • Czy wyzwalacz działa tylko w przewidzianych warunkach (np. Local pickup)?
  • Czy temat i nagłówek wspierają placeholdery i zostały przetestowane na realnym zamówieniu?
  • Czy wersja plain text jest czytelna i zgodna z polityką firmową?
  • Czy style są proste (inline lub minimalny CSS) i nie łamią się w Outlook?
  • Czy dodano logi i mechanizmy awaryjne (np. brak wysyłki, gdy brak odbiorcy)?
  • Czy wiadomość spełnia wymagania prawne (np. stopka z danymi firmy)?

Wzorce rozbudowy:

  • Personalizacja: dodaj kupon lojalnościowy wygenerowany dynamicznie i wstaw do e-maila w dodatkowej treści.
  • Segmentacja: różne szablony dla poszczególnych marek/kategorii (np. inna kolorystyka, logo, sekcja FAQ).
  • Warstwy logiczne: trzymaj progi biznesowe (wartość koszyka, pierwsze zamówienie) w oddzielnych funkcjach, by łatwo testować i rozwijać.

Przykłady szybkich rozszerzeń

Dodanie BCC do działu jakości tylko dla zamówień powyżej 1000 zł:

get_total() >= 1000) {
$headers .= „Bcc: jakosc@twojsklep.pl\r\n”;
}
return $headers;
}, 10, 3);
?>

Własne pole “Godziny odbioru” w ustawieniach sklepu i użycie w e-mailu:

'string’, 'sanitize_callback’ => 'sanitize_text_field’));
add_settings_field(’pickup_hours’, 'Godziny odbioru’, function(){
echo ’’;
}, 'general’);
});

add_action(’woocommerce_email_before_order_table’, function($order, $sent_to_admin, $plain_text, $email){
if (!$order instanceof WC_Order) return;
$shipping_methods = wp_list_pluck($order->get_shipping_methods(), 'method_id’);
if (in_array(’local_pickup’, $shipping_methods, true)) {
echo ’

Godziny odbioru: ’ . esc_html(get_option(’pickup_hours’, 'pn-pt 9:00–17:00′)) . ’

’;
}
}, 10, 4);
?>

Optymalizacja treści i wskaźniki

  • Jasny, krótki temat: zawrzyj numer zamówienia, nazwę sklepu i cel (np. “Gotowe do odbioru”).
  • Przycisk CTA: “Wyznacz trasę” do Google Maps z adresem punktu odbioru; w wersji plain – pełny link.
  • Dane kontaktowe: numer telefonu, link do czatu, godziny pracy.
  • Śledź zgłoszenia supportu po wdrożeniu – spadek liczby pytań “Kiedy mogę odebrać?” potwierdzi skuteczność.

Najczęstsze błędy i jak ich uniknąć

  • Bezpośrednia edycja plików WooCommerce: nadpisuj w motywie potomnym albo używaj filtrów/akcji.
  • Brak wersji plain: część klientów i filtrów antyspamowych preferuje tekstowe kopie.
  • Zbyt skomplikowane CSS: proste style inline i unikanie pozycji absolutnych zwiększają kompatybilność.
  • Niezweryfikowany adres nadawcy: skonfiguruj rekordy SPF/DKIM i spójny From/Reply-To.
  • Brak warunkowania: e-mail wysyłany wszystkim, zamiast tylko do właściwych segmentów – dodaj precyzyjne warunki w triggerze.
< Powrót

Zapisz się do newslettera


Zadzwoń Napisz