Konta uruchamiające co najmniej 5 Google Ads Scripts wydają 18-26% mniej zmarnowanego budżetu — pasożytnicze search terms, niewykryte 404, niespójne stawki. Jednak tylko 12-18% SMB w Polsce ich używa w 2026. Rozbieżność to największe ROI automatyzacji dostępne, za kilka godzin instalacji.
Google Ads Scripts pozostaje w 2026 jedną z najbardziej niewykorzystywanych funkcjonalności platformy. W naszych audytowanych w 2025 kontach tylko 12-18% polskich SMB aktywnie używa Google Ads Scripts (per źródło), podczas gdy około dziesięciu dobrze zaprojektowanych skryptów oszczędza 10-15 godzin tygodniowo dla ops. Ticket wejścia jest jednak minimalny: JavaScript początkujący, darmowe wykonanie hostowane przez Google, zero infrastruktury do utrzymywania.
Ten przewodnik listuje 10 najbardziej rentownych skryptów do natychmiastowego zainstalowania, z kluczowym snippetem kodu, rekomendowanym harmonogramem cron, średnim zyskiem czasu i odpowiednim use case'em dla każdego. Nie jest to pełny copy-paste — po to oficjalna dokumentacja Google Ads Scripts pozostaje referencyjna. Tu skupiamy się na co i dlaczego, ze snippetami, które zabijają. Dla szerszego przeglądu na pilotowanie bez agencji czytaj też nasz przewodnik Pilotowanie Google Ads bez agencji.
Co Google Ads Script może (i czego nie może) robić?
Google Ads Scripts to JavaScript hostowany i wykonywany przez Google na ich infrastrukturze, z natywnym dostępem do obiektów konta Google Ads przez owrappowane API. Brak serwera Node do utrzymywania, brak klucza OAuth do zarządzania, brak zewnętrznego crona do wynajmowania. Piszesz funkcję main(), wklejasz kod do interfejsu Scripts konta, autoryzujesz wymagane uprawnienia, a Google wykonuje go za ciebie — w trybie podglądu (dry-run) lub w harmonogramie cron (godzinowo, codziennie, tygodniowo). Jest to darmowe i działa na serwerach Google.
Use case'y, w których Scripts błyszczy: monitoring (alerty wydatków, anomalie, 404), lekka automatyzacja (dodawanie wykluczeń, pauzowanie low-CVR słów kluczowych), customowe raportowanie (tygodniowy digest e-mailem, eksport Sheets), zaplanowane audyty (brakujące rozszerzenia, zepsuty tracking, spadające QS). Każde powtarzalne i ograniczone zadanie ops — czytanie statystyk, podejmowanie prostej decyzji, wysłanie alertu lub modyfikacja encji — jest idealnym kandydatem.
Przypadki, w których Scripts jest niewystarczający: głęboka analiza statystyczna (brak naukowych libów jak numpy), zależności third-party npm (niemożliwe do zainstalowania), pilotowanie real-time sub-sekundowe (minimum 1 wykonanie na godzinę), workflow przekraczający 30 minut (twardy timeout). Dla tych przypadków przejdź na backend Google Ads API (Python, Go) lub na pilotujący SaaS, który pokrywa monitoring + alerty + akcje infry bez kodu.
na kontach które obserwujemy, konta z 5+ aktywnymi skryptami wydają średnio 18-26% mniej zmarnowanego budżetu (per dojrzałość) (pasożytnicze search terms, niespójne stawki, niewykryte 404) niż konta bez automatyzacji. ROI inwestycji 2-3 godzin w instalację stacku poniżej mierzone jest w tygodniach, nie miesiącach.
Limity techniczne do zapamiętania: 30-minutowy timeout per uruchomienie, dzienna kwota API na bulk mutacjach, minimalna częstotliwość 1 wykonania na godzinę, brak pakietów npm (wszystko musi być czystym ES5+ JavaScriptem kompatybilnym z Rhino) i lekko własnościowa składnia na obiektach AdsApp. Nic blokującego dla 10 skryptów poniżej, ale miej to na uwadze, jeśli projektujesz custom skrypt, który musi przetwarzać duży katalog. Dla workflow, które przekraczają te limity, oficjalne API Google Ads (Python, Java, Go) pozostaje backendowym fallbackiem.
Łączny szacunek: 10-15 godzin tygodniowo oszczędzone, jeśli 10 skryptów działa równolegle, na średnim koncie (3-8 aktywnych kampanii). To ekwiwalent jednej trzeciej fulltimeu junior ops — za 3 godziny początkowej instalacji.
Jak automatycznie wykryć anomalię wydatków?
Skrypt, który wykrywa w mniej niż godzinę nieprawidłowy skok wydatków — wyciek budżetu, bug stawkowania, atak botów lub po prostu źle zaantycypowane przesunięcie sezonowe. Porównujemy aktualne godzinowe wydatki do średniej kroczącej z 7 dni, wyzwalamy alert, jeśli przekraczają próg (tu 1,5× średnia). Bardziej dopracowana wersja: oblicz odchylenie standardowe, alarmuj powyżej 2σ.
Use case: każde konto z dziennym budżetem > 100 €. Krytyczne dla e-commerce o szczytach sezonowych i dla SaaS, gdzie błąd feeda może zniszczyć budżet w 4 godziny.
function main() {
var today = AdsApp.currentAccount().getStatsFor("TODAY").getCost();
var avg7d = AdsApp.currentAccount().getStatsFor("LAST_7_DAYS").getCost() / 7;
if (today > avg7d * 1.5) {
MailApp.sendEmail(
"ops@example.com",
"[SPEND ALERT] Anomaly detected",
"Today: " + today.toFixed(2) + "€ vs 7d avg: " + avg7d.toFixed(2) + "€"
);
}
}
Harmonogram: godzinnie. Czas oszczędzony: około 1 godzina tygodniowo (koniec ręcznych sprawdzeń dashboardu co rano). Ulepszenie poziomu 2: zamień próg 1,5× na realne obliczenie odchylenia standardowego z 30 dni, by uniknąć false positivów związanych ze szczytami końca miesiąca.
Jak automatycznie dodawać wykluczenia z search terms?
Skrypt, który skanuje search terms z ostatnich 30 dni i automatycznie dodaje jako wykluczenia te, które kosztują więcej niż X € z 0 konwersji. Natychmiastowa rentowność: w naszych audytach to średnio 8-15% budżetu Search wycieka na zapytania poza zakresem. Skrypt nie zastępuje cotygodniowego ręcznego przeglądu — wyłapuje najgorszych przestępców natychmiast.
Use case: konta Search z aktywnym broad match lub phrase match, zróżnicowany katalog. Mniej użyteczne, jeśli prowadzisz 100% exact match ściśle zablokowane.
function main() {
var report = AdsApp.report(
"SELECT search_term_view.search_term, metrics.cost_micros, metrics.conversions " +
"FROM search_term_view WHERE segments.date DURING LAST_30_DAYS " +
"AND metrics.cost_micros > 20000000 AND metrics.conversions = 0"
);
var rows = report.rows();
var campaign = AdsApp.campaigns().withIds(["123456789"]).get().next();
while (rows.hasNext()) {
var r = rows.next();
campaign.createNegativeKeyword('[' + r["search_term_view.search_term"] + ']');
}
}
Harmonogram: codziennie. Czas oszczędzony: około 2 godziny tygodniowo (koniec ręcznego polowania na pasożytnicze search terms). Niezbędny guardrail: loguj listę dodanych wykluczeń przy każdym uruchomieniu i owijaj createNegativeKeyword w try/catch — bug tu może wykluczyć skonwertowane zapytania, jeśli odwrócisz operator.
Skrypt 3 · Alert spadku Quality Score
Skrypt, który eksportuje Quality Score twoich top słów kluczowych codziennie do Google Sheet, porównuje do wyniku z poprzedniego tygodnia i alarmuje, jeśli słowo kluczowe spada więcej niż 1 punkt. Niezbędny do reagowania, zanim CPC eksploduje — QS przechodzące z 8 na 6 zwiększa średnie CPC o 40-60%. By wgryźć się w mechanikę Quality Score, zobacz naszą checklistę audytu Google Ads.
Use case: dojrzałe konta Search z 50+ aktywnymi słowami kluczowymi. Pozwala szybko zidentyfikować degradującą się landing page lub reklamę tracącą trafność.
function main() {
var sheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/XXX").getActiveSheet();
var keywords = AdsApp.keywords()
.withCondition("Status = ENABLED")
.withCondition("Impressions > 100")
.forDateRange("LAST_7_DAYS").get();
while (keywords.hasNext()) {
var kw = keywords.next();
sheet.appendRow([new Date(), kw.getText(), kw.getQualityScore()]);
// Compare vs the D-7 value here, alert if drop > 1 pt
}
}
Harmonogram: codziennie. Czas oszczędzony: około 45 minut tygodniowo, ale głównie prewencja strat budżetowych: reagowanie w 24h na spadające QS unika 2 tygodni płacenia nadętego CPC.
Jak monitorować budget pacing przez cały rok?
Skrypt, który porównuje kumulatywne wydatki miesiąca do prorata teoretycznego budżetu (aktualny dzień ÷ dni miesiąca × miesięczny budżet) i wyzwala alert, jeśli delta przekracza ±15%. Niedowydanie = kampanie zdławione przez za niskie stawki lub źle zwymiarowany dzienny budżet; nadwydanie = agresywny pacing, który spali budżet w środku miesiąca. Oba scenariusze drogo kosztują. Zobacz też nasz dedykowany przewodnik po budget pacingu Google Ads.
Use case: wszystkie konta ze stałym miesięcznym budżetem (agencje z miesięcznymi retainerami klienta, wewnętrzne działy marketingu z ograniczoną kopertą).
function main() {
var MONTHLY_BUDGET = 10000; // € — to configure
var now = new Date();
var dayOfMonth = now.getDate();
var daysInMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate();
var expected = MONTHLY_BUDGET * (dayOfMonth / daysInMonth);
var actual = AdsApp.currentAccount().getStatsFor("THIS_MONTH").getCost();
var delta = (actual - expected) / expected;
if (Math.abs(delta) > 0.15) {
MailApp.sendEmail("ops@example.com", "[PACING] Delta " + (delta * 100).toFixed(0) + "%",
"Spent: " + actual + "€ vs expected: " + expected.toFixed(0) + "€");
}
}
Harmonogram: codziennie (koniec dnia). Czas oszczędzony: około 1h30 tygodniowo, plus bezpieczeństwo unikania zawstydzającego rocznego przekroczenia budżetu po stronie finansów.
Skrypt 5 · Detektor zmęczenia copy reklamy (spadające CTR)
Skrypt, który wykrywa reklamy, których CTR przez ostatnie 7 dni spada więcej niż 25% vs CTR z ostatnich 30 dni. Klasyczny symptom zmęczenia kreacji: twoje audytorium widziało reklamę za wiele razy, przewija bez kliknięcia. Reakcja: odśwież copy, przetestuj nowy nagłówek, rotuj assety RSA.
Use case: konta skalujące budżet, retargeting Display, kampanie always-on na tym samym audytorium. Nie użyteczne na ultra-zróżnicowanej zimnej akwizycji.
function main() {
var ads = AdsApp.ads().withCondition("Status = ENABLED").get();
while (ads.hasNext()) {
var ad = ads.next();
var ctr7 = ad.getStatsFor("LAST_7_DAYS").getCtr();
var ctr30 = ad.getStatsFor("LAST_30_DAYS").getCtr();
if (ctr30 > 0 && ctr7 < ctr30 * 0.75) {
Logger.log("FATIGUE: ad " + ad.getId() + " | 7d=" + ctr7 + " | 30d=" + ctr30);
// Optional: label the ad "to-refresh"
}
}
}
Harmonogram: tygodniowo. Czas oszczędzony: około 1 godzina tygodniowo na ręcznym przeglądzie statystyk reklam, a przede wszystkim wcześniejsza detekcja, która unika 2-3 tygodni niskiego CTR.
Skrypt 6 · Anomalia stawek konkurencji (top IS spadło)
Skrypt, który monitoruje twój Impression Share (top i absolute top) na twoich rdzeniowych kampaniach i alarmuje, jeśli tracisz więcej niż 10 punktów w 24h. Typowy sygnał: konkurent właśnie podniósł stawki lub nowy gracz zajął pozycję. Możliwa szybka reakcja: dostosuj swój Target CPA, pchaj wyróżniający asset, aktywuj konkurencyjny sitelink.
Use case: konkurencyjne wertykały (ubezpieczenia, zdrowotne, B2B SaaS, e-commerce moda). Mniej krytyczne w niszach o niskiej konkurencji.
function main() {
var campaigns = AdsApp.campaigns().withCondition("Status = ENABLED").get();
while (campaigns.hasNext()) {
var c = campaigns.next();
var statsYd = c.getStatsFor("YESTERDAY");
var stats7d = c.getStatsFor("LAST_7_DAYS");
var isYd = statsYd.getSearchImpressionShare();
var is7d = stats7d.getSearchImpressionShare();
if (is7d > 0 && (is7d - isYd) > 0.10) {
MailApp.sendEmail("ops@example.com", "[IS DROP] " + c.getName(),
"IS dropped from " + (is7d * 100).toFixed(0) + "% to " + (isYd * 100).toFixed(0) + "%");
}
}
}
Harmonogram: codziennie. Czas oszczędzony: około 1 godzina tygodniowo aktywnego monitoringu konkurencji, zastąpiona pasywnym alertem.
Jak wykryć landing page 404 w twoich reklamach?
Skrypt, który robi HTTP GET na każdym finalnym URL aktywnych reklam, sprawdza kod statusu i alarmuje natychmiast, jeśli URL zwraca 404, 500 lub złamane przekierowanie. Płacenie za wysyłanie ruchu na zepsutą stronę to najbardziej upokarzający błąd kampanii. W praktyce 3% audytowanych kont ma co najmniej jeden permanentnie aktywny URL 404, często po redesignie lub zmianie CMS.
Use case: e-commerce z rotacją produktów (stock-outs, koniec kolekcji), niedawno zmigrowane strony, multi-strony z dynamicznymi URL.
function main() {
var ads = AdsApp.ads().withCondition("Status = ENABLED").get();
var broken = [];
while (ads.hasNext()) {
var ad = ads.next();
var url = ad.urls().getFinalUrl();
if (!url) continue;
try {
var resp = UrlFetchApp.fetch(url, { muteHttpExceptions: true, followRedirects: false });
if (resp.getResponseCode() >= 400) broken.push(url + " → " + resp.getResponseCode());
} catch (e) { broken.push(url + " → FETCH ERROR"); }
}
if (broken.length) MailApp.sendEmail("ops@example.com", "[404] Broken landing pages", broken.join("\n"));
}
Harmonogram: godzinnie, jeśli e-commerce, codziennie w przeciwnym razie. Czas oszczędzony: około 2 godziny tygodniowo, plus bezpośrednia oszczędność na budżecie wydanym na zepsutą stronę (która może osiągnąć setki euro w jeden dzień).
Skrypt 8 · Dryft trackingu konwersji (spadek wskaźnika)
Skrypt, który oblicza współczynnik konwersji z ostatnich 24 godzin vs średnia z 14 dni i alarmuje, jeśli wskaźnik spada więcej niż 40% bez wyjaśnienia wolumenowego. Główny symptom: zepsuty tracking — tag GTM, który już nie odpala, źle skonfigurowany consent mode, rozłączone GA4. Absolutny koszmar, gdy Smart Bidding traci sygnał konwersji. Po pełną re-audyt trackingu zobacz nasz przewodnik trackingu konwersji.
Use case: wszystkie konta z aktywnym Smart Biddingiem. Krytyczne za każdym razem, gdy techniczny redesign jest planowany na stronie.
function main() {
var acct = AdsApp.currentAccount();
var clicks1 = acct.getStatsFor("YESTERDAY").getClicks();
var conv1 = acct.getStatsFor("YESTERDAY").getConversions();
var clicks14 = acct.getStatsFor("LAST_14_DAYS").getClicks();
var conv14 = acct.getStatsFor("LAST_14_DAYS").getConversions();
if (clicks1 === 0 || clicks14 === 0) return;
var rate1 = conv1 / clicks1;
var rate14 = conv14 / clicks14;
if (rate14 > 0 && rate1 < rate14 * 0.6) {
MailApp.sendEmail("ops@example.com", "[TRACKING] Conversion drift",
"CVR 24h=" + (rate1 * 100).toFixed(2) + "% vs 14d=" + (rate14 * 100).toFixed(2) + "%");
}
}
Harmonogram: codziennie. Czas oszczędzony: około 1 godzina tygodniowo, ale głównie ogromna oszczędność Smart Biddingu idącego w bok przez 7 dni przed ręczną detekcją.
Skrypt 9 · Audyt rozszerzeń (brakujące sitelinki)
Skrypt, który listuje wszystkie aktywne kampanie Search i weryfikuje obecność kluczowych rozszerzeń: sitelinki (minimum 4), callouts (minimum 4), structured snippets, business info. Alarm, jeśli kampania nie ma rozszerzeń lub mniej niż minimum. Rozszerzenia podbijają CTR średnio o 10-15% — zapominanie ich to czyste marnotrawstwo. Dokumentacja na supporcie Google Ads dla rozszerzeń.
Use case: MCC agencji z 20+ kontami do nadzorowania lub zespoły marketingowe regularnie uruchamiające nowe kampanie bez ścisłego procesu.
function main() {
var missing = [];
var campaigns = AdsApp.campaigns().withCondition("Status = ENABLED").get();
while (campaigns.hasNext()) {
var c = campaigns.next();
var sitelinks = c.extensions().sitelinks().get().totalNumEntities();
var callouts = c.extensions().callouts().get().totalNumEntities();
if (sitelinks < 4 || callouts < 4) {
missing.push(c.getName() + " → sitelinks=" + sitelinks + ", callouts=" + callouts);
}
}
if (missing.length) MailApp.sendEmail("ops@example.com", "[EXT] Missing extensions", missing.join("\n"));
}
Harmonogram: tygodniowo. Czas oszczędzony: około 30 minut tygodniowo ręcznego audytu zastąpionego, ale głównie systematyczne pokrycie zapewniające, że żadna nowa kampania nie zostaje bez rozszerzeń.
Skrypt 10 · Tygodniowy email digest wyników
Skrypt, który agreguje co poniedziałek rano kluczowe metryki minionego tygodnia (wydatki, kliknięcia, konwersje, CTR, CPA, ROAS) i wysyła podsumowujący e-mail HTML do interesariuszy. Koniec 45 minut co poniedziałek na budowanie tygodniowego PowerPointa. Bonus: dodaj wariację week-over-week, podkreśl top/flop kampanie, top 3 konwertujące search terms.
Use case: wszystkie struktury z powtarzalnym tygodniowym raportowaniem (agencja, in-house, freelance). Zastępuje ręczny deliverable 30-60 minut.
function main() {
var s = AdsApp.currentAccount().getStatsFor("LAST_7_DAYS");
var prev = AdsApp.currentAccount().getStatsFor("LAST_14_DAYS");
var html = "<h2 data-speakable>Weekly digest</h2>" +
"<p>Spend: " + s.getCost().toFixed(0) + "€</p>" +
"<p>Conv: " + s.getConversions() + "</p>" +
"<p>CPA: " + (s.getCost() / Math.max(s.getConversions(), 1)).toFixed(2) + "€</p>" +
"<p>CTR: " + (s.getCtr() * 100).toFixed(2) + "%</p>";
MailApp.sendEmail({
to: "team@example.com",
subject: "[Weekly digest] Google Ads — week " + new Date().toLocaleDateString(),
htmlBody: html
});
}
Harmonogram: tygodniowo, poniedziałek 8:00. Czas oszczędzony: około 1h30 tygodniowo i gwarantowana regularność (koniec digestów zapomnianych w zajęte tygodnie).
Google Ads Script bez error handlingu może wyzwolić masową akcję w przypadku buga API — wyobraź sobie 500 szerokich wykluczeń dodanych przez całą strukturę, bo linia 12 zwróciła undefined. Reguła absolutna: każda mutacja encji (add, set, pause, remove) musi być owinięta w try/catch z notyfikacją błędu i capem modyfikacji encji per uruchomienie (np. maks 50 wykluczeń dodanych/uruchomienie).
Te 10 skryptów pokrywa 90% klasycznych potrzeb automatyzacji. Jeśli chcesz bogatszej warstwy monitoringu (multi-kryterialna statystyczna detekcja anomalii, alerty Slack/webhook, głęboka historyzacja, dashboardy multi-konto), większość tych skryptów jest już wbudowana w SteerAds — nasz moduł Monitoring działa 24/7 bez konieczności utrzymywania kodu, Auto-optimization dodaje automatyczne akcje (wykluczenia, pacing, redystrybucja budżetu), a nasz darmowy audyt wskazuje w 72h skrypty do priorytetowego zainstalowania na twoim koncie. Po bardziej strukturalne skalowanie kontynuuj naszym pełnym przewodnikiem po Performance Max.
Źródła
Oficjalne źródła wykorzystane w tym przewodniku:
FAQ
Czy trzeba umieć kodować, by używać Google Ads Scripts?
Podstawowy JavaScript wystarczy, by zainstalować i dostosować skrypty, które dostarczamy. Obiekty AdsApp.* są dobrze udokumentowane, kompilator wbudowany w interfejs Google Ads ujawnia błędy przed wykonaniem, a większość użytecznych skryptów mieści się w 40-120 liniach. Trzeba umieć czytać funkcję, rozumieć pętlę for i manipulować obiektami JSON — nic więcej. Dla zespołów nietechnicznych ostrożny copy-paste z naszego repo i 2-3 testy podglądu (bez realnego wykonania) pozwalają zainstalować skrypt monitoringu w mniej niż 15 minut. By rozwinąć customowy skrypt ze złożoną logiką biznesową, junior developer jest nadal preferowany.
Czy Google Ads Scripts są bezpieczne?
Tak, po stronie wykonania — Google uruchamia je na własnej sandboxowanej infrastrukturze, nie masz serwera do utrzymywania ani credentiali do hostowania. Główne ryzyko po stronie kodu: zbugowany skrypt, który masowo zmienia konto (np. pauzuje wszystkie kampanie, zmienia wszystkie stawki) bez error handlingu. Zawsze testuj w trybie podglądu przed harmonogramowaniem, owijaj operacje zapisu w try/catch z notyfikacją błędów i dodawaj guardraile (np. limituj liczbę modyfikowanych encji per uruchomienie). W naszym wewnętrznym benchmarku SteerAds 14% poważnych incydentów Google Ads napotkanych przez klientów w audycie wiąże się ze skryptem bez guardraili.
Ile skryptów można uruchomić na koncie Google Ads?
Na poziomie pojedynczego konta Google pozwala do 250 aktywnych skryptów, ale uderzysz w pułap użyteczności znacznie wcześniej — około dziesięciu dobrze zaprojektowanych skryptów pokrywa 90% potrzeb automatyzacji. Realne kwoty, które zablokują cię najpierw, to: 30-minutowe maksymalne wykonanie per skrypt, dzienny limit operacji API (bulk mutacje) i maksymalna częstotliwość 1 wykonania na godzinę dla skryptów godzinowych. MCC (manager account) może wykonać skrypt iterujący po dziesiątkach kont dziecięcych w pojedynczym uruchomieniu, co zmienia grę dla agencji. Zacznij małe, zmierz wpływ, potem skaluj.
Skrypty vs narzędzie SaaS (jak SteerAds): co wybrać?
Oba są komplementarne. Skrypty błyszczą na akcjach jednorazowych, hiper-customowych, gdzie masz już precyzyjną logikę biznesową do zakodowania — SaaS nigdy nie zreprodukuje twojej wewnętrznej reguły wykluczeń. SaaS jak SteerAds pokrywa generyczną infrastrukturę (monitoring 24/7, alerty multi-kanałowe, statystyczna detekcja anomalii, automatyczne audyty, dashboardy multi-konto, głęboka historyzacja) bez wymagania utrzymywania kodu. W naszym wewnętrznym benchmarku SteerAds konta łączące 2-3 customowe skrypty biznesowe + pilotujący SaaS oszczędzają 10-15h/tydzień, vs 4-5h dla tych ze skryptami tylko. Pytanie nie brzmi 'które', ale 'gdzie ustawić kursor'.