Spis treści
- Sposoby na automatyczne raporty Google Ads – porównanie
- Jak działa przepływ: skrypt, arkusz i webhook
- Krok 1: skrypt Google Ads zapisujący dane do Arkuszy
- Krok 2: podsumowanie dzienne na Slacku przez webhook
- Krok 3: raport tygodniowy i wyzwalacze w Apps Script
- Jak zadbać o niezawodność raportu
- Co raportować na Slacku, a co w dashboardzie
- Najczęściej zadawane pytania
Automatyczne raporty Google Ads możesz zbudować bez płatnych narzędzi, łącząc trzy elementy: skrypt Google Ads, który codziennie zapisuje dane kampanii w Arkuszach Google, Apps Script, który liczy wskaźniki i porównania, oraz webhook, który wysyła podsumowanie na kanał w Slacku. Taki przepływ działa bez serwera, kosztuje tyle, ile konto Google, i daje zespołowi te same liczby każdego ranka o tej samej godzinie. Poniżej znajdziesz porównanie dostępnych metod, kod wszystkich trzech elementów, konfigurację webhooka i zasady, które chronią raport przed najczęstszymi błędami, w tym przed zaniżonymi konwersjami z ostatnich dni.
Najważniejsze w skrócie
- Najprostszy automatyczny raport to zaplanowana wysyłka raportu z edytora raportów Google Ads; skrypt z arkuszem daje jednak pełną kontrolę nad danymi i formą.
- Skrypt powinien codziennie nadpisywać dane z ostatnich 7 dni, a nie tylko dopisywać wczoraj, bo konwersje docierają do konta z opóźnieniem.
- Podsumowanie na Slacku wysyłasz przez webhook przychodzący, a jego adres przechowujesz we właściwościach skryptu, nie w kodzie.
- Porównuj dzień z tym samym dniem tygodnia wcześniej, a tydzień z poprzednim tygodniem – porównanie z dniem poprzednim myli wahania tygodniowe z trendem.
- Slack służy do sygnałów i krótkich podsumowań, a analiza trendów i rozbicia na kanały należy do dashboardu.
Sposoby na automatyczne raporty Google Ads – porównanie
Masz do wyboru kilka metod, które różnią się elastycznością i nakładem pracy. W praktyce zespoły często łączą dwie: szybkie podsumowanie w komunikatorze i dashboard do pogłębionej analizy.
| Metoda | Dla kogo | Zalety | Ograniczenia |
|---|---|---|---|
| Zaplanowany raport z edytora raportów Google Ads | małe konto, raport dla jednej osoby | zero kodu, wysyłka e-mailem jako plik | sztywna forma, brak porównań i logiki |
| Skrypt Google Ads + Arkusze + Slack | zespół, kilka kont, codzienne podsumowania | pełna kontrola, bezpłatnie, własne wskaźniki | wymaga utrzymania kodu |
| Looker Studio z łącznikiem Google Ads | raporty dla klientów i zarządu | wizualizacje, łączenie źródeł | brak powiadomień, limity łączników |
| Transfer do BigQuery lub Google Ads API | duże konta, hurtownia danych | historia, SQL, łączenie z CRM | koszty i kompetencje techniczne |
| Narzędzia do automatyzacji (np. n8n) | zespoły z wieloma systemami | przepływy między aplikacjami, modele językowe | kolejne narzędzie do utrzymania |
Ten poradnik opisuje drugą metodę, bo daje najwięcej przy najmniejszym koszcie. Jeśli interesuje Cię wariant z modelem językowym, który pisze komentarz do liczb, zajrzyj do tekstu o automatyzacji raportów w n8n. Pełne połączenie z hurtownią przez API opisujemy w artykule o Google Ads API po zmianach z września 2026.
Jak działa przepływ: skrypt, arkusz i webhook
Każdy element robi jedną rzecz. Skrypt Google Ads działa wewnątrz konta reklamowego, więc ma bezpośredni dostęp do danych i nie potrzebuje żadnych kluczy. Arkusz przechowuje dane w prostej tabeli: jeden wiersz to jeden dzień jednej kampanii. Apps Script przypięty do arkusza liczy sumy, wskaźniki i porównania, a następnie wysyła wiadomość na Slacka.
Rozdzielenie pobierania danych od wysyłania podsumowania ma praktyczny sens. Skrypt Google Ads uruchamiasz np. o 5:00, a podsumowanie o 8:00. Jeśli pobieranie się nie uda, podsumowanie i tak wyjdzie – z wczorajszymi liczbami i ostrzeżeniem, że dane są nieaktualne – a Ty od razu wiesz, gdzie szukać problemu.
Najważniejsza decyzja dotyczy okna danych. Google Ads przypisuje konwersję do dnia kliknięcia, a nie do dnia zakupu, i część konwersji dociera z opóźnieniem. Jeśli skrypt tylko dopisuje wczorajszy dzień, arkusz na zawsze zachowa zaniżone liczby. Dlatego skrypt codziennie usuwa i zapisuje na nowo dane z ostatnich 7 dni; przy długich cyklach zakupowych wydłuż to okno do 14 lub 30 dni.
Krok 1: skrypt Google Ads zapisujący dane do Arkuszy
Utwórz arkusz z zakładką dane, skopiuj jego identyfikator z adresu i wklej go w konfiguracji. Skrypt sam doda nagłówek przy pierwszym uruchomieniu. Uruchamiaj go codziennie wcześnie rano.
var ID_ARKUSZA = 'WSTAW_ID_ARKUSZA';
var ZAKLADKA = 'dane';
var DNI = 7; // nadpisywane okno – konwersje docierają z opóźnieniem
var NAGLOWEK = ['Data', 'Konto', 'Kampania', 'Typ', 'Wyświetlenia', 'Kliknięcia', 'Koszt', 'Konwersje', 'Wartość konwersji'];
function main() {
var tz = AdsApp.currentAccount().getTimeZone();
var konto = AdsApp.currentAccount().getName();
var od = Utilities.formatDate(new Date(Date.now() - DNI * 86400000), tz, 'yyyy-MM-dd');
var doo = Utilities.formatDate(new Date(Date.now() - 86400000), tz, 'yyyy-MM-dd');
var nowe = [];
var it = AdsApp.search(
"SELECT segments.date, campaign.name, campaign.advertising_channel_type, metrics.impressions, metrics.clicks, " +
"metrics.cost_micros, metrics.conversions, metrics.conversions_value FROM campaign " +
"WHERE segments.date BETWEEN '" + od + "' AND '" + doo + "' AND metrics.impressions > 0");
while (it.hasNext()) {
var r = it.next();
nowe.push([r.segments.date, konto, r.campaign.name, r.campaign.advertisingChannelType,
Number(r.metrics.impressions), Number(r.metrics.clicks), Number(r.metrics.costMicros) / 1e6,
Number(r.metrics.conversions), Number(r.metrics.conversionsValue)]);
}
var ark = SpreadsheetApp.openById(ID_ARKUSZA).getSheetByName(ZAKLADKA);
var dane = ark.getLastRow() > 1 ? ark.getDataRange().getValues().slice(1) : [];
var zostaw = dane.filter(function (w) {
var d = w[0] instanceof Date ? Utilities.formatDate(w[0], tz, 'yyyy-MM-dd') : String(w[0]);
return d < od || d > doo || w[1] !== konto; // usuń nadpisywane okno tego konta
});
var wynik = [NAGLOWEK].concat(zostaw, nowe);
ark.clearContents();
ark.getRange(1, 1, wynik.length, NAGLOWEK.length).setValues(wynik);
Logger.log('Zapisano ' + nowe.length + ' wierszy z okresu ' + od + ' – ' + doo);
}
Skrypt zapisuje tylko kampanie z wyświetleniami, żeby arkusz nie rósł o puste wiersze. Kolumna z kontem pozwala trzymać w jednym arkuszu dane z kilku kont: każde konto ma własny skrypt i nadpisuje tylko swoje wiersze. Na koncie menedżera możesz zamiast tego przejść po kontach w jednym skrypcie – ale przy kilkudziesięciu kontach zapis do jednego arkusza staje się wolny i lepiej przenieść dane do BigQuery. Pole metrics.conversions obejmuje akcje uwzględniane w kolumnie Konwersje; jeśli raportujesz też inne akcje, dodaj metrics.all_conversions.
Krok 2: podsumowanie dzienne na Slacku przez webhook
Webhook przychodzący to adres, na który wysyłasz wiadomość w formacie JSON, a Slack publikuje ją na wybranym kanale. Konfiguracja zajmuje kilka minut.
- Utwórz aplikację w Slacku. W panelu aplikacji Slacka dodaj nową aplikację dla swojego obszaru roboczego (do tego mogą być potrzebne uprawnienia administratora).
- Włącz webhooki przychodzące. W ustawieniach aplikacji aktywuj funkcję Incoming Webhooks i dodaj nowy webhook, wybierając kanał, np. #google-ads-raporty.
- Skopiuj adres webhooka. Traktuj go jak hasło: każdy, kto go zna, może publikować na kanale.
- Zapisz adres we właściwościach skryptu. W edytorze Apps Script arkusza otwórz ustawienia projektu i dodaj właściwość skryptu
SLACK_WEBHOOKz adresem jako wartością. - Wklej kod i uruchom go ręcznie. Sprawdź, czy wiadomość dotarła i czy liczby zgadzają się z interfejsem Google Ads.
Poniższy kod w Apps Script arkusza liczy koszt, konwersje, wartość, ROAS i CPA za wczoraj i porównuje je z tym samym dniem tydzień wcześniej.
function dzien(d, tz) { return d instanceof Date ? Utilities.formatDate(d, tz, 'yyyy-MM-dd') : String(d); }
function pln(x) { return String(Math.round(x)).replace(/\B(?=(\d{3})+(?!\d))/g, ' ') + ' zł'; }
function zmiana(a, b) { return b ? ((a - b) / b * 100 >= 0 ? '+' : '') + Math.round((a - b) / b * 100) + '%' : 'b.d.'; }
function sumy(dane, data, tz) {
var s = { koszt: 0, konw: 0, wartosc: 0 };
dane.forEach(function (w) {
if (dzien(w[0], tz) === data) { s.koszt += Number(w[6]); s.konw += Number(w[7]); s.wartosc += Number(w[8]); }
});
s.roas = s.koszt ? s.wartosc / s.koszt : 0;
s.cpa = s.konw ? s.koszt / s.konw : 0;
return s;
}
function podsumowanieDzienne() {
var tz = Session.getScriptTimeZone();
var wczoraj = Utilities.formatDate(new Date(Date.now() - 86400000), tz, 'yyyy-MM-dd');
var tydzienTemu = Utilities.formatDate(new Date(Date.now() - 8 * 86400000), tz, 'yyyy-MM-dd');
var dane = SpreadsheetApp.getActive().getSheetByName('dane').getDataRange().getValues().slice(1);
var a = sumy(dane, wczoraj, tz), b = sumy(dane, tydzienTemu, tz);
var wiadomosc = {
text: 'Google Ads – podsumowanie ' + wczoraj,
blocks: [
{ type: 'header', text: { type: 'plain_text', text: 'Google Ads – ' + wczoraj } },
{ type: 'section', fields: [
{ type: 'mrkdwn', text: '*Koszt*\n' + pln(a.koszt) + ' (' + zmiana(a.koszt, b.koszt) + ')' },
{ type: 'mrkdwn', text: '*Wartość konwersji*\n' + pln(a.wartosc) + ' (' + zmiana(a.wartosc, b.wartosc) + ')' },
{ type: 'mrkdwn', text: '*Konwersje*\n' + a.konw.toFixed(1) + ' (' + zmiana(a.konw, b.konw) + ')' },
{ type: 'mrkdwn', text: '*ROAS / CPA*\n' + a.roas.toFixed(2) + ' / ' + pln(a.cpa) }
] },
{ type: 'context', elements: [{ type: 'mrkdwn',
text: 'Zmiany względem ' + tydzienTemu + '. Konwersje z ostatnich dni mogą jeszcze wzrosnąć.' }] }
]
};
if (!a.koszt) wiadomosc.text = wiadomosc.blocks[0].text.text += ' – brak danych, sprawdź skrypt pobierający';
var url = PropertiesService.getScriptProperties().getProperty('SLACK_WEBHOOK');
UrlFetchApp.fetch(url, { method: 'post', contentType: 'application/json', payload: JSON.stringify(wiadomosc) });
}
Pole text jest wyświetlane w powiadomieniach i na urządzeniach, które nie pokazują bloków, dlatego zawsze je uzupełniaj. Jeśli zespół korzysta z Google Chat, mechanizm jest podobny: webhook tworzysz w ustawieniach pokoju, a treść wiadomości wysyłasz w polu text.
Krok 3: raport tygodniowy i wyzwalacze w Apps Script
Raport tygodniowy pokazuje kampanie, które w ostatnich 7 dniach wydały najwięcej, wraz z ich ROAS. To dobry materiał na poniedziałkowe spotkanie zespołu. Funkcja ustawWyzwalacze() uruchamiana raz tworzy harmonogram dla obu raportów.
function raportTygodniowy() {
var tz = Session.getScriptTimeZone();
var od = Utilities.formatDate(new Date(Date.now() - 7 * 86400000), tz, 'yyyy-MM-dd');
var doo = Utilities.formatDate(new Date(Date.now() - 86400000), tz, 'yyyy-MM-dd');
var dane = SpreadsheetApp.getActive().getSheetByName('dane').getDataRange().getValues().slice(1);
var kampanie = {};
dane.forEach(function (w) {
var d = dzien(w[0], tz);
if (d < od || d > doo) return;
var k = kampanie[w[2]] || (kampanie[w[2]] = { koszt: 0, wartosc: 0 });
k.koszt += Number(w[6]); k.wartosc += Number(w[8]);
});
var top = Object.keys(kampanie).sort(function (x, y) { return kampanie[y].koszt - kampanie[x].koszt; }).slice(0, 5)
.map(function (n, i) {
var k = kampanie[n];
return (i + 1) + '. ' + n + ' – ' + pln(k.koszt) + ', ROAS ' + (k.koszt ? (k.wartosc / k.koszt).toFixed(2) : '0');
});
var url = PropertiesService.getScriptProperties().getProperty('SLACK_WEBHOOK');
UrlFetchApp.fetch(url, { method: 'post', contentType: 'application/json',
payload: JSON.stringify({ text: '*Top 5 kampanii według kosztu, ' + od + ' – ' + doo + '*\n' + top.join('\n') }) });
}
function ustawWyzwalacze() {
ScriptApp.newTrigger('podsumowanieDzienne').timeBased().everyDays(1).atHour(8).create();
ScriptApp.newTrigger('raportTygodniowy').timeBased().onWeekDay(ScriptApp.WeekDay.MONDAY).atHour(9).create();
}
Wyzwalacze czasowe w Apps Script uruchamiają funkcję w wybranej godzinie, ale nie co do minuty – wiadomość może przyjść w ciągu tej godziny. Strefę czasową skryptu ustaw w ustawieniach projektu na Europe/Warsaw, żeby daty w arkuszu i w wiadomości były zgodne z kontem reklamowym.
Jak zadbać o niezawodność raportu
Automatyczny raport traci sens, gdy zespół przestaje mu ufać. Kilka zasad pozwala tego uniknąć:
- Sygnalizuj brak danych. Jeśli koszt za wczoraj wynosi zero, wiadomość powinna to wprost powiedzieć, zamiast pokazywać same zera jak normalny dzień.
- Trzymaj sekrety poza kodem. Adres webhooka przechowuj we właściwościach skryptu, a dostęp do arkusza ogranicz do osób, które go potrzebują.
- Ustal jedną definicję konwersji. Raport ze Slacka, dashboard i raport dla klienta muszą korzystać z tej samej kolumny konwersji, inaczej liczby będą się różnić.
- Dodaj kontrolę z interfejsem. Raz w miesiącu porównaj sumy z arkusza z raportem w Google Ads za ten sam okres.
- Monitoruj błędy skryptu. W Google Ads zaglądaj do historii uruchomień skryptów, gdzie widać status i logi każdego przebiegu, a w Apps Script ustaw powiadomienia o błędach wyzwalaczy tak, by trafiały do właściwej osoby.
Alerty o anomaliach, takich jak gwałtowny wzrost wydatków, warto wysyłać osobnym kanałem i od razu, a nie w porannym podsumowaniu. Gotowe skrypty znajdziesz w artykułach o anomaliach budżetu i o monitorowaniu konta Google Ads.
Co raportować na Slacku, a co w dashboardzie
Slack nadaje się do krótkich sygnałów: czy wczoraj wydarzyło się coś nietypowego i czy trzeba zareagować. Cztery liczby – koszt, wartość konwersji, konwersje i ROAS lub CPA – z porównaniem do tego samego dnia tydzień wcześniej wystarczą w większości zespołów. Więcej pól sprawia, że wiadomość przestaje być czytana.
Analiza trendów, rozbicie na kampanie i kanały oraz łączenie danych z innymi platformami należą do dashboardu. Szablon takiego raportu opisujemy w artykule o dashboardzie e-commerce w Looker Studio, a łączenie kosztów z Google Ads, Meta i GA4 – w tekście o łączeniu danych w Looker Studio. Miesięczne podsumowanie dla klienta lub zarządu znajdziesz w szablonie raportu ROAS, a wskaźnik łączny dla wszystkich kanałów, czyli MER, w artykule o dashboardzie blended ROAS.
Pamiętaj, że liczby z Google Ads nie będą identyczne z GA4 – platformy inaczej przypisują konwersje i liczą je w innym czasie. Jeśli ktoś w zespole zapyta, dlaczego raport na Slacku pokazuje więcej sprzedaży niż GA4, odpowiedź znajdziesz w tekście o rozbieżnościach konwersji między GA4, Google Ads i Meta. Pozostałe poradniki o automatyzacji zebraliśmy w podtemacie Skrypty i automatyzacja, a o raportowaniu wizualnym piszemy na stronie narzędzia Looker Studio.
Najczęściej zadawane pytania
Czy Google Ads może sam wysyłać raporty e-mailem?
Tak. Raport zapisany w edytorze raportów Google Ads można zaplanować do regularnej wysyłki e-mailem, np. codziennie lub co tydzień, w formacie pliku. To dobre rozwiązanie dla małego konta, ale nie pozwala dodać własnych wskaźników, porównań ani wysyłki do komunikatora – do tego potrzebny jest skrypt.
Dlaczego raport pokazuje mniej konwersji za wczoraj niż później w Google Ads?
Google Ads przypisuje konwersję do dnia kliknięcia, a część konwersji dociera z opóźnieniem, nawet kilkudniowym. Wczorajszy dzień jest więc zawsze niekompletny. Dlatego skrypt powinien codziennie nadpisywać dane z ostatnich 7 dni, a przy długich cyklach zakupowych z ostatnich 14 lub 30 dni.
Czy do wysyłania raportów na Slacka potrzebny jest płatny plan?
Webhooki przychodzące działają w aplikacjach Slacka niezależnie od planu, ale do utworzenia aplikacji w obszarze roboczym mogą być potrzebne uprawnienia administratora. Sprawdź zasady swojej firmy, zanim podłączysz zewnętrzny skrypt do kanału, i traktuj adres webhooka jak hasło.
Jak raportować kilka kont Google Ads w jednym arkuszu?
Dodaj do danych kolumnę z nazwą lub identyfikatorem konta i pozwól każdemu skryptowi nadpisywać tylko własne wiersze. Przy kilku kontach możesz uruchomić osobne skrypty, a przy większej liczbie – jeden skrypt na koncie menedżera. Powyżej kilkudziesięciu kont lepiej sprawdza się BigQuery niż arkusz.
Które wskaźniki umieścić w codziennym podsumowaniu?
Wystarczą cztery: koszt, wartość konwersji, liczba konwersji oraz ROAS lub CPA, z porównaniem do tego samego dnia tydzień wcześniej. Dzięki temu widzisz odchylenia bez wpływu różnic między dniami tygodnia. Szczegółową analizę kampanii i kanałów przenieś do dashboardu w Looker Studio.