Przejdź do treści

Automatyczne raporty z Google Ads do Arkuszy i Slacka: skrypty, Apps Script i webhooki

Codzienne kopiowanie danych z Google Ads do arkusza to strata czasu i źródło błędów. Pokazujemy przepływ, w którym skrypt zapisuje dane, Apps Script liczy wskaźniki, a Slack dostaje podsumowanie przed poranną kawą.

Redakcja Pixel Insider8 min czytaniaPoziom: średni

  • Google Ads Scripts
  • Apps Script
  • Slack
  • Arkusze Google
Spis treści
  1. Sposoby na automatyczne raporty Google Ads – porównanie
  2. Jak działa przepływ: skrypt, arkusz i webhook
  3. Krok 1: skrypt Google Ads zapisujący dane do Arkuszy
  4. Krok 2: podsumowanie dzienne na Slacku przez webhook
  5. Krok 3: raport tygodniowy i wyzwalacze w Apps Script
  6. Jak zadbać o niezawodność raportu
  7. Co raportować na Slacku, a co w dashboardzie
  8. 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.

  1. Utwórz aplikację w Slacku. W panelu aplikacji Slacka dodaj nową aplikację dla swojego obszaru roboczego (do tego mogą być potrzebne uprawnienia administratora).
  2. Włącz webhooki przychodzące. W ustawieniach aplikacji aktywuj funkcję Incoming Webhooks i dodaj nowy webhook, wybierając kanał, np. #google-ads-raporty.
  3. Skopiuj adres webhooka. Traktuj go jak hasło: każdy, kto go zna, może publikować na kanale.
  4. Zapisz adres we właściwościach skryptu. W edytorze Apps Script arkusza otwórz ustawienia projektu i dodaj właściwość skryptu SLACK_WEBHOOK z adresem jako wartością.
  5. 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.