Portfolio

E-commerce Development: led-lumina.pl

led-lumina.pl to profesjonalny serwis internetowy, który prezentuje kompleksową ofertę innowacyjnych rozwiązań LED dla klientów indywidualnych i biznesowych....

#Strony www
E-commerce Development: led-lumina.pl

#Katalog oświetleniowy jest katalogiem parametrów

led-lumina.pl prezentował ofertę rozwiązań LED dla klientów indywidualnych i firmowych. Brzmi to jak zwykły sklep z lampami, dopóki nie spojrzy się na to, czym w praktyce różnią się od siebie dwa produkty w takim katalogu. Różnią się liczbami: strumieniem świetlnym, temperaturą barwową, współczynnikiem oddawania barw, kątem rozsyłu, stopniem ochrony obudowy, klasą energetyczną, obsługą ściemniania i tym, czy zasilacz jest w zestawie. Klient indywidualny szukający lampy do kuchni i elektryk kompletujący oświetlenie hali patrzą na ten sam produkt przez zupełnie inny zestaw tych liczb.

Z tego wynika pierwsza decyzja projektowa, która ustawia resztę wdrożenia. Opis produktu nie może być polem tekstowym, w którym ktoś wpisuje parametry w akapicie. Musi być zestawem osobnych atrybutów, bo tylko wtedy da się po nich filtrować, porównywać i budować listy produktów wymiennych. Serwis został oddany w 2012 roku, a wdrożenie zajęło około sześciu tygodni, więc rozstrzygnięcie zapadło na samym początku i nie było już później miejsca na zmianę zdania.

#Model treści, czyli miejsce, w którym takie projekty się przewracają

Domyślny sposób prowadzenia katalogu w WordPressie polega na tym, że każdy produkt jest wpisem, a różnice między wariantami opisuje się słowami. Działa to do momentu, w którym ktoś pyta o wszystkie oprawy o barwie neutralnej i strumieniu powyżej pewnej wartości. Wtedy okazuje się, że ta informacja istnieje wyłącznie w zdaniach, a zdania nie dają się sortować.

Dlatego atrybuty techniczne zostały wyprowadzone do osobnych pól i taksonomii. Pola liczbowe, jak strumień świetlny czy moc, trzymane są jako liczby i dają się zawężać przedziałem. Cechy wyliczeniowe, jak barwa światła czy stopień ochrony, są taksonomią, więc jedno oznaczenie da się przypiąć do wielu produktów i później zmienić w jednym miejscu. Rozróżnienie wygląda na drobiazg administracyjny, a decyduje o tym, czy filtr po zakresie mocy jest zapytaniem do bazy, czy przeszukiwaniem tekstu.

Druga warstwa tego samego problemu dotyczy rodziny produktów. Ta sama oprawa występuje w kilku barwach światła i kilku mocach, i są to z punktu widzenia klienta warianty jednej rzeczy, a z punktu widzenia magazynu osobne pozycje z osobnymi stanami. Gdyby każdy wariant był osobnym wpisem, karta produktu rozmnożyłaby się na kilkanaście niemal identycznych stron, a wyszukiwarka dostałaby do zaindeksowania kilkanaście prawie takich samych tekstów. Gdyby wariantów nie było wcale, nie dałoby się pokazać dostępności. Rozwiązaniem był jeden wpis nadrzędny z opisem i galerią oraz podrzędne warianty niosące wyłącznie parametry i stan.

#Dlaczego cache i stany magazynowe walczą ze sobą

Katalog był spięty z zewnętrznym systemem przez API, żeby dostępność i zmiany oferty nie musiały być przepisywane ręcznie. Na diagramie wygląda to prosto. W działaniu jest to najtrudniejszy fragment całego wdrożenia, bo dwie rzeczy, których się tu oczekuje, są ze sobą sprzeczne.

Strona ma być szybka, a szybka jest wtedy, gdy oddaje gotowy dokument z pamięci podręcznej, nie uruchamiając PHP i nie odpytując bazy. Strona ma jednocześnie pokazywać aktualny stan magazynu, a aktualny stan magazynu z definicji zmienia się poza nią. Jeżeli cache trzyma stronę godzinę, to przez godzinę potrafi obiecywać dostępność produktu, którego już nie ma. Jeżeli cache nie trzyma jej wcale, każde wejście na kartę produktu uruchamia pełny cykl generowania strony.

Rozstrzygnięcie polegało na rozdzieleniu tego, co się nie zmienia, od tego, co się zmienia szybko. Opis, zdjęcia, parametry techniczne i treści pomocnicze są stabilne przez tygodnie i mogą leżeć w cache agresywnie. Stan magazynowy i dostępność dociągane są osobno, już po wyświetleniu strony, i to one decydują o tym, czy przycisk zamówienia jest aktywny. Dzięki temu dokument, który dostaje przeglądarka, jest zawsze ten sam dla wszystkich, a jedyny element zależny od chwili jest wyraźnie wydzielony.

Redis pełni tu rolę pamięci pośredniej dla odpowiedzi z zewnętrznego systemu. Nie chodzi o to, żeby przyspieszyć pojedyncze zapytanie, tylko o to, żeby awaria albo spowolnienie po drugiej stronie nie zatrzymało serwisu. Kiedy źródło nie odpowiada, warstwa pośrednia oddaje ostatnią znaną wartość, a informacja o tym, że dane mogą być nieświeże, jest sygnalizowana zamiast pustego miejsca. To różnica między stroną, która wygląda na zepsutą, a stroną, która wygląda na ostrożną.

#Synchronizacja, której nie da się zrobić raz na dobę

Import oferty z zewnętrznego systemu bywa sprowadzany do jednego zadania nocnego, które przepisuje wszystko od nowa. Przy katalogu oświetleniowym to podejście ma dwie wady, i obie wychodzą dopiero po kilku miesiącach działania.

Pierwsza jest taka, że pełne przepisanie kasuje pracę wykonaną po stronie serwisu. Opisy marketingowe, zdjęcia aranżacyjne, powiązania między produktami i teksty przygotowane pod wyszukiwarkę nie pochodzą z systemu magazynowego, więc każdy pełny import musi je ominąć. Jeżeli tego nie rozstrzygnąć w kodzie, rozstrzygnie się to samo, i to zawsze na niekorzyść treści.

Druga wada dotyczy tempa. Nocny import oznacza, że przez cały dzień serwis pokazuje stan sprzed nocy. Dlatego dane zostały podzielone według tego, jak szybko naprawdę się starzeją. Struktura katalogu i parametry techniczne zmieniają się rzadko i mogą przyjść w przebiegu zbiorczym. Dostępność zmienia się w ciągu godzin i idzie osobnym, lekkim kanałem, który dotyka wyłącznie pola stanu. Rozdzielenie tych dwóch rzeczy jest tańsze niż przyspieszanie jednego wielkiego zadania, bo zmniejsza nie czas wykonania, tylko zakres tego, co w ogóle trzeba przeliczyć.

#Zdjęcia produktowe i to, ile naprawdę ważą

Oprawa oświetleniowa sprzedaje się zdjęciem, a zdjęcie oprawy oświetleniowej jest trudne fotograficznie i ciężkie transmisyjnie. Zwykle występuje w kilku ujęciach, często na ciemnym tle, czasem w aranżacji wnętrza. Katalog liczący setki pozycji zamienia się przez to w bibliotekę obrazów, przy której kod strony jest marginesem.

Praca wydajnościowa skupiła się więc nie na minifikacji skryptów, tylko na obrazach, bo tam leżała masa. Pliki są przetwarzane przy wgraniu do zestawu rozmiarów odpowiadających miejscom, w których faktycznie się pojawiają: miniatura na liście, średni podgląd na karcie, pełny rozmiar w powiększeniu. Miniatura z listy nigdy nie jest tym samym plikiem co zdjęcie z powiększenia przeskalowanym w przeglądarce, bo takie przeskalowanie oszczędza tylko piksele, a nie transfer.

Dystrybucją zajmuje się warstwa CDN, i to ona odpowiada za drugą część rachunku. Obrazy są niezmienne, więc mogą leżeć w pamięci węzłów brzegowych bardzo długo, a kolejne wejście na listę produktów nie dotyka serwera pochodzenia w ogóle. Infrastruktura po stronie AWS obsługuje to, czego nie da się rozdać z brzegu: składowanie plików źródłowych, kopie zapasowe i operacje przetwarzania, które są kosztowne, ale wykonywane raz.

#Frontend, warstwa stylów i rok 2012

Układ i rozmieszczenie elementów dostarczył klient. Naszą częścią było przełożenie tego na szablony, zachowanie responsywne i strukturę, którą da się utrzymywać po starcie. To rozróżnienie warto postawić wprost, bo w opisach wdrożeń zwykle znika, a decyduje o tym, gdzie leżała praca.

Warstwa stylów została napisana w SASS, i w 2012 roku nie była to decyzja kosmetyczna. Katalog ma wiele powtarzalnych komponentów, które różnią się jednym wymiarem: kafel produktu na liście, w wynikach filtrowania, w bloku produktów powiązanych i w podglądzie koszyka to cztery warianty tego samego elementu. Bez zmiennych i zagnieżdżeń kończy się to czterema niezależnymi kopiami arkusza, które rozjeżdżają się przy pierwszej zmianie. Z nimi zmiana wysokości kafla jest jedną poprawką.

Interfejs korzysta z asynchronicznego pobierania danych, żeby zmiana filtra nie przeładowywała całej strony. Tutaj kryje się pułapka, w którą wpada wiele katalogów z tamtego okresu: jeżeli wynik filtrowania nie ma własnego adresu, to nie da się go wysłać koledze, dodać do zakładek ani zaindeksować. Lista wyników po filtrowaniu musi więc być odzwierciedlona w adresie, nawet gdy przeładowanie strony nie następuje. Bez tego cała warstwa dynamiczna działa przeciwko widoczności serwisu, którą ten sam projekt próbuje budować.

#Widoczność w wyszukiwarce przy katalogu o powtarzalnych opisach

Sklep oświetleniowy ma problem, którego nie ma serwis redakcyjny. Opisy produktów pochodzą od producentów, więc te same zdania stoją na kilkunastu stronach różnych sprzedawców. Wyszukiwarka widzi wtedy kilkanaście niemal identycznych dokumentów i sama wybiera, który pokazać, co zwykle nie kończy się dobrze dla najmniejszego z nich.

Odpowiedź leży w warstwie, której producent nie dostarcza. Kategorie i widoki filtrowania dostają własne teksty wprowadzające, pisane pod pytanie, które faktycznie zadaje kupujący: czym różni się barwa ciepła od neutralnej w pomieszczeniu mieszkalnym, kiedy stopień ochrony obudowy ma znaczenie, co oznacza brak informacji o ściemnianiu w specyfikacji. To treść, której nie ma w katalogu producenta, bo producent opisuje produkt, a nie decyzję zakupową.

Dane strukturalne opisują produkt w formie zrozumiałej dla wyszukiwarki, a semantyczne znaczniki HTML5 porządkują dokument tak, żeby parametry techniczne były tabelą z powiązanymi nagłówkami, a nie zbiorem wierszy ułożonych wizualnie. Ta druga rzecz jest jednocześnie kwestią dostępności: tabela specyfikacji bez powiązania nagłówków z komórkami jest dla czytnika ekranu ciągiem liczb bez znaczenia, a specyfikacja to główna treść tej strony.

#Płatności, wysyłka i miejsce, w którym kończy się odpowiedzialność serwisu

Integracja z bramkami płatności i systemami przewoźników dokłada do projektu kategorię błędów, której nie ma nigdzie indziej. Wszystkie pozostałe awarie da się naprawić i powtórzyć operację. Płatność jest zdarzeniem jednorazowym, a jej rozstrzygnięcie przychodzi z zewnątrz, często z opóźnieniem i czasem dwa razy.

Dlatego potwierdzenie transakcji nie może opierać się na tym, że użytkownik wrócił na stronę podziękowania. Wraca albo nie wraca, zamyka kartę, traci zasięg, klika wstecz. Stan zamówienia rozstrzyga wyłącznie powiadomienie przychodzące od operatora, a obsługa tego powiadomienia musi być odporna na powtórzenie, bo operator w razie wątpliwości wyśle je ponownie. Jeżeli obsługa nie jest odporna, powtórzone powiadomienie tworzy drugie zamówienie na tę samą płatność.

Podobne rozróżnienie dotyczy wysyłki. Serwis zna wymiary i wagę pozycji, więc potrafi policzyć koszt, ale nie zna stanu ładunku u przewoźnika ani jego chwilowych ograniczeń. Granica jest więc świadoma: strona podaje wycenę na podstawie danych, które ma, i przekazuje przesyłkę dalej, zamiast udawać, że ma wgląd w system, którego nie ma.

#Bezpieczeństwo bez polegania na wtyczce

Zabezpieczenia w tym projekcie są realizowane po stronie kodu i serwera, a nie przez dołożenie wtyczki, która obiecuje ochronę. Powód jest prosty i nie ma w sobie nic ideologicznego: wtyczka bezpieczeństwa działa w tym samym procesie PHP co reszta serwisu, więc może zareagować dopiero wtedy, gdy żądanie już do tego procesu dotarło. Filtrowanie ruchu, ograniczanie liczby prób i blokada na poziomie warstwy brzegowej zatrzymują je wcześniej i taniej.

Po stronie aplikacji liczy się to, co dzieje się z danymi wejściowymi. Formularze mają walidację serwerową, bo walidacja w przeglądarce jest wygodą dla użytkownika, a nie zabezpieczeniem. Operacje zmieniające stan są chronione przed wykonaniem z obcej strony. Zapytania do bazy są parametryzowane, więc treść wpisana przez odwiedzającego nigdy nie staje się częścią składni zapytania.

#Utrzymanie po starcie

Opieka nad serwisem obejmowała aktualizacje silnika, motywu i wtyczek, przegląd logów oraz regularne kopie zapasowe. Ta lista brzmi rutynowo, więc warto powiedzieć, czym różni się w sklepie od zwykłej strony wizytówkowej.

Aktualizacja w katalogu spiętym z zewnętrznym systemem nie jest operacją jednego kliknięcia, bo zmiana w silniku potrafi dotknąć sposobu, w jaki działa integracja, a tego nie widać, dopóki nie przyjdzie kolejna synchronizacja. Dlatego zmiany szły przez środowisko testowe z kopią realnych danych, nie przez czystą instalację z motywem demonstracyjnym. Katalog z setkami pozycji i kilkoma integracjami zachowuje się zupełnie inaczej niż pusty WordPress, a przypadki brzegowe wychodzą wyłącznie na realnym rozkładzie danych.

Kopie zapasowe mają tu drugą, rzadziej wymienianą rolę. W sklepie najcenniejsze są nie pliki, tylko baza z zamówieniami, więc odtworzenie musi być ćwiczone, a nie tylko deklarowane. Kopia, której nikt nigdy nie przywrócił, jest hipotezą, nie zabezpieczeniem.

#Co z tego wdrożenia przenosi się dalej

Przenosi się sposób pracy: rozdzielenie danych stabilnych od danych szybkozmiennych, atrybuty jako pola i taksonomie zamiast tekstu, warstwa pośrednia między serwisem a zewnętrznym systemem oraz testy na kopii produkcji. Te rozstrzygnięcia wyglądają tak samo w każdym katalogu, niezależnie od branży.

Nie przenosi się model treści tego projektu ani jego integracje, bo powstały pod dane jednego klienta i pod brief z kategorii Strony www. Zestaw atrybutów oświetleniowych nie ma sensu nigdzie poza oświetleniem, a kształt wymiany danych zależy od systemu, który stoi po drugiej stronie. Kolejne wdrożenie zaczyna się więc od analizy zakresu, a wycena idzie po niej, nie przed nią.

FAQ do artykułu

Często zadawane pytania

Najważniejsze odpowiedzi, które pomagają wdrożyć temat w praktyce.

SEO-readyGEO-readyAEO-ready4 Q&A
Jakiego zakresu dotyczył projekt led-lumina.pl?#
led-lumina.pl to realizacja z kategorii Strony www, oddana w 2012 roku. Stoi za nią: WordPress, Redis, AWS, HTML5 oraz CSS3.
Jak wyglądał przebieg prac przy led-lumina.pl?#
Wdrożenie zajęło około sześciu tygodni i ruszyło w 2012 roku. Stoi na: WordPress, Redis, AWS, HTML5 oraz CSS3. Układ dostarczył klient. Na jego podstawie zbudowałem szablony i model treści, a ścieżki, którymi idzie ruch, sprawdziłem na kopii produkcji, nie na pustej instalacji.
Co było najtrudniejsze technicznie w led-lumina.pl?#
Najwięcej uwagi pochłonęło spięcie: WordPress, Redis, AWS, HTML5 oraz CSS3. Treść, konfiguracja i kod siedzą w osobnych warstwach, więc wycofanie zmian po starcie rusza jedną z nich, a nie wszystkie trzy. Przypadki brzegowe wychodzą na kopii produkcji i tam idą testy.
Co z projektu led-lumina.pl da się wykorzystać przy kolejnym wdrożeniu?#
Przenosi się warstwa techniczna: WordPress, Redis, AWS, HTML5 oraz CSS3. Na kolejnym wdrożeniu wygląda podobnie. Nie przenosi się model treści tego projektu ani jego integracje, bo powstały pod dane jednego klienta i pod brief z kategorii Strony www. Kolejne wdrożenie zaczyna się od analizy zakresu, a wycena idzie po niej.

Potrzebujesz FAQ dopasowanego do branży i rynku? Przygotujemy wersję pod Twoje cele biznesowe.

Porozmawiajmy