W tym wpisie dowiesz się, jak krok po kroku wdrożyć GTM server side. Poznasz więc sposób tagowania po stronie serwera z wykorzystaniem: serwerów podglądu i tagowania uruchamianych w środowisku dockerowym, a także Nginx jako serwera proxy.
Zagadnienia poruszane w tym artykule:
- Czym w ogóle jest tagowanie po stronie serwera oraz dlaczego warto je wdrożyć?
- Konfiguracja po stronie Tag Managera
- Nginx jako proxy dla kontenerów dockerowych
- Niestandardowe zachowanie kontenerów uruchomionych na podstawie obrazów przygotowanych przez Google i jak sobie z tym poradzić?
Czym jest i do czego służy tagowanie po stronie serwera, czyli server side tagging w teorii
Przed wprowadzeniem tagowania po stronie serwera dostępne było wyłącznie umiejscawianie i uruchamianie tagów po stronie przeglądarki urządzenia klienckiego. W konsekwencji nie mieliśmy możliwości kontrolowania tego, jakie dane dokąd są przesyłane.
Źródło obrazka: Dokumentacja Google → Client-side tagging
Tagowanie po stronie serwera wprowadza dodatkową warstwę kontroli przepływu danych między aplikacją a narzędziami np. do analizy, konwersji, reklam.
Źródło obrazka: Dokumentacja Google → Server-side tagging
Dodatkowo niezaprzeczalnymi zaletami tagowania po stronie serwera są:
- poprawa wydajności strony z powodu wykonywania kodu na serwerze, a nie na urządzeniu klienckim,
- umożliwienie wprowadzenia bardziej restrykcyjnych polityk dotyczących bezpieczeństwa zawartości → Content Security Policy,
- zwiększenie prywatności, ponieważ można np. usunąć adres IP z danych przesyłanych do końcowych punktów.
Pewnym drobnym minusem są oczywiście koszty, ponieważ musimy posiadać serwer i mieć w zespole osobę kompetentną do zarządzania nim.
Przygotowania po stronie Tag Managera
W tej części dowiesz się, jak uzyskać “server container id” niezbędny do realizacji wdrożenia na serwerze.
- Po otwarciu strony głównej Tag Managera należy wybrać opcję “Utwórz kontener”.
2. W kolejnym widoku jedną z widocznych opcji na samym dole listy jest “Server”. Wskazujemy go i podajemy dowolną nazwę. Placeholder podpowiada, iż może to być np. www.mojawitryna.pl – w przypadku ze screena jest podane “test”. Klikamy “Utwórz”.
3. Pojawia się okno z dwoma opcjami. Jedna z nich daje możliwość samodzielnej konfiguracji serwera tagowania. Wybieramy ją, co w efekcie powoduje pojawienie się dodatkowego pola z długim ciągiem znaków. Jest to właśnie “server container id”, który będzie potrzebny później do konfiguracji kontenerów serwerów tagowania i podglądu w dockerze.
4. Klikamy przycisk “Zamknij” w powyższym oknie i przechodzimy do zakładki “Administracja” → “Ustawienia kontenerów”.
5. W oknie, które się pojawi, klikamy przycisk “Dodaj adres URL” i wpisujemy subdomenę kontenera, który będzie działał jako serwer tagowania.
6. Następnie klikamy przycisk “Zapisz” znajdujący się w prawym górnym rogu. To wszystko.
Konfiguracja kontenerów Dockera
W tym miejscu przejdziemy do przedstawienia i omówienia konfiguracji docker-compose zawierającej dwa kontenery: serwer podglądu i serwer tagowania.
Zwraca uwagę fakt, iż oba serwisy – preview-server oraz server-side-tagging-cluster, korzystają z tego samego obrazu. Natomiast różnią się pewnymi detalami.
Pierwszy z serwisów będzie wykorzystywany w momencie, gdy użytkownik kliknie przycisk “Podgląd” w Menedżerze tagów Google widoczny w prawym górnym rogu obszaru roboczego:
Wymaga on ustawienia zmiennej środowiskowej RUN_AS_PREVIEW_SERVER na wartość “true”. Druga zmienna – CONTAINER_CONFIG jest wspólna dla obu serwisów i zawiera wartość “server container id”. Pobierana jest z odrębnego pliku, do czego wrócimy nieco później.
Z kolei drugi serwis odpowiada za przesyłanie adekwatnych danych i wymaga konfiguracji zmiennej PREVIEW_SERVER_URL. Należy go uruchomić dopiero po tym jak “preview-server” będzie również uruchomiony. Google zaleca, by konfigurować oba serwisy pod odrębnymi subdomenami i wskazuje, by każda z nich znajdowała się w domenie danej aplikacji oraz koniecznie posiadała dostęp wykorzystujący protokół https.
Każdy z serwisów ma swoją odrębną nazwę, która przydaje się przy wyszukiwaniu na liście uruchomionych kontenerów, szczególnie jeżeli wdrożenie tagowania po stronie serwera obejmuje więcej niż jedną aplikację. Wskazane porty będą później wykorzystane w konfiguracji Nginxa.
Zmienne środowiskowe w zewnętrznym pliku
Kontenery wspomniane w poprzedniej sekcji wykorzystują zewnętrzny plik .env znajdujący się w głównym katalogu projektu wraz z plikiem docker-compose.yml. Jego struktura jest następująca:
Wystawiamy wszystko na zewnątrz, czyli Nginx jako reverse proxy
Mając przygotowany pliki docker-compose.yml oraz .env zaczynamy konfigurować Nginx, który będzie pełnił funkcję proxy dla dwóch omawianych wcześniej serwisów — serwera podglądu i serwera tagowania.
W jednym z poprzednich artykułów opisywałem przypadek zdokeryzowanego Nginx pełniącego funkcję serwera proxy. Tym razem Nginx występuje jako oddzielna instancja, a nie kontener dockerowy.
Tworzymy dwa pliki. Nazwijmy je preview.example.com odpowiadający konfiguracji serwera podglądu oraz sst.example.com dla serwera tagowania. Każdy z nich będzie się różnił tylko podaną nazwą subdomeny oraz kolejnym portem przekazanym w dyrektywie “proxy_pass”. Wyróżniamy dwa bloki “server {}”. Poniżej pierwszy z nich:
Konfiguracja dla portu 80. Zgodnie z dokumentacją Nginx, nie trzeba go jawnie podawać w dyrektywie “listen”:
“If the directive is not present then either *:80 is used if nginx runs with the superuser privileges, or *:8000 otherwise. “
Drugi blok jest bardziej złożony:
Analizując po kolei strukturę tego bloku na początku wskazujemy, na jakim porcie, dla jakiej subdomeny Nginx ma nasłuchiwać oraz określamy, iż ruch ma być szyfrowany i wykorzystywać http2. Następnie w sekcji “# SSL” ustalamy ścieżki do certyfikatów i konfigurujemy ssl, a w “# CONFIGS” bezpieczne nagłówki.
- Blok “location {}” zawiera adekwatną konfigurację umożliwiającą zadziałanie Nginxowi jako proxy.
- Dyrektywa “proxy_set_header Host” ustawia nagłówek “Host” w przekazywanym do backendu zapytaniu HTTP na wartość “$host” przechowującą nazwę hosta z oryginalnego żądania klienta lub nazwę z “server_name” z powyższej konfiguracji.
- Dyrektywa “proxy_set_header X-Real-IP” przechowuje adres ip klienta, który nawiązał połączenie z serwerem Nginx.
- Dyrektywa “proxy_set_header X-Forwarded-For” zawiera adres ip klienta łączący się z serwerem Nginx wraz z adresami serwerów proxy.
- Dyrektywa “proxy_set_header X-Forwarded-Host” zawiera nazwę hosta z oryginalnego zapytania wraz z nazwami serwerów proxy.
- Dyrektywa “proxy_set_header X-Forwarded-Proto” zawiera protokół http/https, który był użyty w żądaniu klienta.
- Dyrektywa “proxy_pass” określa gdzie Nginx ma przekierować żądania.
- Dyrektywa “add_header X-Robots-Tag” dodaje nagłówek do odpowiedzi HTTP wysyłanej do klienta. Wartość “noindex, nofollow” informuje roboty indeksujące, iż dana strona nie zezwala na indeksowanie i śledzenie linków.
Nginx – bezpieczne nagłówki, konfiguracja ssl i certyfikaty
Wyżej skupiliśmy się na rozkładaniu na czynniki pierwsze bloków “server {}”, wspomnieliśmy jednak o konfiguracji ssl i bezpiecznych nagłówków.
Poniżej plik ssl-config.conf:
Plik powstał w oparciu o Mozilla SSL Generator, aby zapewnić odpowiedni poziom bezpieczeństwa zestawionego połączenia.
Drugi plik – secure-headers.conf zawiera nagłówki mające zwiększyć poziom bezpieczeństwa aplikacji internetowej:
Strict-Transport-Security wymusza użycie przez klienta protokołu https do łączenia z aplikacją.
- X-XSS-Protection chroni przed atakami typu Cross Site Scripting.
- X-Frame-Options chroni przed atakami typu Clickjacking.
- X-Content-Type-Options chroni przed atakami typu MIME sniffing.
Nagłówek Set-Cookie w takiej konfiguracji oznacza, iż ciastka są dostępne we wszystkich ścieżkach na stronie, nie są dostępne dla skryptów JS i są przesyłane tylko przez zabezpieczone połączenia protokołem HTTPS.
Mając gotową konfigurację Nginx dla obu subdomen należy najpierw wykomentować linie “listen”, “ssl_trusted_certificate”, “ssl_certificate”, “ssl_certificate_key”, ponieważ certyfikaty będą dopiero generowane, a następnie przeładować konfigurację Nginx poleceniem:
Teraz należy wykonać poniższe polecenie w celu uzyskania certyfikatów Lets Encrypt dla subdomen, pod którymi będą działały kontenery:
A następnie odkomentować linie wspomniane wyżej i ponownie przeładować konfigurację Nginx. Kiedy konfiguracja Nginx jest kompletna można uruchomić kontenery dockerowe wykonując z poziomu głównego katalogu projektu polecenie:
Niestandardowe zachowanie kontenerów dockerowych…
Kilkanaście minut od uruchomienia status kontenerów zmienił się na “unhealthy”. Uzyskana informacja od inżynierów Google pozwala twierdzić, iż “unhealthy” nie oznacza, iż kontener nie działa, a iż oprogramowanie sugeruje restart, np. w celu pobrania nowszej wersji dodatkowych modułów. Ta informacja wymusiła utworzenie skryptu bash uruchamianego cyklicznie w celu sprawdzenia czy są jakieś kontenery z ww. statusem i jeżeli tak, by je restartował. Poniżej kod:
Po zapisaniu pliku należy mu nadać uprawnienia do wykonania dla danego użytkownika poleceniem:
A następnie można do tablicy crona dodać linię, np.
Dzięki czemu skrypt będzie wykonywany co minutę i w razie potrzeby uruchomi ponownie “chory” kontener.
Pewność, iż wszystko działa jak należy jest bezcenna
To, czy wszystko działa, można sprawdzić na kilka sposobów. Jednym z nich jest sprawdzenie w logu — wyświetlenie logów poleceniem docker compose logs nazwa-serwisu i sprawdzenie, czy pojawiają się linie podobne do poniższej:
Drugim sposobem jest uruchomienie polecenia docker-compose ps i sprawdzenie, czy w kolumnie “State” jest widoczne “Up (healthy)”.
Trzecim sposobem jest sprawdzenie endpointa “/healthz”. jeżeli w przeglądarce wyświetli się “ok”, to zdecydowanie oznacza, iż jest w porządku. Alternatywnie można skorzystać z narzędzia cURL i polecenia curl https://subdomena.mojastrona.pl/healthz.
A co jeżeli chcę mieć klaster obsługujący tagowanie?
Jest to jak najbardziej możliwe. Wtedy wystarczy choćby na odrębnej fizycznej maszynie, uruchomić kolejne (jeden lub więcej) kontenery serwera tagowania, utworzyć dla nich kolejne subdomeny, analogiczną konfigurację Nginx i przypisać do nich ten sam “server container id” użyty w pierwszej instancji.
Podsumowanie: server side tagging z wykorzystaniem Docker i Nginx – co na pewno musisz wiedzieć?
Wdrożenie tagowania po stronie serwera na dockerze z wykorzystaniem Nginx i Docker Compose może być procesem problematycznym, ale też zaskakującym, szczególnie dla osób, które nie miały z nim wcześniej styczności. Dlatego właśnie w artykule pokazaliśmy, jak zrobić to krok po kroku. Przed rozpoczęciem wdrożenia, warto zrozumieć, czym w ogóle jest tagowanie po stronie serwera i dlaczego jest tak bardzo istotne. Nie bez znaczenia jest także to, jak poradzić sobie z konfiguracją poszczególnych serwisów w obrębie systemu Nginx i Docker Compose. Wiele kwestii może nas zaskoczyć także po udanym wdrożeniu, dlatego odpowiednie przygotowanie to w tym przypadku klucz do sukcesu.