UI w PrestaShop to nie jeden interfejs, a dwa: front office, który widzi klient, i back office, w którym pracuje Twój zespół. Zmiany w obu miejscach mają inne konsekwencje — jedno wpływa na konwersję, drugie na czas obsługi zamówień. Ten tekst zbiera zasady, które pozwalają poprawiać interfejs bez psucia sklepu i bez przepłacania za kolejne wtyczki. Zaczynamy od rozróżnienia pojęć, a kończymy na tym, kiedy opłaca się napisać własny moduł.
W PrestaShop „UI” to skrót myślowy i częste źródło kosztownych pomyłek. To dwa interfejsy zbudowane na innych technologiach, rozwijane przez różne osoby i mierzone innymi wskaźnikami.
Front office to strona, którą widzi klient. Kod odpowiedzialny za wygląd pochodzi z motywu w katalogu /themes/ — szablony, CSS i JS. W PrestaShop 1.7 i 8 motywy opierają się przede wszystkim na Smarty (pliki .tpl) i tej technologii trzyma się większość gotowych szablonów; PrestaShop 9 rozwija obsługę Twig w motywach, dlatego zanim zaczniesz edytować plik, sprawdź, w jakiej technologii pracuje Twój motyw. Wygląd składa się z hooków (m.in. displayTop, displayHome, displayProductAdditionalInfo, displayShoppingCart, displayBeforeBodyClosingTag) — moduł niepodpięty pod hook po prostu się nie pokaże.
Back office od wersji 1.7 działa na Symfony: routing, kontrolery, szablony Twig. Listy produktów, zamówień i klientów to komponenty grid z własnymi kolumnami i filtrami. Hooki panelu (displayBackOfficeHeader, actionAdminControllerSetMedia) służą do dodawania skryptów i pozycji w menu, nie do zmiany sklepu dla klienta.
Konsekwencja praktyczna: przebudowa motywu nie poprawi panelu, a nowa kolumna w back office nie zmieni niczego dla klienta. Zmiany rób w motywie potomnym i we własnym module, a nie w plikach core ani w katalogu override — po aktualizacji PrestaShopu poprawki znikną. Zakres i kolejność takich prac opisujemy w sekcji o wdrożeniach i rozwoju PrestaShop, a punkt startowy do kodu znajdziesz w dokumentacji dla deweloperów PrestaShop.
| Warstwa | Front office | Back office |
|---|---|---|
| Kto pracuje | Klient sklepu | Twój zespół: obsługa, magazyn, marketing |
| Technologia szablonów | Smarty (.tpl) w motywie; Twig rozwijany w PrestaShop 9 | Symfony + Twig |
| Gdzie leży kod | /themes/, moduły, CSS i JS motywu | Kontrolery i szablony Symfony, gridy list, moduły |
| Główne hooki | displayTop, displayHome, displayProductAdditionalInfo, displayShoppingCart | displayBackOfficeHeader, actionAdminControllerSetMedia |
| Co mierzysz | Konwersja, porzucenia koszyka, Core Web Vitals | Czas obsługi zamówienia, liczba kliknięć, liczba pomyłek |
Na froncie klient podejmuje decyzje na czterech ekranach: liście produktów (kategoria i wyniki wyszukiwania), karcie produktu, koszyku i checkoutcie. Jeśli któryś z nich jest niewygodny, reszta pracy nad sklepem nie ma znaczenia.
Zamiast zgadywać, sięgnij po dane: lista Zamówienia → Koszyki pokazuje porzucone koszyki, GA4 lej krok po kroku, a darmowy Microsoft Clarity daje nagrania sesji. Obejrzyj 20–30 nagrań z telefonów, nie z desktopu. Osobno zmierz Core Web Vitals — wolna karta produktu potrafi zabić konwersję nawet przy dobrze ułożonym formularzu.
| Ekran | Typowe blokery | Jak to sprawdzić |
|---|---|---|
| Lista produktów | Brak liczby wyników, filtry bez możliwości wyczyszczenia, kafle bez ceny i dostępności | Nagrania sesji, test na telefonie, GA4 dla zdarzeń filtrów |
| Karta produktu | Wersje i rozmiary schowane w select, brak kosztu dostawy, wolne ładowanie galerii | Core Web Vitals, test dodania do koszyka na mobile |
| Koszyk | Cena dostawy dopiero w checkoutcie, brak edycji ilości bez przeładowania | Porzucone koszyki w Zamówienia → Koszyki |
| Checkout | 5 kroków, wymuszona rejestracja, brak płatności przy jednej stronie | Lej w GA4, test zamówienia testowego na 3 urządzeniach |
Panel administracyjny rzadko wymaga przebudowy wizualnej. Zwykle wystarczy dopasowanie go do procesu, który i tak wykonujesz codziennie.
Zacznij od konfiguracji, bo jest darmowa:
Własny moduł ma sens wtedy, gdy zadanie powtarza się codziennie i wymaga klikania w trzech miejscach. Typowe przypadki: zamówienie ma jednym kliknięciem trafić do ERP (hooki actionValidateOrder i actionOrderStatusUpdate), masowa edycja z regułą opartą na danych z zewnętrznego systemu, cykliczny raport wysyłany mailem. Policz, czy warto: 40 paczek dziennie i 30 sekund klikania na paczkę to 20 minut dziennie, około 7 godzin miesięcznie.
Pułapka: moduł pisany przez nadpisywanie kontrolerów Symfony psuje się przy każdej aktualizacji. Lepiej dodać własną zakładkę w menu i korzystać z hooków niż łatać pliki core.
| Potrzeba | Rozwiązanie bez modułu | Kiedy pisać własny moduł |
|---|---|---|
| Masowa zmiana cen i stanów | Akcje masowe na liście Katalog → Produkty, import CSV | Gdy reguła zależy od danych z ERP |
| Raport sprzedaży | Menedżer SQL + eksport CSV | Gdy raport ma być generowany i wysyłany cyklicznie |
| Obsługa zamówień | Zapisane widoki listy, zbiorcza zmiana statusu, wydruk z listy | Gdy zamówienie trzeba dopiąć do WMS lub ERP |
| Dostęp dla magazyniera | Profil pracownika z uprawnieniami per kontroler | Rzadko — wystarcza konfiguracja |
Dobre UI w sklepie nie zależy od tego, czy motyw ładnie wygląda, ale od tego, czy klient w kilka sekund wie, gdzie kliknąć. Poniżej reguły, które działają niezależnie od szablonu — od classic w PrestaShop po motywy kupione w marketplace.
Przyciski akcji (CTA). Jedna sekcja to jeden główny przycisk. „Dodaj do koszyka” musi być wizualnie mocniejszy niż „Zobacz szczegóły”. Jeśli oba mają ten sam kolor i tę samą wagę, klient się waha, a wahanie kosztuje konwersję.
Kontrast. Tekst 4,5:1, elementy interfejsu 3:1. Biały tekst na jasnym szarym tle to najczęstszy błąd w gotowych szablonach — wygląda „nowocześnie” na ekranie projektanta i jest nieczytelny na telefonie w słońcu.
Rozmiary klikalnych elementów. Minimum z WCAG 2.2 to 24×24 CSS px, ale w praktyce na mobile celuj w 44–48 px wysokości przycisku i co najmniej 8 px odstępu między sąsiadującymi akcjami. Inaczej klient klika „Usuń” zamiast „Zwiększ ilość” i dzwoni z pretensjami.
Dostępność. Przejdź Tabem całą ścieżkę od wejścia na stronę do złożenia zamówienia. Jeśli w pewnym momencie focus znika (bo ktoś wpisał outline: none), napraw to przed wszystkim innym. Każdy obraz treściowy potrzebuje sensownego alt („naklejka na słoik 5 cm”, nie „IMG_2034”), każdy input — powiązanego label.
Spójność wzorców. Jeden styl przycisków w całym sklepie: jeden promień, jeden kolor akcji, jeden wariant drugorzędny. Komunikat „Produkt dodany do koszyka” zawsze w tym samym miejscu — nie raz w modalu, raz pod przyciskiem. Stany koszyka muszą być rozróżnialne na pierwszy rzut oka: pusty, z produktami, z kodem rabatowym.
Te reguły wdrożysz też przy okazji większych prac — zobacz, jak podchodzimy do wdrożeń PrestaShop.
| Element | Minimum | Uwaga praktyczna |
|---|---|---|
| Kontrast tekstu | 4,5:1 (WCAG 2.1 AA, 1.4.3) | Dla tekstu 24 px+ lub 19 px bold wystarczy 3:1 |
| Kontrast elementów UI | 3:1 (WCAG 2.1 AA, 1.4.11) | Obramowania pól, ikony, widoczny stan focus |
| Cel dotykowy | 24×24 CSS px (WCAG 2.2 AA, 2.5.8) | Na mobile celuj w 44–48 px i 8 px odstępu |
| Tekst alternatywny | opisowy alt dla obrazów treściowych | Obrazy dekoracyjne: alt="" |
Najczęstszy scenariusz: ktoś dokleja CSS na końcu pliku motywu, po pół roku aktualizuje sklep i cała praca znika. Kolejność poniżej idzie od najbezpieczniejszej metody do najbardziej ryzykownej.
Child theme zamiast edycji motywu nadrzędnego. Nie dotykaj plików themes/classic/. Utwórz motyw potomny, np. themes/classic-child/, z własnym config/theme.yml (z wpisem parent: classic) oraz katalogami templates/ i assets/. Nadpisujesz wtedy tylko te szablony, które naprawdę musisz, a aktualizacja motywu bazowego niczego nie kasuje.
Override klas i kontrolerów. Katalog override/ pozwala zmienić metodę klasy bez ruszania core. Działa, ale to najczęstsze źródło awarii po aktualizacji: core się zmienia, Twój override zostaje ze starą sygnaturą i sklep łapie błąd 500. Prowadź listę wszystkich plików w override/ i po każdej aktualizacji sprawdzaj je po kolei, zaczynając od kontrolerów zamówienia i koszyka. Więcej o tym, jak przejść aktualizację bez przestoju, piszemy w tekście o aktualizacji PrestaShop bez awarii.
Hooki i własny moduł. Zamiast wklejać kod do szablonu, podepnij się pod hook — np. displayProductAdditionalInfo, displayShoppingCartFooter, actionFrontControllerSetMedia. Logika mieszka w module, szablon zostaje czysty, a przy aktualizacji nie ma czego nadpisywać. Listę hooków i ich parametrów znajdziesz w dokumentacji dla deweloperów PrestaShop.
Backup i staging. Przed każdą zmianą w UI: kopia plików i bazy, potem wdrożenie na subdomenę testową z noindex i wyłączoną wysyłką maili (Parametry zaawansowane → E-mail). Dopiero po przejściu pełnej ścieżki zakupu na stagingu idziesz na produkcję.
| Metoda | Co daje | Ryzyko przy aktualizacji |
|---|---|---|
| Child theme | Zmiany w CSS i szablonach bez ruszania motywu nadrzędnego | Niskie — pliki potomne zostają |
| Override klas i kontrolerów | Zmiana logiki bez edycji core | Wysokie — zmiany w core wymagają poprawek w override |
| Własny moduł + hooki | Nowe funkcje dokładane obok szablonu | Niskie — moduł żyje niezależnie |
| Edycja plików motywu lub core | Szybki efekt na teraz | Krytyczne — aktualizacja nadpisuje zmiany bez ostrzeżenia |
Interfejs to nie tylko układ przycisków, ale też waga tego, co wysyłasz do przeglądarki. Trzy metryki Core Web Vitals mają konkretne progi liczone dla 75. percentyla rzeczywistych użytkowników: LCP poniżej 2,5 s, CLS poniżej 0,1, INP poniżej 200 ms.
LCP. Najczęściej psuje go baner na stronie głównej: pięć slajdów po 2000 px i kilkaset kB każdy. Zamiana na WebP lub AVIF (typowo 25–35% mniej niż JPEG) plus jeden obraz hero ładowany bez loading="lazy" — lazy loading na obrazie hero opóźnia LCP, nie przyspiesza. Wszystko poniżej pierwszego ekranu: loading="lazy" i wymiary w atrybutach.
CLS. Rezerwuj miejsce na media: width i height w znaczniku img albo aspect-ratio w CSS. Nie wstawiaj banerów cookie ani pasków promocyjnych, które wsuwają treść po załadowaniu. Fonty ładuj z font-display: swap. W PrestaShop typowy winowajca to moduły „ostatnio przeglądane” i cross-selling doczytujące się po pierwszym renderze.
INP. Liczy się czas reakcji na klik. Trzy skrypty zewnętrzne — czat, pixel, heatmapa — potrafią razem dodać kilkaset milisekund. Ładuj je z defer lub async, najlepiej przez Google Tag Manager, a zbędne wtyczki wyłącz.
Od strony serwera zacznij od wymagań serwera i PHP dla PrestaShop: OPcache, aktualna wersja PHP i cache stron robią więcej niż kolejna wtyczka optymalizacyjna. W back office sprawdź Parametry zaawansowane → Wydajność i sekcję CCC (Combine, Compress, Cache). Po włączeniu wyczyść cache i przetestuj layout — CSS doklejany przez moduły potrafi się wtedy rozjechać.
| Metryka | Próg (75. percentyl) | Co najczęściej go psuje | Pierwszy krok |
|---|---|---|---|
| LCP | poniżej 2,5 s | Ciężki slider hero, brak cache, wolny serwer | Kompresja obrazów do WebP/AVIF i cache stron |
| CLS | poniżej 0,1 | Brak wymiarów obrazów, wsuwane bannery, fonty bez font-display: swap | width/height lub aspect-ratio dla wszystkich mediów |
| INP | poniżej 200 ms | Czaty, piksele, heatmapy, ciężki JS w motywie | defer/async, GTM, wyłączenie zbędnych skryptów |
Trzy błędy w UI PrestaShop kosztują najwięcej: edycja plików core, konflikt dwóch modułów na tym samym hooku i praca wyłącznie na desktopie. Każdy z nich da się wykryć w kilkanaście minut, jeśli wiesz, gdzie patrzeć.
Core i motyw nadrzędny. Zmiana w /classes, /controllers albo w plikach motywu classic przeżyje do pierwszej aktualizacji. AutoUpgrade porównuje pliki i nadpisuje te, które uzna za zmienione — po aktualizacji zostaje biały ekran albo znika przycisk dodawania do koszyka. Reguła: layout w motywie potomnym, logika w module, override tylko wtedy, gdy naprawdę nie ma innego wyjścia i zawsze w repozytorium. Po każdej aktualizacji wejdź w BO → Zaawansowane → Wydajność i przejrzyj listę nadpisań.
Konflikt hooków. Dwa moduły podpięte do displayHeader lub displayShoppingCart potrafią się wzajemnie nadpisać. Objawy: cena pokazuje się netto, znika wybór wariantu, koszyk gubi pozycję. Test: BO → Moduły → Pozycje, wyłączaj moduły po jednym i odświeżaj front po każdym wyłączeniu.
Desktop vs mobile. Sprawdzaj szerokość 360 px w DevTools, nie na własnym telefonie. Najczęściej wychodzą: CTA poza ekranem, sticky header zasłaniający treść, tabela rozmiarów bez przewijania poziomego.
Diagnostyka: _PS_MODE_DEV_ = true w config/defines.inc.php — wyłącznie na stagingu, bo pokazuje ścieżki plików i zapytania SQL. Do tego logi w var/logs, konsola przeglądarki na błędy JS oraz porównanie staging vs produkcja przy tej samej wersji PHP.
| Pułapka | Objaw | Jak wykryć | Co zrobić |
|---|---|---|---|
| Edycja plików core | Biały ekran, brak koszyka po aktualizacji | Diff plików przed i po AutoUpgrade, lista nadpisań w BO | Przenieść zmianę do modułu lub motywu potomnego |
| Konflikt na hooku | Znika CTA, cena netto, brak wariantu | Moduły → Pozycje, wyłączanie po jednym | Odpiąć jeden moduł lub zmienić kolejność wykonania |
| Rozjazd desktop/mobile | Przycisk poza ekranem, zasłonięta treść | DevTools przy 360 px i 768 px | Poprawki w CSS motywu potomnego, test na stagingu |
Wtyczka z Marketplace kusi ceną: 30–40 zł miesięcznie. Własny moduł to kilka tysięcy złotych jednorazowo. Rachunek wygląda inaczej, gdy policzysz trzy lata, ryzyko i czas pracy zespołu.
Kiedy wygrywa moduł dedykowany. Wtedy, gdy funkcja jest specyficzna dla Twojego procesu: integracja z konkretnym kurierem, własny algorytm rabatowy, eksport zamówień do ERP, niestandardowy sposób wyliczania kosztu dostawy. Wtyczka z rynku realizuje scenariusz „średni”, więc zwykle wymusza kompromis — albo zmieniasz proces, albo dopisujesz obejścia.
Wydajność i bezpieczeństwo. Każda wtyczka to kod wykonujący się przy każdym żądaniu i kolejny dostawca z dostępem do plików sklepu przez mechanizm aktualizacji. Przy 40 aktywnych modułach dochodzi kilkadziesiąt dodatkowych zapytań do bazy i zasobów ładowanych na stronie. Moduł pisany pod projekt podpina się tylko pod potrzebne hooki i nie ciągnie zbędnych bibliotek. Mechanikę hooków i strukturę modułu opisuje dokumentacja dla deweloperów PrestaShop.
Wycena na godziny, nie z cennika. Uczciwa oferta rozbija pracę na etapy: analiza 2–4 h, implementacja, testy na stagingu, wdrożenie, dokumentacja. Stawki dla PrestaShop oscylują w widełkach 140–180 zł/h, więc 12–20 h to realny zakres dla pojedynczej funkcji. Pytaj o rozbicie na godziny i o to, co dzieje się, gdy zakres się zmieni.
Opieka po wdrożeniu. Moduł trzeba utrzymywać: aktualizacje PrestaShop i PHP potrafią go zepsuć. Ustal SLA — czas reakcji, zakres prac w abonamencie, okno wdrożeniowe poza godzinami szczytu. Bez tego wracasz do punktu wyjścia. Szerszy kontekst znajdziesz w opisie PrestaShop.
| Wariant | Koszt startowy | Koszt w 3 lata | Główne ryzyko |
|---|---|---|---|
| Wtyczka w subskrypcji | 0 zł | ok. 1 080–1 440 zł przy 30–40 zł/mc | wzrost ceny, brak wsparcia dla nowej wersji PHP |
| Wtyczka jednorazowa | 300–900 zł | 300–900 zł plus poprawki | autor porzuca projekt, brak aktualizacji |
| Moduł dedykowany | 12–20 h × 140–180 zł/h | wdrożenie plus opieka 600–1 500 zł/rok | zależność od jednego wykonawcy |
Edycja plików core i motywu nadrzędnego zamiast pracy na child theme.
Jak wykryć: Sprawdź katalog sklepu: brak folderu z motywem potomnym, pliki .tpl i .css z datą modyfikacji nowszą niż data instalacji, brak kontroli wersji. Wystarczy porównanie z czystą paczką motywu w tej samej wersji.
Jak naprawić: Przenieś zmiany do child theme (motywu potomnego), a pliki nadrzędne przywróć do stanu z paczki. Kolejne modyfikacje rób wyłącznie w motywie potomnym.
Dwa lub więcej modułów nadpisuje ten sam hook, a efekt jest nieprzewidywalny.
Jak wykryć: W panelu przejdź do pozycji hooków i sprawdź, ile modułów wisi na tym samym hooku (np. displayHeader lub displayProductAdditionalInfo). Objawy: elementy dublują się, znikają albo zmieniają kolejność po wyłączeniu jednego modułu.
Jak naprawić: Zostaw jeden moduł odpowiedzialny za dany hook, resztę wyłącz lub przenieś na inny hook. Jeśli oba są potrzebne, ustaw priorytet wykonania i przetestuj kolejność renderowania.
Rozjazd między wyglądem i działaniem na desktopie i mobile — poprawki robione tylko w widoku desktopowym.
Jak wykryć: Przejdź całą ścieżkę zakupu na realnym telefonie, nie tylko w zwężonym oknie przeglądarki. Sprawdź, czy przyciski nie są zasłonięte, czy pola formularza dają się wypełnić i czy koszyk jest widoczny bez przewijania w bok.
Jak naprawić: Popraw breakpointy w CSS motywu potomnego i przetestuj ponownie na co najmniej dwóch urządzeniach oraz w dwóch przeglądarkach mobilnych.
Wgranie zmian UI bezpośrednio na produkcję, bez kopii zapasowej i bez środowiska testowego.
Jak wykryć: Brak stagingu, brak backupu plików i bazy z ostatnich 24 godzin, brak zapisu, co dokładnie zostało zmienione i kiedy. Jeśli odpowiedź na którekolwiek z tych pytań brzmi „nie wiem”, to jest właśnie ten błąd.
Jak naprawić: Postaw kopię sklepu na subdomenie testowej, wykonaj backup plików i bazy przed wdrożeniem i wypchnij zmiany na produkcję dopiero po testach.
Doklejanie CSS i JavaScript bezpośrednio w szablonach .tpl zamiast przez moduł lub hook.
Jak wykryć: Przeszukaj pliki motywu pod kątem bloków