// --- CONFIGURATION ---
// !! REPLACE THESE NAMES with the EXACT names of your campaigns !!
const CAMPAIGN_1_NAME = 'Your Primary Campaign Name';
const CAMPAIGN_2_NAME = 'Your Backup Campaign Name';
// Budget exhaustion threshold (e.g., 0.98 = 98%)
const BUDGET_THRESHOLD = 0.98;
// Daily reset hour (24-hour format)
const RESET_HOUR = 1;
// Bidding amounts
const DAY_BID = 15; // 6 AM - 10 PM
const NIGHT_BID = 12; // 10 PM - 6 AM
function main() {
const now = new Date();
const currentHour = now.getHours();
// 1. DAILY RESET
if (currentHour === RESET_HOUR) {
Logger.log('*** Running Daily Campaign Reset ***');
resetCampaigns();
}
// Get campaigns
const campaign1 = getCampaignByName(CAMPAIGN_1_NAME);
const campaign2 = getCampaignByName(CAMPAIGN_2_NAME);
if (!campaign1 || !campaign2) {
Logger.log('ERROR: One or both configured campaigns were not found.');
return;
}
// 2. TIME-BASED BIDDING
const bidAmount = (currentHour >= 22 || currentHour < 6) ? NIGHT_BID : DAY_BID;
[campaign1, campaign2].forEach(c => {
if (c) {
c.bidding().setCpc(bidAmount);
Logger.log(`Set bid for ${c.getName()} to $${bidAmount}`);
}
});
// 3. CHECK PRIMARY CAMPAIGN
if (campaign1.isEnabled()) {
checkAndSwitchToBackup(campaign1, CAMPAIGN_1_NAME, campaign2, CAMPAIGN_2_NAME);
}
// 4. CHECK BACKUP CAMPAIGN
else if (!campaign1.isEnabled() && campaign2.isEnabled()) {
checkAndSwitchBackToMain(campaign2, CAMPAIGN_2_NAME, campaign1, CAMPAIGN_1_NAME);
}
}
// --- HELPER: Switch from primary to backup ---
function checkAndSwitchToBackup(currentCampaign, currentName, backupCampaign, backupName) {
const dailyBudget = currentCampaign.getBudget().getAmount();
const todaySpend = getCampaignCostToday(currentName);
const spendPercentage = todaySpend / dailyBudget;
Logger.log(`Checking ${currentName}. Spend: $${todaySpend.toFixed(2)} (${(spendPercentage*100).toFixed(2)}%)`);
if (spendPercentage >= BUDGET_THRESHOLD) {
Logger.log(`BUDGET REACHED for ${currentName}. Switching to ${backupName}.`);
currentCampaign.pause();
Logger.log(`${currentName} PAUSED.`);
if (!backupCampaign.isEnabled()) {
backupCampaign.enable();
Logger.log(`${backupName} ENABLED.`);
}
}
}
// --- HELPER: Switch back from backup to primary ---
function checkAndSwitchBackToMain(currentCampaign, currentName, mainCampaign, mainName) {
const dailyBudget = currentCampaign.getBudget().getAmount();
const todaySpend = getCampaignCostToday(currentName);
const spendPercentage = todaySpend / dailyBudget;
Logger.log(`Checking ${currentName}. Spend: $${todaySpend.toFixed(2)} (${(spendPercentage*100).toFixed(2)}%)`);
if (spendPercentage >= BUDGET_THRESHOLD) {
Logger.log(`BACKUP BUDGET EXHAUSTED for ${currentName}. Switching back to ${mainName}.`);
currentCampaign.pause();
Logger.log(`${currentName} PAUSED.`);
if (!mainCampaign.isEnabled()) {
mainCampaign.enable();
Logger.log(`${mainName} RE-ENABLED.`);
}
}
}
// --- HELPER: Reset campaigns daily ---
function resetCampaigns() {
const c1 = getCampaignByName(CAMPAIGN_1_NAME);
const c2 = getCampaignByName(CAMPAIGN_2_NAME);
if (c1 && !c1.isEnabled()) {
c1.enable();
Logger.log('RESET: Primary Campaign ENABLED.');
}
if (c2 && c2.isEnabled()) {
c2.pause();
Logger.log('RESET: Backup Campaign PAUSED.');
}
}
// --- HELPER: Get campaign by name ---
function getCampaignByName(name) {
const campaignIterator = AdsApp.campaigns()
.withCondition(`Name = '${name}'`)
.get();
if (campaignIterator.hasNext()) {
return campaignIterator.next();
}
return null;
}
// --- HELPER: Get today's cost for a campaign ---
function getCampaignCostToday(name) {
const report = AdsApp.report(
`SELECT Cost
FROM CAMPAIGN_PERFORMANCE_REPORT
WHERE CampaignName = '${name}'
DURING TODAY`
);
const rows = report.rows();
if (rows.hasNext()) {
return parseFloat(rows.next().Cost); // Cost is already in account currency
}
return 0;
}