From a top SEO firm to end-to-end performance marketing solutions
rebranding logo

AdWords budget keeper script stops you from exceeding your budget

Every PPC specialist, who actively manages ad campaigns with strict budget limits knows that it can be a struggle to stay within the budget.

Spend it all, first just Facebook, now also Google!

Changes in Google Ads (AdWords) in late 2017 aggravate this risk further: as of November 2017 Google AdWords will be allowed to spend up to twice the specified daily budget on any given day of the month, while still promising to not spend more than 30.4 times the specified daily budget over the entire month.

There is no point contemplating the reasons for these changes and if they are right or wrong. Just like Facebook has already been doing for a long time, Google simply wants to have advertisers spend as much money as they are willing to within their set budgets. The 500 € gap of missed advertising spend is exactly what Google is focusing on, as its goal is to maximize ad spend for all advertisers and as a result grow their own revenues. In comparison, Facebook has already for a long time had a system in place that would spend your budget to the last cent, even if you only had 50 cents left and the average cost per click was 2 €.

In the past in Google AdWords it happened frequently that a campaign with a daily budget set to say 100 € achieved a monthly spend of only 2,500 € due to some lower performing days, on which the daily budgets were not fully exhausted.

No more worrying about exceeding the budget with our Google Ads – AdWords Budget Monitoring script

In order to keep our clients’ budgets under control, we have developed a script at Pizza SEO that sends an e-mail notification in case a campaign spends the AdWords budget:

  • too quickly,
  • too slowly or
  • is not running at all.

You can customize the script to your specific needs. It is controlled from a Google Spreadsheet and sends tables with the data to users by e-mail.

If necessary, you can add a different e-mail to each separate AdWords account. This is highly beneficial in case you are dealing with a MCC account that contains various client accounts which are being operated by different PPC specialists in a Google ads management agency.

How does this AdWords monitoring script work?

This AdWords script checks all accounts that are listed within the Google spreadsheet by their account ID.

Based on the the number of impressions, it evaluates whether the campaign is active on any given day.

Based on the consumption of the campaign credit within the given month, the script evaluates how much credit the campaign should spend until the end of the month by contrasting the numbers with actual visitor numbers in the table.

In case a campaign in one one of the accounts spends less than proportional share of budget (underspends) or too much (overspends), the script will send out a notification e-mail.

Step by step instructions

  1. Make a copy of the spreadsheet.
  2. Fill in the AdWords ID for the accounts you wish to keep track off as well as the specified Monthly budget. The name of the account can be added but is not required. If you already have these datapoints in another table, you can simply import them to the spreadsheet with the help of Google Spreadsheet’s IMPORTRANGE function (see instructions).
  3. In the columns Overspending % & Underspending % you can specify the limit of when you wish to be notified. If you do not wish to get notifications in some instances, for example when the campaign is spending less than the allocated budget, then you can simply add the word “NO” to the relevant field within the spreadsheet. In the Email column you will add all e-mail addresses that you wish to send notifications to.

    An example of a filled-in table

  4. Copy the script and put it on your MCC account (manager account).
  5. Instead of SHEET_URL insert the URL of the spreadsheet you have created in the prior step into the script code.
  6. The script will now check the first 100 rows of the table. If you have more than 100 accounts you wish to keep track off, please change the section in the script “A1:G:100” to “A1:G300” for example.
  7.  We recommend to set the script schedule to daily in the morning hours.
  8. The running of the script results in a table such as the one you can see below:

    An example table of results

Show script code

Author: Nina Varhaníková

* Running and budget control - Google Adwords                                                                                     *
* The script will send an email notifaction if the adspend is below, above budget, or if the campaign is not running at all.      *
* Set the script to run once a day or as needed                                                                                   *
* Created by:  Nina Varhanikova                                                                                                   *
* Company: Pizza SEO                                                                                                               *

// Place URL of the spreadsheet template inside the brackets
var ss_config = SpreadsheetApp.openByUrl('SHEET_URL');

function main() {

function ALERT()
 //Find out current day and the number of days in the month
 var now = new Date();
 var day = now.getDate();
 var month = now.getMonth();
 var year= now.getFullYear();
 var nr_days_month= new Date(year, month+1, 0).getDate();
 //Choose data from a sheet
 var sheet = ss_config.getSheetByName("Budget");
 //Data range
 var sheet_range = sheet.getRange("A1:G100").getValues();
 //Choose e-mails
 var emails= [];
 emails[0] = sheet_range[1][6];
 for (var y = 1; y < sheet_range.length; y++)
   var recorded_email= "false";
   for (var z = 0; z < emails.length; z++)
     if (emails[z]==sheet_range[y][6])
       var recorded_email= "true";
   if(recorded_email == "false" && sheet_range[y][6] != "")
 //Choose account by e-mail
 for(var x = 0; x < emails.length; x++)
   var check_email_content= "false";
   if(emails[x] != "")
     var email_content = '<html><head><style>table, th, td {border: 1px solid black; border-collapse: collapse;} th, td {padding: 5px;text-align: left;}</style></head><body><table style="width:40%"><thead><tr><th>Client</th><th>Status</th><th>Underspending/Overspending</th></tr></thead>';

     //Choose account ID
     var select_account= MccApp.accounts().get();
     while (select_account.hasNext())
       var account =;  ;
       //Compare account ID with ID in sheet
       var accountID= account.getCustomerId();
       var email_name= "ALERT - Running and budget control";
       email_content = email_content + '<tbody>';
       for(var i = 0; i < sheet_range.length; i++)
         if(sheet_range[i][6] == emails[x])
           if(sheet_range[i][0] == accountID)
             var account_name = AdWordsApp.currentAccount().getName();
             //Account statistics today
             var statistics_today= account.getStatsFor("TODAY");
             var impressions_today= statistics_today.getImpressions();
             //Account statistics current month
             var statistics_month= account.getStatsFor("THIS_MONTH");
             var cost= statistics_month.getCost();
             //Monthly cost estimation
             var overspending= cost+ ((cost/day)*(nr_days_month-day));        
             var budget = sheet_range[i][3];
             var overspending_percent= Math.round(100*(overspending-budget)/budget);
             var overspending_final= overspending_percent+ "%";
             //Choose accounts without impressions
             var campaign_status= "Campaign is running";
             if(impressions_today < 1)
               campaign_status= "Campaign is not running";
               check_email_content = "true";
               email_content = email_content + '<tr>';
               email_content = email_content + '<td>'+account_name+'</td>'+ '<td style="background-color:rgba(255, 200, 51, 0.5)">'+campaign_status+'</td>'+'<td>'+overspending_final+'</td>';
             //Choose budgets that do not meet the prespecified budgets
             if(sheet_range[i][4] != "NO" && campaign_status!= "Campaign is not running")
               var allowed_underspending= -sheet_range[i][4];
               if(overspending_percent <= allowed_underspending)
                 email_content = email_content + '<tr>';
                 email_content = email_content + '<td>'+account_name+'</td>'+ '<td>'+campaign_status+'</td>'+'<td style="background-color:rgba(0, 204, 102, 0.3)">'+overspending_final+'</td>';
                 check_email_content = "true";
             if(sheet_range[i][5] != "NO" && campaign_status!= "Campaign is not running")
               if(overspending_percent >= sheet_range[i][5])
                 email_content = email_content + '<tr>';
                 email_content = email_content + '<td>'+account_name+'</td>'+ '<td>'+campaign_status+'</td>'+'<td style="background-color:rgba(255, 0, 0, 0.3)">'+overspending_final+'</td>';
                 check_email_content = "true";
               email_content = email_content + '</tr>';
     email_content = email_content + '</tbody></table>';
     //Send e-mail
     if(check_email_content == "true")
       MailApp.sendEmail(emails[x], email_name, email_content,{'htmlBody':email_content});

If you encounter any problems with the script, or you have suggestions for further improvements, get in touch with me by email or comment below the post!