Budget Overspend Script Not Working As Expected

104 views
Skip to first unread message

Sam Goddard

unread,
Feb 26, 2025, 5:45:28 PMFeb 26
to Google Ads Scripts Forum
Hello,


I have implemented a script in order to control ad spend on an account which varies wildly from one day to the next, causing all kinds of sales headaches.

The site uses mainly shopping campaigns (although I'd want it to work for search & PMAX campaigns too).

The aim of the script would be to turn off a campaign if it overspent by 20% & then turn it back on the next day. 

I'm running it every hour.

Yesterday, one of my campaigns spent twice its daily budget (which Google allows but which doesn't help the client). Can you let me know what might be wrong please?

Thanks



config = {
  overdeliveryThreshold: '20%', // The maximum over budget the campaign can go before it gets paused
  accounts: ['XXX-XXX-XXXX'] // The accounts in this MCC the script will run on, ignore if using on a single account - I have added the client's account number here
}

function main() {  
  try {
    AdsManagerApp.accounts().withIds(config.accounts).executeInParallel('pauseOverspendingCampaigns');
  } catch(e) {
    pauseOverspendingCampaigns();
  }
}

function pauseOverspendingCampaigns() {
 
  var labelName = 'Paused - Budget Overdelivery';
 
  // Unpause any campaigns that were previously paused
  var date = Utilities.formatDate(new Date(), AdsApp.currentAccount().getTimeZone(), 'MMMM dd, yyyy HH:mm:ss Z');
  var hour = parseFloat(date.split(' ')[3].substring(0, 2));
  if (hour < 3) {
    var campaigns = AdsApp.campaigns().withCondition('LabelNames CONTAINS_ANY ["' + labelName +'"]').get();
    while (campaigns.hasNext()) {
      var campaign = campaigns.next();
      campaign.removeLabel(labelName);
      campaign.enable();
    }
  }

  // If the label already doesn't exist, create it
  if (AdsApp.labels().withCondition('Name = "' + labelName + '"').get().totalNumEntities() === 0) AdsApp.createLabel(labelName);
 
  // Iterate through campaigns and check for any that are overspending
  var campaigns = AdsApp.campaigns().forDateRange('TODAY').withCondition('Cost > 0 AND Status = ENABLED').get();
  while (campaigns.hasNext()) {
    var campaign = campaigns.next();
    var budget = campaign.getBudget().getAmount();
    var cost = campaign.getStatsFor('TODAY').getCost();
    var threshold = (parseFloat(config.overdeliveryThreshold.replace('%', '')) / 100) + 1;
    var maxSpend = budget * threshold;
    if (cost > maxSpend) {
      campaign.applyLabel(labelName);
      campaign.pause();
    }
  }
}

Google Ads Scripts Forum Advisor

unread,
Feb 26, 2025, 5:55:04 PMFeb 26
to adwords...@googlegroups.com

Hi,

Thank you for reaching out to the Google Ads Scripts support team.

Please be informed that the method “AdsApp.campaigns()” will only iterate through Search & Display campaigns. To iterate through Performance Max campaigns and Shopping campaigns, I would recommend that you use “AdsApp.performanceMaxCampaigns()”, and “AdsApp.shoppingCampaigns()” methods.

I hope this helps! Feel free to get back to us with the following details if you still face any issues.

  • Google Ads account ID/CID
  • Name of the affected script
You can share the requested details via Reply privately to the author option or a direct private reply to this email. 

Thanks,
 
Google Logo Google Ads Scripts Team

Feedback
How was our support today?

rating1    rating2    rating3    rating4    rating5
[2025-02-26 22:54:34Z GMT] This message is in relation to case "ref:!00D1U01174p.!5004Q02vH4Ax:ref" (ADR-00290006)



Alejandro Perez

unread,
Apr 9, 2025, 2:37:50 PMApr 9
to Google Ads Scripts Forum
Is it possible to customize this script for Demand Gen campaigns? or maybe to email us if the Demand Gen overspends?

Google Ads Scripts Forum Advisor

unread,
Apr 9, 2025, 7:03:05 PMApr 9
to adwords...@googlegroups.com
Hi,

I would like to inform you that Demand Gen campaigns are not yet supported in Google Ads Scripts. Currently we don't have any specific method available for Demand Gen campaigns like AdsApp.campaigns() or AdsApp.videoCampaigns(). We recommend you to please follow our blog posts for future updates and announcements. 

I would recommend you to use the reporting option where you are able to get the campaign data related to the Demand Gen based on the campaign channel type. You can go through the below sample example used to get the data. Refer to the reporting documentation to get the data and based on your logic you can send email alerts using the MailApp method once the budget exceeds. In order to add additional fields you can go through the Campaign query builder
 
function main(){

let report = AdsApp.report(
    "SELECT campaign_budget.amount_micros, metrics.cost_micros FROM campaign WHERE campaign.advertising_channel_type = 'DEMAND_GEN' AND segments.date DURING TODAY");

let rows = report.rows();
while (rows.hasNext()) {
    let row = rows.next();
  console.log(row);
}
}

Thanks,
 
Google Logo Google Ads Scripts Team

Feedback
How was our support today?

rating1    rating2    rating3    rating4    rating5

[2025-04-09 23:02:22Z GMT] This message is in relation to case "ref:!00D1U01174p.!5004Q02vH4Ax:ref" (ADR-00290006)



Alejandro Perez

unread,
Apr 9, 2025, 10:41:40 PMApr 9
to Google Ads Scripts Forum
Thank you! it did work great
Reply all
Reply to author
Forward
0 new messages