Pause campaigns if monthly budget has been reached.

229 views
Skip to first unread message

Andrew Rozynski

unread,
Sep 29, 2023, 5:29:29 PM9/29/23
to Google Ads Scripts Forum
Hi, there is this simple script that I'm using to pause all campaigns if the monthly budget has been reached. The problem is it's not adding the spend from Pmax and Discovery campaigns. How can I modify it to make it work?

function main() {
  /***
    This script will auto-pause campaigns when the account exceeds its monthly budget.
    No more daily monitoring of account budgets!
  ***/
 
  Logger.log("**********************");
  Logger.log("Running BUDGET - Pause All Campaigns script...");
  Logger.log("**********************");
 
  // THIS AMOUNT WILL VARY CLIENT BY CLIENT
  // MAKE SURE IT IS CORRECT
  var monthlyBudget = 1978.36;



  var totalCost = 0;
  var campaignsList = [];

 
  var campaignIterator = AdWordsApp.campaigns().get();

 
  while (campaignIterator.hasNext()) {
    var campaign = campaignIterator.next();

   
    // Save each current campaign into an array for ease of iteration
    campaignsList.push(campaign);
   
    // Use THIS_MONTH to get data for all days in the current month

    var stats = campaign.getStatsFor('THIS_MONTH');
    var campaignCost = stats.getCost();
    totalCost += campaignCost;
  }

 
  Logger.log("Account cost for this month: " + totalCost);
 
  // If totalCost of combined campaigns exceeds defined monthlyBudget, pause all!
  if (totalCost >= monthlyBudget){
    Logger.log("Monthly budget met or exceeded. Auto-pausing all campaigns!");

   
    for (var i = 0; i < campaignsList.length; i++) {
      var campaign = campaignsList[i];

      Logger.log("Pausing campaign: " + campaign.getName());
      campaign.pause();
    }
  } else {
    Logger.log("Total monthly cost currently under budget.");
    Logger.log("Monthly Cost: " + totalCost);
    Logger.log("Monthly Budget: " + monthlyBudget);
  }
}

Nils Rooijmans

unread,
Oct 2, 2023, 4:26:38 AM10/2/23
to Google Ads Scripts Forum
unfortunately, discovery campaign entities are not supported via scripts You will need to get the costs via the Report API.

I've created a script that shows you how to get the cost of all campaigns in your account, irrespective of campaign type.


Hope this helps,

Nils Rooijmans


Sigurd Fabrin

unread,
Oct 2, 2023, 6:45:18 AM10/2/23
to Google Ads Scripts Forum
As Nils mentions, it is not as straightforward any longer to get data across different campaign types. And it is even more complicated to make changes like pausing campaigns of different types.

With all the different campaign types that are more or less supported in scripts, I often use bulk uploads for these sort of tasks.
In this instance: Fetch cost data via an api report and if cost > xx,  create and upload a spreadsheet with instructions to pause all campaigns in the account. And also send an email when campaigns are paused.

Something like this approach
const settings = {  
  maxSpend:50000, // pause all campaigns if cost is above this amount during this month
  notify: { // send email to these people when campaigns are paused
    'Sigurd':'sig...@example.com',
    'Sigurd 2':'sigurd-@@example.com',
    'Sigurd 3':'sigu...@example.com'
  }  
}
function main() {
  const today = new Date();
  const timeZone = AdsApp.currentAccount().getTimeZone();
  const startDate = Utilities.formatDate(today,timeZone,'yyyy-MM')+'-01';
  const endDate = Utilities.formatDate(today,timeZone,'yyyy-MM-dd');
  const query = `
    SELECT
      customer.id,
      campaign.id,
      campaign.name,
      metrics.cost_micros
    FROM
      campaign
    WHERE
      segments.date BETWEEN '${startDate}' AND '${endDate}'
      AND campaign.status = ENABLED
      AND campaign.serving_status = SERVING`;
  const response = AdsApp.search(query);
  const campaigns = [];
  const campaignNames = [];
  let totalCost = 0;
  console.log(`Spend during ${startDate} - ${endDate}:`);
  while (response.hasNext()) {
    const row = response.next();
    campaigns.push([row.customer.id,row.campaign.id,row.campaign.name])
    campaignNames.push(row.campaign.name)
    const cost = parseFloat(row.metrics.costMicros)/1000000
    totalCost += cost;
    console.log(`"${row.campaign.name}": ${cost.toFixed(2)}`);
  }
  if (totalCost > settings.maxSpend) {
    console.log(`\nTotal spend: ${totalCost.toFixed(0)}. Max was ${settings.maxSpend}, so ${(totalCost-settings.maxSpend).toFixed(0)} overspend`);
    pauseCampaigns(campaigns);
    sendEmail(settings.notify,campaignNames,totalCost,settings.maxSpend,startDate+' - '+endDate);
  }
  else {
    console.log(`\nTotal spend ${totalCost.toFixed(0)}. Max is ${settings.maxSpend}, so still have ${(settings.maxSpend-totalCost).toFixed(0)} left`);
  }
}
function pauseCampaigns(campaigns) {
  const bulkUpload = AdsApp.bulkUploads().newCsvUpload([
    'Action',
    'Customer id',
    'Campaign id',    
    'Campaign',
    'Campaign status'
  ]);
  for (i=0;i<campaigns.length;i++) {
    bulkUpload.append({
      'Action':'edit',
      'Customer id':campaigns[i][0],
      'Campaign id':campaigns[i][1],
      'Campaign':campaigns[i][2],
      'Campaign status':'paused'  
    })
  }
  bulkUpload.setFileName(`Spend limit reached: Pause ${campaigns.length} campaign(s)`);
  bulkUpload.apply(); // change to .preview() to review changes in the bulk uploads section before applying
  console.log(`Spend limit reached: ${campaigns.length} campaign(s) paused. See details in bulk upload log`);
}
function sendEmail(recipients,campaigns,totalCost,maxSpend,dates) {
  const accountName = AdsApp.currentAccount().getName();
  for (const [name,email] of Object.entries(recipients))
    MailApp.sendEmail(
      email,`The spend limit of ${maxSpend} has been reached and ${campaigns.length} campaign(s) have been paused`,
`Hi ${name},\n\nThe spend limit of ${maxSpend} in the "${accountName}" Google Ads account has been reached. Total spend for the period ${dates} reached ${totalCost.toFixed(0)}.
\nThe campaign(s) listed below have now been paused:
\n"${campaigns.join('"\n"')}"`
  );
}


Sigurd

Andrew Rozynski

unread,
Oct 2, 2023, 5:37:20 PM10/2/23
to Google Ads Scripts Forum
Thank you both for the solutions!

Google Ads Scripts Forum Advisor

unread,
Oct 3, 2023, 4:20:43 PM10/3/23
to adwords...@googlegroups.com
Hi,

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

The solution provided by @Nils and @Sigurd Fabrin are correct.  Please let us know if you run into any issues with this solution.

Please reach out to us if you have any queries related to the Google Ads Scripts.

 
This message is in relation to case "ref:_00D1U1174p._5004Q2p33cE:ref"

Thanks,
 
Google Logo Google Ads Scripts Team


Reply all
Reply to author
Forward
0 new messages