I wanted to create a script which increases the bidding to +40% on specific dates. Unfortunately its not working and i dont know why:
const CONFIG = {
CAMPAIGN_NAMES: [
"2025IBrandIDE"
// ➜ weitere Kampagnennamen hier ergänzen
],
// +40% am Spieltag:
GAME_DAY_BID_MODIFIER: 1.4,
// Zeitfenster am Spieltag (ganzer Tag). Bei Bedarf ändern (z. B. 14–23 Uhr).
START_HOUR: 0, START_MIN: 0,
END_HOUR: 24, END_MIN: 0,
// Heimspieltage (aus deiner Liste; Duplikate möglich – werden bereinigt)
GAME_DATES_DDMMYY: [
"28.08.25","30.08.25","20.09.25","04.10.25","25.10.25","01.11.25",
"22.11.25","06.12.25","20.12.25","14.01.26","17.01.26",
"31.01.26","14.01.26","28.02.26","21.03.26","11.04.26",
"25.04.26","09.05.26"
],
// E-Mail-Benachrichtigung
NOTIFY: true,
NOTIFY_ON_SUCCESS: true, // auf false setzen, wenn nur Fehler-Mails gewünscht sind
EMAIL_TO: "
te...@test.de"
};
function main() {
const tz = AdsApp.currentAccount().getTimeZone();
const todayIso = Utilities.formatDate(new Date(), tz, "yyyy-MM-dd");
const gameDatesIso = dedupAndNormalize_(CONFIG.GAME_DATES_DDMMYY);
const isGameDay = gameDatesIso.has(todayIso);
const summary = {
tz,
todayIso,
isGameDay,
created: 0,
removed: 0,
skipped: [],
errors: []
};
try {
CONFIG.CAMPAIGN_NAMES.forEach(name => {
const it = AdsApp.campaigns().withCondition(`Name = "${name}"`).get();
if (!it.hasNext()) {
summary.skipped.push(`Kampagne nicht gefunden: ${name}`);
return;
}
const c = it.next();
if (isGameDay) {
if (!hasOurGameSchedule_(c)) {
c.addAdSchedule({
dayOfWeek: getTodayDayOfWeek_(tz),
startHour: CONFIG.START_HOUR,
startMinute: CONFIG.START_MIN,
endHour: CONFIG.END_HOUR,
endMinute: CONFIG.END_MIN,
bidModifier: CONFIG.GAME_DAY_BID_MODIFIER
});
summary.created++;
Logger.log(`✅ ${name}: Spieltags-Schedule angelegt (+${Math.round((CONFIG.GAME_DAY_BID_MODIFIER - 1) * 100)}%)`);
} else {
Logger.log(`ℹ️ ${name}: Spieltags-Schedule existiert bereits`);
}
} else {
const removed = removeOurGameSchedules_(c);
summary.removed += removed;
if (removed > 0) {
Logger.log(`✅ ${name}: ${removed} Spieltags-Schedule(s) entfernt`);
} else {
Logger.log(`ℹ️ ${name}: Kein Spieltags-Schedule zu entfernen`);
}
}
});
// Erfolgsmail
if (CONFIG.NOTIFY && CONFIG.NOTIFY_ON_SUCCESS) {
sendReportEmail_(/*isError=*/false, summary);
}
} catch (e) {
summary.errors.push(String(e));
Logger.log(`❌ Fehler: ${e}`);
// Fehlermail
if (CONFIG.NOTIFY) {
sendReportEmail_(/*isError=*/true, summary);
}
// Fehler weiterwerfen, damit im Ausführungsprotokoll sichtbar
throw e;
}
}
/** ---------- Helpers ---------- **/
function sendReportEmail_(isError, s) {
const subject = `[Google Ads] FCA-Spieltag-Script ${isError ? "FEHLER" : "OK"} – ${s.todayIso} (${s.isGameDay ? "Heimspiel" : "Nicht-Spieltag"})`;
const body =
`Konto-Zeitzone: ${
s.tz}
Datum (ISO): ${s.todayIso}
Heimspieltag: ${s.isGameDay ? "JA" : "NEIN"}
Aktionen:
- Angelegte Spieltags-Schedules: ${s.created}
- Entfernte Spieltags-Schedules: ${s.removed}
- Übersprungen: ${s.skipped.length ? ("\n • " + s.skipped.join("\n • ")) : "–"}
${s.errors.length ? "Fehler:\n • " + s.errors.join("\n • ") : "Keine Fehler protokolliert."}
`;
MailApp.sendEmail({
to: CONFIG.EMAIL_TO,
subject: subject,
htmlBody: body.replace(/\n/g, "<br>"),
noReply: true
});
}
function dedupAndNormalize_(ddmmyyList) {
const set = new Set();
ddmmyyList.forEach(s => {
const m = s.match(/^(\d{2})\.(\d{2})\.(\d{2})$/);
if (!m) return;
const [ , dd, mm, yy ] = m;
const yyyy = (parseInt(yy,10) >= 70 ? '19' : '20') + yy; // '25' → 2025, '26' → 2026
set.add(`${yyyy}-${mm}-${dd}`);
});
return set;
}
function getTodayDayOfWeek_(tz) {
const d = Utilities.formatDate(new Date(), tz, "u"); // 1=Mon ... 7=Son
const map = { "1":"MONDAY","2":"TUESDAY","3":"WEDNESDAY","4":"THURSDAY","5":"FRIDAY","6":"SATURDAY","7":"SUNDAY" };
return map[d];
}
function hasOurGameSchedule_(campaign) {
const it = campaign.targeting().adSchedules().get();
while (it.hasNext()) {
const s = it.next();
if (isOurPattern_(s)) return true;
}
return false;
}
function removeOurGameSchedules_(campaign) {
let count = 0;
const it = campaign.targeting().adSchedules().get();
while (it.hasNext()) {
const s = it.next();
if (isOurPattern_(s)) {
s.remove();
count++;
}
}
return count;
}
// Muster: genau unser Zeitfenster & genau unser Modifikator
function isOurPattern_(s) {
return s.getStartHour() === CONFIG.START_HOUR &&
s.getStartMinute() === CONFIG.START_MIN &&
s.getEndHour() === CONFIG.END_HOUR &&
s.getEndMinute() === CONFIG.END_MIN &&
nearlyEq_(s.getBidModifier(), CONFIG.GAME_DAY_BID_MODIFIER);
}
function nearlyEq_(a,b,eps){ eps = eps || 1e-6; return Math.abs(a-b) <= eps; }