Google Tag Manager jest istotnym, a czasem wręcz jednym z niezbędnych narzędzi do implementacji właściwego pomiaru zachowań użytkowników podczas uruchamiania i zarządzania kampaniami reklamowymi. Wersja rozwiązania typu server-side zapewnia dodatkowe możliwości w zakresie wdrożeń integracji, ale nie jest wolna od problemów — jednym z kluczowych zagadnień jest to, ile aplikacja kosztuje i w jaki sposób można ograniczyć koszty.

Czego nauczysz się z artykułu?

  • Jakie są możliwości instalacji Google Tag Manager Server-Side w usłudze Google Cloud Platform
  • Czym jest Docker oraz jego charakterystyka
  • Jak przeprowadzić prawidłową instalację — od instalacji podstawowych pakietów, po wydajną konfigurację serwera HTTP
Wersja skrócona: Artykuł szczegółowo opisuje sposób instalacji Dockera, serwera HTTP, uruchomienia właściwej aplikacji oraz instalacji certyfikatu SSL. To wszystko integruje się z konfiguracją Google Tag Manager i uruchamia na środowisku produkcyjnym.

Jak można zainstalować Google Tag Manager Server-Side?

Więcej o zagadnieniu Google Tag Manager Server-Side napisałem w niniejszym wpisie:

Google Tag Manager Server-Side — czym jest, jak działa i ile kosztuje?
Zmiany technologiczne na rynku reklamowym i idący za tym postęp dostarcza nowe rozwiązania służące lepszemu pomiarowi skuteczności kampanii reklamowych. Jednym z tych rozwiązań jest rozszerzenie znanego powszechnie narzędzia Google Tag Manager — Google Tag Manager Server-Side.

W bardzo dużym, acz szczegółowym, skrócie:

  • Google Tag Manager Server-Side jest zaprzeczeniem dotychczasowego, spopularyzowanego podejścia Google do płatności za ich usługi - o ile dotychczasowy model bazował na używaniu danych na potrzeby ekosystemu reklamowego tejże firmy, tak utrzymanie instancji Google Tag Managera Server-Side wymaga stosownych zasobów serwerowych
  • domyślnie Google proponuje skorzystanie z Google Cloud Platform i ich instancji Cloud Run lub App Engine. Dostępne są w bezpłatnym wariancie pod wymogiem przestrzegania bardzo szczegółowych limitów. Jednocześnie, Google w dokumentacji technicznej proponuje przykładową, minimalną konfigurację ich rozwiązania, co ma kosztować ~90 USD netto miesięcznie. Tańsze rozwiązanie App Engine jest dostępne, acz preferowane jest korzystanie z droższego Cloud Run
  • należy pamiętać, iż w ramach Google Cloud Platform można dokupić usługi dodatkowe, które nie są objęte powyższą estymacją (np. autoskalowanie zasobów) — są dodatkowo płatne, gdzie co prawda trudno przy podążaniu za instrukcją krok po kroku popełnić błąd (i np. pominąć notyfikację o przekroczeniu odpowiedniego progu finansowego), ale przy próbie wyjścia poza standardowy schemat, może być to bolesny finansowo błąd

Istnieje również trzeci sposób — samodzielna instalacja na własnym serwerze. Każdy sposób opisano w dokumentacji technicznej Google, lecz w mojej opinii przykład z implementacją na własnej infrastrukturze za pomocą Dockera wykonano lakonicznie, stąd skupię się na nim w tym wpisie.

Jednocześnie niezmiennie zalecam używanie Google Cloud Platform dla firm, które nie posiadają w swoich szeregach ludzi, którzy potrafią zarządzać samodzielnie serwerami VPS lub dedykowanymi. Google Cloud Platform co prawda jest dla osoby nietechnicznej skomplikowane, jednak znacznie mniej niż samodzielna instalacja. Istotne jest realne rozpoznanie potrzeb, zaproponowanie rozwiązania i wdrożenie — pamiętaj, że ryzykujesz niedostępnością usługi, a co za tym idziesz, możesz stracić pieniądze.

Czym jest Docker?

Docker to otwarte oprogramowanie umożliwiające automatyzację wdrażania, skalowania i zarządzania aplikacjami w kontenerach. Kontenery dockerowe są lekkie i przenośne, umożliwiające paczkowanie aplikacji wraz z wszystkimi ich zależnościami do standardowego formatu, który może być uruchomiony zarówno na lokalnym komputerze, jak i na zdalnych serwerach. Docker pozwala na oszczędność zasobów, ponieważ różne kontenery na tym samym systemie hosta współdzielą jądro systemu operacyjnego i używają programów już zainstalowanych na systemie hosta.

Architektura Docker składa się z Docker Engine, ekosytemu aplikacji i narzędzi oraz obrazów, kontenerów i plików Dockerfile. Docker Engine to serwer, który jest odpowiedzialny za tworzenie i zarządzanie kontenerami. Dockerfile to skrypt w języku Docker zawierający instrukcje, które pozwalają Docker Engine na budowanie obrazów kontenerów. Obrazy Docker to statyczne instantki plików, a kontenery Docker to te obrazy uruchomione w runtime.

Porównanie Docker vs wirtualne maszyny. Źródło: https://www.docker.com/resources/what-container/

Korzystanie z Dockera znacznie upraszcza procesy związane z rozwojem oprogramowania. Dzięki umiejętności tworzenia izolowanych środowisk dla aplikacji, Docker eliminuje problem pt. u mnie działa. To oznacza, że jeżeli aplikacja działa w kontenerze na jednym komputerze, powinna bez problemu działać na każdym innym komputerze, na którym jest uruchomiony Docker.

Docker ma wiele zalet w porównaniu do tradycyjnych maszyn wirtualnych (VM). Typowo, VM obsługiwaliby całe systemy operacyjne, które generowałyby duże obciążenia dla zasobów sprzętowych. Kontenery Docker na razie dzielą jądro systemu operacyjnego hosta i uruchamiają tylko procesy potrzebne do obsłużenia konkretnej aplikacji, co zasadniczo zmniejsza użycie zasobów.

Wreszcie, Docker stał się standardem w konteneryzacji i jest nieodłącznym elementem zarządzania architekturą serwerową. Docker integruje się z wieloma narzędziami do automatyzacji CI/CD (ang. continuous integration/continuous development), takimi jak Jenkins, GitLab i wiele innych. Jego rosnąca popularność i akceptacja wynika z możliwości usprawnienia procesów wytwarzania oprogramowania, poprawy bezpieczeństwa i ułatwienia wdrożeń. Bez względu na to, czy jest to mały projekt start-upu, czy duża korporacja, Docker pomaga organizacjom szybciej dostarczać oprogramowanie bez kompromisów co do jakości.

Proces instalacji

Na początku musisz wyposażyć się w serwer wirtualny. Blog który czytasz jest utrzymywany na serwerach firmy cyberFolks — korzystam z ich usług ze względu na sensowną jakość i bardzo dobre wsparcie. Zdecydowanie na potrzeby samego Google Tag Managera wystarczy pakiet vps_UP! (w mojej opinii do większości stron jak np. ten blog, czy mniejsze sklepy internetowe, jest to wystarczająca pojemność do instalacji aplikacji i cena ~50 PLN netto vs 90 USD netto prezentuje się znacznie korzystniej). Dla przykładu przeprowadzę proces na obrazie serwera Ubuntu 22.04.03 LTS (Jammy Selfish).

Wyznacz mysubdomenę, która będzie odnosiła się do Google Tag Manager Server-Side. Podłączmy pod nią rekord A, który będzie wskazywał na otrzymany adres IP.

Potem połączmy się ze serwerem za pomocą SSH. Po zalogowaniu wywołajmy dwa standardowe polecenia:

$ user@example-vps: apt-get update
$ user@example-vps: apt-get upgrade

Po aktualizacji zależności czas na zainstalowanie trzech aplikacji — Dockera, Nginxa i UFW:

$ user@example-vps: apt-get docker.io nginx ufw

NGINX to popularne oprogramowanie, które jest używany jako serwer HTTP (czyli do utrzymywania stron www), serwer proxy, serwer poczty i serwer proxy dla protokołów e-mail takich jak IMAP, POP3 i SMTP. Pierwszy raz został wydany w 2004 roku i od tego czasu zdobył ogromną popularność ze względu na swoją wydajność, stabilność, bogate funkcje, prostą konfigurację i niskie zużycie zasobów.

Działa na architekturze opartej na zdarzeniach, co oznacza, że zamiast tworzyć nowy proces lub wątek dla każdego nowego połączenia (co ma miejsce w tradycyjnych serwerach webowych, takich jak Apache), NGINX korzysta z niewielkiej, stałej liczby procesów lub wątków do obsługi wielu połączeń równocześnie. Ta architektura pozwala mu skalować się bardzo dobrze i zapewniać doskonałą wydajność, nawet przy dużej ilości ruchu.

NGINX może być używany jako serwer proxy. Ta konfiguracja jest używana do dystrybucji ruchu do wielu serwerów, do obsługi żądań statycznych, dynamicznych, strumieniowych lub realizacji cache dla szybszych odpowiedzi. Dzięki temu można ładować aplikacje webowe bez obciążania głównej aplikacji serwera. Daje to możliwość obsługi większych ilości ruchu i oferowania lepszej wydajności.

Właśnie NGINX jest potrzebny po to, by skorzystać z możliwości skonfigurowania jako serwer proxy. Obraz Dockera który później uruchomimy uruchamia swój serwer HTTP, acz dla bezpieczeństwa nie jest wskazane wystawianie aplikacji bezpośrednio w takiej formie.

Z kolei, UFW (Uncomplicated Firewall) to interfejs użytkownika dla zarządzania zaporą sieciową, zaprojektowany z myślą o prostocie i wygodzie użytkowania. UFW to narzędzie linii poleceń, które jest prekonfigurowane do potrzeb większości użytkowników, oferując jednocześnie możliwość zaawansowanej konfiguracji. UFW został stworzony dla systemu operacyjnego Ubuntu, ale działa na innych dystrybucjach Linuxa, które korzystają z iptables.

UFW pozwala na łatwe dodawanie i usuwanie reguł zapory sieciowej z interaktywnego i prostego w użyciu interfejsu. Użytkownicy mogą skonfigurować, które usługi mają być dostępne dla publicznego ruchu sieciowego, a które mają być zablokowane. Ten uproszczony interfejs ułatwia zarządzanie zaporą sieciową nawet dla początkujących użytkowników, chroniąc jednocześnie systemy przed nieautoryzowanym dostępem.

Skoro mamy instalację za sobą, skonfigurujmy zaporę:

$ user@example-vps: ufw allow 'Nginx Full'
$ user@example-vps: ufw allow 'OpenSSH'

Dzięki tym regułom będzie można zalogować się do serwera za pomocą SSH i otworzyć witrynę internetową.

Dalej, czas na uruchomienie Dockera:

$ user@example-vps: docker run -restart always -p 8080:8080 -e CONTAINER_CONFIG='<config string>' -e PREVIEW_SERVER_URL='<HTTPS preview server url>' gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable

Rozkładając komendę na czynniki pierwsze:

  • docker run - wywołanie polecenia run z pakietu pakietu docker
  • -restart always - parametr always dla klucza restart powoduje, że instancja będzie automatycznie resetowała się wtedy, kiedy napotka błąd lub wyłączy się. Można ustawić to oczywiście w inny tryb, acz w przypadku Google Tag Manager Server-Side zależy nam, żeby działał cały czas. Uważam, że nie ma potrzeby innego ustawienia - dlaczego, wyjaśnię poniżej
  • -p 8080:8080 - ustawienie portu, dla którego serwer HTTP naszego kontenera włączy się. Domyślnie każdy nasłuch jest realizowany na port 80 - tam działa już zainstalowany wcześniej NGINX
  • gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable - wybór, który obraz powinien uruchomić się w kontenerze

Ostatnie dwa ustawienia omówię osobno, ponieważ jest to bardzo istotne dla zrozumienia charakteru działania aplikacji:

  • -e CONTAINER_CONFIG='<config stream>'
  • -e PREVIEW_SERVER_URL='<HTTPS preview server url>'

Najprościej będzie to wytłumaczyć w postaci wizualnej:

W istocie instalacja Google Tag Manager Server-Side sprowadza się do tego, iż uruchamiamy serwer pośredniczący zapytania pomiędzy klientem, a końcowym usługodawcą. Należy zaznaczyć, że cała konfiguracja leży dalej na serwerach Google. Zmienna CONTAINER_CONFIG służy wprowadzeniu unikalnego klucza konfiguracyjnego, który uzyskujesz przy tworzeniu Google Tag Managera Server-Side w sposób manualny.

PREVIEW_SERVER_URL jest ustawieniem serwera poglądowego. Wpisujesz tutaj subdomenę, na której Twój kontener ma być aktywny. Na przykład dla tej strony internetowej to jest analytics.kacperduras.pl.

Zrzut ekranu z przykładowym kluczem

Kolejno, skonfigurujemy NGINXa, tworząc plik konfiguracyjny w odpowiedniej lokalizacji:

$ user@example-vps: cd /etc/nginx/sites-available/
$ user@example-vps: touch google-tag-manager.conf
$ user@example-vps: nano google-tag-manager.conf

Poniżej załączam przykładową, minimalną konfigurację, która wystarczy do uruchomienia serwera proxy:

server {
  listen 80;
  listen [::]:80;

  server_name domain.com www.domain.com;

  location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $http_host;
    proxy_pass http://127.0.0.1:8080;
  }
}

Dzięki temu każde zapytanie będzie przekierowane do aplikacji na porcie 8080 - w tym przypadku, naszego kontenera. Pamiętaj, żeby w miejscu domain.com wprowadzić subdomenę, na której ma działać kontener.

Przy okazji skonfigurujmy domyślny serwer HTTP:

$ user@example-vps: nano default

Na przykład w taki sposób:

server {
  listen 80 default_server;
  listen [::]:80 default_server;

  server_name _;

  location / {
    return 403;
  }
}

Dzięki temu, przy wpisaniu adresu IP serwera w przeglądarkę, wyświetli się błąd dotyczący braku dostępu do zawartości.

Zrestartujmy i sprawdźmy, czy konfiguracja załączyła się w porządku:

$ user@example-vps: sudo service nginx restart

Jeśli tak i nie pojawił się żaden błąd, pora na skonfigurowanie darmowego certyfikatu SSL od Let's Encrypt za pomocą aplikacji certbot:

$ user@example-vps: sudo apt-get install certbot python3-certbot-nginx
$ user@example-vps: sudo certbot --nginx -d example.com -d www.example.com
$ user@example-vps: sudo certbot renew --dry-run

W miejscu `example.com` wpiszmy domenę, kolejno wystarczy załączyć zaporę:

$ user@example-vps: sudo ufw enable

I wszystko gotowe. Jako test odpytajmy serwer, czy odpowiada. Na potrzeby poglądowe załączam link do mojego:

https://analytics.kacperduras.pl/healtz

Najpopularniejsze problemy i rozwiązania

Pytanie: Dlaczego Google zaleca minimum dwa kontenery, a Ty instalujesz tylko raz?
Odpowiedź: W znacznej ilości usług instalacji Google Tag Manager Server-Side którą dotychczas zrealizowałem wystarczył jeden serwer w standardowej konfiguracji. Google promuje podejście dywersyfikacji zasobów i rozkładania równomiernego obciążenia tak, by minimalizować ryzyko niedostępności usługi. Należy pamiętać, że usługa load balancingu jest dodatkowo płatna względem minimalnych estymacji założonych przez Google, a wraz ze wzrostem ilości zapytań potrzebnej do obsługi, będą też potrzebne większe instancje o lepszej specyfikacji.

Pytanie: Skorzystam z Twojej porady, w jaki sposób mam postępować, gdy wzrośnie ruch i co za tym idzie, ilość zapytań?
Odpowiedź: Na początek spróbuj zwiększyć konfigurację serwera, a następnie uruchomić równoległy obok i uruchomić dodatkowy, który będzie odpowiadał za pośredniczenie w rozdzielaniu ruchu. NGINX posiada wbudowaną funkcję load balancingu, polecam sprawdzić ją w praktyce. Z doświadczenia polecam również HaProxy. W ramach mojego blogu korzystam z usług firmy CloudFlare, która łączy kilkanaście usług w jedną, zwartą całość. Pamiętaj, że przy konfiguracji równoległych serwerów zadbaj, by komunikowały się w prywatnej sieci lub miały do siebie wyłącznie wzajemny dostęp, bez otwierania komunikacji na zewnątrz.

Pytanie: Jak potem nadzorować, czy wszystko działa w porządku?
Odpowiedź: Monitoruj aplikację, pomocne będzie tutaj Docker Engine API oraz usługi do monitorowania infrastruktury, np. Zabbix lub rozwiązania SaaS typu UptimeRobot.

Pytanie: Czy muszę to wdrażać?
Odpowiedź: W mojej opinii tak. Uzasadniłem to tutaj.

Pytanie: Wyskoczył mi błąd lub mam dodatkowe pytanie. Pomożesz mi?
Odpowiedź: Jasne, zapraszam do kontaktu.

Pomyślnie zasubskrybowałeś Kacper Duras
Witaj ponownie! Pomyślnie zalogowano.
Świetnie! Pomyślnie zarejestrowano.
Sukces! Twój e-mail został zaktualizowany.
Twój link wygasł
Sukces! Sprawdź swój e-mail i kliknij link, aby zakończyć logowanie.