O projekcie
Sklep wielobranżowy, w którym katalog utrzymuje się sam: dostawy, zmiany cen i stanów oraz nowości producenta wchodzą automatycznie, a towar świeżo wprowadzony do oferty jest na stronie w kilka minut od pojawienia się w feedzie. Właściciel nie przepisuje niczego ręcznie i nie dowiaduje się o nowościach z newslettera producenta.
Rzecz, od której zaczyna się cały projekt i która odróżnia go od zwykłego importera: FEED PRODUCENTA TO NIE JEST KATALOG SKLEPU. W pliku siedzi wszystko, co producent sprzedaje — także to, czego ten sklep sprzedawać nie chce albo nie może: towar poniżej progu marży, pozycje bez zdjęć, kategorie objęte ograniczeniami, warianty dublujące się z tym, co już stoi w sklepie. Wpuszczenie pliku prosto do katalogu oznacza oddanie producentowi decyzji, czym ten sklep jest.
Dlatego między feedem a katalogiem stoi brama, a nie rura. Każda pozycja przechodzi przez reguły, które rozstrzygają jedno z trzech: wchodzi od razu, czeka na decyzję człowieka, albo nie wchodzi nigdy. Reguły są danymi, nie kodem — właściciel zmienia próg marży albo wyłącza kategorię bez wdrożenia. Nowość, która spełnia wszystkie warunki, publikuje się sama; nowość wątpliwa ląduje w kolejce z podanym powodem, a nie ginie.
Druga trudność bierze się z tego, że sklep jest OGÓLNOBRANŻOWY. Nie ma jednego zestawu cech ani jednego odwzorowania kategorii: narzędzia, chemia i tekstylia opisują się zupełnie inaczej, a drzewo producenta prawie nigdy nie pokrywa się z drzewem sklepu — część gałęzi trzeba rozbić, część scalić. Mapowanie jest więc osobnym, trwałym bytem: raz ustalone, przeżywa zmiany nazw po stronie producenta, bo trzyma się identyfikatorów, nie napisów.
Najgroźniejsza rzecz w całym potoku nie jest jednak ani ceną, ani kategorią, tylko POZYCJĄ, KTÓRA ZNIKNĘŁA Z FEEDU. To zdanie ma dwa zupełnie różne znaczenia: „producent wycofał towar” albo „plik urwał się w połowie”. Potraktowanie drugiego jak pierwszego chowa pół sklepu w jednym przebiegu. Import porównuje więc rozmiar i kompletność pliku z poprzednimi przebiegami i przy nagłym ubytku zatrzymuje się i woła człowieka, zamiast wykonać polecenie, którego nikt nie wydał.
Ceny liczą się z reguł, nie z pliku. Cena zakupu od producenta przechodzi przez marżę zależną od kategorii i marki, zaokrąglenie zgodne z polityką sklepu i próg, poniżej którego towar w ogóle się nie pojawia. Zmiana ceny u producenta przelicza cenę sklepową przy najbliższym przebiegu, ale obniżka poniżej progu nie „przecenia” towaru — wypycha go do kolejki decyzji, bo sprzedawanie ze stratą powinno być wyborem, nie skutkiem ubocznym automatu.
Jest jeszcze pułapka, o której przy takich wdrożeniach zwykle nikt nie mówi, a która potrafi zniszczyć widoczność sklepu: opis producenta stoi identycznie w kilkudziesięciu innych sklepach. Setki nowych podstron z cudzą treścią to podręcznikowa cienka zawartość. Dlatego karta produktu dostaje własny opis budowany z cech i danych technicznych, a pozycja, która nie ma jeszcze dość treści, jest w sklepie dostępna, ale wyłączona z indeksowania — dopóki nie ma czym się wyróżnić, nie startuje w wyszukiwarce z pustymi rękami.
Całość chodzi w zadaniach cyklicznych, porcjami, z pamięcią stanu po każdej partii — bo pełny przebieg po kilkudziesięciu tysiącach indeksów nie mieści się w jednym uruchomieniu PHP i nie może zaczynać się od nowa po każdym potknięciu. Każdy przebieg zostawia dziennik: ile pozycji weszło, ile czeka, ile odrzucono i z jakiego powodu — więc na pytanie „skąd się wziął ten produkt w sklepie” zawsze jest odpowiedź.
Problem
Ogólnobranżowy sklep żyje z szerokości oferty, a oferta producenta zmienia się codziennie: nowe indeksy, wycofania, nowe ceny. Ręczne przepisywanie jest nie do utrzymania, a wpuszczenie feedu prosto do katalogu oddaje producentowi decyzję, czym ten sklep jest — razem z towarem poniżej marży, pozycjami bez zdjęć i cudzymi opisami w kilkudziesięciu innych sklepach.
Rozwiązanie
Między feedem a katalogiem stoi brama reguł: każda pozycja wchodzi od razu, czeka na decyzję albo nie wchodzi nigdy. Nowości spełniające warunki publikują się same w kilka minut, wątpliwe trafiają do kolejki z powodem. Ceny liczą się z marż i progów, nie z pliku, a karta produktu dostaje własny opis, żeby nie startować jako cienka zawartość.
Funkcje
- nowość producenta widoczna w sklepie w kilka minut od pojawienia się w feedzie
- brama reguł zamiast rury: wchodzi od razu, czeka na decyzję albo nigdy
- reguły jako dane — próg marży i wyłączona kategoria bez wdrożenia
- mapowanie kategorii po identyfikatorach, więc przeżywa zmianę nazw u producenta
- nagły ubytek pozycji zatrzymuje import zamiast chować pół sklepu
- cena liczona z marży, zaokrąglenia i progu, a nie przepisywana z pliku
- obniżka poniżej progu idzie do decyzji, nie do przeceny
- własny opis z cech i dane wyłączone z indeksowania, dopóki treść jest za cienka
Moduły
sklep-pobieranie
warstwa wejściaŚciąga feed, porównuje go z poprzednim przebiegiem i nazywa różnice.
- odczyt pliku producenta z rozpoznaniem formatu i kodowania, bez zakładania jednego kształtu
- różnica względem poprzedniego przebiegu: nowe, zmienione, zniknięte — trzy osobne listy
- kontrola kompletności pliku przed użyciem: nagły ubytek zatrzymuje przebieg i woła człowieka
- identyfikator producenta jako klucz; nazwa produktu nigdy nie służy do dopasowania
- przebieg porcjowany ze stanem po każdej partii — potknięcie nie cofa całej pracy
sklep-brama
warstwa regułRozstrzyga, co wchodzi do katalogu od razu, co czeka na decyzję, a co nigdy.
- trzy wyjścia zamiast dwóch — „czeka na decyzję” jest pełnoprawnym wynikiem, nie błędem
- warunki wpuszczenia jako dane: próg marży, wymagane zdjęcie, wykluczone kategorie i marki
- powód decyzji zapisany przy pozycji, więc kolejka nie jest workiem bez wyjaśnień
- pozycja odrzucona raz nie wraca co przebieg, dopóki nie zmieni się warunek albo dane
- zmiana reguły przelicza kolejkę wstecz, zamiast czekać na kolejną dostawę
sklep-katalog
warstwa kataloguZamienia pozycję z feedu w kartę produktu sklepu, a nie w kopię cudzej karty.
- mapowanie drzewa producenta na drzewo sklepu z rozbijaniem i scalaniem gałęzi
- zestawy cech osobne dla branż — narzędzia i chemia nie opisują się tym samym schematem
- własny opis budowany z cech i danych technicznych zamiast przepisania opisu producenta
- zdjęcia pobierane do sklepu, przeskalowane; brak zdjęcia to powód do kolejki, nie pusta karta
- karta bez dość treści zostaje dostępna, ale wyłączona z indeksowania
sklep-ceny
warstwa cenowaLiczy cenę sklepową z reguł i pilnuje progu, poniżej którego nie schodzi sama.
- marża zależna od kategorii i marki, nie jedna stawka na cały katalog
- zaokrąglenie zgodne z polityką sklepu, stosowane po marży, nie przed
- próg opłacalności: poniżej niego towar nie wchodzi i nie przecenia się sam
- zmiana ceny u producenta przelicza cenę przy najbliższym przebiegu, z zapisem poprzedniej
- promocja ustawiona ręcznie nie jest nadpisywana przez automat do jej wygaśnięcia
Architektura
- Podstawa
- WordPress z WooCommerce; logika w osobnej wtyczce integracyjnej, nie w motywie
- Klucz danych
- identyfikator producenta, nigdy nazwa produktu — nazwy zmieniają się bez uprzedzenia
- Reguły wpuszczania
- progi, wykluczenia i wymagania trzymane w bazie jako dane; zmiana nie wymaga wdrożenia
- Bezpiecznik importu
- nagły ubytek pozycji w feedzie zatrzymuje przebieg — „wycofane” i „plik się urwał” to dwie różne rzeczy
- Kategorie
- trwałe mapowanie drzewa producenta na drzewo sklepu, z rozbijaniem i scalaniem gałęzi
- Ceny
- marża per kategoria i marka, zaokrąglenie po marży, próg opłacalności jako twarda granica
- Treść
- własny opis z cech zamiast opisu producenta; karta bez dość treści dostępna, ale bez indeksowania
- Zdjęcia
- pobierane do sklepu i przeskalowane, nigdy podlinkowane z serwera producenta
- Przebiegi
- zadania cykliczne porcjami ze stanem po każdej partii; pełny katalog nie mieści się w jednym uruchomieniu
- Dziennik
- ile weszło, ile czeka, ile odrzucono i dlaczego — na pytanie „skąd ten produkt” zawsze jest odpowiedź
Technologie
- PHP
- WordPress
- WooCommerce
- MySQL
- Claude
Autor
Mariusz PerzyńskiClient Relations & Operations