Modelowane listy odbiorców nie zawierają konkretnych osób, tylko prawdopodobieństwa. Wyjaśniam, jak powstają, gdzie ich szukać w panelu i jak czytać ich raporty.
Prawie każdy projekt, w którym uczestniczę, dochodzi w pewnym momencie do tej samej ściany. Klient pyta o coś, co brzmi prosto — jaki jest realny zysk z kanału płatnego po odjęciu zwrotów i kosztu obsługi — a odpowiedź wymaga danych z trzech systemów, które nigdy się ze sobą nie rozmawiały.
Można to obejść ręcznym zestawianiem plików raz w miesiącu. Robiłem tak latami i wiem, jak się to kończy: liczby zależą od tego, kto składał arkusz i którego dnia. Alternatywą jest zbudowanie jednego miejsca, w którym surowe dane z analityki, systemu sprzedaży i narzędzi reklamowych leżą obok siebie w tej samej strukturze.
Poniżej opisuję, jak podchodzę do takiego projektu — z perspektywy osoby od marketingu, a nie inżyniera danych. Kolejność ma znaczenie, bo najczęstszy błąd to zaczynanie od pulpitu.
Interfejs GA4 jest zoptymalizowany pod szybkie odpowiedzi na typowe pytania. To jego zaleta i jego ograniczenie.
Trzy rzeczy, które zmusiły mnie do sięgnięcia po surowe zdarzenia. Pierwsza: raporty standardowe operują na przetworzonych zestawieniach, a przy nietypowych kombinacjach wymiarów wyniki potrafią zostać oszacowane albo przycięte ze względu na ochronę prywatności. Druga: retencja danych szczegółowych jest ograniczona, więc porównanie rok do roku na poziomie pojedynczych zdarzeń po prostu przestaje być możliwe. Trzecia: żadne narzędzie analityczne nie zna Twojej marży, kosztu wysyłki ani tego, które zamówienie wróciło do magazynu.
Eksport surowych zdarzeń rozwiązuje wszystkie trzy naraz. Dostaję pełną, nieprzetworzoną tabelę zdarzeń, którą przechowuję tak długo, jak chcę, i mogę ją połączyć z czymkolwiek innym.
Jest też koszt: od tego momentu ktoś w firmie odpowiada za jakość tych danych. Hurtownia nie naprawia bałaganu, tylko go skaluje.
Połączenie właściwości GA4 z BigQuery to kilka kliknięć w ustawieniach, ale kilka decyzji przy tej okazji zostaje z projektem na lata.
Ostatni punkt powtarzam klientom uparcie, bo każdy miesiąc zwłoki to bezpowrotnie utracona historia. Koszt przechowywania kilku miesięcy zdarzeń średniej wielkości sklepu jest znikomy w porównaniu z wartością danych porównawczych.
Kto zna arkusze i proste zapytania, przy pierwszym kontakcie z tabelą zdarzeń GA4 przeżywa mały szok. Nie ma w niej jednej kolumny na wartość transakcji ani jednej na źródło ruchu.
Każdy wiersz to jedno zdarzenie, a jego szczegóły siedzą w powtarzalnej strukturze parametrów: nazwa parametru w jednej kolumnie, wartość w jednej z kilku kolumn zależnie od typu. Do wyciągnięcia identyfikatora transakcji potrzebne jest rozpakowanie tej struktury. Podobnie z pozycjami zamówienia, które są zagnieżdżoną tablicą.
Praktyczna konsekwencja jest taka, że nikt nie powinien pisać tych rozpakowań za każdym razem od nowa. Buduję jedną warstwę widoków, która sprowadza zdarzenia do płaskiej postaci: jedna tabela sesji, jedna tabela zamówień, jedna tabela pozycji zamówienia. Reszta zapytań korzysta już tylko z tej warstwy.
Druga konsekwencja dotyczy interpretacji. Zdarzenia mają swoje znaczniki czasu i identyfikatory, ale przypisanie ich do sesji nie jest oczywiste — trzeba świadomie zdecydować, jak liczyć sesję i konsekwentnie trzymać się tej definicji we wszystkich raportach.
To sedno całego przedsięwzięcia i miejsce, w którym projekty najczęściej się zatrzymują. Bez wspólnego identyfikatora hurtownia jest tylko drogim archiwum.
W handlu internetowym najpewniejszym kluczem jest numer zamówienia. Musi być identyczny w zdarzeniu zakupu i w systemie sprzedażowym — nie „prawie identyczny”, bez prefiksów dodawanych przez jeden z systemów i bez zmiany formatu przy eksporcie. Sprawdzenie tego zajmuje jedno zapytanie i oszczędza tygodnie nieporozumień.
Dla firm usługowych rolę klucza pełni identyfikator zapytania z formularza, przekazywany dalej do systemu obsługi klienta. Tam dochodzi jeszcze jedna trudność: status leada zmienia się w czasie, więc trzeba ustalić, czy interesuje nas stan aktualny, czy stan na moment kontaktu.
Osobna sprawa to identyfikator zalogowanego użytkownika. Daje możliwość spojrzenia na wartość klienta w czasie, ale jest daną osobową w rozumieniu przepisów i wymaga świadomej decyzji o tym, co dokładnie przekazujemy i na jakiej podstawie. Nigdy nie przesyłam do warstwy analitycznej adresu e-mail ani innych danych identyfikujących wprost.
Kiedy zdarzenia i zamówienia są już w jednym miejscu, brakuje trzeciego elementu: kosztu. Dane o wydatkach trzeba pobrać z narzędzi reklamowych, każde ma własne interfejsy programistyczne, a różnice w definicjach są większe, niż się wydaje.
Trzy pułapki, na które zwracam uwagę przy zestawianiu kosztów z przychodem. Waluta i kurs — jeśli konto rozlicza się w innej walucie niż sklep, trzeba ustalić jeden kurs i jedną datę jego pobrania. Strefa czasowa — narzędzie reklamowe, właściwość analityczna i system sprzedażowy potrafią mieć trzy różne, co daje przesunięcia na granicach dni i miesięcy. Korekty wstecz — dane o kosztach zmieniają się jeszcze kilka dni po zakończeniu okresu, więc raport zbudowany na danych z wczoraj będzie się później delikatnie różnił.
Do pobierania kosztów używam gotowych połączeń, a nie własnego kodu, tam gdzie to możliwe. Utrzymywanie własnej integracji z interfejsem narzędzia reklamowego to zobowiązanie na lata, bo interfejsy się zmieniają — sprzedawcy przechodzący z jednego interfejsu produktowego na nowszy przekonali się o tym w 2025 roku.
Hurtownia bez porządku zamienia się w wysypisko tabel o nazwach kończących się na „final_v3″. Dlatego od pierwszego dnia trzymam trzy poziomy.
Poziom surowy: dane wgrane bez żadnej ingerencji, tylko dopisane. Nigdy ich nie modyfikuję. Poziom pośredni: oczyszczone, ujednolicone tabele o stabilnej strukturze — to tu żyją definicje sesji, zamówienia i kosztu. Poziom raportowy: gotowe zestawienia, z których korzystają pulpity i ludzie z biznesu.
Rachunek za BigQuery zależy głównie od tego, ile danych przeczyta zapytanie, a nie od tego, ile ich przechowujesz. Trzy nawyki, które trzymają koszt w ryzach: zapytania zawsze z ograniczeniem zakresu dat, tabele podzielone według daty, oraz gotowe tabele wynikowe odświeżane raz na dobę zamiast pulpitu, który przy każdym otwarciu przelicza rok danych. Ta ostatnia rzecz jest najczęstszym źródłem nieprzyjemnych niespodzianek — pulpit odświeżany przez dwudziestu odbiorców kilka razy dziennie potrafi kosztować więcej niż całe przechowywanie.
Na koniec rzecz nudna, a decydująca o tym, czy ekosystem przetrwa: dokumentacja definicji. Jedna strona z zapisem, co w tej firmie znaczy „zamówienie”, „sesja”, „przychód netto” i „nowy klient”. Bez tego po roku dwa działy będą raportować dwie różne prawdy z tej samej hurtowni.
Używamy plików cookies, aby ułatwić Ci nawigację oraz wykonywanie określonych funkcji. Szczegółowe informacje o wszystkich plikach cookies znajdziesz w każdej kategorii zgody poniżej.
Pliki cookies oznaczone jako "Niezbędne" są przechowywane w Twojej przeglądarce, ponieważ są one kluczowe dla zapewnienia podstawowych funkcji strony.
Używamy również plików cookies firm trzecich, które pomagają nam analizować, w jaki sposób korzystasz z tej strony, zapamiętują Twoje preferencje oraz dostarczają treści i reklamy odpowiednie dla Ciebie. Te pliki cookies będą przechowywane w Twojej przeglądarce tylko za Twoją uprzednią zgodą.
Możesz zdecydować, czy chcesz włączyć lub wyłączyć niektóre bądź wszystkie te pliki cookies, jednak wyłączenie niektórych z nich może wpłynąć na Twoje doświadczenia podczas przeglądania strony.
| Cookie | Czas przechowywania | Opis |
|---|---|---|
| __cf_bm | 13 minutes | Cloudflare bot management — distinguishes humans from bots. |
| rc::* | Persistent | Google reCAPTCHA — localStorage holding anti-bot challenge state. |
| Cookie | Czas przechowywania | Opis |
|---|---|---|
| wpEmojiSettingsSupports | Session | WordPress — sessionStorage flag caching whether the browser can render emoji (feature detection). |
| ytidb* | Persistent | YouTube — IndexedDB storing playback/search state for embedded videos. |
| Cookie | Czas przechowywania | Opis |
|---|---|---|
| _ga_* | 400 days | Google Analytics 4 — persists session state per property. |
| _ga | 400 days | Google Analytics — distinguishes unique users via a client id. |
| Cookie | Czas przechowywania | Opis |
|---|---|---|
| NID | 183 days | Google — stores preferences for personalized ads. |
| fr | 90 days | Meta — encrypted Facebook id and browser id for ads. |
| _gcl_au | 90 days | Google AdSense/Ads — experiments with advertising efficiency (conversion linker). |
| Cookie | Czas przechowywania | Opis |
|---|---|---|
| __Secure-YNID | 180 days | |
| YSC | Session | |
| __Secure-ROLLOUT_TOKEN | 180 days | |
| VISITOR_INFO1_LIVE | 180 days | |
| VISITOR_PRIVACY_METADATA | 180 days | |
| datr | 400 days | |
| sb | 400 days | |
| wd | 7 days |