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.
Jest jeden rodzaj awarii na koncie Google Ads, który nie daje o sobie znać w żadnym raporcie skuteczności. Kampania działa, wyświetlenia są, kliknięcia są, a użytkownik po kliknięciu trafia na komunikat o nieistniejącej stronie. Koszt jest realny, wynik zerowy.
Zdarza się to zawsze z tych samych powodów: sklep zmienił strukturę adresów, produkt zniknął z oferty, ktoś przebudował sekcję na stronie i nie zostawił przekierowań, wygasła promocja i landing został skasowany. Reklamy nikt wtedy nie rusza, bo formalnie w Google Ads nic się nie zmieniło.
Google wyłapuje część takich sytuacji sam i potrafi odrzucić reklamę z powodu niedziałającego adresu docelowego, ale robi to własnym tempem i nie dla wszystkich adresów. Dlatego na kontach, na których zależy mi na spokoju, wdrażam skrypt sprawdzający adresy codziennie. Poniżej opisuję, jak to robię.
Zanim cokolwiek wkleję do panelu, ustalam listę miejsc, w których w koncie siedzą adresy URL. Jest ich więcej, niż większość osób pamięta.
Osobno traktuję adresy produktów z pliku dla Merchant Center. Skrypt w Google Ads ich nie obejmie — tam błędy zgłasza sam Merchant Center i to inna procedura.
Ręcznie sprawdzam adresy przy audycie i przy wdrożeniu, ale to jednorazowa czynność. Problem z martwymi linkami polega na tym, że pojawiają się między audytami, w losowym momencie, zwykle po wdrożeniu na stronie, o którym nikt reklamodawcy nie uprzedził.
Google Ads scripts to narzędzie wbudowane w panel: kod w JavaScripcie, który uruchamia się według harmonogramu i ma dostęp do struktury konta oraz do możliwości pobierania stron internetowych. Nie trzeba serwera, nie trzeba dostępu do API, nie trzeba niczego instalować. Dla tego zadania jest to najprostsze narzędzie, jakie znam.
Druga zaleta jest organizacyjna. Skrypt zostawia po sobie zapis: arkusz z listą adresów, kodów odpowiedzi i dat sprawdzenia. Kiedy klient pyta, od kiedy reklama prowadziła w pustkę, mam odpowiedź, a nie domysł. Przy rozliczaniu odpowiedzialności między agencją a działem IT klienta ten arkusz bywa ważniejszy niż samo powiadomienie.
Nie piszę tego od zera i nikomu nie radzę — Google udostępnia gotowe rozwiązanie do sprawdzania linków w bibliotece skryptów i to jest właściwy punkt startu. Warto natomiast rozumieć, z czego się składa, bo prawie zawsze trzeba je dopasować.
Logika ma cztery elementy. Pierwszy to zebranie adresów — selektory typu AdsApp.ads() i AdsApp.keywords() z filtrem na aktywne elementy w aktywnych kampaniach, plus rozszerzenia. Filtr na status jest istotny, bo w koncie leżą setki wstrzymanych elementów, których nikt nie zamierza włączać.
Drugi to odpytanie każdego adresu przez UrlFetchApp.fetch(). Trzy ustawienia mają tu znaczenie: wyciszenie wyjątków HTTP, żeby błąd 404 nie przerywał całego przebiegu, decyzja o tym, czy podążać za przekierowaniami, oraz nagłówek identyfikujący zapytanie. Jeśli chcę widzieć łańcuchy przekierowań, wyłączam automatyczne podążanie i sprawdzam nagłówek z nowym adresem samodzielnie.
Trzeci to klasyfikacja odpowiedzi. Kody z rodziny 4xx i 5xx to alarm. Przekierowania nie są błędem, ale warto je logować, bo łańcuch trzech przeskoków oznacza, że ktoś przebudował serwis i zapomniał zaktualizować reklamy. Przekroczenie czasu odpowiedzi zapisuję osobno, bo to często problem z wydajnością strony, nie z adresem.
Czwarty to raportowanie: zapis do arkusza przez SpreadsheetApp i wiadomość przez MailApp, wysyłana wyłącznie wtedy, gdy coś się znalazło. Skrypt, który codziennie przysyła maila „wszystko w porządku”, po tygodniu zaczyna wpadać do folderu, którego nikt nie czyta.
To jest część, na której najczęściej wykłada się pierwsze wdrożenie.
Skrypt ma limit czasu jednego uruchomienia. Przy koncie z kilkoma tysiącami unikalnych adresów jeden przebieg nie zdąży sprawdzić wszystkiego. Rozwiązanie jest w gotowym skrypcie Google: zapisujemy w arkuszu, dokąd doszliśmy, i przy następnym uruchomieniu ruszamy od tego miejsca. Skrypt planuję wtedy co godzinę, a nie raz na dobę.
Adresy trzeba odfiltrować z duplikatów. Setki słów kluczowych prowadzą zwykle na kilkadziesiąt różnych stron, więc zbieranie unikalnych adresów przed odpytywaniem skraca przebieg wielokrotnie i zmniejsza liczbę zapytań do serwera klienta.
Trzeba też uprzedzić dział techniczny po stronie klienta. Serwer z zabezpieczeniem przed botami potrafi odpowiadać na takie zapytania kodem 403 albo stroną weryfikacyjną, a wtedy skrypt raportuje awarię, której nie ma. Rozwiązaniem jest dopisanie adresu skryptu do wyjątków albo umówienie się na rozpoznawalny nagłówek. Warto to ustalić przed pierwszym uruchomieniem, żeby nie zaczynać wdrożenia od fałszywego alarmu.
Przy koncie menedżera nie uruchamiam osobnego skryptu w każdym koncie. Skrypt na poziomie menedżera przechodzi po wybranych kontach i pozwala wykonywać przebiegi równolegle, a raport zbiera w jednym miejscu. Przy kilkunastu klientach to różnica między pięcioma minutami dziennie a niczym.
Robię to w tej kolejności i nie skracam żadnego etapu.
Zaczynam od skopiowania gotowego rozwiązania do konta i autoryzacji dostępu — skrypt musi mieć zgodę na pobieranie stron zewnętrznych oraz na arkusze i pocztę. Potem tworzę pusty arkusz na raport i wklejam jego adres do konfiguracji.
Pierwsze uruchomienie robię na ograniczonym zakresie: jedna kampania, tryb podglądu, wynik czytam z logu. Chodzi o sprawdzenie dwóch rzeczy — czy adresy w ogóle się zbierają i czy serwer klienta odpowiada normalnie na te zapytania. Dopiero potem rozszerzam zakres na całe konto.
Harmonogram ustawiam co godzinę przy dużych kontach i raz dziennie przy małych, zawsze wcześnie rano. Powiadomienia kieruję na skrzynkę, którą naprawdę czytam, i dodaję do treści maila numer konta, bo przy skrypcie z poziomu menedżera bez tego nie wiadomo, o którego klienta chodzi.
Na koniec dopisuję do arkusza kolumnę na status obsługi. Bez tego przy trzeciej awarii nie wiadomo, które adresy zostały już naprawione, a które czekają, i raport zamienia się w listę, do której nikt nie zagląda.
Traktuję go jako czujnik dymu, nie jako kontrolę jakości.
Nie wyłapie miękkiego błędu 404 — strony, która zwraca poprawny kod 200 i wyświetla komunikat „produktu nie ma w ofercie”. Dla skryptu wszystko jest w porządku, dla użytkownika strona jest bezużyteczna. To trzeba sprawdzać ręcznie albo dodatkowo szukać w treści charakterystycznej frazy, jeśli sklep jej używa.
Nie wyłapie też adresu, który działa, ale prowadzi nie tam, gdzie powinien: reklama konkretnego modelu kierująca po przebudowie na kategorię ogólną albo na stronę główną. Kod odpowiedzi jest poprawny, sens reklamy zniknął.
Nie oceni wreszcie, czy strona ładuje się sensownie na telefonie i czy formularz na niej działa. Skrypt widzi surową odpowiedź serwera, a nie stronę po wykonaniu skryptów przeglądarki.
Dlatego u siebie łączę dwie rzeczy: automat pilnuje kodów odpowiedzi codziennie, a ja raz w miesiącu klikam ręcznie w reklamy najważniejszych kampanii i patrzę, gdzie faktycznie trafiam. Automat wyłapuje awarie, człowiek wyłapuje nonsensy. Jedno drugiego nie zastąpi, ale razem zamykają tę kategorię problemów praktycznie do zera.
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 |