Dokumentacja

M Cart Recovery

M Cart Recovery for WooCommerce to wtyczka, która przed pierwszym dodaniem produktu do koszyka prosi kupującego o adres e-mail, zapisuje kopię koszyka we własnej bazie sklepu i wysyła przypomnienia z linkiem odtwarzającym dokładnie ten sam koszyk. Podręcznik dotyczy wersji 1.0.0 i jest napisany dla administratora tuż po instalacji: co uruchamia się po aktywacji, jakie są wszystkie ustawienia i ich wartości domyślne oraz które operacje mogą zatrzymać sprzedaż, zapisywać dane klientów mimo pozornego wyłączenia, usunąć rekordy albo po cichu przerwać wysyłkę wiadomości.

Napisano dla wersji 1.1.2. WordPress 7.0+ PHP 7.4+

Co robi i dla kogo jest

Wtyczka blokuje pierwsze dodanie produktu do koszyka przez odwiedzającego, którego adresu jeszcze nie zna, do momentu podania adresu e-mail, zapisuje powstały koszyk, po skonfigurowanym czasie bezczynności oznacza go jako porzucony i wysyła do trzech przypomnień z linkiem, który odtwarza koszyk z tymi samymi wariantami i ilościami oraz kieruje kupującego do kasy. Kupujący, których adres jest już znany, a należy do nich każdy zalogowany użytkownik, trafiają do bazy, nie widząc okna ani razu. Raporty pokazują koszyki śledzone, porzucone i odzyskane oraz odzyskany przychód. Rozwiązanie jest dla sklepów, które chcą odzyskiwać koszyki bez przekazywania danych zewnętrznej usłudze: wszystko trafia do dwóch własnych tabel w bazie i jest wysyłane pocztą samego sklepu. WooCommerce musi być zainstalowany i aktywny: nagłówek wtyczki zawiera Requires Plugins: woocommerce, a bez WooCommerce kod zatrzymuje się i wyświetla komunikat administratorowi.

Wymagania, instalacja, aktywacja

Plik readme.txt podaje WordPress 7.0 lub nowszy, WooCommerce 10.0 lub nowszy oraz PHP 7.4 lub nowsze. Nie ma w nim zalecenia HTTPS; ten wiersz występuje wyłącznie w README.md, pliku dla programistów. W kodzie sprawdzana jest tylko wersja PHP: przy aktywacji na PHP starszym niż 7.4 wtyczka wyłącza się z komunikatem „M Cart Recovery requires PHP 7.4 or newer”. Wersji WordPressa ani WooCommerce nic nie weryfikuje w trakcie działania.

  1. Najpierw zainstaluj i włącz WooCommerce.
  2. Wgraj katalog m-cart-recovery do wp-content/plugins/ albo zainstaluj plik ZIP przez Plugins > Add New.
  3. W sekcji Plugins aktywuj M Cart Recovery for WooCommerce.
  4. WordPress jednorazowo przekieruje Cię do WooCommerce > Cart Recovery > Settings. Przekierowanie następuje przy kolejnym otwarciu strony administracyjnej, opiera się na transiencie ważnym 30 sekund i wymaga uprawnienia manage_woocommerce, więc jeśli trafisz gdzie indziej, otwórz stronę z menu WooCommerce.
  5. Zanim zrobisz cokolwiek innego, przeczytaj następną sekcję: zbieranie adresów działa już w Twoim sklepie.

Co dzieje się w chwili aktywacji

Aktywacja tworzy dwie tabele z prefiksem Twojej bazy, wp_mcr_carts i wp_mcr_email_log, zapisuje mcr_db_version, dodaje opcje mcr_settings i mcr_templates, jeśli jeszcze nie istnieją, oraz ustawia 30-sekundowy transient przekierowania. Nie planuje żadnych zadań. Dwa cykliczne zadania powstają w MCR_Scheduler::ensure_scheduled() na haku init z priorytetem 20, czyli przy następnym żądaniu po aktywacji, niezależnie od tego, czy będzie to strona administracyjna, czy wejście do sklepu. Domyślna wartość ustawienia enabled to 1, więc okno zbierania adresu działa od pierwszego załadowania strony, po angielsku, z tekstem zaszytym w kodzie. Wtyczka zawiera wyłącznie plik languages/m-cart-recovery.pot i nie ma skompilowanego tłumaczenia litewskiego ani polskiego, dlatego zarówno okno, jak i ekrany administracyjne pozostaną angielskie, dopóki nie przepiszesz treści w ustawieniach.

  • Enable cart capture and recovery emails: włączone. Kod okna pojawia się na każdej stronie sklepu, a skrypt przechwytuje kliknięcia dodania do koszyka.
  • Trzy wiadomości przypominające: wszystkie włączone, z opóźnieniem 0, 1440 i 4320 minut od oznaczenia koszyka jako porzuconego.
  • Mark abandoned after: 60 minut.
  • Retain recovery records: 90 dni.
  • Sender name: nazwa witryny. Sender email: adres administratora WordPressa.
  • mcr_process_abandoned_carts: co pięć minut, pierwszy przebieg mniej więcej minutę po utworzeniu zadania.
  • mcr_cleanup_old_data: raz na dobę, pierwszy przebieg mniej więcej godzinę po utworzeniu zadania.
  • Show optional marketing consent: włączone, ale synchronizacja z MailWizz jest wyłączona (mailwizz_enabled ma wartość 0), więc nic nigdzie nie wychodzi.
  • Permanently delete plugin tables and settings on uninstall: wyłączone.
Uwaga

Od chwili aktywacji żaden gość nie doda niczego do koszyka bez wpisania adresu e-mail. Nie ma okresu przejściowego ani trybu podglądu. Aktywuj na środowisku testowym albo w godzinach niskiego ruchu i przygotuj się na natychmiastowe odznaczenie Enable cart capture and recovery emails na karcie Settings, na którą nastąpi przekierowanie.

Gdzie w wp-admin znajdują się ekrany

Wszystko mieści się na jednej stronie, WooCommerce > Cart Recovery (slug strony m-cart-recovery), podzielonej na pięć kart. Dostęp wymaga uprawnienia manage_woocommerce, które domyślnie mają role Administrator i Shop manager. Na liście Plugins pojawia się też odnośnik Settings otwierający kartę Settings. W nagłówku widoczna jest plakietka Recovery active albo Recovery paused, zależnie od ustawienia enabled, i opisuje ona wyłącznie to ustawienie, a nie to, czy koszyki są zapisywane.

  • Reports: wskaźniki z 30 dni, wykres słupkowy z 14 dni i krótkie wyjaśnienie, jak działa odzyskiwanie. Ta karta otwiera się jako pierwsza.
  • Abandoned carts: wszystkie zapisane rekordy koszyków, z filtrem statusu i wyszukiwaniem po adresie lub nazwisku, po 20 wierszy na stronę, w każdym wierszu odnośnik Delete.
  • Email templates: sekwencja przypomnień, po jednym edytorze na wiadomość.
  • Settings: silnik odzyskiwania, teksty okna w sklepie i przełącznik usuwania danych przy odinstalowaniu.
  • Integrations: dane dostępowe MailWizz, przycisk Test connection i hak dla innych platform.

Settings: Recovery engine

Pierwszy panel karty Settings odpowiada za czas, okres przechowywania i tożsamość nadawcy. Wartości spoza dozwolonego zakresu są przy zapisie przycinane, a nie odrzucane, więc po zapisaniu sprawdź, co zostało w polu. Nieprawidłowy adres nadawcy jest po cichu zastępowany adresem administratora WordPressa.

  • Enable cart capture and recovery emails. Domyślnie: włączone. Po wyłączeniu kod okna nie jest wypisywany, arkusz stylów i skrypt sklepu nie są ładowane, żaden koszyk nie jest oznaczany jako porzucony i żadne przypomnienie nie wychodzi. Koszyki nadal są zapisywane, a codzienne czyszczenie działa dalej. Zobacz sekcję o tym, czego to pole nie zatrzymuje.
  • Mark abandoned after (minutes). Domyślnie: 60. Zakres: od 5 do 43200 (30 dni). Czas liczony jest z kolumny updated_at rekordu koszyka, która jest nadpisywana przy każdym żądaniu, w którym zadziała jeden z czterech haków koszyka. Jednym z nich jest woocommerce_cart_updated, wywoływany przez WooCommerce przy zapisie koszyka do sesji, więc w większości sklepów zwykłe przeglądanie przesuwa moment porzucenia. Nie traktuj tej liczby jako czasu od ostatniej zmiany koszyka.
  • Retain recovery records (days). Domyślnie: 90. Zakres: od 7 do 3650. Zadanie czyszczące i tak stosuje własny dolny próg 7 dni.
  • Sender name. Domyślnie: nazwa witryny.
  • Sender email. Domyślnie: adres administratora WordPressa. Trafia dosłownie do nagłówka From każdego przypomnienia.

Settings: Email capture dialog

Dopóki zbieranie adresów jest włączone, kod okna trafia do stopki każdej strony sklepu, również dla zalogowanych odwiedzających i dla każdego, czyj adres jest już znany. O tym, czy okno w ogóle się otworzy, decyduje jedna flaga, mcrCapture.captured, wpisywana do strony przez wp_localize_script w chwili renderowania. Ma wartość true, gdy adres podaje już sesja WooCommerce, rekord klienta albo zalogowane konto, i wtedy skrypt niczego nie przechwytuje. Skrypt obserwuje elementy dodawania do koszyka WooCommerce: przyciski klasyczne i AJAX, formularze na stronie produktu, przyciski blokowe i zwykłe odnośniki add-to-cart. Zamknięcie okna anuluje oczekujące dodanie: produkt nie trafia do koszyka. Poniżej edytuje się siedem elementów: sześć pól tekstowych i jedno pole wyboru. Napis Cart protection, etykieta Email address i tekst przycisku zamykania pochodzą z pliku tłumaczeń, a nie z ustawień, a wtyczka zawiera wyłącznie languages/m-cart-recovery.pot, więc te trzy pozostaną angielskie niezależnie od tego, co tu wpiszesz.

  • Title. Domyślnie: Save your cart.
  • Message. Domyślnie: Enter your email to add this item and keep your cart available if you leave.
  • Email placeholder. Domyślnie: you@example.com.
  • Button. Domyślnie: Continue shopping.
  • Show optional marketing consent. Domyślnie: włączone. Dodaje niezaznaczone pole wyboru; za zgodę uznaje się tylko zaznaczone.
  • Marketing consent label. Domyślnie: Send me occasional product news and offers.
  • Privacy note. Domyślnie: We use your email to save this cart and send recovery reminders. Marketing emails are optional.
Uwaga

Ponieważ flaga captured jest wpisywana do HTML w chwili renderowania, cache całych stron, który zapisze kopię wygenerowaną dla odwiedzającego z już znanym adresem, podaje potem captured=true każdemu gościowi otrzymującemu tę kopię, a okno nic dla nich nie robi. Kosztuje to nie sprzedaż, lecz zebrane adresy, i wp-admin o tym nie informuje. Wyłącz strony sklepu z cache całych stron albo przyjmij, że zbieranie działa tylko częściowo, i porównaj wskaźnik Tracked carts z rzeczywistym ruchem.

Settings: Data removal

Jedno pole wyboru, Permanently delete plugin tables and settings when the plugin is uninstalled, domyślnie wyłączone. Dopóki wtyczka jest zainstalowana, nic nie zmienia. Odczytuje je jednorazowo plik uninstall.php w momencie usuwania wtyczki przez WordPressa. Pozostawienie go wyłączonym chroni dane przy ponownej instalacji.

Email templates: sekwencja przypomnień

Trzy wiadomości są domyślnie włączone. Każda ma nazwę wewnętrzną, przełącznik aktywności, opóźnienie w minutach (od 0 do 43200), temat, nagłówek i treść HTML edytowaną w uproszczonym edytorze WordPressa. Opóźnienia są bezwzględne, liczone od chwili oznaczenia koszyka jako porzuconego, a nie od poprzedniej wiadomości, dlatego wartości domyślne to 0, 1440 i 4320: natychmiast, po 24 godzinach, po 72 godzinach. Wyłączone szablony są pomijane, a kolejny włączony zachowuje własne opóźnienie. Treści przechodzą przez wp_kses_post przy zapisie i ponownie przy wysyłce, więc skrypty i niedozwolone znaczniki są usuwane.

  • First reminder, opóźnienie 0, temat: You left something in your cart at {site_name}.
  • Second reminder, opóźnienie 1440 minut, temat: Still thinking it over?
  • Final reminder, opóźnienie 4320 minut, temat: A final reminder about your saved cart.
  • Znaczniki dostępne w temacie, nagłówku i treści: {first_name}, {last_name}, {site_name}, {cart_items}, {cart_total}, {checkout_url}, {unsubscribe_url}.
  • Gdy imię nie jest znane, {first_name} zastępowany jest słowem „there”. {cart_items} generuje tabelę HTML z produktami, ilościami i kwotami.
  • Każda wiadomość ma automatyczną stopkę z odnośnikiem Stop cart reminders, nawet jeśli nie użyjesz {unsubscribe_url} w treści.
Uwaga

Ponieważ opóźnienia liczy się od porzucenia, zadanie przetwarzania przesuwa dokładnie jeden szablon na koszyk w jednym przebiegu, a samo zadanie działa co pięć minut, ustawienie tej samej wartości dla wszystkich trzech wyśle temu samemu kupującemu trzy wiadomości mniej więcej co pięć minut, wszystkie w ciągu około dziesięciu minut. Przed zapisem zostaw sensowne odstępy.

Integrations: MailWizz i inne platformy

Synchronizacja z MailWizz jest domyślnie wyłączona. Po włączeniu i podaniu API URL, klucza API oraz UID listy kupujący, który zaznaczy zgodę marketingową, trafia do kolejki w tle, z której jego adres e-mail wysyłany jest metodą POST na <api url>/lists/<list uid>/subscribers z nagłówkiem X-Api-Key. Dla osób bez zaznaczonej zgody nic nie jest wysyłane, a same przypomnienia nie zależą od MailWizz. Test connection wykonuje zapytanie tylko do odczytu o jednego subskrybenta i pokazuje kod HTTP; wynik ostatniej rzeczywistej synchronizacji zapisywany jest w opcji mcr_mailwizz_status i widoczny pod polami. Dowolną inną platformę podłączysz przez hak zbierania adresu, który uruchamia się po każdym udanym zapisie, a jego drugim argumentem jest wartość zgody.

  • Ze ścieżki sklepowej witrynę opuszcza wyłącznie adres e-mail. MCR_Capture::ajax_capture_email() wywołuje queue_sync( $email, '', '' ), a MCR_MailWizz::sync() przepuszcza treść żądania przez array_filter, który przed wysłaniem POST usuwa puste FNAME i LNAME. Imię nie jest przesyłane, bo okno zbierania adresu w ogóle o nie nie pyta.
  • UID listy przy zapisie przechodzi przez sanitize_key: litery są zamieniane na małe, a wszystko poza a-z, 0-9, podkreśleniem i myślnikiem jest usuwane. UID z wielkimi literami zostaje zapisany w zmienionej postaci, pole nadal wygląda wiarygodnie, a każda synchronizacja kończy się błędem, który w mcr_mailwizz_status trudno powiązać z tym polem. Po każdym zapisie przeczytaj pole List UID ponownie.
  • Test connection nie jest opcjonalny. Tylko on potwierdza, że URL, klucz i UID przetrwały zapis.
  • Wiersz statusu pod polami pochodzi z ostatniej rzeczywistej synchronizacji, a nie z ostatniego testu. Udany test i czerwony status jednocześnie oznaczają, że dane dostępowe działają, a problem leży po stronie przesyłanej treści lub listy.
add_action(
	'mcr_customer_email_captured',
	function ( $email, $marketing_consent ) {
		if ( ! $marketing_consent ) {
			return;
		}
		// Queue your own provider sync here.
	},
	10,
	2
);
Uwaga

Klucz API MailWizz jest przechowywany otwartym tekstem w opcji mcr_settings i trafia do kodu HTML strony jako ukryte pole na karcie Settings oraz jako wartość pola hasła na karcie Integrations. Odczyta go każdy z uprawnieniem manage_woocommerce i każdy, kto ma kopię bazy danych. Używaj klucza ograniczonego do tej jednej listy i wymień go, gdy odchodzi osoba obsługująca sklep.

Raporty i lista koszyków

Każdy wskaźnik na karcie Reports filtruje po created_at z ostatnich 30 dni, czyli po dacie utworzenia rekordu koszyka, a nie po dacie jakiejkolwiek aktywności. Koszyk utworzony 40 dni temu i porzucony dziś rano nie pojawi się w żadnym wskaźniku, łącznie z odzyskanym przychodem. W tym oknie: tracked carts to wszystkie rekordy (rekord powstaje dopiero wtedy, gdy znany jest adres), Currently abandoned pokazuje, ile z nich ma teraz status abandoned, Recovered liczy status recovered, a współczynnik konwersji to odzyskane podzielone przez sumę porzuconych i odzyskanych. Odzyskany przychód sumuje kolumnę cart_total rekordów recovered, a cart_total przy dopasowaniu zamówienia jest nadpisywany jego kwotą. Podtytuł liczy wiersze dziennika wiadomości ze statusem sent z tych samych 30 dni. Wykres obejmuje 14 dni, również według daty utworzenia. Abandoned carts pokazuje każdy rekord niezależnie od wieku: status, skrócony opis dwóch pozycji, kwotę, liczbę faktycznie wysłanych wiadomości i czas ostatniej aktywności w strefie czasowej witryny. Zamówienie jest wiązane z koszykiem najpierw po kluczu bieżącej sesji, a gdy to zawiedzie, po ostatnio zaktualizowanym aktywnym lub porzuconym koszyku z tym samym adresem e-mail do rozliczeń.

Pierwsza konfiguracja po kolei

Zrób to bez przerw. Wtyczka działa już podczas konfiguracji, więc pierwszy krok jest tym, który daje czas.

  1. Na karcie Settings odznacz Enable cart capture and recovery emails i zapisz. To natychmiast usuwa okno ze sklepu. Nie zatrzymuje jednak zapisywania koszyków; jeśli chcesz zatrzymać także je na czas konfiguracji, wyłącz całą wtyczkę i włącz ją ponownie po zakończeniu.
  2. Ustaw Sender name i Sender email na prawdziwą skrzynkę w domenie sklepu, dozwoloną przez Twoje rekordy SPF i DKIM.
  3. Ustaw Mark abandoned after. 60 minut to rozsądny start. Czytaj to jako czas od ostatniej zarejestrowanej aktywności koszyka, a w większości sklepów obejmuje ona zwykłe przeglądanie.
  4. Ustaw Retain recovery records na okres, który uzasadnisz wobec klienta i którego później nie będzie trzeba skracać.
  5. Przepisz Title, Message, Email placeholder, Button i Privacy note w języku swoich klientów i pamiętaj, że trzy stałe teksty okna pozostaną angielskie.
  6. Zdecyduj, czy w ogóle pokazywać pole zgody marketingowej, a jeśli je zostawiasz, przeredaguj etykietę tak, by jasno mówiła, na co kupujący się zgadza.
  7. Otwórz Email templates, przepisz wszystkie trzy wiadomości, zapisz raz, a potem przeładuj kartę i sprawdź, czy wszystkie trzy nadal tam są.
  8. Jeśli korzystasz z MailWizz, wypełnij Integrations, zapisz, przeczytaj ponownie pole List UID, a potem kliknij Test connection i poczekaj na komunikat o powodzeniu.
  9. Ponownie włącz Enable cart capture and recovery emails i zapisz.
  10. Przetestuj w oknie prywatnym bez sesji WordPressa: dodaj produkt, podaj jednorazowy adres, zamknij kartę. Odczekaj czas porzucenia plus pięć minut, a następnie sprawdź rekord i przypomnienie w Abandoned carts.
  11. W sklepie o niskim ruchu wyłącz na poziomie serwera tryb WP-Cron sterowany żądaniami i wywołuj wp-cron.php prawdziwym cronem co pięć minut, inaczej przypomnienia będą się opóźniać.

Zagrożenie: okno e-mail może zatrzymać całą sprzedaż

Dopóki zbieranie adresów jest włączone, gość nie doda niczego do koszyka bez podania poprawnego adresu e-mail. Skrypt anuluje kliknięcie, otwiera okno i powtarza pierwotną akcję dopiero po potwierdzeniu zapisu przez serwer. Jeśli to żądanie się nie powiedzie, kupujący utknie: zamknięcie okna anuluje dodanie, a kolejne kliknięcie po prostu otwiera je ponownie. W kodzie widać dwa scenariusze awarii. Nonce powstaje przy renderowaniu strony, a sprawdzany jest przy wysyłce formularza, więc strona serwowana dostatecznie długo z cache całych stron może nieść nonce, którego WordPress już nie przyjmuje. Z kolei ogranicznik liczy próby wyłącznie po $_SERVER['REMOTE_ADDR'] i nie obsługuje nagłówków proxy. Piętnaście prób w ciągu pięciu minut, poprawnych lub nie, i szesnasta zwraca „Too many attempts. Please wait a few minutes.” Każda zliczona próba nadaje licznikowi nowe pięć minut, więc okno przesuwa się do przodu, dopóki próby napływają; próba odrzucona go nie przedłuża, dlatego blokada znika pięć minut po piętnastej zliczonej próbie. Za CDN lub reverse proxy, które nie nadpisuje REMOTE_ADDR, wszyscy odwiedzający dzielą jeden licznik, co ogranicza cały sklep do piętnastu zapisów na pięć minut i w międzyczasie blokuje pozostałych.

  1. Najszybsze rozwiązanie przy dostępie do panelu: WooCommerce > Cart Recovery > Settings, odznacz Enable cart capture and recovery emails, zapisz. Okno przestaje się pojawiać natychmiast, dodawanie do koszyka znów działa, a zapisane koszyki pozostają.
  2. Bez dostępu do panelu, przez WP-CLI: zmień ustawienie wewnątrz opcji, nic nie wyłączając, albo wyłącz wtyczkę.
  3. Bez WP-CLI: zmień przez SFTP nazwę katalogu wp-content/plugins/m-cart-recovery. WordPress wyłącza wtyczkę, której plik zniknął. Tabele i opcje przetrwają tę operację.
  4. Jeśli winny był ogranicznik, najpierw poczekaj. Odrzucona próba nie przedłuża licznika, więc blokada znika sama pięć minut po piętnastej zliczonej próbie; po czyszczenie sięgaj dopiero wtedy, gdy próby wciąż napływają i wciąż odnawiają licznik. Klucze to mcr_rate_ plus skrót adresu, więc nie da się trafić w pojedynczy: wp transient delete --all kasuje wszystkie transienty w witrynie, nie tylko te liczniki, a na witrynie z trwałym cache obiektów, Redis lub Memcached, liczników nie ma w bazie, więc to polecenie w ogóle ich nie dosięgnie. wp cache flush je usuwa, ale opróżnia cały cache obiektów: transienty WooCommerce, dane sesji i wszystko inne, co korzysta z tej samej bazy Redis, łącznie z innymi witrynami na tej samej instancji. W ruchliwym sklepie oznacza to lawinę zapytań do pustego cache'u na dodatek do i tak zepsutej kasy. Potem, przed ponownym włączeniem, popraw REMOTE_ADDR na poziomie proxy lub hostingu.
  5. Jeśli winna była pamięć podręczna, wyłącz strony sklepu i admin-ajax.php z cache całych stron, a potem powtórz test w oknie prywatnym.
wp option patch update mcr_settings enabled 0
wp plugin deactivate m-cart-recovery
wp cache flush
wp transient delete --all
Uwaga

To jest awaria, która kosztuje pieniądze. Gdy żądanie zapisu adresu zawiedzie, nie ma żadnej ścieżki awaryjnej do koszyka: uszkodzony nonce, wspólny licznik ogranicznika, błąd JavaScriptu albo zablokowany admin-ajax.php oznaczają, że nikt niczego nie kupi, a wp-admin o tym nie informuje. Przez pierwszą dobę po włączeniu zbierania obserwuj liczbę zamówień.

Zagrożenie: pole enable nie zatrzymuje zbierania danych

Odznaczenie Enable cart capture and recovery emails zatrzymuje trzy rzeczy: kod okna w stopce, arkusz stylów i skrypt sklepu oraz pięciominutowy przebieg przetwarzania, który kończy się natychmiast. Niczego więcej nie zatrzymuje. MCR_Capture::register() podpina woocommerce_add_to_cart, woocommerce_cart_item_removed, woocommerce_cart_item_restored, woocommerce_cart_updated oraz zapis na shutdown, nie zaglądając do tego ustawienia, a MCR_Capture::capture_current_cart() też go nie sprawdza. Każdy koszyk kupującego, którego adres jest już znany, a należy do nich każdy zalogowany użytkownik, nadal trafia do wp_mcr_carts. Te wiersze powstają ze statusem active, zadanie przetwarzania, które przesunęłoby je dalej, jest pomijane, a MCR_Cart_Repository::cleanup() usuwa wyłącznie wiersze o statusie abandoned, completed, recovered lub unsubscribed. Wstrzymana wtyczka gromadzi więc adresy e-mail klientów, których nic w niej nigdy nie usunie, dłużej niż wynika to ze skonfigurowanego okresu przechowywania, o którym poinformowano klientów.

  • Co pole zatrzymuje: okno, jego CSS i JavaScript, oznaczanie porzuceń i wszystkie przypomnienia.
  • Czego nie zatrzymuje: zapisu koszyków na shutdown, punktu wp_ajax_mcr_capture_email, linków przywracających, linków rezygnacji, dopasowywania zamówień, uzupełniania adresu w kasie, codziennego czyszczenia ani ekranów administracyjnych.
  • Jedynym rzeczywistym zatrzymaniem jest wyłączenie wtyczki. Wyłączenie odpina wszystko i usuwa harmonogram zadań, a tabele, opcje, ustawienia, szablony i wszystkie zapisane koszyki zostają na miejscu.
  • Wiersze zapisane przy wstrzymanej wtyczce zachowują status active bezterminowo. Aktywny wiersz usuwa tylko opróżnienie koszyka WooCommerce przez kupującego, odnośnik Delete na karcie Abandoned carts, narzędzie usuwania danych osobowych WordPressa oraz Twój własny SQL.
wp plugin deactivate m-cart-recovery
wp db query "SELECT status, COUNT(*) FROM wp_mcr_carts GROUP BY status"
wp db query "DELETE l FROM wp_mcr_email_log l JOIN wp_mcr_carts c ON c.id = l.cart_id WHERE c.status = 'active'"
wp db query "DELETE FROM wp_mcr_carts WHERE status = 'active'"
Uwaga

Jeśli odznaczono to pole z powodu kwestii prywatności, odznaczenie jej nie rozwiązało. Wyłącz wtyczkę, policz wiersze active i usuń je. W poleceniach podstaw własny prefiks bazy i wcześniej wykonaj zrzut: usuwanie wierszy active kasuje także koszyki, które kupujący właśnie kompletują.

Zagrożenie: zalogowani klienci nie widzą okna, a wiadomości dostają

MCR_Capture::get_customer_email() sprawdza najpierw sesję WooCommerce, potem WC()->customer->get_billing_email(), a na końcu adres konta zalogowanego użytkownika. Każdy z tych trzech wystarczy, by zapisać koszyk. Zalogowany klient nigdy więc nie widzi okna, nie dostaje informacji o prywatności, o nic nie jest pytany, a mimo to powstaje jego wiersz w wp_mcr_carts pod identyfikatorem konta, z marketing_consent 0, i po upływie czasu bezczynności rusza pełna sekwencja trzech wiadomości. To samo dotyczy pracowników sklepu: każdy administrator i shop manager, który zostawi produkty w koszyku testowym, zostaje zapisany pod adresem swojego konta, dlatego własny adres pojawia się na liście Abandoned carts. Kod okna trafia do strony także dla tych odwiedzających; skrypt po prostu go nie otwiera, bo strona została wyrenderowana z flagą captured już ustawioną.

  • Posiadacze kont są zapisywani na podstawie adresu konta, bez okna, bez informacji o prywatności i bez jakiegokolwiek kroku zgody.
  • Jedyną możliwością rezygnacji jest odnośnik Stop cart reminders w stopce przypomnienia, a obejmuje on ten jeden rekord koszyka, a nie adres.
  • Zgoda marketingowa nigdy nie jest u nich udzielona, więc do MailWizz nic o nich nie trafia. Dotyczy ich wyłącznie lokalny zapis i wiadomości przypominające.
  • Każdą zmianę testuj w oknie prywatnym bez sesji WordPressa. Test na koncie zalogowanym pomija okno i wpisuje Twój własny adres do tabeli.
  • Sugerowany tekst prywatności, który wtyczka dopisuje w Settings > Privacy, zaczyna się od „When a shopper provides an email to save a cart” i tej ścieżki nie opisuje. Przepisz go przed publikacją.
  • Rekord koszyka zalogowanego użytkownika jest kluczowany po identyfikatorze konta, a nie po sesji, więc czyszczenie ciasteczek go nie rozdziela: jeden użytkownik ma jeden rekord.

Zagrożenie: dane, które znikają bez pytania

Cztery różne ścieżki trwale usuwają rekordy koszyków. Żadna nie wymaga potwierdzenia; sprawdzany jest wyłącznie nonce. Żadna nie tworzy archiwum, a wtyczka nie ma cofania. Jedyna droga powrotu to kopia zapasowa bazy.

  • Odnośnik Delete na liście Abandoned carts. Jedno kliknięcie usuwa wiersz koszyka i wszystkie jego wpisy w dzienniku wiadomości. Przeglądarka o nic nie pyta, sprawdzany jest tylko nonce, więc pomyłka jest nieodwracalna.
  • Codzienne czyszczenie według okresu przechowywania. Usuwa koszyki o statusie abandoned, completed, recovered lub unsubscribed, których ostatnia aktualizacja jest starsza niż Retain recovery records, razem z dziennikami. Wybiera najwyżej 500 identyfikatorów na przebieg i działa raz na dobę, więc pułap to 500 rekordów dziennie łącznie, a nie 500 na partię. Sklep generujący ponad 500 wygasających rekordów dziennie nigdy nie nadrobi zaległości, a dane osobowe zostają bezterminowo poza skonfigurowanym okresem. Czyszczenie działa nawet wtedy, gdy Enable cart capture and recovery emails jest wyłączone.
  • Opróżnienie koszyka WooCommerce. Gdy WooCommerce wywoła woocommerce_cart_emptied, aktywny rekord tej sesji jest usuwany razem z dziennikami.
  • Narzędzie usuwania danych osobowych w Tools > Erase Personal Data. Jednym przebiegiem usuwa do 100 rekordów koszyków dla wskazanego adresu wraz z ich dziennikami.
wp db query "SELECT status, COUNT(*) AS rows_now FROM wp_mcr_carts GROUP BY status"
wp db query "SELECT COUNT(*) FROM wp_mcr_carts WHERE status IN ('abandoned','completed','recovered','unsubscribed') AND updated_at < DATE_SUB(UTC_TIMESTAMP(), INTERVAL 90 DAY)"
Uwaga

Skracanie Retain recovery records niszczy dane z opóźnieniem. Zmiana z 90 na 7 początkowo nic nie zmienia, a przy najbliższym uruchomieniu codziennego zadania zaczyna usuwać około trzech miesięcy koszyków, historii wiadomości i stojących za nimi raportów, po 500 rekordów dziennie i nie szybciej. Przed zmniejszeniem tej liczby wykonaj zrzut bazy, a potem przez kilka dni uruchamiaj drugie z powyższych zapytań: jeśli zaległość nie maleje, przyczyną jest pułap, a deklarowany okres przechowywania nie jest dotrzymywany.

Zagrożenie: wiadomości, które przestają wychodzić bez ostrzeżenia

Przypomnienia wychodzą przez wp_mail z nagłówkiem From złożonym z Sender name i Sender email, dodawanym do każdej wiadomości. Jeśli ten adres nie jest adresem, w którego imieniu Twoja domena może wysyłać, wiadomość zostanie odrzucona przez serwer odbiorcy albo trafi do spamu, a wtyczka zapisze tylko to, co zwróci wp_mail. Niepowodzenia trafiają do tabeli dziennika wiadomości ze statusem failed i treścią „wp_mail() did not accept the message.”, ale żaden ekran administracyjny ich nie pokazuje: jedynym widocznym objawem jest kolumna Emails na liście Abandoned carts, która zostaje na zerze mimo rosnącej liczby koszyków. W całej wtyczce nie ma przycisku wysyłki testowej, więc dostarczalność trzeba sprawdzić prawdziwym koszykiem.

  • Ustaw Sender email na skrzynkę, która naprawdę istnieje w domenie sklepu, i potwierdź, że SPF, DKIM oraz DMARC pozwalają Twojemu serwerowi wysyłać w jej imieniu.
  • Jeśli używasz wtyczki SMTP, która musi zarządzać nagłówkiem From, usuń nagłówek tej wtyczki filtrem mcr_recovery_email_headers, zamiast z nim walczyć.
  • Aby zobaczyć niepowodzenia, sprawdź w tabeli dziennika wiadomości wp_mcr_email_log z Twoim prefiksem wiersze, w których status ma wartość failed.
  • Przypomnienia są wysyłane wyłącznie w HTML. Nie ma wersji tekstowej, co niektóre filtry antyspamowe biorą pod uwagę.
  • Koszyk, którego zapisana zawartość nie daje się już odczytać jako niepusta tablica, jest pomijany przed dojściem do wp_mail i nic nie trafia do dziennika. Jeśli rekord stoi na zerze wiadomości, a status się nie zmienia, sprawdź jego kolumnę cart_contents. Ta sama kolumna sprawia też, że link przywracający z już wysłanego przypomnienia po cichu przestaje działać, co opisuje sekcja o skanerach linków.
add_filter(
	'mcr_recovery_email_headers',
	function ( $headers ) {
		return array_values(
			array_filter(
				$headers,
				function ( $header ) {
					return 0 !== stripos( $header, 'From:' );
				}
			)
		);
	}
);

Zagrożenie: sekwencja wiadomości może zniknąć przy zapisie

MCR_Admin::save_templates() zapisuje MCR_Settings::sanitize_templates( $_POST['templates'] ) wprost do opcji mcr_templates. Nie ma scalania z dostarczonymi wartościami domyślnymi ani minimum: całą sekwencją staje się to, co przyszło w żądaniu POST. Formularz niesie trzy pola tekstu sformatowanego i piętnaście mniejszych, więc żądanie jest duże. Limit max_input_vars na hostingu, moduł bezpieczeństwa ograniczający rozmiar żądania albo ucinające je proxy zapisują mniej szablonów, niż wprowadzono, albo pustą tablicę. MCR_Admin::render_templates() renderuje wyłącznie szablony już zapisane i nie oferuje przycisku dodania nowego, więc gdy opcja zawiera pustą tablicę, na ekranie zostaje tylko lista znaczników i przycisk Save, a przypomnienia milkną na dobre, nigdzie nie zgłaszając błędu.

  1. Sprawdź, co jest zapisane: wp option get mcr_templates --format=json. Powinny być trzy obiekty.
  2. Jeśli szablonów brakuje albo tablica jest pusta, usuń opcję w całości: wp option delete mcr_templates. MCR_Settings::get_templates() wraca do dostarczonej sekwencji trzech wiadomości zawsze, gdy opcji nie ma, więc wartości domyślne pojawiają się natychmiast, po angielsku, z opóźnieniami 0, 1440 i 4320.
  3. Przepisz trzy wiadomości, zapisz raz, a potem przeładuj kartę i przed odejściem upewnij się, że wszystkie trzy wróciły.
  4. Jeśli znów zostaną obcięte, podnieś max_input_vars na hostingu i sprawdź wszystko, co filtruje lub ogranicza treść żądań POST.
  5. Trzymaj własną kopię trzech tematów, nagłówków i treści poza WordPressem. Wtyczka nie ma eksportu ani historii wersji.
wp option get mcr_templates --format=json
wp option delete mcr_templates
Uwaga

Obcięty zapis przebiega bezgłośnie. Ekran przekierowuje z komunikatem Changes saved. i pokazuje tylko te szablony, które przetrwały, więc wygląda poprawnie. Przeładowanie karty po każdym zapisie to jedyna kontrola, jaką wtyczka daje.

Przetwarzanie w tle i czas

Wtyczka korzysta z Action Scheduler, gdy udostępnia go WooCommerce, w grupie m-cart-recovery, a awaryjnie z WP-Cron z własnym pięciominutowym interwałem zarejestrowanym jako mcr_five_minutes. Oba zadania powstają na haku init z priorytetem 20, przy pierwszym żądaniu po aktywacji, więc witryna, która nie otrzyma żadnego żądania, nie zaplanuje niczego. Działają dwa cykliczne zadania: mcr_process_abandoned_carts co pięć minut, które oznacza nieaktywne koszyki jako porzucone i wysyła zaległe przypomnienia, oraz mcr_cleanup_old_data raz na dobę. Trzeci hak, mcr_sync_marketing_contact, kolejkowany jest na żądanie dla MailWizz. Jeden przebieg przetwarzania obsługuje najwyżej 20 koszyków i przesuwa dokładnie jeden szablon na koszyk, więc duża zaległość topnieje w tempie około 240 koszyków na godzinę. Przebiegi nie nakładają się dzięki blokadzie w opcji mcr_processing_lock, która jest automatycznie odrzucana, gdy ma ponad dziesięć minut, więc przerwany przebieg odblokowuje się przy kolejnym uruchomieniu.

Rozwiązywanie problemów

Problemy, które faktycznie się zdarzają, i to, co sprawdzić najpierw.

  • Okno w ogóle się nie pojawia. Zbieranie jest wyłączone; jesteś zalogowany albo sesja lub rekord klienta zawiera już adres, więc strona została wyrenderowana z flagą captured ustawioną na true; strona przyszła z cache wygenerowanego dla takiego odwiedzającego; albo Twój motyw dodaje produkt do koszyka elementem, którego skrypt nie obserwuje, i wtedy okno jest całkowicie omijane.
  • Okno się pojawia, ale wysłanie nic nie daje. Otwórz konsolę przeglądarki i sprawdź odpowiedź admin-ajax.php: 403 oznacza nieudany nonce, zwykle przez cache całych stron; 429 to ogranicznik liczby żądań; 409 oznacza, że przy tym żądaniu sesja WooCommerce była niedostępna; 400 oznacza, że adres nie przeszedł kontroli is_email.
  • Na liście Abandoned carts widzisz własny adres. Podczas testu byłeś zalogowany. Adresy kont są zbierane bez żadnego okna. Usuń wiersz i testuj w oknie prywatnym.
  • Koszyki nigdy nie stają się porzucone. Nie działa zadanie pięciominutowe (sprawdź Action Scheduler lub WP-Cron), wyłączone jest Enable cart capture and recovery emails (cały przebieg jest pomijany), rekord nie ma przypisanego adresu albo jego cart_contents to pusta tablica.
  • Koszyki pozostają aktywne znacznie dłużej, niż sugeruje opóźnienie. Czas porzucenia liczony jest z updated_at, a ta kolumna odświeża się przy każdym zapisie koszyka do sesji przez WooCommerce, co w większości sklepów dzieje się podczas zwykłego przeglądania.
  • Koszyki są porzucone, ale nic nie wychodzi. Wszystkie szablony są wyłączone, opcja mcr_templates jest pusta, opóźnienie jeszcze nie minęło, zapisana zawartość koszyka jest pusta albo wp_mail zawodzi.
  • Ekran Email templates nie pokazuje żadnego edytora. Opcja mcr_templates zawiera pustą tablicę. Usuń opcję, aby przywrócić dostarczoną sekwencję.
  • Ten sam kupujący dostaje sekwencję dwa razy. Gość, który wyczyści ciasteczka, dostaje nowy klucz sesji, a więc nowy rekord koszyka i nową sekwencję; to samo dotyczy kupującego, który otworzy link przywracający na drugim urządzeniu. Rezygnacja dotyczy jednego rekordu, nie adresu.
  • Sekwencja u kupującego wciąż zaczyna się od nowa. Każda zmiana zawartości koszyka celowo przywraca rekord do statusu active i zeruje liczniki, więc sekwencja rusza od nowego porzucenia.
  • Rekordy przechodzą w unsubscribed kilka sekund po pierwszym przypomnieniu. Firmowy skaner linków pobrał adres rezygnacji. Link przywracający z tej wiadomości również już nie działa.
  • Link przywracający otwiera stronę główną i nic nie robi. Albo token nie przeszedł kontroli wzorca 64 znaków, zwykle dlatego, że program pocztowy przełamał adres, albo cart_contents rekordu nie odczytuje się już jako tablica. W obu przypadkach handle_restore() kończy działanie bez komunikatu i bez przekierowania.
  • Odzyskany przychód wygląda błędnie. Dopasowanie idzie najpierw po kluczu sesji, a potem po najnowszym aktywnym lub porzuconym koszyku z tym samym adresem e-mail do rozliczeń, więc zamówienie z innego urządzenia może zostać przypisane do innego koszyka. Wskaźniki obejmują ponadto tylko rekordy utworzone w ciągu ostatnich 30 dni.
  • Link przywracający zgłasza, że koszyka już nie ma. Rekord ma status completed, recovered lub unsubscribed albo został już usunięty przez czyszczenie.

Prywatność i dane

Bez włączonego MailWizz nic nie opuszcza witryny. Po jego włączeniu na skonfigurowany adres API wysyłany jest metodą POST wyłącznie adres e-mail osób, które zaznaczyły zgodę; puste pola imienia i nazwiska są usuwane z treści żądania przed wysłaniem. Same przypomnienia rzecz jasna wychodzą Twoją pocztą. Cała reszta zostaje w dwóch lokalnych tabelach. Wtyczka rejestruje eksport i usuwanie danych osobowych w Tools > Export Personal Data oraz Tools > Erase Personal Data, a także dopisuje sugerowany tekst do przewodnika polityki prywatności w Settings > Privacy, który warto dostosować do własnej jurysdykcji zamiast publikować w wersji dostarczonej. Ten sugerowany tekst opisuje tylko kupującego, który podaje adres w oknie, więc nie obejmuje zalogowanych klientów, zapisywanych bez pytania.

  • wp_mcr_carts przechowuje: adres e-mail, imię i nazwisko, ID użytkownika, znacznik zgody marketingowej, zawartość koszyka w JSON, kwotę, walutę, status, 64-znakowy token przywracający, znaczniki czasu, ID dopasowanego zamówienia oraz klucz koszyka będący HMAC z identyfikatora konta albo sesji WooCommerce, a nie odwracalnym identyfikatorem.
  • wp_mcr_email_log przechowuje: ID koszyka, numer szablonu, odbiorcę, temat, status, treść błędu i znacznik czasu.
  • Surowy adres IP nie jest nigdzie zapisywany. Ogranicznik liczby żądań zamienia adres na wartość HMAC, która staje się kluczem transienta i nigdy nie trafia do tabel wtyczki.
  • Po udanym zapisie ustawiane jest jedno ciasteczko: mcr_email_captured, wartość 1, na rok, z flagą secure przy HTTPS. Żaden fragment kodu wtyczki go nie odczytuje. O tym, czy okno się otworzy, decyduje serwer na podstawie sesji WooCommerce, rekordu klienta i zalogowanego konta.
  • Rekordów o statusie active czyszczenie według okresu przechowywania nie usuwa nigdy, tylko abandoned, completed, recovered i unsubscribed. Jeśli na dłużej wyłączysz zbieranie albo kupujący będą dalej przeglądać sklep, wiersze active zostaną bezterminowo.

Odinstalowanie: co znika, a co zostaje

Wyłączenie i usunięcie działają zupełnie inaczej, a całą różnicę robi jedno pole wyboru, które trzeba było zaznaczyć wcześniej.

  1. Wyłączenie usuwa harmonogram zadań mcr_process_abandoned_carts, mcr_cleanup_old_data oraz wszystkich zakolejkowanych mcr_sync_marketing_contact, zarówno w Action Scheduler, jak i w WP-Cron, a także odpina wszystko, w tym zapis koszyków oraz linki przywracające i rezygnacji. Tabele, opcje, ustawienia, szablony i wszystkie zapisane koszyki pozostają na miejscu, a ponowne włączenie przywraca harmonogram przy następnym żądaniu.
  2. Usunięcie wtyczki na liście Plugins uruchamia uninstall.php. Zawsze usuwa harmonogram tych samych zadań. Następnie odczytuje opcję Permanently delete plugin tables and settings i zatrzymuje się, jeśli jest wyłączona.
  3. Przy włączonej opcji odinstalowanie kasuje tabele wp_mcr_carts i wp_mcr_email_log oraz opcje mcr_settings, mcr_templates, mcr_db_version, mcr_mailwizz_status i mcr_processing_lock. Nie ma kroku eksportu ani drugiego potwierdzenia poza standardowym pytaniem WordPressa.
  4. Przy wyłączonej opcji nic nie jest usuwane. Jeśli później zechcesz pozbyć się pozostałości, ręcznie skasuj dwie tabele i pięć opcji.
  5. W obu przypadkach transienty zostają: uninstall.php nie usuwa liczników ogranicznika z kluczami mcr_rate_, komunikatu mcr_admin_error_ ani pozostawionego mcr_activation_redirect. Wygasają samoczynnie.
  6. W obu przypadkach ciasteczko mcr_email_captured w przeglądarkach odwiedzających oraz wartości mcr_email i mcr_marketing_consent w sesjach WooCommerce nie są ruszane. One także wygasają same.
Uwaga

Zaznacz Permanently delete plugin tables and settings tylko wtedy, gdy masz pewność, że nie będziesz instalować wtyczki ponownie. Usuwanie następuje w chwili, gdy WordPress kasuje pliki wtyczki, zanim zdążysz zmienić zdanie, i zabiera ze sobą wszystkie rekordy koszyków oraz całą historię wiadomości. Wcześniej wykonaj zrzut bazy danych.

Automatyczne aktualizacje

Wtyczka sprawdza majevski.com pod kątem nowych wydań i proponuje je przez zwykły ekran aktualizacji WordPressa — ten sam komunikat, lista zmian i instalacja jednym kliknięciem jak przy każdej innej wtyczce. Sprawdzenia są buforowane, nigdy nie spowalniają strony i są odporne na awarie: jeśli majevski.com jest nieosiągalny, witryna po prostu działa dalej i próbuje później. Pakiet aktualizacji jest przyjmowany wyłącznie z majevski.com przez HTTPS, a starsza wersja nigdy nie jest proponowana. Wersje starsze niż 1.1.0 nie znają jeszcze kanału aktualizacji, więc nie widzą nowych wydań — zainstaluj raz ręcznie 1.1.0 lub nowszą, a każde kolejne wydanie przyjdzie samo.

Potrzebujesz czegoś podobnego?

Wszystko na tej stronie zaprojektowała, zbudowała i utrzymuje jedna osoba. Jeśli potrzebujesz tego samego dla swojej firmy, napisz, co masz na myśli.

Umów rozmowę otwiera się w nowej karcie