Portfolio

Tech Platform: zamki-szkocji.com

zamki-szkocji.com to kompleksowy portal informacyjny poświęcony zamkom Szkocji, który łączy bogactwo historycznych treści, interaktywne mapy, galerie zdjęć o...

#Logotypy#Strony www
Tech Platform: zamki-szkocji.com

#zamki-szkocji.com, Twój przewodnik po magicznych zamkach Szkocji

zamki-szkocji.com to portal informacyjny o zamkach Szkocji: teksty historyczne, mapa, galerie zdjęć i bieżące informacje przydatne przy planowaniu wyjazdu. Odbiorcą jest ktoś, kto czyta o architekturze obronnej z ciekawości, a potem, często tego samego wieczoru, chce ustalić, czy dany zamek da się odwiedzić w czerwcu i ile czasu zajmie dojazd z Edynburga. Te dwa tryby czytania wyglądają podobnie w statystykach, a wymagają zupełnie różnych rzeczy od serwisu. Pierwszy potrzebuje długiego tekstu, który da się czytać na telefonie w autobusie. Drugi potrzebuje danych, które da się porównać: gdzie to leży, czy jest otwarte, jak daleko od następnego punktu na trasie.

Cały projekt powstał wokół tego rozdwojenia. Serwis ruszył w 2012 roku, stoi na WordPressie, a warstwę wydajnościową domykają Redis i infrastruktura AWS z CDN przed plikami multimedialnymi. Prace nad wdrożeniem zajęły około sześciu tygodni, układ i rozmieszczenie elementów dostarczył klient, a po mojej stronie było przełożenie tego układu na model treści, szablony i integracje, które przetrwają kolejne lata dopisywania kolejnych obiektów.

Warto to powiedzieć wprost, bo takie portale bardzo często umierają nie z powodu technologii, tylko z powodu decyzji podjętej w pierwszym tygodniu. Jeśli zamek jest zwykłym wpisem blogowym, to po dwustu zamkach nie da się już zrobić nic sensownego: żadnej mapy bez ręcznego przepisywania współrzędnych, żadnego filtra po regionie bez przeglądania tagów, żadnego zestawienia “zamki dostępne zimą”, bo ta informacja siedzi w środku akapitu.

#Model treści, czyli zamek jako rekord, a nie jako wpis

Podstawową decyzją było potraktowanie zamku jako osobnego typu treści z własnym zestawem pól, a nie jako kolejnego artykułu. W WordPressie oznacza to własny custom post type i własne taksonomie: region, okres historyczny, styl architektoniczny. Dzięki temu przynależność obiektu do Highlands albo do architektury tower house nie jest słowem w tekście, tylko wartością w bazie, po której da się filtrować, sortować i budować listy bez dotykania treści.

Różnica ujawnia się dopiero przy skali. Dopóki obiektów jest kilkanaście, tagi wystarczają i każdy alternatywny model wygląda na przerost formy. Przy kilkuset wpisach tagi przestają być klasyfikacją, a stają się chmurą synonimów: część zamków jest opisana jako “Highlands”, część jako “północ”, część jako obie rzeczy naraz, i nikt już nie wie, która lista jest kompletna. Taksonomia z zamkniętym zestawem terminów wymusza decyzję w momencie dodawania obiektu, kiedy redaktor ma jeszcze przed oczami źródło, z którego pisze.

Ceną jest sztywność. Zamknięty słownik trzeba na starcie przemyśleć, a jego późniejsza zmiana to migracja danych, nie edycja tekstu. Przy tym projekcie ta cena była łatwa do zaakceptowania, bo podział geograficzny Szkocji i klasyfikacja stylów obronnych to rzeczy, które nie zmieniają się z roku na rok. Zupełnie inaczej wyglądałaby ta decyzja dla serwisu o wydarzeniach albo o ofertach, gdzie słownik żyje razem z rynkiem.

Do każdego obiektu dochodzą pola, których nie da się wyrazić kategorią: współrzędne, opis dojazdu, galeria, materiały wideo, oś czasu wydarzeń związanych z zamkiem. Oś czasu jest tu ciekawym przypadkiem, bo kusi, żeby zapisać ją jako gotowy HTML w treści wpisu. Wtedy wygląda dobrze od pierwszego dnia i jest nieużywalna w każdym innym miejscu serwisu. Zapisana jako zestaw dat i zdarzeń daje się wyświetlić w kilku układach, posortować i, co ważniejsze, poprawić w jednym miejscu, kiedy okaże się, że data przebudowy skrzydła jest podana w dwóch źródłach inaczej.

Redaktorska strona tego modelu bywa niedoceniana. Formularz dodawania zamku z osobnymi polami jest dłuższy i mniej wygodny niż puste okno edytora, więc na etapie odbioru zawsze pada pytanie, czy nie prościej wpisywać wszystko w treść. Prościej, przez pierwsze dwa miesiące. Potem zaczyna się praca, której nikt nie planował: ręczne wyszukiwanie obiektów, w których ktoś zapomniał podać wieku budowli, poprawianie tego samego opisu dojazdu w trzech miejscach i tłumaczenie nowej osobie, w jakiej kolejności ma pisać akapity, żeby strona wyglądała spójnie. Pola w formularzu są zapisaną wersją tej instrukcji.

Osobna zaleta pojawia się przy każdej przebudowie wyglądu. Kiedy dane siedzą w polach, zmiana układu karty zamku jest zmianą szablonu i dotyczy wszystkich obiektów naraz. Kiedy siedzą w treści, jest to praca ręczna na każdym wpisie i w praktyce nigdy nie zostaje dokończona, bo przy pięćdziesiątym rekordzie ktoś uznaje, że reszta może zostać po staremu.

#Mapa i dane geolokalizacyjne

Interaktywna mapa korzysta z Google Maps API i z własnych endpointów, które oddają dane o lokalizacjach w formie nadającej się do rysowania znaczników. To nie jest ozdobnik nad listą, tylko druga droga wejścia do serwisu: część użytkowników zaczyna od nazwy zamku, a część od obszaru, po którym będzie się poruszać.

Techniczny sens własnego endpointu jest prosty. Gdyby mapa miała pobierać pełne wpisy, przy każdym otwarciu ciągnęłaby całą treść historyczną, żeby narysować punkt i dymek z trzema zdaniami. Wydzielony endpoint zwraca tylko to, co mapa rysuje, więc odpowiedź jest mała, dobrze się cache’uje i nie zmienia się przy każdej korekcie tekstu w artykule. Tekst wpisu zmienia się często, zbiór współrzędnych prawie nigdy.

Drugi powód jest utrzymaniowy. Dane lokalizacyjne przechodzą przez jedno miejsce, więc reguły w rodzaju “nie pokazuj obiektu bez współrzędnych” i “nie publikuj na mapie ruin bez opisu dojazdu” pilnowane są w kodzie, a nie w nawyku redaktora. W serwisie, który rośnie przez lata, to jest różnica między mapą, która pokazuje aktualny stan bazy, a mapą, którą trzeba raz na rok ręcznie przeglądać.

Przy okazji mapy wychodzi typowy kompromis zewnętrznej usługi. Mapa dostawcy daje kafelki, geokodowanie i zachowanie, którego użytkownik nauczył się gdzie indziej, a w zamian wiąże serwis z cudzym limitem zapytań i cudzą polityką kluczy. Zamiast udawać, że tego kosztu nie ma, ogranicza się liczbę wywołań: mapa ładuje się dopiero, kiedy jest potrzebna, a nie na każdym podstronie z listą, a odpowiedzi endpointu są buforowane, żeby przewijanie listy nie generowało ruchu do dostawcy.

#Wydajność, cache i multimedia

Portal o zamkach jest z natury ciężki od zdjęć. To jest jego treść, więc odchudzanie strony przez wyrzucanie galerii byłoby rozwiązaniem problemu przez usunięcie powodu, dla którego ktoś tu przychodzi. Wydajność trzeba więc było ugryźć od strony infrastruktury, nie od strony zakresu.

Warstwa pierwsza to cache obiektowy w Redis. WordPress przy każdym żądaniu składa stronę z wielu drobnych zapytań: opcje, metadane, relacje taksonomii. Na stronie archiwum z kilkudziesięcioma obiektami i ich metadanymi liczba tych zapytań rośnie szybciej, niż wynikałoby to z liczby widocznych elementów. Redis trzyma wynik tych odczytów poza bazą, więc kolejne żądanie nie odtwarza tej samej pracy od zera. To pomaga najbardziej tam, gdzie pełny cache strony nie działa: przy widokach z parametrami, przy odpowiedziach endpointu mapy, przy zalogowanym redaktorze.

Warstwa druga to CDN przed plikami multimedialnymi. Zdjęcia zamków są duże, ruch jest rozrzucony geograficznie, a serwis czyta się z Polski, z Wysp i z miejsc, w których ktoś planuje wakacje. Serwowanie tych plików z jednego miejsca oznacza, że połowa odbiorców czeka na transfer przez pół Europy za każdym razem. Sieć dostarczania treści przenosi ten koszt do lokalizacji bliżej użytkownika i, co równie ważne, zdejmuje z serwera aplikacyjnego pracę, której nie warto tam trzymać.

Galerie i przełączanie mediów obsługuje AJAX, więc przeglądanie kolejnych zdjęć nie przeładowuje całej strony. Korzyść jest oczywista, koszt mniej. Treść ładowana po stronie przeglądarki nie istnieje dla części odbiorców: robota indeksującego w gorszym scenariuszu, czytnika ekranu w gorszym jeszcze. Dlatego adres pojedynczego zdjęcia i opis obiektu muszą istnieć w zwykłym dokumencie HTML, a warstwa AJAX ma być przyspieszeniem nawigacji, a nie jedynym sposobem dotarcia do treści.

Testy wydajnościowe robiłem na kopii produkcji, nie na czystej instalacji. To jest różnica, którą widać dopiero, kiedy się ją raz przeoczy. Pusty WordPress z motywem i dwoma wpisami odpowiada szybko zawsze, niezależnie od tego, jak napisane są zapytania. Dopiero baza z pełnym zestawem obiektów, ich metadanych, relacji taksonomii i historią komentarzy pokazuje, które zapytanie skanuje pół tabeli, a które korzysta z indeksu.

Jest jeszcze jeden aspekt cache’u, który przy serwisach turystycznych zaskakuje. Ruch nie rozkłada się równo: rośnie sezonowo i skacze po publikacji materiału w mediach albo po udostępnieniu wpisu w dużej grupie tematycznej. Dlatego strojenie wydajności pod średnią z miesiąca jest mało warte. Liczy się zachowanie serwisu w godzinie, w której odwiedza go kilkadziesiąt razy więcej osób niż zwykle, a to jest moment, w którym pomaga nie tyle szybszy kod, co fakt, że większość odpowiedzi w ogóle nie dociera do aplikacji.

Warto też pilnować, żeby czasy wygasania cache były świadomą decyzją, a nie wartością domyślną wtyczki. Opis zamku może spokojnie leżeć w cache godzinami, bo zmienia się kilka razy w roku. Informacja o czasowym zamknięciu obiektu nie może, bo to jest dokładnie ta treść, dla której ktoś wchodzi na stronę przed wyjazdem. Rozdzielenie tych dwóch przypadków jest tańsze niż globalne skrócenie czasu życia cache, które psuje wydajność wszędzie po to, żeby naprawić jeden widok.

#SEO i dane strukturalne

Warstwa wyszukiwarkowa opiera się na semantycznym HTML5, uporządkowanych metadanych i danych strukturalnych schema.org opisujących artykuły o zamkach. Sens jest jeden: opisać maszynie to, co człowiek czyta z układu strony. Nagłówek, data, autor, miejsce, zdjęcie. Bez tego wyszukiwarka zgaduje, a zgaduje najgorzej dokładnie tam, gdzie treść jest długa i bogata.

Adresy podstron są czytelne i wynikają ze struktury, a nie z identyfikatorów. Przy serwisie, który żyje kilkanaście lat, to jest decyzja o kosztach na później: adres, który da się przeczytać, da się też utrzymać przy przebudowie, a adres z parametrem trzeba przekierowywać i tłumaczyć.

Trzeba tu powiedzieć rzecz, której w opisach portfolio zwykle się nie mówi. Pozycje w wyszukiwarce zależą od tego, jak dobre są teksty o zamkach i od tego, kto do nich linkuje, a warstwa techniczna tylko usuwa przeszkody. Dane strukturalne nie sprawią, że słaby opis wyprzedzi dobry. Sprawią natomiast, że dobry opis nie przepadnie przez to, że wyszukiwarka nie umiała rozpoznać, czym jest strona. Nie mam pomiarów efektu tej pracy, których mógłbym tu uczciwie użyć, więc ich nie podaję.

#Komentarze, oceny i to, co się z nimi dzieje po roku

Użytkownicy mogą dodawać opinie, recenzje i uwagi do konkretnych obiektów, a system ocen porządkuje te głosy. Funkcja jest prosta do uruchomienia i trudna do utrzymania, bo każdy otwarty formularz w serwisie z widocznością w wyszukiwarce jest w ciągu kilku tygodni znajdowany przez automaty.

Dlatego decyzje wokół komentarzy dotyczą nie tyle wyglądu, co progu wejścia i moderacji: co trafia od razu na stronę, co czeka na zatwierdzenie, jak szybko da się odsiać spam bez czytania go w całości. Praktyczny wniosek z tego wdrożenia jest taki, że sensowniej jest ustawić moderację ostrzej i poluzować ją później, niż sprzątać treść po kilku miesiącach, kiedy pod opisem zamku wisi trzydzieści linków do sklepów z torebkami.

Oceny mają dodatkowy efekt uboczny, o którym warto wiedzieć: stają się treścią serwisu. Podpięcie ich pod dane strukturalne ma sens tylko wtedy, kiedy głosów jest realnie wiele i pochodzą od ludzi. Przy małej próbce lepiej pokazać opinie jako opinie i nie robić z nich wskaźnika, który sugeruje więcej, niż da się obronić.

#Wsparcie i utrzymanie strony

Opieka nad serwisem obejmuje aktualizacje rdzenia, motywu i wtyczek, przeglądanie logów, kopie zapasowe oraz drobne zmiany funkcjonalne i graficzne. Przy portalu, który działa od 2012 roku, utrzymanie jest większą częścią historii niż samo wdrożenie, i tak należy o nim myśleć przy planowaniu budżetu.

Najważniejsza zasada jest taka, że aktualizacje testuje się na kopii, a nie na produkcji. Serwis z własnym typem treści, własnymi taksonomiami i integracją zewnętrznej mapy ma kilka miejsc, w których zmiana w rdzeniu albo we wtyczce potrafi zmienić zachowanie bez komunikatu o błędzie: zmienia się sposób budowania zapytania, znika filtr, na którym opierał się jeden widok, dostawca mapy wycofuje starą metodę uwierzytelniania.

Kopie zapasowe traktuję jako procedurę odtworzenia, a nie jako plik na dysku. Backup, którego nigdy nie odtwarzano, jest deklaracją. Wartość ma dopiero ten, z którego raz postawiono działającą kopię serwisu i zmierzono, ile to trwało.

#Podsumowanie

zamki-szkocji.com jest przykładem projektu, w którym o trwałości zdecydowały rzeczy niewidoczne z zewnątrz: potraktowanie zamku jako rekordu z polami zamiast jako artykułu, wydzielenie danych mapy do własnego endpointu, rozdzielenie cache obiektowego od dostarczania multimediów i utrzymanie treści w dokumencie HTML nawet tam, gdzie nawigację przyspiesza AJAX.

Co z tego przenosi się na kolejne wdrożenie? Warstwa techniczna: WordPress, Redis, AWS i CDN, dane strukturalne, sposób testowania na kopii produkcji. Nie przenosi się model treści tego serwisu ani jego integracje, bo powstały pod jeden zbiór danych i pod jeden sposób czytania. Kolejny projekt zaczyna się od rozpoznania zakresu, a wycena idzie po nim, nie przed.

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 zamki-szkocji.com?#
zamki-szkocji.com to realizacja z kategorii Logotypy, oddana w 2012 roku. Stoi za nią: WordPress, Redis, AWS, HTML5 oraz AJAX.
Jak wyglądał przebieg prac przy zamki-szkocji.com?#
Wdrożenie zajęło około sześciu tygodni i ruszyło w 2012 roku. Stoi na: WordPress, Redis, AWS, HTML5 oraz AJAX. 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 zamki-szkocji.com?#
Wąskim gardłem była wydajność pod realnym ruchem i cache. zamki-szkocji.com wymagało testów na środowisku zbliżonym do produkcji.
Co z projektu zamki-szkocji.com da się wykorzystać przy kolejnym wdrożeniu?#
Przenosi się warstwa techniczna: WordPress, Redis, AWS, HTML5 oraz AJAX. 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 Logotypy. 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