5 min read

How to prevent Google Ads Overspending

How to prevent Google Ads Overspending

Have you ever started work on a Monday morning and, when checking accounts over, realised you’d overspent? 


Have you ever wondered what the best solution to overspending on a Google Ads account could be?


Maybe you’ve considered setting rules in place to pause individual campaigns when they overspend or even decided to work over the weekend to make sure nothing goes wrong?


With this in mind, I have written a Google Ads overspend script, named the Hard Stop Script, which will allow you to stop worrying about a huge overspend over the weekend or bank holiday and have peace of mind that yours or your clients’ budgets aren’t being overshadowed by spend.



Firstly, let’s look at why and how Google Ads overspend:

Why does Google Ads overspend on a campaign?

Google Ads’ bidding algorithms and optimisations figure out which days of the month to adjust spend in order to gain more clicks and conversions, for example, when search volume spikes, or conversion rates are higher. This means that on some days you may spend above or below your daily campaign budget – as much as two times your average daily budget. Therefore, it is crucial to find ways to minimise the risk of potentially spending double your clients’ budget, and this is exactly what this Hard Stop Script is all about.


Introducing the Google Ads Hard Stop Script

Hard Stop will prevent any horror overspends, which can be critical to put in place generally, but more importantly, over a time away from an account, such as during a bank holiday weekend, or at a time of higher spend such as Black Friday.

Some accounts will be able to take advantage of monthly spend limits within their settings, however, this is only available to accounts that aren’t using the invoice billing method.

The script works best when run on an hourly basis, in order to be as strict as possible on budgets. It will read the current spend of the account for the month and compare it to the budget you can enter at the top of the script. If it exceeds the amount, it will iterate through all currently live campaigns, add the label ‘PAUSED BY HS’ (it will create this if you don’t have the label in your account already), and then pause all live campaigns. The script will then email you with a note on what’s just happened, and you can enter the email address (or email addresses) that you’d like to be notified at the top of the script. At the beginning of the next month, the script will take all campaigns which were paused and labelled, set them back live and remove the label.

See below for the script, feel free to copy and paste and upload onto your accounts. You need to just adjust the budget and email addresses, and you’re good to go.



// HARD STOP SCRIPT

// IF YOU’RE LOOKING TO PREVENT A MASSIVE OVERSPEND, ENTER YOUR MONTHLY BUDGET,

// AND THIS SCRIPT WILL PAUSE EVERYTHING IF YOU GO OVER. IT WILL THEN REENABLE

// THE CAMPAIGNS AND REMOVE THE LABEL ON THE FIRST DAY OF THE NEXT MONTH.

// Written By Aaron Digby, Honchō Search, 24/05/2022 \\

function main() {

// Enter Your Monthly Budget \\

var budget = 1000;

// Enter Your Preferred Email Address For The Emergency Email \\

var emailAddress = ‘example@example.com’;

// Enter Preferred Label Name

var campaignLabel = “PAUSED BY HS”;

// PULL SPEND FROM ACCOUNT

var query = “SELECT metrics.cost_micros, customer.id” +

” FROM customer” +

” WHERE segments.date DURING THIS_MONTH”;

var report = AdsApp.report(query);

var rows = report.rows();

if (rows.hasNext()) {

 

var row = rows.next();

var spend = (row[“metrics.cost_micros”] / 1000000).toFixed(2);

var account = row[“customer.id”];

 

if (spend > budget){

Logger.log(spend)

Logger.log(“OVER BUDGET – PAUSING ALL CAMPAIGNS”);

}

}

// FINDS IF ACCOUNT HAS LABEL, IF NOT, IT CREATES ONE

function labelMaker() {

try {

var labelSelector = AdsApp.labels();

var labelIterator = labelSelector.get();

var createCampaignLabel = true;

 

while (labelIterator.hasNext()) {

var label = labelIterator.next();

var labelName = label.getName();

 

if (labelName == campaignLabel) {

createCampaignLabel = false;

}

}

if (createCampaignLabel) {

AdsApp.createLabel(campaignLabel);

Logger.log(“Creating Campaign Label ‘” + campaignLabel + “‘.”)

}

} catch (e) {

Logger.log(

“Error Creating Label – Already Exists Within Account”

)

}

}

labelMaker();

/* CYCLES THROUGH SEARCH, DISPLAY, SHOPPING & VIDEO CAMPAIGNS AND

PAUSES THOSE WHICH ARE LIVE AND LABELS THEM */

if(spend > budget){

var campaignSelector = AdsApp

.campaigns()

.withCondition(“campaign.status = ENABLED”)

 

var campaignIterator = campaignSelector.get();

 

while (campaignIterator.hasNext()){

var campaign = campaignIterator.next();

Logger.log(campaign.getName())

 

campaign.applyLabel(campaignLabel);

campaign.pause();

}

var shoppingCampaignSelector = AdsApp

.shoppingCampaigns()

.withCondition(“campaign.status = ENABLED”)

 

var shoppingCampaignIterator = shoppingCampaignSelector.get();

while (shoppingCampaignIterator.hasNext()){

var shoppingCampaign = shoppingCampaignIterator.next();

Logger.log(shoppingCampaign.getName())

 

shoppingCampaign.applyLabel(campaignLabel);

shoppingCampaign.pause();

}

 

var videoCampaignSelector = AdsApp

.videoCampaigns()

.withCondition(“campaign.status = ENABLED”)

 

var videoCampaignIterator = videoCampaignSelector.get();

while (videoCampaignIterator.hasNext()){

var videoCampaign = videoCampaignIterator.next();

Logger.log(videoCampaign.getName())

 

videoCampaign.applyLabel(campaignLabel);

videoCampaign.pause();

}

}

/* ENABLES PREVIOUSLY PAUSED CAMPAIGNS AND REMOVES LABEL AT THE

START OF THE FOLLOWING MONTH */

var d = new Date();

d.toUTCString();

Logger.log(d.toUTCString())

Logger.log(d.getUTCDate())

Logger.log(d.getUTCHours())

Logger.log(“Now Enabling Campaigns Previously Paused By The HS Script”)

var labelSelector = AdsApp.labels()

.withCondition(“label.name = ‘” + campaignLabel + “‘”)

var labelIterator = labelSelector.get();

var labelID;

if (labelIterator.hasNext()) {

var label = labelIterator.next();

 

labelID = label.getId()

}

Logger.log(account)

Logger.log(labelID)

if (labelID != null){

var campaignSelector = AdsApp

.campaigns()

.withCondition(“campaign.status = PAUSED”)

.withCondition(“campaign.labels CONTAINS ALL (‘customers/” + account + “/labels/” + labelID + “‘)”)

 

var campaignIterator = campaignSelector.get();

 

while (campaignIterator.hasNext()){

var campaign = campaignIterator.next();

Logger.log(campaign.getName())

 

var utcDate = d.getUTCDate();

var utcHours = d.getUTCHours();

 

if(utcDate == 1 && utcHours == 1) {

 

campaign.enable();

campaign.removeLabel(campaignLabel);

}

}

 

 

var shoppingCampaignSelector = AdsApp

.shoppingCampaigns()

.withCondition(“campaign.status = PAUSED”)

.withCondition(“campaign.labels CONTAINS ALL (‘customers/” + account + “/labels/” + labelID + “‘)”)

 

var shoppingCampaignIterator = shoppingCampaignSelector.get();

 

while (shoppingCampaignIterator.hasNext()){

var shoppingCampaign = shoppingCampaignIterator.next();

Logger.log(shoppingCampaign.getName())

 

var utcDate = d.getUTCDate();

var utcHours = d.getUTCHours();

 

if(utcDate == 1 && utcHours == 1) {

 

shoppingCampaign.enable();

shoppingCampaign.removeLabel(campaignLabel);

}

 

}

 

var videoCampaignSelector = AdsApp

.videoCampaigns()

.withCondition(“campaign.status = PAUSED”)

.withCondition(“campaign.labels CONTAINS ALL (‘customers/” + account + “/labels/” + labelID + “‘)”)

 

var videoCampaignIterator = videoCampaignSelector.get();

 

while (videoCampaignIterator.hasNext()){

var videoCampaign = videoCampaignIterator.next();

Logger.log(videoCampaign.getName())

 

var utcDate = d.getUTCDate();

var utcHours = d.getUTCHours();

 

if(utcDate == 1 && utcHours == 1) {

 

videoCampaign.enable();

videoCampaign.removeLabel(campaignLabel);

}

 

}

}

// COMPOSE AND SEND ALERT EMAIL \\

var accountName = AdsApp.currentAccount().getName()

var subject = ‘URGENT BUDGET OVERSPEND EMAIL FOR ‘ + accountName.toUpperCase();

var message = ‘THE HARD STOP SCRIPT HAS PAUSED ALL CAMPAIGNS’;

if (spend > budget){

MailApp.sendEmail(

emailAddress,

subject,

message)

}

}


A couple of crucial points to note though:

  1. Due to the fact that Google’s API is not currently up to date, this will not work with Performance Max campaigns. The script will read the whole accounts spend, pause all other campaigns and send you an urgent email, but these will still run.
  2. When using a script for the first time, you will need to authorise it twice.
  3. When previewing the script, it will say it failed due to it not being able to find the label. This is standard, as the preview won’t actually have created the label, meaning when it iterates through your account labels, it won’t be there. But when it runs, it will create the label. 

I will update this script to include Performance Max once Google Ads updates their API.

Hope you find this useful, and feel free to message me with any suggestions or improvements.



Google Ads FAQs

How often should you check your Google Ads campaign spend?

It depends. Daily checks can be extremely useful to make sure nothing goes wrong, but can be time consuming. Taking a quick glance every couple of days is best to utilise your time, however, when first uploading a new campaign or adjusting budgets, you may want to do this on a more regular basis.


How often will Google overspend on a campaign?

Google’s internal optimisation means that the daily budget that you assign to a campaign may be over or underspent each day, based on the days of the month when you’re most likely to get clicks and/or conversions. This means that your daily spend on a campaign can be up to two times your daily budget. This is crucial to note as many people assume that the daily budget is all that will be spent in a day.


How much should I spend on a Google Ads campaign?

It depends on the campaign. You can use keyword and performance planner within Google to predict the search volume and the average CPC to predict how much can be spent on a daily basis. Once your campaign has been running for a few days, you can use Impression Share lost to Budget, to figure out how many impressions you missed out on, due to lack of budget, and adjust your daily spend from there.


Aaron Digby, Paid Search Analyst

If you need support from Honcho’s Paid Media team, get in touch today

Explore Our Services

DIGITAL PR 

Earn authoritative links and drive brand awareness with Digital PR

PAID SEARCH

Deliver instant traffic and revenue through Paid Search and Shopping

SOCIAL ADS

Reach new audiences and retarget existing ones on social channels 

CONTENT

Attract and engage website visitors with a well executed content strategy

Latest Blog Posts

Honchō Scoops Up Two UK Search Awards!

3 min read

Honchō Scoops Up Two UK Search Awards!

It’s official, we've added not one, but two shiny trophies to our awards cabinet! We’re over the moon to share that we’ve triumphed at the UK Search...

Read More
The Best Ecommerce Attribution Models for Your Brand

5 min read

The Best Ecommerce Attribution Models for Your Brand

Understand ecommerce attribution models which attribution models can maximise your marketing efforts and ROI.

Read More
The Role of Social Commerce in Ecommerce

3 min read

The Role of Social Commerce in Ecommerce

Explore how social commerce is changing the way we shop online, blending social interactions with digital commerce for a seamless buying experience.

Read More