Google Ads Script to Receive High CPC Bid Alerts

“You’re spending tons of my money every month, you better be damned proficient at what you do. Failure is not an option!

Sounds familiar?

It’s a quote from a job interview conducted by a VP of Marketing. I was helping him out, recruiting an in-house PPC specialist earlier this year.
Yep. We’ve got a long way to go there. But that’s a different story (next to his style of management, failures are, of course, the only way to make the most out his ad spend).

His words did remind me though, of the importance of not completely f@#king up. Not making the mistakes that make us look like the incompetent idiot in the room.

Yet, that is just what I did. A couple of months ago. I f@#ked up.

Let’s say you live on a houseboat in Amsterdam and are leaving for a three week trip to the Italian Alpes to enjoy some pasta and the snow.

It’s winter.

Winters in Amsterdam can be windy, rainy and cold. So, obviously, before you leave the house there are the obvious things you check.

Got my keys? Check. Got my wallet? Check. Passport? Check. (Actually, don’t need that one. Thank you, Schengen Area.) Windows closed? Check. Lights off? Check.

Central heating turned down? Ah, not yet. Let me fix that just quickly.

So I did… Quickly.

I swiftly reprogrammed the system to keep the houseboat at a temperature of 16 degrees Celcius (60,8°F  that is).

Or at least, I thought I did.

In reality, I reprogrammed the damn thing to 26 degrees Celcius. That’s a one-digit mistake keeping the houseboat at a temperature of 78,8° F.
That’s three weeks, 24/7, having my heating system pumping gas to keep the rain and icy wind from the canals to lower my houseboat’s temperature below 26 degrees.

And since the Dutch government nearly doubled the tax on gas over the last few years, this had me running slightly over the budget for my trip.

>>> Fast forward to PPC Land.

The same sort of mistakes happen in many accounts I’ve audited, managed and outsourced in the past.
The most obvious one being is forgetting the dot in your manual CPC bid. Suddenly that bid on a top3 keyword increased from $1.65 to $19 instead of the intended $1.90. Suffice it to say this had some horrible impact on our KPI’s.

Google Ads - High CPC Bid Mistake
Google Ads – High CPC Bid Mistake

CPC bid errs are human. I’ve had them happen to me many times. I’ve seen them happen to others even more.
And I DO NOT want any of my clients or team members to catch me making this mistake EVER again!

So I thought: “Wouldn’t it be nice if I could get an alert if CPC bids raise above a certain level?”
Yep. That would be nice.

The next steps were easy. Here’s what I did:

  • Step 1: Determine CPC bid threshold
  • Step 2: Create a new Google sheet
  • Step 3: Decide upon an email address to receive email alerts
  • Step 4: Write a Google Ads script to monitor CPC bids of all enabled keywords.
    Let’s have the script report alerts in the Google sheet and send me an ALERT email if issues occur.
  • Step 5: Schedule the script to run hourly

No more surprises, no more CPC bid f#$kups.
You can have the same.

 

➥  ACTION: Block Facebook for the next ten minutes and install the script.

Peace of mind is your BONUS.
(Don’t worry if you have never run a script before. You do not need any coding skills. It is as simple as copy-paste.)

 

"Thanks to this script I receive near-immediate alerts to erroneous CPC changes so I can take quick action. This is a HUGE time saver that prevents a lot of manual pinpointing. My lack of knowledge in scripting almost prevented me from using this script, but fortunately, Nils was very helpful in fixing some error messages and I got things working in no time. This has shown me how useful scripts are. I'll definitely be looking for other ones that would apply to my accounts."

Mindy Noordhoff, Director of Search Marketing at Light Marketing

Nils Rooijmans
2020-05-21T10:03:27+00:00

Mindy Noordhoff, Director of Search Marketing at Light Marketing

"Thanks to this script I receive near-immediate alerts to erroneous CPC changes so I can take quick action. This is a HUGE time saver that prevents a lot of manual pinpointing. My lack of knowledge in scripting almost prevented me from using this script, but fortunately, Nils was very helpful in fixing some error messages and I got things working in no time. This has shown me how useful scripts are. I'll definitely be looking for other ones that would apply to my accounts."
0
0
Nils Rooijmans

 

Join thousands of PPC geeks who already have access:

(If the button above isn’t working for you, you can sign up here to get access.)

 

INSTRUCTIONS:

  1. See the script code below. Install the script in your account.
    Don’t worry if you have never done this before. You do not need any coding skills. It is as simple as copy-paste. Simply follow these instructions on how to set up and schedule Google Ads scripts.
  2. Create a new Google Sheet
    (tip for chrome users: simply type ‘sheets.new’ in the address bar)
  3. Add the complete URL of the spreadsheet  to the script (line 1)
  4. Add your email address to the script
  5. Set your CPC limit
  6. Preview
  7. Schedule to run hourly.

 

Subscribe to my mailing list to receive more scripts and updates on how to start learning to write your own Google Ads Scripts.

var SPREADSHEET_URL = "YOUR_SHEET_URL_GOES_HERE" ;  //insert a new blank spreadsheet url

var CAMPAIGNLABEL= ""; // use this to only monitor campaigns with specific label

var CPC_THRESHOLD = 5.00; // set your highest cpc limit

var EMAIL_ADDRESSES = "YOUR_EMAIL_ADDRESS_GOES_HERE"; //insert your email
var EMAIL_SUBJECT = "[ALERT] - Google Ads - HIGH CPC Bid Keyword(s)"
var EMAIL_BODY = ""; // add any text you would like to add to your email alerts
    
function main() {

  //prepare the Spreadsheet
  var ss = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
  var sheet = ss.getActiveSheet();
  sheet.clear(); //remove earlies alerts
  var header = [
    "Campaign Name", 
    "AdGroup Name",
    "Keyword ",
    "CPC Bid" 
  ];
 

  // create list of campaigns to check
  var campaignSelector = AdWordsApp.campaigns()
    .withCondition("Status = ENABLED");
  if (CAMPAIGNLABEL!="") {
    campaignSelector=campaignSelector
       .withCondition("LabelNames CONTAINS_ANY ['"+CAMPAIGNLABEL+"']");
  }
  var campaignIds=[];
  var campaignIterator = campaignSelector.get();
  while (campaignIterator.hasNext()) {
    var campaign = campaignIterator.next();
    
    // add campaigns with Manual bidding to list of campaigns to check
    var campaignBiddingStrategy = campaign.getBiddingStrategyType();
    if(campaignBiddingStrategy=='MANUAL_CPC') {
    	var campaignId = campaign.getId();
    	campaignIds.push(campaignId) ;      
    }
  }
  Logger.log(" Nr of campaign to check: "+campaignIds.length);
  

  // check for issues
  var issues = [];
  if (campaignIds.length > 0) {
    issues = checkKeywords(campaignIds);
  }

 
  // report issues 	
  var totalNrOfIssues = issues.length;  
  if (totalNrOfIssues > 0) { // there is at least one issue

    Logger.log("Total NR of Issues: "+totalNrOfIssues);
    
    var lastRow = sheet.getLastRow();

    // write issues to sheet
    var range = sheet.getRange(lastRow+1, 1, totalNrOfIssues, header.length);
    range.setValues(issues);
    sheet.sort(3, true); // sort by Keyword asc
    sheet.insertRows(1);
    range = sheet.getRange(1, 1, 1, header.length);
    range.setValues([header]);

    // send the email
    var emailBody = 
      "Number of issues: " + totalNrOfIssues + "\n" + 
      "See details: "+ SPREADSHEET_URL + "\n" + EMAIL_BODY;

    MailApp.sendEmail(EMAIL_ADDRESSES, EMAIL_SUBJECT, emailBody);
  }
} 



function checkKeywords(campaignIds) {
  
  var cpcThreshold = CPC_THRESHOLD * 1000000; // AWQL queries take Money micros values for CpcBid metrics;  20000 == 0.02 EUR
  var issues = [];
      
  var awq="SELECT CampaignName, AdGroupName, Criteria, Id, CpcBid FROM KEYWORDS_PERFORMANCE_REPORT WHERE CampaignId IN ["+campaignIds.join(",")+"] AND AdGroupStatus='ENABLED' AND Status='ENABLED' AND CpcBid > "+cpcThreshold ;  
  
  var rows=AdWordsApp.report(awq, {
       includeZeroImpressions: true,
       returnMoneyInMicros: false,
       }).rows() ;  
  
  while (rows.hasNext()) {
    var row = rows.next();
    var campaignName = row['CampaignName'].toString().trim();
    var adGroupName = row['AdGroupName'].toString().trim();
    var keyword = row['Criteria'].toString().trim();
    var keywordBid=row['CpcBid'].toString().trim() ;
    issues.push([campaignName, adGroupName, keyword, keywordBid]) ;
  }
  //Logger.log(issues.length+" issues");
  return issues;
}

 

Subscribe to my mailing list to receive more scripts and updates on how to start learning to write your own Google Ads Scripts.