Rozwiązanie w przystępny sposób prezentuje dane, dzieląc je na Shopping vs pozostałe kanały.
Dodatkowo wskazuje kluczowe metryki dla obu tych segmentów:
koszt, konwersje, ROAS i CPA.
W razie pytań lub sugestii zapraszam na moją grupę FB:
https://www.facebook.com/groups/zaawansowane.google.ads
Skrypt ten na bieżąco rozwijam.

Aktualizacja 20.03.2025:
1. Nowa metryka: wartość konwersji dla wszystkich segmenetów.
2. Możliwość wyboru zakresu dat dla lepszej analizy.
W arkuszu jest również zapisywany analizowany zakres dat, co ułatwia dokumentację i porównywanie wyników z różnych okresów.
Dzięki temu będzie można podjąć świadomą decyzję:
-czy pozostawić obecne kampanie z pełnym zestawem zasobów (Full Assets)
-czy przetestować Feed Only lub No Feed jako osobne kampanie
-czy przejść na Standard Shopping.
Konfiguracja:
- Wybieramy tryb analizy dat. Możemy wybrać opcję „DAYS” aby analizować określoną liczbę dni wstecz, lub „CUSTOM” aby podać własny zakres dat.
- Ustalamy liczbę dni, które chcemy przeanalizować. Opcja używana gdy tryb analizy to „DAYS”. Standardowo przyjąłem 45, ale warto sprawdzać również dłuższe okresy.
- Definiujemy własny zakres dat (opcjonalnie). Gdy używamy trybu „CUSTOM”, możemy podać konkretny przedział dat do analizy w formacie YYYYMMDD (np. „20240101” dla 1 stycznia 2024).
- Podajemy link do arkusza, w którym mają zostać zapisane dane.
- Określamy, jaki % wydatków na pozostałe kanały ma być brany pod uwagę.
Zalecam standardowe 10%.
Jeśli kampania PMax przeznacza na inne kanały mniej niż 10% całego budżetu, trudno będzie wyciągnąć sensowne wnioski. Chyba że ogólny budżet kampanii jest bardzo wysoki. Wtedy można zmniejszyć ten próg, np. do 5%. - Określamy minimalny wydatek kampanii PMax, aby była brana pod uwagę.
Domyślnie jest to 100.
Miłego analizowania!
Skopiuj poniższy kod:
/* Copyright 2025 Krzysztof Bycina, www.LiveAds.pl Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Konfiguracja skryptu - tutaj możesz dostosować parametry działania var config = { // Czy pokazywać szczegółowe logi w konsoli LOG: true, // Wybór trybu analizy dat DATE_MODE: "DAYS", // "DAYS" lub "CUSTOM" - ustaw "DAYS" aby analizować X dni wstecz, lub "CUSTOM" aby podać własny zakres dat // Liczba dni wstecz do analizy (używane gdy DATE_MODE = "DAYS") DAYS_TO_ANALYZE: 45, // Własny zakres dat (używane gdy DATE_MODE = "CUSTOM") CUSTOM_START_DATE: "20240101", // Format: YYYYMMDD CUSTOM_END_DATE: "20240131", // Format: YYYYMMDD // URL do arkusza Google, w którym zostaną zapisane wyniki // WAŻNE: Musisz mieć uprawnienia edycji do tego arkusza! SPREADSHEET_URL: "https://docs.google.com/spreadsheets/d/aaaaaaaaaaaaaaaaa/edit", // Minimalny procent wydatków na "inne kanały" (nie-Shopping), // powyżej którego kampania zostanie uwzględniona w raporcie THRESHOLD_PERCENTAGE: 10, // Minimalny całkowity wydatek na kampanię, // żeby została uwzględniona w analizie MIN_TOTAL_SPEND: 100 }; //Kod skryptu - tutaj już nic nie zmieniaj function main(){try{var a=SpreadsheetApp.openByUrl(config.SPREADSHEET_URL);_cs(a);_sb(a); _pa();config.LOG&&Logger.log("Zakończono przetwarzanie konta")}catch(b) {Logger.log("Błąd w funkcji main: "+b)}} function _cs(a){var b=a.getSheets();if(1<b.length)for(var c=0;c<b.length-1;c++) a.deleteSheet(b[c]);a=a.getSheets()[0];a.clear();a.setName("Opis")} function _pa(){try{var a=_gdr(),b=AdsApp.currentAccount().getName(),c=_gcd(a); if(0<Object.keys(c).length){_usd(c,a);var d=_pfr(c);if(d&&0<d.length){ var e=SpreadsheetApp.openByUrl(config.SPREADSHEET_URL);_sts(e,b,d);config.LOG&& (Logger.log("Zapisano raport dla konta: "+b),Logger.log("Liczba kampanii przekraczających próg: " +(d.length-1)))}else config.LOG&&Logger.log("Brak kampanii przekraczających próg dla konta: "+b)} else config.LOG&&Logger.log("Brak kampanii z wydatkami dla konta: "+b)}catch(f) {Logger.log("Błąd w processAccount dla "+b+": "+f)}} function _gcd(a){var b={},c=AdsApp.report("SELECT campaign.id, campaign.name, "+ "metrics.cost_micros, metrics.conversions, metrics.conversions_value FROM campaign "+ "WHERE campaign.advertising_channel_type = 'PERFORMANCE_MAX' AND metrics.cost_micros > 0 "+ "AND segments.date BETWEEN '"+a.startDate+"' AND '"+a.endDate+"'"),d=c.rows(); for(;d.hasNext();){var e=d.next(),f=parseFloat(e["metrics.cost_micros"]||0)/1E6, g=parseFloat(e["metrics.conversions"]||0),h=parseFloat(e["metrics.conversions_value"]||0), k=0<f?h/f:0,l=0<g?f/g:0;b[e["campaign.id"]]={name:e["campaign.name"],totalSpend:f, totalConversions:g,totalConversionValue:h,totalRoas:k,totalCpa:l,shoppingSpend:0, shoppingConversions:0,shoppingConversionValue:0,shoppingRoas:0,shoppingCpa:0}}return b} function _usd(a,b){if(0!==Object.keys(a).length){var c=AdsApp.report("SELECT campaign.id, "+ "metrics.cost_micros, metrics.conversions, metrics.conversions_value FROM shopping_performance_view "+ "WHERE campaign.id IN ('"+Object.keys(a).join("','")+"') AND segments.date BETWEEN '"+ b.startDate+"' AND '"+b.endDate+"'"),d=c.rows();for(;d.hasNext();){var e=d.next(), f=e["campaign.id"],g=Math.abs(parseFloat(e["metrics.cost_micros"]||0)/1E6), h=parseFloat(e["metrics.conversions"]||0),k=parseFloat(e["metrics.conversions_value"]||0); a[f]&&(a[f].shoppingSpend+=g,a[f].shoppingConversions+=h,a[f].shoppingConversionValue+=k, 0<a[f].shoppingSpend&&(a[f].shoppingRoas=a[f].shoppingConversionValue/a[f].shoppingSpend), 0<a[f].shoppingConversions&&(a[f].shoppingCpa=a[f].shoppingSpend/a[f].shoppingConversions))}}} function _pfr(a){var b=[],c={_t:0,_ct:0,_cv:0,_ss:0,_sc:0,_scv:0,_os:0,_oc:0,_ocv:0}; for(var d in a)if(a.hasOwnProperty(d)){var e=a[d];if(e.totalSpend>=config.MIN_TOTAL_SPEND){ var f=Math.min(e.shoppingSpend,e.totalSpend),g=e.totalSpend-f,h=g/e.totalSpend*100, k=Math.max(0,e.totalConversions-e.shoppingConversions), l=Math.max(0,e.totalConversionValue-e.shoppingConversionValue),m=0<g?l/g:0,n=0<k?g/k:0; h>config.THRESHOLD_PERCENTAGE&&(c._t+=e.totalSpend,c._ct+=e.totalConversions, c._cv+=e.totalConversionValue,c._ss+=f,c._sc+=e.shoppingConversions,c._scv+=e.shoppingConversionValue, c._os+=g,c._oc+=k,c._ocv+=l,b.push([e.name,e.totalSpend,e.totalConversions,e.totalConversionValue,e.totalRoas,e.totalCpa, f,f/e.totalSpend,e.shoppingConversions,e.shoppingConversionValue,e.shoppingRoas,e.shoppingCpa,g,g/e.totalSpend,k, l,m,n]))}} if(0<b.length){var p=0<c._t?c._cv/c._t:0,q=0<c._ss?c._scv/c._ss:0,r=0<c._os?c._ocv/c._os:0, t=0<c._ct?c._t/c._ct:0,u=0<c._sc?c._ss/c._sc:0,v=0<c._oc?c._os/c._oc:0; b.push(["SUMA",c._t,c._ct,c._cv,p,t,c._ss,c._ss/c._t,c._sc,c._scv,q,u,c._os,c._os/c._t,c._oc, c._ocv,r,v])}return b} function _gdr(){var a="CUSTOM"===config.DATE_MODE?{startDate:config.CUSTOM_START_DATE,endDate:config.CUSTOM_END_DATE}: function(){var b=new Date;b.setDate(b.getDate()-1);var c=new Date;c.setDate(c.getDate()-config.DAYS_TO_ANALYZE); return{startDate:_fd(c),endDate:_fd(b)}}();return a} function _fd(a){return a.getFullYear()+(a.getMonth()+1).toString().padStart(2,"0")+ a.getDate().toString().padStart(2,"0")} function _fm(a){return a&&8===a.length?a.substr(6,2)+"."+a.substr(4,2)+"."+a.substr(0,4):a} function _sb(a){var b=a.getSheetByName("Opis");b.clear();b.setColumnWidth(1,50);b.setColumnWidth(2,600);b.setColumnWidth(3,50);var c=[["","Cześć!",""],["","",""],["","Nazywam się Krzysztof Bycina i specjalizuję się w Google Ads dla e-commerce, prowadzeniu działań międzynarodowych oraz zarządzaniu dużymi budżetami.",""],["","",""],["","Mam nadzieję, że ten skrypt pomoże Ci w lepszym zrozumieniu wydatków kampanii Performance Max oraz ich efektywności.",""],["","",""],["","Jeśli masz wątpliwości co do ogólnej skuteczności Twojego konta reklamowego, to zapraszam do kontaktu. Dla nowych klientów oferuję bezpłatny i niezobowiązujący audyt.",""],["","",""],["","Myślę, że szczególnie warto porozmawiać, jeśli wydajesz na reklamy kilkadziesiąt tysięcy złotych miesięcznie lub więcej.",""],["","",""],["","",""],["","",""],["","Kontakt:",""],["","",""],["","krzysztof@liveads.pl",""],["","",""],["","www.liveads.pl/wspolpraca",""],["","",""],["","",""],["","INSTRUKCJA OBSŁUGI SKRYPTU:",""],["","",""],["","1. KONFIGURACJA - główne parametry skryptu można dostosować w sekcji \"config\" na początku kodu",""],["","",""],["","2. ANALIZA - skrypt analizuje kampanie Performance Max i ich podział wydatków na Shopping i inne formaty",""],["","",""],["","3. PRÓG ANALIZY - uwzględniane są tylko kampanie, gdzie wydatki na \"inne formaty\" przekraczają % określony w THRESHOLD_PERCENTAGE",""],["","",""],["","4. KOLOROWANIE - skrypt automatycznie oznacza kolorem komórki z niską efektywnością kanałów innych niż Shopping",""],["","",""],["","5. RAPORT - wyniki zapisane zostaną w arkuszu określonym w SPREADSHEET_URL",""],["","",""],["","6. WYBÓR DAT - możesz wybrać analizę na podstawie liczby dni wstecz lub określić dokładny przedział dat w konfiguracji",""]],d=[[1,35],[3,42],[5,42],[7,63],[9,42],[20,30],[21,25],[22,40],[24,40],[26,40],[28,40],[30,40],[32,40]],e=b.getRange(1,1,c.length,3);e.setValues(c);e.setFontFamily("Arial").setFontSize(12).setVerticalAlignment("middle");b.getRange(1,2).setFontWeight("bold").setFontSize(20);b.getRange(5,2).setFontWeight("bold");b.getRange(13,2).setFontWeight("bold").setFontSize(16);b.getRange(20,2).setFontWeight("bold").setFontSize(16);b.getRange(22,2,11,1).setFontSize(11);b.getRange(1,2,c.length,1).setWrap(!0);for(var f=0;f<d.length;f++)b.setRowHeight(d[f][0],d[f][1]);b.getRange(15,2,1,1).setFontColor("#1155cc");b.getRange(17,2,1,1).setFontColor("#1155cc");b.getRange(1,2,c.length,1).setHorizontalAlignment("left")} function _sts(a,b,c){var d=a.insertSheet(b),e={main:"#4A86E8",shopping:"#93C47D",other:"#E69138"}, f=[["KAMPANIA","","","","","","PRODUKTY (SHOPPING)","","","","","","POZOSTAŁE KANAŁY","","","","",""], ["Nazwa kampanii","Wydatek","Konwersje","Wart. konw.","ROAS","CPA","Wydatek","Udział %","Konwersje","Wart. konw.","ROAS","CPA", "Wydatek","Udział %","Konwersje","Wart. konw.","ROAS","CPA"]],g=d.getRange(1,1,2,f[0].length);g.setValues(f); var h=d.getRange(1,1,1,f[0].length);h.setValues([f[0]]);d.getRange(1,1,1,6).merge(). setBackground(e.main);d.getRange(1,7,1,6).merge().setBackground(e.shopping); d.getRange(1,13,1,6).merge().setBackground(e.other);var k=d.getRange(2,1,1,f[1].length); k.setValues([f[1]]);d.getRange(2,1,1,6).setBackground(e.main); d.getRange(2,7,1,6).setBackground(e.shopping);d.getRange(2,13,1,6).setBackground(e.other); g.setFontWeight("bold").setHorizontalAlignment("center").setVerticalAlignment("middle").setFontColor("white"); if(0<c.length){d.setColumnWidth(1,300);for(var l=2;l<=f[1].length;l++)d.setColumnWidth(l,120); for(l=3;l<=c.length+2;l++){var m=c[l-3];d.getRange(l,1).setValue(m[0]); d.getRange(l,2).setValue(m[1]).setNumberFormat('#,##0.00 "PLN"'); d.getRange(l,3).setValue(m[2]).setNumberFormat("#,##0"); d.getRange(l,4).setValue(m[3]).setNumberFormat('#,##0.00 "PLN"'); d.getRange(l,5).setValue(m[4]).setNumberFormat("#,##0.00"); d.getRange(l,6).setValue(m[5]).setNumberFormat("#,##0.00"); d.getRange(l,7).setValue(m[6]).setNumberFormat('#,##0.00 "PLN"'); d.getRange(l,8).setValue(m[7]).setNumberFormat("0.0%"); d.getRange(l,9).setValue(m[8]).setNumberFormat("#,##0"); d.getRange(l,10).setValue(m[9]).setNumberFormat('#,##0.00 "PLN"'); d.getRange(l,11).setValue(m[10]).setNumberFormat("#,##0.00"); d.getRange(l,12).setValue(m[11]).setNumberFormat("#,##0.00"); d.getRange(l,13).setValue(m[12]).setNumberFormat('#,##0.00 "PLN"'); d.getRange(l,14).setValue(m[13]).setNumberFormat("0.0%"); d.getRange(l,15).setValue(m[14]).setNumberFormat("#,##0"); d.getRange(l,16).setValue(m[15]).setNumberFormat('#,##0.00 "PLN"'); d.getRange(l,17).setValue(m[16]).setNumberFormat("#,##0.00"); d.getRange(l,18).setValue(m[17]).setNumberFormat("#,##0.00"); var n=m[6],p=m[10],q=m[11],r=m[12],t=m[14],u=m[16],v=m[17],w=Math.max(.1*n,100); if(r>w&&0<n){var x=d.getRange(l,13,1,6);if(0===t)0<q&&r>q?x.setBackground("#FF0000"). setFontColor("white"):200<r&&x.setBackground("#FF0000").setFontColor("white"); else{var y=0<p?u/p:1,z=0<q?v/q:1;.5>y&&1.4<z?x.setBackground("#FF9999"): .7>y&&1.3<z&&x.setBackground("#FFE5CC")}}}var A=c.length+2; d.getRange(A,1,1,f[1].length).setBackground("#E6E6E6").setFontWeight("bold"); d.getRange(3,1,c.length,1).setHorizontalAlignment("left"); d.getRange(3,2,c.length,f[1].length-1).setHorizontalAlignment("center"); var B=d.getRange(1,1,c.length+2,f[1].length); B.setBorder(!0,!0,!0,!0,!0,!0,"black",SpreadsheetApp.BorderStyle.SOLID); var C=c.length+4;d.getRange(C,1,1,3).merge(); d.getRange(C,1).setValue("LEGENDA:").setFontWeight("bold").setHorizontalAlignment("left"); d.getRange(C+1,1,1,f[1].length).merge(); d.getRange(C+1,1).setValue("⛔ Czerwone tło z białym tekstem - brak konwersji przy wydatkach >200 PLN lub >CPA w Shopping (jeśli dostępne)"). setHorizontalAlignment("left");d.getRange(C+2,1,1,f[1].length).merge(); d.getRange(C+2,1).setValue("🔴 Czerwone tło - znacząco gorsze wyniki (ROAS <50% i CPA >140% względem Shopping)"). setHorizontalAlignment("left");d.getRange(C+3,1,1,f[1].length).merge(); d.getRange(C+3,1).setValue("🟡 Jasnopomarańczowe tło - gorsze wyniki (ROAS <70% i CPA >130% względem Shopping)"). setHorizontalAlignment("left");var D=_gdr();d.getRange(C+5,1,1,f[1].length).merge(); d.getRange(C+5,1).setValue("Analizowany okres: "+_fm(D.startDate)+" do "+_fm(D.endDate)). setHorizontalAlignment("left").setFontWeight("bold")}d.setFrozenRows(2);d.getRange(1,1,c.length+2,1).setWrap(!0); d.setRowHeight(1,30);d.setRowHeight(2,40)}