Dokumentacja

M SEO Editor

M SEO Editor daje witrynie WordPress dokładnie tyle danych dla wyszukiwarek i serwisów społecznościowych, ile potrzeba: tytuły i opisy meta, Open Graph i Twitter Cards, mapę witryny XML oraz jeden graf Schema.org na stronę, z poprawną obsługą produktów WooCommerce. Wtyczka działa od chwili aktywacji, więc strona ustawień służy do dostrajania wartości domyślnych, a nie do włączania funkcji. Jedno warto wiedzieć od razu: wybór typów treści do mapy witryny oraz źródło marki WooCommerce zostają zamrożone w chwili aktywacji, więc kolejność instalowania wtyczek ma znaczenie. Ten podręcznik opisuje wersję 1.0.0 i jest przeznaczony dla administratora, który właśnie zainstalował wtyczkę.

Napisano dla wersji 1.1.2. WordPress 6.5+ PHP 7.4+

Instalacja i aktywacja

Wtyczka wymaga WordPressa 6.5 lub nowszego i PHP 7.4 lub nowszego. Bez kompilacji, bez klucza licencyjnego, bez konta.

  1. Najpierw zainstaluj WooCommerce i każdą wtyczkę rejestrującą własne typy treści. Przed aktywacją M SEO Editor przeczytaj ostrzeżenie poniżej.
  2. Pobierz plik ZIP albo skopiuj katalog m-seo-editor do /wp-content/plugins/.
  3. W kokpicie przejdź do Wtyczki (Plugins), następnie Dodaj nową wtyczkę (Add New) i Wyślij wtyczkę na serwer (Upload), wskaż plik ZIP i zainstaluj.
  4. Aktywuj wtyczkę na liście wtyczek.
  5. W menu kokpitu kliknij M SEO. Na liście wtyczek pojawia się też odnośnik Settings prowadzący prosto tam.
Uwaga

Aktywacja zapisuje w bazie listę typów treści i taksonomii wchodzących do mapy witryny jeden raz i nigdy jej nie aktualizuje. Wszystko zarejestrowane później, przede wszystkim produkty WooCommerce, będzie poza tą listą, dopóki nie zostanie zaznaczone ręcznie na karcie Sitemap.

Co działa zaraz po aktywacji

Aktywacja zapisuje ustawienia domyślne w opcji mse_settings, stan mapy witryny w opcji mse_rewrite_state, rejestruje trasy mapy i raz odświeża reguły przepisywania, dzięki czemu /sitemap.xml odpowiada od razu. Istniejąca opcja mse_settings nigdy nie jest nadpisywana, więc dezaktywacja i ponowna aktywacja zachowuje konfigurację. Wszystko poniżej działa jeszcze zanim otworzysz stronę ustawień.

  • Tytuły z wbudowanych szablonów: %%title%% %%sep%% %%sitename%% dla treści oraz %%sitename%% %%sep%% %%tagline%% dla strony głównej z listą najnowszych wpisów.
  • Opisy meta pobierane z ręcznie wpisanej zajawki albo generowane z treści i przycinane do około 160 znaków.
  • Znacznik canonical dobierany do kontekstu żądania, zastępujący ten wypisywany przez sam WordPress.
  • Znaczniki Open Graph i Twitter Cards (og_enabled ma wartość 1), typ karty summary_large_image.
  • Jeden graf JSON-LD na stronę: WebSite, Organization, WebPage, BreadcrumbList, a we wpisach także Article.
  • Mapa witryny XML (sitemap_enabled ma wartość 1), obejmująca publiczne typy treści i taksonomie istniejące w chwili aktywacji: wszystkie typy publiczne poza załącznikami oraz kategorie i tagi. Obrazki wyróżniające są dołączane. Wbudowana mapa wp-sitemap.xml zostaje wyłączona, a do generowanego przez WordPressa pliku robots.txt dopisany jest wiersz Sitemap:.
  • Przy aktywnym WooCommerce: dane strukturalne produktu i znaczniki Open Graph z ceną, oba włączone. Żadne z nich nie zależy od tego, kiedy WooCommerce zostało zainstalowane.
  • Separator tytułów: półpauza. Typ grafu wiedzy: organizacja, nazwana tak jak tytuł witryny.

Co pozostaje puste, dopóki tego nie uzupełnisz

Te pola są dostarczane puste. Żadne z nich niczego nie psuje, ale pierwsze cztery warto ustawić pierwszego dnia.

  • Tytuł strony głównej i jej opis meta.
  • Nazwa organizacji lub osoby oraz logo (kg_name, kg_logo_id).
  • Domyślny obrazek społecznościowy (default_og_image_id).
  • Nazwa użytkownika witryny w serwisie X (Twitter) i lista adresów profili społecznościowych.
  • Szablon tytułu i pole noindex dla każdego typu treści.
  • Lista wykluczeń z mapy witryny (sitemap_exclude_ids).

Gdzie znajdziesz wtyczkę w wp-admin

Wtyczka dodaje jedną pozycję menu najwyższego poziomu, M SEO, z ikoną lupy, blisko dołu menu kokpitu. Nagłówek strony to M SEO Editor, adres to admin.php?page=m-seo-editor. Dostęp wymaga uprawnienia manage_options, czyli w praktyce roli administratora. Użytkownik bez niego nigdy nie dociera do tej strony: WordPress ukrywa pozycję menu, a na bezpośrednie wejście odpowiada własnym komunikatem "Sorry, you are not allowed to access this page." Wtyczka powtarza tę kontrolę wewnątrz strony jako drugą linię obrony, więc jej własnego komunikatu nikt nie zobaczy. Strona ma karty General, Social i Sitemap, a przy aktywnym WooCommerce także WooCommerce. Każda karta ma własny przycisk Save Changes, a zapis jednej karty nigdy nie kasuje wartości z pozostałych. Na ekranie edycji wpisu, strony, produktu i własnego typu treści wtyczka dodaje panel, którego nagłówek zaczyna się od SEO, a kończy nazwą wtyczki; jest umieszczony wysoko w głównej kolumnie, pod edytorem. Wygląda tak samo w edytorze blokowym, w edytorze klasycznym i na ekranach produktów WooCommerce.

Karta General

Trzy sekcje: Titles & descriptions, Content types i Knowledge graph. Pola strony głównej działają tylko wtedy, gdy strona główna wyświetla najnowsze wpisy. Jeśli stroną główną jest strona statyczna, jej tytuł i opis pochodzą z panelu SEO tej strony, a oba ustawienia strony głównej są pomijane.

  • Title separator: osiem możliwości (dywiz, półpauza, pauza, kropka środkowa, punktor, kreska pionowa, znak », czyli prawy cudzysłów ostrokątny, tylda). Domyślnie półpauza. Nierozpoznana wartość jest zastępowana półpauzą.
  • Homepage title: domyślnie puste, co daje %%sitename%% %%sep%% %%tagline%%.
  • Homepage meta description: domyślnie puste, wtedy używany jest opis witryny.
  • Content types: po jednym wierszu na każdy publiczny typ treści (załączniki są celowo pominięte), a w nim szablon tytułu (domyślnie pusty, czyli %%title%% %%sep%% %%sitename%%) oraz pole "Hide from search results (noindex)", domyślnie wyłączone.
  • Zmienne szablonów: %%title%%, %%sitename%%, %%tagline%%, %%sep%%, %%excerpt%%, %%category%%, a przy aktywnym WooCommerce także %%price%% i %%sku%%. Nieznana zmienna zapisana małymi literami i podkreśleniami zamienia się w pustkę. Wszystko inne między znacznikami %%, na przykład wielka litera albo cyfra, trafia do tytułu dokładnie tak, jak zostało wpisane, więc %%Title%% i %%price2%% będą widoczne w wynikach wyszukiwania. Separatory osierocone przez pustą zmienną są zwijane, a pojedyncze usuwane z początku i końca tytułu.
  • This site represents: "An organisation" (domyślnie) albo "A person".
  • Organisation or person name: domyślnie puste, używany jest tytuł witryny.
  • Logo: domyślnie brak. Służy jako obraz wydawcy w danych strukturalnych; kwadratowe, co najmniej 112 na 112 px.

Karta Social

Wyjście Open Graph i Twitter Cards oraz lista profili zasilająca pole sameAs w danych strukturalnych. Obrazek udostępniania wybierany jest w trzech krokach: najpierw obrazek społecznościowy wpisu, potem jego obrazek wyróżniający, a na końcu domyślny obrazek ustawiony tutaj. Gdy nie ma żadnego z nich, znaczniki obrazka są pomijane, a typ karty Twittera zmienia się automatycznie z dużego obrazka na zwykłe summary.

  • Social meta tags: "Output Open Graph and Twitter Card tags", domyślnie włączone. Po wyłączeniu wtyczka nie wypisuje żadnych znaczników og: ani twitter:, a serwisy społecznościowe zgadują same.
  • Default social image: domyślnie brak. Zalecany rozmiar to 1200 na 630 px.
  • Card type: "Summary with large image" (domyślnie) albo "Summary".
  • Site username: domyślnie puste. Zapisywane bez znaku @, od jednego do piętnastu znaków: liter, cyfr lub podkreśleń. Błędna wartość jest odrzucana, poprzednia zostaje zachowana, a komunikat wyjaśnia powód. Nazwa trafia też na listę sameAs jako https://x.com/nazwa.
  • Profile URLs: domyślnie puste, po jednym adresie w wierszu. Wiersz, który WordPress potrafi naprawić, zostaje naprawiony, a nie odrzucony: po wpisaniu facebook.com/mypage zapisuje się i trafia do sameAs jako http://facebook.com/mypage, po niezabezpieczonym http. Usuwane są tylko wiersze nie do uratowania i tylko one są liczone w komunikacie. Wpisuj pełny adres https:// samodzielnie i sprawdź pole po zapisie.

Karta Sitemap

Gdy mapa jest włączona, u góry karty widnieje odnośnik do działającego indeksu. Indeks znajduje się pod /sitemap.xml, mapy podrzędne pod /sitemap-{typ}.xml, druga i kolejne strony pod /sitemap-{typ}-2.xml, a arkusz czytelny w przeglądarce pod /sitemap.xsl. W witrynie korzystającej wciąż ze zwykłych bezpośrednich odnośników (Plain) te same dokumenty serwowane są pod /?mse_sitemap=index i tam właśnie kieruje robots.txt. Mapy wysyłane są z nagłówkami X-Robots-Tag: noindex oraz Cache-Control: public, max-age=3600.

  • Sitemap: "Generate an XML sitemap", domyślnie włączone. Zastępuje wbudowaną mapę WordPressa; po wyłączeniu wraca mapa domyślna.
  • Include content types: zaznaczone jest to, co zaznaczono w chwili aktywacji, czyli wszystkie istniejące wtedy publiczne typy treści poza załącznikami. To lista zapisana, a nie ustalana na bieżąco.
  • Include taxonomies: zaznaczone jest to, co zaznaczono w chwili aktywacji, czyli kategorie i tagi, a kategorie produktów tylko wtedy, gdy WooCommerce już wówczas działało. Również lista zapisana.
  • Images: "Include featured and product gallery images", domyślnie włączone.
  • Exclude content: identyfikatory wpisów lub stron po przecinku, domyślnie puste.
  • Jedna strona mapy mieści do 1000 adresów. Podział na strony liczony jest na podstawie liczby opublikowanych wpisów jeszcze przed zastosowaniem noindex i wykluczeń, więc ostatnia strona dużego typu bywa krótka albo pozbawiona wpisów. To celowe, a dokument XML pozostaje poprawny.
  • Automatycznie pomijane są: wszystko, co nieopublikowane, wpisy chronione hasłem, treści oznaczone jako noindex, całe typy treści oznaczone jako noindex, wykluczone identyfikatory, produkty WooCommerce o widoczności w katalogu Hidden oraz terminy bez wpisów. Mapa autorów ani użytkowników nie powstaje w ogóle.
  • Wpisy taksonomii nie mają daty lastmod. Mają ją tylko wiersze typów treści.

Karta WooCommerce

Ta karta istnieje tylko przy aktywnym WooCommerce. Węzeł Product obejmuje produkty proste i zmienne: nazwę, opis, obrazek, sku, gtin (z pola global unique id w WooCommerce 9.2 i nowszym), markę oraz Offer, a dla produktów zmiennych AggregateOffer z lowPrice, highPrice i offerCount. Pole priceValidUntil pojawia się tylko przy produkcie prostym, który jest w promocji z datą końcową; AggregateOffer produktu zmiennego nigdy go nie zawiera. Pole aggregateRating dodawane jest tylko wtedy, gdy recenzje są włączone w całej witrynie, a produkt ma co najmniej jedną. Archiwum produktów podlega ustawieniom panelu SEO strony Shop.

  • Product structured data: "Replace WooCommerce structured data with the richer M SEO version", domyślnie włączone. Odpina własne generatory WooCommerce dla Product, WebSite i BreadcrumbList, żeby strona nigdy nie zawierała dwóch encji Product. Dane strukturalne w e-mailach z zamówieniami pozostają nietknięte.
  • Product Open Graph: dodaje product:price:amount, product:price:currency i product:availability na potrzeby katalogów Facebooka i Pinterest Rich Pins. Domyślnie włączone.
  • Brand source: wartość zapisana w chwili aktywacji, czyli "Brands (WooCommerce)" tylko wtedy, gdy taksonomia product_brand już wówczas istniała, a w przeciwnym razie "None". Lista pokazuje Brands i wszystkie globalne atrybuty produktu, ale zapisana wartość nigdy sama się nie aktualizuje. Po instalacji WooCommerce już po tej wtyczce ustawienie zostaje na "None", więc marka nie trafia do schematu Product, dopóki nie zostanie wybrana i zapisana.

Panel SEO przy wpisie, stronie i produkcie

Panel ma trzy karty. Search engine pokazuje podgląd wyniku w stylu Google nad polem tytułu SEO (do 200 znaków) i polem opisu meta (do 400 znaków). Oba symbole zastępcze pokazują, co zostanie użyte, jeśli zostawisz pole puste, i oba działają na żywo: wskaźnik pod każdym polem podaje liczbę znaków i rzeczywistą szerokość w pikselach, ostrzegając powyżej 580 px i sygnalizując przekroczenie powyżej 620 px dla tytułu, a dla opisu granice wynoszą 920 px i 990 px. Karta Social zawiera podgląd karty udostępniania, Social title, Social description, Social image oraz og:type. Karta Advanced zawiera Canonical URL, noindex i nofollow. Wyczyszczenie pola usuwa zapisaną wartość, zamiast zapisywać pustą. Zapis wymaga prawa edycji wpisu i na tym kontrola się kończy: dziewięć kluczy meta nie jest wystawionych do REST API, a zapis przez WP-CLI poleceniem wp post meta trafia prosto do bazy, w ogóle jej nie przechodząc.

Uwaga

Opcja Automatic przy og:type podaje wartość zgadywaną tak, jakby wpis był zwykłą stroną pojedynczą. Dla wpisów i stron pokazuje Automatic (article), dla produktów Automatic (product) i tam jest poprawna. Na statycznej stronie głównej, na stronie wpisów i na stronie Shop w WooCommerce rzeczywiste wyjście to website, podczas gdy panel wciąż pokazuje article. Błędna jest sama etykieta, nie wyjście.

Pierwsze uruchomienie, po kolei

Żaden z tych kroków nie jest obowiązkowy, ale to najkrótsza droga od świeżej aktywacji do poprawnie skonfigurowanej witryny. Na tym etapie nie ruszaj żadnego pola noindex.

  1. Otwórz M SEO, kartę General. Wybierz separator, który ma się pojawiać w kartach przeglądarki i wynikach wyszukiwania.
  2. Jeśli strona główna wyświetla najnowsze wpisy, wpisz jej tytuł i opis meta. Jeśli jest to strona statyczna, pomiń oba pola i edytuj panel SEO tej strony.
  3. W sekcji Content types ustaw szablon tytułu tylko tam, gdzie domyślny %%title%% %%sep%% %%sitename%% nie pasuje. Cokolwiek wpiszesz, zostaw w tym %%title%%.
  4. W sekcji Knowledge graph wybierz organizację albo osobę, wpisz nazwę i wskaż kwadratowe logo. Zapisz.
  5. Przejdź do karty Social. Zostaw znaczniki włączone, wgraj domyślny obrazek społecznościowy 1200 na 630, sprawdź typ karty, wpisz nazwę użytkownika X bez znaku @ i wklej po jednym pełnym adresie https:// w wierszu. Zapisz, a potem odczytaj pole ponownie i sprawdź, czy nic nie zostało przepisane na http.
  6. Przejdź do karty Sitemap. Zaznacz wszystkie typy treści i taksonomie, które mają być w wyszukiwarce, zwłaszcza to, co zainstalowano po tej wtyczce. Odznacz to, co do wyszukiwarki nie należy. Zapisz.
  7. Kliknij odnośnik u góry karty Sitemap i sprawdź, czy indeks się wyświetla i czy zawiera to, czego oczekujesz.
  8. Jeśli WooCommerce jest aktywne, otwórz kartę WooCommerce, zostaw obie opcje włączone i wybierz źródło marki pasujące do katalogu, nawet jeśli wygląda na już wybrane. Zapisz.
  9. Otwórz jeden wpis i jedną stronę, obejrzyj podgląd wyniku i popraw tytuł oraz opis tam, gdzie wersja automatyczna brzmi źle.
  10. Zgłoś /sitemap.xml w Google Search Console i Bing Webmaster Tools.

Charakter ryzyka

Warto jasno nazwać, co może pójść źle. M SEO Editor nie ma funkcji logowania, zapory, przekierowań ani poczty: nie zablokuje dostępu do kokpitu i w ogóle nie dotyka wysyłki e-maili. Potrafi natomiast usunąć z wyników wyszukiwania całą witrynę albo jej część, po cichu zostawić treści poza mapą witryny i trwale skasować każde wpisane kiedykolwiek pole SEO. Potrafi też sprawić, że jedna zwykła strona odpowie 404 odwiedzającemu, który kliknie spreparowany odnośnik; opisuje to osobna sekcja poniżej. Każde ustawienie da się przywrócić ręcznie, ale nic nie przywróci go automatycznie, a dwa z nich kasują zapisany wybór bez żadnego działania z twojej strony. Dane niszczy wyłącznie usunięcie wtyczki.

Niebezpieczne: noindex przy pojedynczym wpisie

Ta sama dyrektywa dostępna jest przy każdym wpisie, na karcie Advanced panelu SEO. Dla strony z podziękowaniem to właściwe narzędzie, wszędzie indziej niewłaściwe. Wpis z noindex znika z mapy witryny, serwowany jest bez znacznika canonical i nie dostaje żadnych danych strukturalnych. Przy produkcie WooCommerce ten ostatni punkt boli podwójnie: skoro wtyczka odpięła już znaczniki Product generowane przez samo WooCommerce, strona produktu z noindex zostaje bez danych strukturalnych z obu wtyczek i po cichu traci wyniki rozszerzone. Dopóki noindex jest włączony, wpisany przy tym wpisie adres canonical również jest pomijany.

  1. Pierwszym poleceniem wypisz wszystkie wpisy, które mają teraz tę flagę.
  2. Odznacz pole na karcie Advanced w panelu SEO i zaktualizuj wpis. Albo usuń wiersz meta bezpośrednio drugim poleceniem, zastępując 123 identyfikatorem wpisu.
  3. Przeładuj adres publiczny i sprawdź, czy wrócił znacznik canonical i skrypt JSON-LD.
  4. Poczekaj na kolejne odwiedziny robota albo poproś o zaindeksowanie w Search Console.
wp post list --post_type=any --meta_key=_mse_noindex --meta_value=1 --fields=ID,post_title
wp post meta delete 123 _mse_noindex

Niebezpieczne: nadpisanie adresu canonical

Pole Canonical URL na karcie Advanced zastępuje własny adres strony tym, co zostanie wpisane. Wskazanie innego adresu mówi wyszukiwarkom, że ta strona jest duplikatem i nie powinna się pozycjonować; zrobione przez pomyłkę albo skopiowane z szablonu do kilku wpisów, usuwa te strony z wyników, choć wciąż zwracają 200 i dla odwiedzającego wyglądają zdrowo. Nic na ekranie nie sygnalizuje błędu. Co gorsza, wpisana wartość przechodzi przez mechanizm czyszczenia adresów WordPressa, który naprawia, zamiast odrzucać: wartość bez protokołu, example.com albo przekręcone exmaple.com, zostaje zapisana jako http://exmaple.com i wypisana jako działający canonical wskazujący poza witrynę. Pole nie zostaje puste, a taki stan nie jest bezpieczny. Usuwane jest tylko to, czego nie da się uratować, na przykład javascript:.

  1. Pierwszym poleceniem wypisz wszystkie wpisy z zapisanym adresem canonical, a drugim odczytaj rzeczywistą wartość podejrzanego wpisu.
  2. Otwórz objęty wpis, przejdź do panelu SEO, na kartę Advanced, a następnie całkowicie wyczyść pole Canonical URL. Symbol zastępczy pokazuje poprawny domyślny odnośnik.
  3. Zaktualizuj wpis i uruchom drugie polecenie ponownie. Nie może nic zwrócić. Jeśli wiersz nadal istnieje, usuń go trzecim poleceniem.
  4. Podejrzyj źródło strony i sprawdź, czy odnośnik canonical wskazuje teraz na nią samą.
  5. Powtórz przy każdym wpisie, który dostał tę samą błędną wartość, a dla najważniejszych poproś o zaindeksowanie.
wp post list --post_type=any --meta_key=_mse_canonical --fields=ID,post_title
wp post meta get 123 _mse_canonical
wp post meta delete 123 _mse_canonical
Uwaga

Canonical wskazujący gdzie indziej to najcichszy sposób na utratę pozycji przy użyciu tej wtyczki. Strona dalej działa, ruch już nie. Ponieważ literówka bez protokołu jest po cichu uzupełniana do http://, zawsze odczytuj zapisaną wartość, zamiast ufać ekranowi.

Niebezpieczne: noindex albo canonical na stronie wpisów lub stronie Shop

Dwie zwyczajnie wyglądające strony rządzą całymi archiwami. Strona wskazana w Settings, Reading jako strona wpisów rządzi archiwum bloga, a strona Shop w WooCommerce rządzi archiwum produktów: wtyczka sprowadza każde z tych archiwów z powrotem do odpowiedniej strony i czyta zapisany na niej panel SEO. Zaznaczenie tam noindex sprawia, że całe archiwum serwowane jest z dyrektywą noindex, traci znacznik canonical i traci dane strukturalne, czyli dokładnie tyle samo, ile ukrycie całego typu treści na karcie General. Wpisanie tam adresu w pole Canonical URL przenosi ten canonical na całe archiwum. Na żadnym z tych ekranów edycji nic nie mówi, że strona jest wyjątkowa, a polecenia kontrolne z poprzednich sekcji pokazują ją wśród zwykłych treści, więc trzeba ją sprawdzić z nazwy.

  1. Odczytaj identyfikatory obu stron dwoma pierwszymi poleceniami poniżej. Pusta wartość page_for_posts oznacza, że wpisy wyświetla sama strona główna i osobnej strony wpisów nie ma.
  2. Otwórz każdą z tych stron w edytorze, przejdź do panelu SEO, na kartę Advanced, a następnie sprawdź, czy noindex jest odznaczony, a pole Canonical URL puste, chyba że zostało ustawione świadomie. Zaktualizuj stronę.
  3. Albo odczytaj i usuń obie wartości meta z wiersza poleceń, zastępując 123 identyfikatorem strony.
  4. Otwórz archiwum bloga oraz /shop/ i podejrzyj źródło: znacznik meta robots nie może zawierać noindex, odnośnik canonical musi wskazywać na samo archiwum, a skrypt JSON-LD musi wrócić.
wp option get page_for_posts
wp option get woocommerce_shop_page_id
wp post meta get 123 _mse_noindex
wp post meta get 123 _mse_canonical
wp post meta delete 123 _mse_noindex
wp post meta delete 123 _mse_canonical
Uwaga

Jedno pole wyboru na stronie wpisów albo na stronie Shop wyindeksowuje całe archiwum, choć ustawienie, które zwykle to robi, leży zupełnie gdzie indziej. Gdy z wyszukiwarki znika cały blog albo całe archiwum sklepu, a karta General wygląda czysto, te dwie strony są następnym miejscem do sprawdzenia.

Niebezpieczne: noindex i canonical nie są zarezerwowane dla administratora

Panel SEO pojawia się przy każdym obsługiwanym typie treści u każdego, kto może edytować dany wpis, a jego procedura zapisu sprawdza dokładnie jedno: prawo edycji wpisu. Oznacza to, że Editor może oznaczyć noindex na dowolnej stronie witryny albo skierować jej canonical gdzie indziej, a Author lub Contributor może zrobić to samo ze swoimi treściami. Nikt nie potrzebuje uprawnienia manage_options ani wizyty na stronie ustawień. Trzy poprzednie sekcje opisują szkody, których administrator nie musi wyrządzić osobiście, więc lepiej to skontrolować niż zakładać, że się nie zdarzyło.

  1. Uruchamiaj oba polecenia poniżej regularnie albo po nadaniu komuś praw edycji.
  2. Każda niespodzianka na pierwszej liście to strona obecnie ukryta przed wyszukiwarką. Wpisy z drugiej listy mają zapisany własny canonical; przed decyzją odczytaj go poleceniem wp post meta get.
  3. Błędy naprawiaj dokładnie tak, jak opisują dwie poprzednie sekcje: odznacz pole, wyczyść pole tekstowe albo usuń wiersz meta.
  4. Nie ma na to przełącznika per rola. Jeśli to nie może się zdarzyć, ogranicz liczbę ról mogących edytować opublikowane treści.
wp post list --post_type=any --meta_key=_mse_noindex --meta_value=1 --fields=ID,post_title,post_author
wp post list --post_type=any --meta_key=_mse_canonical --fields=ID,post_title,post_author

Niebezpieczne: kolejność instalacji zamraża wybór do mapy witryny

Aktywacja zapisuje w mse_settings listę typów treści i taksonomii wchodzących do mapy witryny jeden raz i nigdy do niej nie wraca. Ustawienia odczytywane są przez scalenie zapisanej opcji z wartościami domyślnymi, a scalanie uzupełnia wyłącznie brakujące klucze, więc zapisane listy zawsze wygrywają. Po instalacji WooCommerce, wtyczki z własnymi typami treści albo motywu rejestrującego własny typ już po M SEO Editor tego typu po prostu nie ma na liście. Na ekranie nie ma o tym słowa: mapa wygląda zdrowo, indeks się wyświetla, a brakuje w nim całego katalogu. To samo zamrożenie dotyczy pola Brand source na karcie WooCommerce, które zostaje na None i pozostawia markę poza każdym schematem Product. Naprawa to jeden zapis na każdej karcie; ceną niewiedzy są miesiące produktów nieodwiedzanych przez roboty.

  1. Po instalacji czegokolwiek, co dodaje typ treści albo taksonomię, otwórz M SEO, kartę Sitemap.
  2. Zaznacz nowe typy treści w Include content types i nowe taksonomie w Include taxonomies. Zapisz.
  3. Otwórz kartę WooCommerce, wybierz Brand source ponownie, nawet jeśli wygląda na już wybrane, i zapisz. Zapisana wartość None sama się nie zmieni.
  4. Kliknij odnośnik u góry karty Sitemap i sprawdź, czy nowa mapa podrzędna jest w indeksie.
  5. Aby zobaczyć, co jest naprawdę zapisane, a nie co sugerują pola wyboru, odczytaj opcję poniższym poleceniem i sprawdź sitemap_post_types, sitemap_taxonomies oraz wc_brand_source.
wp option get mse_settings --format=json
Uwaga

Sklep, który aktywował M SEO Editor przed instalacją WooCommerce, nie ma w mapie witryny ani jednego produktu i nie ma marki w schemacie Product, a nic nigdzie tego nie zgłasza. Po każdej instalacji wtyczki sprawdź karty Sitemap i WooCommerce.

Niebezpieczne: zapis karty Sitemap przy wyłączonej innej wtyczce

Przy zapisie karty Sitemap przesłany wybór jest przecinany z typami treści i taksonomiami istniejącymi w tej chwili. Typ, którego wtyczka jest wyłączona, nie istnieje, więc nie zostaje narysowany jako pole wyboru i wypada z zapisanej listy. Ponowna aktywacja tamtej wtyczki go nie przywraca: wpisu nie ma już w opcji, a pole wraca niezaznaczone. Boli to zwłaszcza podczas zwykłego szukania konfliktu wtyczek, gdzie wyłączanie po kolei jest całą metodą. Dzieje się po cichu, przetrwa ponowną aktywację i usuwa z mapy witryny cały typ treści.

  1. Nie zapisuj karty Sitemap, gdy jakakolwiek wtyczka jest tymczasowo wyłączona. Jeśli to konieczne, najpierw zanotuj, których typów brakuje na liście.
  2. Po ponownej aktywacji tamtej wtyczki wróć do M SEO, Sitemap, zaznacz ponownie typy treści i taksonomie, które wróciły, i zapisz.
  3. Kliknij odnośnik u góry karty i sprawdź, czy mapa podrzędna tego typu znowu jest na liście.
  4. Jeśli nie wiadomo, co przepadło, porównaj zapisaną listę z typami, które faktycznie istnieją.
wp option get mse_settings --format=json
wp post-type list --public=1 --field=name

Niebezpieczne: wyłączenie mapy witryny albo jej opróżnienie

Dwa ustawienia na karcie Sitemap potrafią po cichu opróżnić to, co zostało zgłoszone wyszukiwarkom. Odznaczenie "Generate an XML sitemap" sprawia, że /sitemap.xml zaczyna zwracać 404, z robots.txt znika wiersz Sitemap:, a zadanie wraca do domyślnej mapy WordPressa pod /wp-sitemap.xml, która nie odpowiada już adresowi zarejestrowanemu w Search Console. Osobno: odznaczenie wszystkich pól w sekcji "Include content types" jest przyjmowane bez protestu i usuwa z mapy wszystkie adresy wpisów. Indeks nie wygląda potem na pusty, bo mapy taksonomii biorą się z osobnego ustawienia: dopóki kategorie i tagi są zaznaczone, /sitemap-category.xml i /sitemap-post_tag.xml nadal się pojawiają, choć wpisów, stron i produktów już w niej nie ma. Dopiero po odznaczeniu także taksonomii indeks robi się naprawdę pusty. Żadna z tych operacji nie niszczy danych, obie cofniesz, zaznaczając pola i zapisując.

  1. Otwórz M SEO, kartę Sitemap, a następnie ponownie zaznacz "Generate an XML sitemap".
  2. Zaznacz typy treści i taksonomie, które mają być w wyszukiwarce. Zapisz.
  3. Kliknij odnośnik u góry karty i sprawdź, czy indeks wymienia mapy podrzędne.
  4. Otwórz /robots.txt i sprawdź, czy wiersz Sitemap: wrócił. Jeśli nie, przeczytaj następną sekcję, zanim uznasz wtyczkę za zepsutą.
Uwaga

Mapa, która się wyświetla, ale nie wymienia niczego istotnego, jest gorsza od takiej, która zwraca 404, bo monitoring widzi zdrowy dokument. Po każdej zmianie na tej karcie otwórz indeks i sprawdź, co w nim jest.

Gdy wiersz Sitemap nigdy nie pojawia się w robots.txt

Wtyczka dopisuje wiersz Sitemap: do pliku robots.txt generowanego przez WordPressa w locie. Zatrzymują to dwie rzeczy i żadna nie jest winą wtyczki. Po pierwsze, prawdziwy plik robots.txt leżący w katalogu głównym: wtedy WordPress niczego nie generuje, więc wiersz da się dopisać tylko ręcznie. Po drugie, Settings, Reading, "Discourage search engines from indexing this site": dopóki to pole jest zaznaczone, wiersz nie zostaje dopisany, a sam WordPress dodaje do każdej strony noindex obejmujący całą witrynę. To pole jest najszybszym sposobem na usunięcie witryny WordPress z wyszukiwarki, nie ma nic wspólnego z tą wtyczką i właśnie od niego trzeba zacząć, gdy witryna znika z Google po uruchomieniu. Inaczej czytelnik wykonujący kontrolę z poprzedniej sekcji będzie czekał na wiersz, który nigdy nie nadejdzie.

  1. Otwórz Settings, Reading, a następnie odznacz "Discourage search engines from indexing this site". Zapisz.
  2. Otwórz Settings, Permalinks i naciśnij raz Save, co odtworzy reguły przepisywania.
  3. Otwórz /robots.txt w przeglądarce. Wiersz Sitemap: musi tam być.
  4. Jeśli go nie ma, sprawdź przez FTP albo menedżer plików, czy w katalogu głównym nie leży fizyczny robots.txt. Jeśli leży, dopisz wiersz Sitemap: ręcznie; WordPress tego nie zrobi.
  5. Podejrzyj źródło dowolnej strony publicznej i sprawdź, czy w znaczniku meta robots nie został noindex.
Uwaga

"Discourage search engines from indexing this site" jest normalne na witrynie testowej i zabójcze na produkcyjnej. Ustawia się je poza tą wtyczką, więc M SEO o nim nie informuje, a skutek wygląda dokładnie jak awaria wtyczki.

Gdy znacznik canonical znika sam

Przy każdym żądaniu publicznym wtyczka usuwa znacznik canonical wypisywany przez WordPressa i wstawia własny. Ta podmiana jest bezwarunkowa, ale zamiennik nie zawsze powstaje. Nie ma canonical na stronie z noindex i to jest zamierzone. Nie ma go też przy żądaniu, którego wtyczka nie potrafi zaklasyfikować, przy terminie, dla którego nie da się ustalić odnośnika archiwum, oraz wszędzie tam, gdzie własny filtr mse_canonical zwraca pustą wartość. Strata w każdym z tych przypadków wygląda inaczej. Żądanie, którego wtyczka nie potrafi zaklasyfikować, nie dostaje w ogóle skryptu JSON-LD, a nie skrócony; w pozostałych dwóch dane strukturalne kurczą się do węzłów WebSite i wydawcy. Tylko na stronie pojedynczej brakuje canonical, który czysty WordPress by wypisał, bo rdzeń wypisuje go wyłącznie przy treści pojedynczej, więc w archiwum nie ma czego tracić względem rdzenia. Takie żądania są rzadkie, ale warto je rozpoznać, zamiast szukać błędu w motywie.

  1. Podejrzyj źródło strony. Jeśli brakuje odnośnika canonical, najpierw sprawdź, czy strona nie ma noindex, na poziomie wpisu albo typu treści. Jeśli ma, to jest wyjaśnienie, a rozwiązanie opisują wcześniejsze sekcje.
  2. Jeśli noindex nie ma, poszukaj w motywie albo wtyczce towarzyszącej własnego filtra mse_canonical lub mse_context.
  3. Jako doraźne rozwiązanie na jednej ważnej stronie wpisz poprawny adres w pole Canonical URL w panelu SEO tego wpisu.
  4. W archiwum terminu sprawdź, czy taksonomia jest zarejestrowana z działającym odnośnikiem archiwum. Termin, dla którego odnośnika nie da się zbudować, nie dostaje canonical.

Parametr mse_sitemap przy zwykłych adresach

Mapa witryny jest osiągalna przez publiczny parametr zapytania i właśnie dlatego działa w witrynach ze zwykłymi bezpośrednimi odnośnikami. Skutkiem ubocznym jest to, że parametr działa przy każdym adresie publicznym, nie tylko przy /sitemap.xml. Dopisanie ?mse_sitemap=index do adresu dowolnej strony zwraca pod tym adresem indeks mapy z kodem HTTP 200. Dopisanie ?mse_sitemap= i dowolnej wartości, której wtyczka nie rozpoznaje, zamienia tę stronę w 404 dla osoby, która otworzyła odnośnik, i dzieje się to w witrynie całkowicie sprawnej, z włączoną mapą. Przy wyłączonej mapie albo gdy przejęła ją inna wtyczka SEO, robi to każda wartość, łącznie z index. Odpowiedzi z kodem 200 niosą nagłówek X-Robots-Tag: noindex, więc wyszukiwarki duplikatów nie zaindeksują; odpowiedź 404 takiego nagłówka nie ma, a w żadnym z tych przypadków nic nie jest zapisywane ani zmieniane. Nie ma ustawienia, które to wyłącza, i nie ma czego naprawiać. Opisujemy to po to, żeby zgłoszenie o "stronie, która zwraca 404 tylko jednemu odwiedzającemu" nie zostało uznane za atak.

Szablon tytułu bez %%title%%

Pole szablonu tytułu na karcie General przyjmuje dowolny tekst i jest używane dokładnie tak, jak zostało zapisane. Szablon w rodzaju "Kup w %%sitename%%" nie zawiera żadnej zmiennej zależnej od strony, więc każda strona tego typu treści dostaje identyczny znacznik title. Google traktuje witrynę pełną identycznych tytułów jako treść zduplikowaną i cały typ traci widoczność. Nic nie ostrzega, a podgląd wyniku przy wpisie wygląda poprawnie, bo pokazuje ten sam identyczny tytuł. Zasada jest prosta: każdy szablon pisany dla typu treści musi zawierać %%title%% albo inną zmienną różną dla każdego elementu, na przykład %%sku%%.

  1. Otwórz M SEO, General, Content types, i przeczytaj szablon każdego typu, dla którego został napisany.
  2. Jeśli szablon nie ma %%title%% ani innej zmiennej różnej dla każdego elementu, dopisz %%title%% albo całkowicie wyczyść pole.
  3. Wyczyszczone pole wraca do %%title%% %%sep%% %%sitename%%, co jest zawsze bezpieczne.
  4. Zapisz, a potem otwórz na stronie publicznej dwa różne elementy tego typu i sprawdź, czy znaczniki title się różnią.

Niebezpieczne: usunięcie wtyczki kasuje wszystkie pola SEO

Dezaktywacja wtyczki niczego nie usuwa. Usunięcie uruchamia uninstall.php, który kasuje opcje mse_settings i mse_rewrite_state, a następnie usuwa z każdego wpisu w witrynie dziewięć kluczy meta: _mse_title, _mse_description, _mse_canonical, _mse_noindex, _mse_nofollow, _mse_og_title, _mse_og_description, _mse_og_image_id oraz _mse_og_type. W instalacji wielowitrynowej przechodzi po wszystkich witrynach sieci i robi to samo w każdej. Dzieje się tak zarówno po naciśnięciu Delete na liście wtyczek, jak i po uruchomieniu wp plugin delete z wiersza poleceń: wiersz poleceń nie usuwa plików, tylko wykonuje tę samą procedurę odinstalowania. Wszystkie ręcznie wpisane tytuły i opisy SEO znikają w jednym kroku, bez eksportu i bez cofnięcia. Wewnątrz WordPressa nie ma ścieżki odzyskania: jedyna droga powrotna to przywrócenie bazy danych.

  1. Zanim cokolwiek zostanie usunięte, zrób zrzut bazy poniższym poleceniem i przechowaj go poza serwerem. Dotyczy to wiersza poleceń dokładnie tak samo jak listy wtyczek.
  2. Jeśli wtyczka ma tylko przestać działać, dezaktywuj ją zamiast usuwać. Dezaktywacja zachowuje wszystkie ustawienia i wszystkie pola.
  3. Jeśli przechodzisz na inną wtyczkę SEO, najpierw zainstaluj i skonfiguruj nową, przenieś pola, które potrafi zaimportować, a M SEO Editor usuń na końcu.
  4. Jeśli usunięcie już nastąpiło, przywróć wp_options i wp_postmeta z najnowszej kopii zapasowej. Nic innego nie odzyska tych wierszy.
wp db export mse-seo-backup.sql
Uwaga

Usunięcie działa nieodwracalnie i w całej sieci, tak samo z listy wtyczek, jak i przez wp plugin delete. Czyści dane meta wtyczki z każdego wpisu w każdej witrynie sieci multisite, nie tylko w tej, którą masz przed sobą.

Gdy działa inna wtyczka SEO

Jeśli aktywne są Yoast SEO, Rank Math, All in One SEO, SEOPress albo The SEO Framework, M SEO Editor całkowicie się wycofuje: żadnych znaczników meta, żadnych danych strukturalnych, żadnej mapy witryny, a trasy mapy nie są nawet przejmowane, więc /sitemap.xml zwraca 404, a nie stronę główną. W kokpicie administratorzy widzą ostrzeżenie "M SEO Editor is paused." Strona ustawień i panel SEO pozostają w pełni sprawne, nic nie jest usuwane, więc dane czekają. Wyłącz drugą wtyczkę, a wszystko wraca przy kolejnym wczytaniu strony kokpitu, wraz z jednorazowym automatycznym odświeżeniem reguł przepisywania, które oddaje /sitemap.xml. Jeśli naprawdę chcesz obu naraz, filtr wymusi wyjście, kosztem zdublowanych znaczników na każdej stronie.

add_filter( 'mse_seo_conflict', '__return_empty_string' );
Uwaga

Wymuszenie wyjścia przy działającej innej wtyczce SEO umieszcza na każdej stronie dwa tytuły, dwa canonicale i dwa grafy schema. Wyszukiwarki uznają to za zepsutą witrynę. Używaj tylko do testu, nigdy na stałe.

Rozwiązywanie problemów

Wtyczka otacza swoje wyjście w sekcji head komentarzami HTML z numerem wersji, więc podgląd źródła od razu mówi, czy w ogóle działa. Jeśli mapa witryny zwraca 404 tam, gdzie wcześniej działała, zwykle winne są nieaktualne reguły przepisywania: zapisz raz bezpośrednie odnośniki w Settings, Permalinks, albo uruchom poniższe polecenie.

  • W źródle strony nie ma znaczników M SEO: działa inna wtyczka SEO, a ta się wycofała. Poszukaj w kokpicie komunikatu o wstrzymaniu.
  • W mapie witryny brakuje całego typu treści: został zarejestrowany po aktywacji M SEO Editor albo wypadł przy zapisie karty Sitemap, gdy jego wtyczka była wyłączona. Zaznacz go na karcie Sitemap i zapisz.
  • Brak marki w schemacie Product: Brand source wciąż ma wartość None, bo WooCommerce pojawiło się po wtyczce. Wybierz je ponownie na karcie WooCommerce i zapisz.
  • Tytuł i opis strony głównej są pomijane: stroną główną jest strona statyczna. Te dwa pola działają tylko wtedy, gdy strona główna wyświetla najnowsze wpisy. Edytuj panel SEO tej strony.
  • /sitemap.xml zwraca 404: odśwież reguły przepisywania; sprawdź, czy w katalogu głównym nie leży fizyczny plik sitemap.xml albo czy reguła serwera nie przechwytuje adresu przed WordPressem; upewnij się, że mapa jest włączona; przy zwykłych odnośnikach użyj /?mse_sitemap=index. Po przeniesieniu witryny albo zmianie domeny trzeba raz ręcznie zapisać bezpośrednie odnośniki.
  • Brak wiersza Sitemap: w robots.txt: w katalogu głównym leży fizyczny plik robots.txt albo zaznaczone jest Settings, Reading, "Discourage search engines from indexing this site".
  • Strony brakuje w mapie witryny: nie jest opublikowana, jest chroniona hasłem, ona sama lub cały jej typ treści ma noindex, jej identyfikator jest na liście wykluczeń albo, w przypadku produktu, jego widoczność w katalogu to Hidden.
  • Ostatnia strona mapy jest krótka albo bez wpisów: tak ma być. Podział na strony liczy się przed odfiltrowaniem treści z noindex i wykluczeń.
  • Wszystkie strony jednego typu treści mają ten sam tytuł: jego szablon tytułu nie zawiera %%title%%.
  • W wynikach wyszukiwania widać zmienną w rodzaju %%Title%%: rozpoznawane są tylko nazwy pisane małymi literami. Zapisz ją małymi literami.
  • Karta Twittera pokazuje mały obrazek: nie udało się ustalić żadnego obrazka, więc typ karty zmieniono na summary. Ustaw obrazek wyróżniający albo domyślny obrazek społecznościowy.
  • Wygrywa tytuł z motywu: wtyczka działa przez API tytułów WordPressa, więc motyw wypisujący własny, zakodowany na sztywno znacznik title omija ją.
  • Zapisana wartość wróciła do poprzedniej: nazwa użytkownika X została odrzucona jako niepoprawna albo usunięto wiersze z adresami profili, których nie dało się uratować. Powód znajdziesz w komunikacie u góry strony ustawień. Wiersz po cichu naprawiony na http nie wywołuje żadnego komunikatu.
  • Zmiany nie widać po stronie publicznej: mapy wysyłane są z godzinnym nagłówkiem cache, a pamięć podręczna strony lub CDN może trzymać stare wyjście sekcji head.
wp rewrite flush

Prywatność i dane

Nic nie opuszcza witryny. Wtyczka nie wysyła żadnych zewnętrznych żądań HTTP, nie ustawia ciasteczek, nie rejestruje zadań cron, nie tworzy tabel w bazie, nie wysyła e-maili i nie powiadamia wyszukiwarek. Bez konta, bez klucza licencyjnego, bez telemetrii. Wszystko, co przechowuje, mieści się w tabelach, które WordPress i tak ma: jedna opcja, mse_settings, z całą konfiguracją; jedna opcja, mse_rewrite_state, ze słowem active albo standdown, żeby trasy mapy witryny dało się czysto przekazać; oraz dziewięć kluczy meta wpisów z przedrostkiem _mse_, zapisywanych tylko tam, gdzie pole zostało wypełnione, bo puste pola są usuwane, a nie przechowywane. Wybór logo albo obrazka społecznościowego zapisuje wyłącznie identyfikator z biblioteki mediów, nigdy kopię. Żadne dane osobowe odwiedzających nie są odczytywane, przechowywane ani przesyłane, a mapa autorów ani użytkowników nie powstaje.

Odinstalowanie

Dezaktywacja i usunięcie to dwie zupełnie różne operacje i tę różnicę warto powiedzieć wprost jeszcze raz. Dezaktywacja odświeża reguły przepisywania i zatrzymuje wyjście: znikają znaczniki meta, dane strukturalne i mapa witryny, wraca wbudowana mapa WordPressa pod /wp-sitemap.xml, z robots.txt znika wiersz Sitemap:, a WooCommerce znowu wypisuje własne dane strukturalne. Wszystkie ustawienia i wszystkie wpisane pola pozostają nietknięte i wracają w chwili ponownej aktywacji, łącznie z zamrożonym wyborem do mapy witryny. Usunięcie uruchamia dodatkowo opisaną wyżej procedurę odinstalowania i kasuje obie opcje oraz wszystkie dziewięć kluczy meta z każdego wpisu, w każdej witrynie sieci multisite. W obu przypadkach nic więcej nie zostaje: wpisy, strony, produkty, zajawki, obrazki wyróżniające i biblioteka mediów nigdy nie są ruszane, a do posprzątania nie ma ani tabel, ani zadań cron, ani wartości tymczasowych, ani plików poza katalogiem wtyczki. Reguły przepisywania odtwarzają się same przy kolejnym odświeżeniu, więc żaden adres mapy nie zostaje zawieszony.

Filtry dla programistów

Każdą wartość wypisywaną przez wtyczkę można zmienić z motywu albo małej wtyczki towarzyszącej, bez ruszania jej kodu. Najprzydatniejsze: mse_settings filtruje całą konfigurację przy odczycie, w ten sposób WPML lub Polylang dostają wartości osobne dla każdego języka, a także tak można nadpisać w kodzie zamrożone listy mapy witryny; mse_title, mse_description i mse_canonical korygują wartości końcowe dla danego żądania; mse_og_tags, mse_twitter_tags, mse_og_type i mse_og_image obejmują zestaw społecznościowy; mse_robots_flags decyduje o noindex i nofollow; mse_template_vars rejestruje własne %%zmienne%%; mse_schema_graph, mse_schema_product, mse_schema_article_types, mse_schema_search_action i mse_breadcrumb_trail kształtują dane strukturalne przed wypisaniem; mse_sitemap_post_types, mse_sitemap_taxonomies, mse_sitemap_entry, mse_sitemap_term_entry, mse_sitemap_index, mse_sitemap_query_args i mse_sitemap_max_urls kształtują mapę witryny, a zwrócenie pustego wpisu usuwa adres; mse_post_types, mse_metabox_post_types i mse_register_meta_args decydują, gdzie pojawia się panel SEO; mse_context udostępnia rozpoznany kontekst żądania, na którym opierają się wszystkie pozostałe decyzje; mse_seo_conflict steruje wycofaniem; mse_output_comment i mse_sitemap_taxonomy_choices są kosmetyczne.

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