Spis treści
- Jak działają skrypty Google Ads i jakie mają ograniczenia
- Wspólna funkcja alertów i pomocnicze funkcje
- Skrypty Google Ads do kontroli kosztów i budżetu
- Skrypty do kontroli reklam, stron docelowych i statusów
- Skrypty do kontroli konwersji, haseł i jakości
- Jak wdrożyć i utrzymać zestaw skryptów
- Najczęściej zadawane pytania
Skrypty Google Ads to programy w JavaScripcie uruchamiane bezpośrednio na koncie reklamowym, które pobierają dane zapytaniami GAQL, porównują je z progami i wysyłają alerty lub zapisują wyniki w Arkuszach Google. Do monitorowania konta wystarczy zestaw kilku krótkich skryptów: każdy sprawdza jedną rzecz – koszty, budżety, odrzucone reklamy, niedziałające strony, statusy kampanii, spadki konwersji, drogie hasła bez sprzedaży, Wynik Jakości i historię zmian. Poniżej znajdziesz wspólną funkcję alertów i 10 skryptów do skopiowania, każdy z opisem, kiedy go uruchamiać i jak interpretować wynik.
Najważniejsze w skrócie
- Skrypty Google Ads działają na infrastrukturze Google, bez własnego serwera i bez tokena deweloperskiego, a najczęściej mogą być uruchamiane co godzinę.
- Każdy skrypt powinien sprawdzać jedną rzecz i mieć własny próg; łatwiej wtedy dostroić alerty i znaleźć błąd.
- Wspólna funkcja wysyłająca e-mail i wiadomość na Slacka pozwala skrócić każdy skrypt do kilkunastu linijek.
- Pojedyncze uruchomienie trwa maksymalnie 30 minut, a na koncie menedżera skrypt może przetwarzać do 50 kont równolegle.
- Alerty o spadku konwersji porównuj w pełnych tygodniach i z opóźnieniem, bo konwersje docierają do konta z poślizgiem.
Jak działają skrypty Google Ads i jakie mają ograniczenia
Skrypt to kod JavaScript wklejany w edytorze w sekcji narzędzi (działania zbiorcze, skrypty). Ma dostęp do obiektu AdsApp, który pozwala czytać i zmieniać elementy konta, oraz do usług Google takich jak MailApp, SpreadsheetApp i UrlFetchApp. Dane pobierasz metodą AdsApp.search(), przekazując zapytanie w języku GAQL – tym samym, którego używa Google Ads API. Pola w wynikach mają nazwy w notacji camelCase, np. metrics.costMicros.
W odróżnieniu od API skrypty nie wymagają tokena deweloperskiego ani projektu Google Cloud, więc zmiany w dostępie do API z września 2026 roku ich nie dotyczą – opisujemy je w tekście o Google Ads API po zmianach z września 2026. Ograniczenia, o których warto pamiętać:
- pojedyncze uruchomienie może trwać do 30 minut,
- najczęstszy harmonogram to co godzinę,
- usługi takie jak
UrlFetchAppiMailAppmają dzienne limity wywołań, - w trybie podglądu skrypt nie wprowadza zmian na koncie, ale wysyła e-maile i zapisuje dane w arkuszach.
Od 22 kwietnia 2026 roku w skryptach dostępne jest także Merchant API jako interfejs zaawansowany, co pozwala łączyć kontrolę kampanii z danymi z Merchant Center.
Wspólna funkcja alertów i pomocnicze funkcje
Zamiast powtarzać ten sam kod w każdym skrypcie, wklej poniższy blok na końcu każdego z nich. Funkcja alert() wysyła e-mail, a jeśli podasz adres webhooka – także wiadomość na Slacka. Gdy lista problemów jest pusta, nic nie wysyła.
// === Wspólne funkcje – wklej na końcu każdego skryptu ===
var EMAIL = '[email protected]';
var SLACK_WEBHOOK = ''; // opcjonalnie
var ID_ARKUSZA = 'WSTAW_ID_ARKUSZA'; // dla skryptów zapisujących dane
function zapytanie(gaql) {
var it = AdsApp.search(gaql), wynik = [];
while (it.hasNext()) wynik.push(it.next());
return wynik;
}
function alert(temat, linie) {
if (!linie || !linie.length) return;
var konto = AdsApp.currentAccount().getName();
var tresc = linie.join('\n');
MailApp.sendEmail(EMAIL, '[Google Ads] ' + temat + ' – ' + konto, tresc);
if (SLACK_WEBHOOK) {
UrlFetchApp.fetch(SLACK_WEBHOOK, {
method: 'post', contentType: 'application/json',
payload: JSON.stringify({ text: '*' + temat + '* – ' + konto + '\n' + tresc.substring(0, 3000) })
});
}
}
function zl(micros) { return (Number(micros) / 1e6).toFixed(2) + ' zł'; }
function data(dniWstecz) {
var tz = AdsApp.currentAccount().getTimeZone();
return Utilities.formatDate(new Date(Date.now() - dniWstecz * 86400000), tz, 'yyyy-MM-dd');
}
Konfiguracja webhooka Slacka i bardziej rozbudowane wiadomości opisujemy w artykule o automatycznych raportach z Google Ads do Arkuszy i Slacka.
Skrypty Google Ads do kontroli kosztów i budżetu
Pierwsze trzy skrypty pilnują pieniędzy: wychwytują kampanie, które wydały znacznie więcej niż zwykle, kampanie tracące ruch przez za niski budżet i sytuację, w której konto przestało się wyświetlać.
Skrypt 1: koszt kampanii wyższy niż średnia. Porównuje wczorajszy koszt każdej kampanii ze średnią z siedmiu wcześniejszych dni. Uruchamiaj go raz dziennie rano. Wersję godzinową, która reaguje w ciągu dnia, znajdziesz w tekście o skryptach wyłapujących anomalie w budżecie.
function main() {
var hist = {}, linie = [];
zapytanie("SELECT campaign.id, metrics.cost_micros FROM campaign WHERE segments.date BETWEEN '" +
data(8) + "' AND '" + data(2) + "' AND campaign.status = 'ENABLED'")
.forEach(function (r) { hist[r.campaign.id] = Number(r.metrics.costMicros) / 7; });
zapytanie("SELECT campaign.id, campaign.name, metrics.cost_micros FROM campaign WHERE segments.date = '" +
data(1) + "' AND campaign.status = 'ENABLED'")
.forEach(function (r) {
var sr = hist[r.campaign.id] || 0, k = Number(r.metrics.costMicros);
if (k > 100e6 && sr > 0 && k > sr * 1.6) linie.push(r.campaign.name + ': ' + zl(k) + ' (średnio ' + zl(sr) + ')');
});
alert('Kampanie z kosztem o 60% wyższym od średniej', linie);
}
Skrypt 2: kampanie ograniczone budżetem. Wyszukuje kampanie w sieci wyszukiwania, które w ostatnich 7 dniach straciły ponad 20% możliwych wyświetleń z powodu budżetu. To sygnał, że rentowna kampania może sprzedawać więcej.
function main() {
var linie = zapytanie(
"SELECT campaign.name, campaign_budget.amount_micros, metrics.search_budget_lost_impression_share " +
"FROM campaign WHERE segments.date DURING LAST_7_DAYS AND campaign.status = 'ENABLED' " +
"AND campaign.advertising_channel_type = 'SEARCH' AND metrics.search_budget_lost_impression_share > 0.2")
.map(function (r) {
return r.campaign.name + ': utrata przez budżet ' + Math.round(r.metrics.searchBudgetLostImpressionShare * 100) +
'%, budżet ' + zl(r.campaignBudget.amountMicros) + ' dziennie';
});
alert('Kampanie ograniczone budżetem', linie);
}
Skrypt 3: konto bez wyświetleń. Sprawdza, czy w ostatnich kilku pełnych godzinach konto miało jakiekolwiek wyświetlenia. Brak ruchu w środku dnia zwykle oznacza problem z płatnościami, zawieszenie lub masowe odrzucenia. Uruchamiaj co godzinę; ze względu na opóźnienie danych skrypt pomija ostatnią godzinę.
function main() {
var tz = AdsApp.currentAccount().getTimeZone();
var h = parseInt(Utilities.formatDate(new Date(), tz, 'H'), 10);
if (h < 10) return;
var wysw = zapytanie("SELECT segments.hour, metrics.impressions FROM customer WHERE segments.date DURING TODAY " +
"AND segments.hour >= " + (h - 4) + " AND segments.hour < " + (h - 1))
.reduce(function (s, r) { return s + Number(r.metrics.impressions); }, 0);
if (wysw === 0) alert('Brak wyświetleń w ostatnich godzinach',
['Zero wyświetleń między ' + (h - 4) + ':00 a ' + (h - 1) + ':00. Sprawdź płatności, statusy kampanii i odrzucenia.']);
}
Skrypty do kontroli reklam, stron docelowych i statusów
Kolejne trzy skrypty wykrywają przyczyny, dla których budżet przestaje pracować: odrzucone reklamy, strony zwracające błędy i kampanie z ograniczonym statusem.
Skrypt 4: odrzucone reklamy w aktywnych grupach. Wypisuje reklamy z odrzuceniem we włączonych kampaniach i grupach reklam. Uruchamiaj kilka razy dziennie, a po większych zmianach kreacji – co godzinę.
function main() {
var linie = zapytanie(
"SELECT campaign.name, ad_group.name, ad_group_ad.ad.id FROM ad_group_ad " +
"WHERE ad_group_ad.policy_summary.approval_status = 'DISAPPROVED' AND ad_group_ad.status = 'ENABLED' " +
"AND ad_group.status = 'ENABLED' AND campaign.status = 'ENABLED'")
.map(function (r) { return r.campaign.name + ' > ' + r.adGroup.name + ' > reklama ' + r.adGroupAd.ad.id; });
alert('Odrzucone reklamy: ' + linie.length, linie.slice(0, 50));
}
Skrypt 5: niedziałające strony docelowe. Zbiera końcowe adresy URL reklam, które miały wyświetlenia w ostatnich 7 dniach, i sprawdza kod odpowiedzi serwera. Strona z błędem 404 lub 5xx to najszybszy sposób na przepalenie budżetu. Kampanie Performance Max mają adresy w grupach zasobów (asset_group.final_urls), więc dla nich dodaj osobne zapytanie.
function main() {
var urls = {}, linie = [];
zapytanie("SELECT ad_group_ad.ad.final_urls FROM ad_group_ad WHERE segments.date DURING LAST_7_DAYS " +
"AND metrics.impressions > 0 AND ad_group_ad.status = 'ENABLED'")
.forEach(function (r) { (r.adGroupAd.ad.finalUrls || []).forEach(function (u) { urls[u.split('#')[0]] = 1; }); });
Object.keys(urls).slice(0, 300).forEach(function (u) {
try {
var kod = UrlFetchApp.fetch(u, { muteHttpExceptions: true, followRedirects: true }).getResponseCode();
if (kod >= 400) linie.push(kod + ' ' + u);
} catch (e) { linie.push('BŁĄD ' + u + ' – ' + e.message); }
});
alert('Strony docelowe z błędami', linie);
}
Uwaga: niektóre serwery blokują ruch z infrastruktury Google lub zwracają kod 403 dla automatycznych zapytań. Jeśli widzisz takie wyniki dla działających stron, sprawdź reguły zapory sieciowej – ten sam problem może dotyczyć robotów sprawdzających reklamy i produkty, o czym piszemy w tekście o odrzuceniach w Merchant Center.
Skrypt 6: kampanie z ograniczonym statusem. Korzysta z pola campaign.primary_status, które pokazuje, czy kampania może się w pełni wyświetlać, i z listy przyczyn ograniczenia. Uruchamiaj raz dziennie.
function main() {
var linie = zapytanie(
"SELECT campaign.name, campaign.primary_status, campaign.primary_status_reasons FROM campaign " +
"WHERE campaign.status = 'ENABLED' AND campaign.primary_status IN ('NOT_ELIGIBLE', 'LIMITED', 'MISCONFIGURED')")
.map(function (r) { return r.campaign.name + ': ' + r.campaign.primaryStatus + ' – ' + (r.campaign.primaryStatusReasons || []).join(', '); });
alert('Kampanie z ograniczonym statusem', linie);
}
Skrypty do kontroli konwersji, haseł i jakości
Ostatnia grupa pilnuje efektywności: spadków konwersji, drogich zapytań bez sprzedaży i Wyniku Jakości słów kluczowych.
Skrypt 7: spadek konwersji tydzień do tygodnia. Porównuje konwersje z ostatnich 7 pełnych dni z poprzednimi 7 dniami i zgłasza kampanie, w których liczba spadła o ponad 40% (przy minimum 10 konwersjach w okresie bazowym). Nagły spadek do zera na wszystkich kampaniach jednocześnie zwykle oznacza problem z tagiem, a nie z kampaniami – wtedy sięgnij po procedurę z artykułu jak sprawdzić, czy tag działa.
function main() {
var teraz = {}, przed = {}, linie = [];
zapytanie("SELECT campaign.id, campaign.name, metrics.conversions FROM campaign WHERE segments.date BETWEEN '" +
data(7) + "' AND '" + data(1) + "' AND campaign.status = 'ENABLED'")
.forEach(function (r) { teraz[r.campaign.id] = { n: r.campaign.name, k: Number(r.metrics.conversions) }; });
zapytanie("SELECT campaign.id, metrics.conversions FROM campaign WHERE segments.date BETWEEN '" +
data(14) + "' AND '" + data(8) + "' AND campaign.status = 'ENABLED'")
.forEach(function (r) { przed[r.campaign.id] = Number(r.metrics.conversions); });
Object.keys(teraz).forEach(function (id) {
var a = przed[id] || 0, b = teraz[id].k;
if (a >= 10 && b < a * 0.6) linie.push(teraz[id].n + ': ' + b.toFixed(1) + ' konw. (poprzednio ' + a.toFixed(1) + ')');
});
alert('Spadek konwersji o ponad 40%', linie);
}
Pamiętaj, że Google Ads przypisuje konwersje do dnia kliknięcia, a część z nich dociera z opóźnieniem. Ostatnie dni zawsze wyglądają gorzej, dlatego przy krótkich cyklach zakupowych przesuń okno o 1–2 dni, a przy dłuższych porównuj okresy sprzed tygodnia.
Skrypt 8: hasła z kosztem bez konwersji. Zapisuje w arkuszu 100 najdroższych zapytań z ostatnich 30 dni, które nie przyniosły konwersji i kosztowały ponad 50 zł. Po automatycznej migracji kampanii do AI Max we wrześniu 2026 roku ten raport jest szczególnie przydatny, bo rozszerzone dopasowanie częściej trafia w nowe zapytania – więcej w tekście o AI Max for Search. Hasła z kampanii Performance Max nie trafiają do search_term_view; dla nich korzystaj ze statystyk haseł opisanych w artykule o Performance Max w 2026 roku.
function main() {
var w = zapytanie(
"SELECT search_term_view.search_term, campaign.name, metrics.clicks, metrics.cost_micros FROM search_term_view " +
"WHERE segments.date DURING LAST_30_DAYS AND metrics.conversions = 0 AND metrics.cost_micros > 50000000 " +
"ORDER BY metrics.cost_micros DESC LIMIT 100")
.map(function (r) { return [r.searchTermView.searchTerm, r.campaign.name, Number(r.metrics.clicks), Number(r.metrics.costMicros) / 1e6]; });
var ark = SpreadsheetApp.openById(ID_ARKUSZA).getSheetByName('hasla');
ark.clearContents().appendRow(['Hasło', 'Kampania', 'Kliknięcia', 'Koszt (zł)']);
if (w.length) ark.getRange(2, 1, w.length, 4).setValues(w);
alert('Hasła bez konwersji (30 dni): ' + w.length, w.slice(0, 10).map(function (x) { return x[0] + ' – ' + x[3].toFixed(2) + ' zł'; }));
}
Skrypt 9: historia Wyniku Jakości. Raz w tygodniu dopisuje do arkusza Wynik Jakości słów kluczowych, które miały ponad 100 wyświetleń w ostatnich 30 dniach. Po kilku miesiącach widzisz trend dla każdego słowa i możesz powiązać spadki ze zmianami reklam lub stron docelowych.
function main() {
var dzis = data(0);
var w = zapytanie(
"SELECT campaign.name, ad_group.name, ad_group_criterion.keyword.text, ad_group_criterion.quality_info.quality_score, " +
"metrics.impressions FROM keyword_view WHERE segments.date DURING LAST_30_DAYS " +
"AND ad_group_criterion.status = 'ENABLED' AND metrics.impressions > 100")
.map(function (r) {
var q = r.adGroupCriterion.qualityInfo ? r.adGroupCriterion.qualityInfo.qualityScore : '';
return [dzis, r.campaign.name, r.adGroup.name, r.adGroupCriterion.keyword.text, q || '', Number(r.metrics.impressions)];
});
var ark = SpreadsheetApp.openById(ID_ARKUSZA).getSheetByName('wynik_jakosci');
if (w.length) ark.getRange(ark.getLastRow() + 1, 1, w.length, 6).setValues(w);
}
Skrypt 10: dzienne podsumowanie zmian na koncie. Liczy zmiany z ostatnich 24 godzin według autora, typu klienta (interfejs, Edytor, API, skrypt, rekomendacje) i typu zasobu. Dzięki temu widzisz, kto i czym zmieniał konto – także wtedy, gdy zmiany wprowadzały automatycznie stosowane rekomendacje lub asystent AI. Jak kontrolować zmiany proponowane przez asystenta, opisujemy w tekście o Ask Advisor w Google Ads.
function main() {
var tz = AdsApp.currentAccount().getTimeZone();
var od = Utilities.formatDate(new Date(Date.now() - 86400000), tz, 'yyyy-MM-dd HH:mm:ss');
var doo = Utilities.formatDate(new Date(), tz, 'yyyy-MM-dd HH:mm:ss');
var licznik = {};
zapytanie("SELECT change_event.user_email, change_event.client_type, change_event.change_resource_type " +
"FROM change_event WHERE change_event.change_date_time >= '" + od + "' " +
"AND change_event.change_date_time <= '" + doo + "' LIMIT 10000")
.forEach(function (r) {
var e = r.changeEvent, k = e.userEmail + ' | ' + e.clientType + ' | ' + e.changeResourceType;
licznik[k] = (licznik[k] || 0) + 1;
});
alert('Zmiany na koncie (24 h)', Object.keys(licznik).sort().map(function (k) { return licznik[k] + ' × ' + k; }));
}
Jak wdrożyć i utrzymać zestaw skryptów
Dziesięć skryptów to dziesięć źródeł powiadomień, więc zanim je włączysz, ustal harmonogram i odbiorców. Poniższa tabela to propozycja na start.
| Skrypt | Harmonogram | Odbiorca alertu |
|---|---|---|
| 1. Koszt wyższy niż średnia | codziennie rano | specjalista prowadzący konto |
| 2. Ograniczenie budżetem | raz w tygodniu | specjalista i osoba decydująca o budżecie |
| 3. Brak wyświetleń | co godzinę | specjalista i opiekun konta |
| 4. Odrzucone reklamy | kilka razy dziennie | specjalista |
| 5. Strony z błędami | codziennie | specjalista i administrator strony |
| 6. Ograniczony status | codziennie | specjalista |
| 7. Spadek konwersji | codziennie | specjalista i analityk |
| 8. Hasła bez konwersji | raz w tygodniu | specjalista (arkusz) |
| 9. Wynik Jakości | raz w tygodniu | arkusz, bez alertu |
| 10. Podsumowanie zmian | codziennie rano | lider zespołu |
Wdrażaj je w takiej kolejności:
- Zacznij od skryptów 3, 4 i 5. Wykrywają sytuacje, w których konto traci pieniądze lub sprzedaż natychmiast.
- Każdy skrypt uruchom najpierw w podglądzie. Sprawdź w logach, czy zapytania zwracają dane i czy progi nie generują dziesiątek alertów.
- Dostrój progi po tygodniu. Jeśli alert przychodzi codziennie, a nie wymaga działania, podnieś próg lub zmień częstotliwość.
- Dodaj kolejne skrypty co kilka dni. Łatwiej wtedy ocenić, który generuje wartościowe powiadomienia.
- Prowadź listę skryptów. Zapisz, co robi każdy skrypt, kto jest jego właścicielem i kiedy go zmieniano.
Skrypty kontrolują konto reklamowe, ale nie zastąpią monitoringu pomiaru. Spadek konwersji bywa skutkiem błędu tagu, dlatego warto połączyć je z alertami o spadku zdarzeń w GA4 i BigQuery. Jeśli liczby w Google Ads i GA4 zaczną się rozjeżdżać, przyczyny znajdziesz w tekście o rozbieżnościach konwersji między GA4, Google Ads i Meta. Wszystkie poradniki o automatyzacji zebraliśmy w podtemacie Skrypty i automatyzacja, a podstawowe pojęcia, takie jak CPA i AI Max, wyjaśnia nasz słownik.
Najczęściej zadawane pytania
Czy skrypty Google Ads są bezpłatne?
Tak. Skrypty są wbudowaną funkcją Google Ads i nie wymagają dodatkowych opłat, serwera ani tokena deweloperskiego. Korzystają z usług Google, takich jak Gmail i Arkusze, w ramach dziennych limitów. Płatne mogą być jedynie zewnętrzne narzędzia, do których skrypt wysyła dane, np. płatny plan komunikatora.
Ile skryptów można uruchomić na jednym koncie?
Na koncie można utrzymywać wiele skryptów, a każdy ma własny harmonogram. W praktyce ograniczeniem nie jest liczba, tylko czas działania (do 30 minut na uruchomienie) i dzienne limity usług. Lepiej mieć kilka krótkich skryptów sprawdzających jedną rzecz niż jeden duży, który trudno utrzymać.
Czy skrypt może zepsuć coś na koncie?
Skrypty, które tylko czytają dane i wysyłają alerty, nie zmieniają konta. Ryzyko pojawia się przy skryptach wstrzymujących kampanie lub zmieniających stawki. Zawsze testuj je w trybie podglądu, który nie wprowadza zmian, ogranicz ich działanie do kampanii z etykietą i zapisuj każdą automatyczną zmianę w logu.
Dlaczego skrypt pokazuje mniej konwersji niż raport w Google Ads?
Najczęściej z powodu opóźnienia konwersji i innego zakresu dat. Google Ads przypisuje konwersje do dnia kliknięcia, więc dane z ostatnich dni są niekompletne. Różnicę mogą też powodować kolumny konwersji: metrics.conversions obejmuje tylko akcje uwzględniane w kolumnie Konwersje, a nie wszystkie konwersje.
Czy te skrypty działają w kampaniach Performance Max?
Częściowo. Skrypty kosztów, budżetów, statusów, konwersji i historii zmian obejmują wszystkie typy kampanii. Skrypty oparte na reklamach, słowach kluczowych i raporcie wyszukiwanych haseł dotyczą głównie kampanii w sieci wyszukiwania; dla Performance Max adresy URL i zasoby pobierasz z grup zasobów, a hasła ze statystyk haseł.