AdWords daily budget is a safety measure implemented to ensure that you don't overspend your budget and ensure that your budget pacing is done well for the month, quarter or year.
However, sometimes you'll have campaigns that you would like to fully fund, such as your brand keywords.
Your competitors will sometimes bid on your keywords to drain your campaigns' daily budget before taking hold of the first position in the search result for YOUR brand term.
That's not an ideal situation. It would be great if our campaigns are fluid to changes, alerts us in case our key campaigns' budget is drained and makes the necessary changes to ensure it is fully funded.
Thankfully, AdWords has such a functionality that we can implement such functionality via AdWords Script.
First of all, as we'll be making live changes to your campaign, it's best to have a log sheet to record all the changes.
Head over to Google Drive and create a new spreadsheet. Give the new spreadsheet a name and name the worksheet as "Hourly Log".
Format the sheet as per the snapshot below. The colour is optional but please follow the arrangement of the cells.
Next, take down the sheet ID of your newly-created spreadsheet. You can get the sheet ID from the URL of the spreadsheet.
Once you have the ID, insert it into the sheetId variable in the code below.
var sheetId = "your_sheet_id";
var ss = SpreadsheetApp.openById(sheetId);
var worksheetName = 'Hourly Log'
var sheet = ss.getSheetByName(worksheetName);
You've now connected AdWords Script to your log sheet.
Please make sure that all the code (with the exception of the optional function at the end of this post) is in the function main(){ } portion of the AdWords Script.
The function to automatically increase budget should not be applied to all campaigns because:
This function should only apply to the 20% of your account that contribute 80% of the performance ala Pareto principle.
Hence, we'll scope the jurisdiction of this tool by applying a new label to it.
Head over to AdWords, select the campaigns you want to monitor and apply a brand new label to it.
With your brand new label applied to the relevant campaigns, copy the name of the label and insert into the following code in AdWords Script:
var label = "your_label_name"
var campaignSelector = AdWordsApp.campaigns().withCondition("LabelNames CONTAINS_ANY ['"+ label +"']").withCondition("Status = ENABLED").forDateRange("TODAY");
var campaignIterator = campaignSelector.get();
The campaignIterator object will be used to gather all your campaign data to be logged and analysed.
To loop through the campaignIterator object to obtain the data, we will use the while (campaignIterator.hasNext()) loop.
Following is the code to loop through the data and append/push into the four empty arrays:
var campaignIds = [];
var campaigns = [];
var budgets = [];
var spends = [];
while (campaignIterator.hasNext()) {
var campaign = campaignIterator.next();
campaignIds.push(campaign.getId());
campaigns.push(campaign.getName());
budgets.push(campaign.getBudget().getAmount());
spends.push(campaign.getStatsFor("TODAY").getCost());
}
The four arrays now house the campaign IDs, the campaign names, the campaign budgets and spends.
We'll now be pushing the data we've collected in the four arrays into the log sheet we've created earlier.
Before that, let's get the current time the sheet is running for logging purposes.
var timeNow = (new Date()).toLocaleString()
The time will be based on your account's time zone.
Next, we'll build a 2D array that has all the data we want to log and push it to the log sheet.
var pushToSheet = [[timeNow,'',''],["Campaign Name", "Budget", "Spend"]];
for (i in spends){
pushToSheet.push([campaigns[i], budgets[i], spends[i]]);
}
sheet.clearContents();
var range = sheet.getRange(1, 1, pushToSheet.length, 3);
range.setValues(pushToSheet);
If you run or preview the code as is (after some authorization), you will now see all the relevant campaigns' data in the Hourly Log sheet.
Now that the stage is set, we'll be analysing the spend data we've collected.
Before that, please define the budget increment (in %) that you want the tool to apply every time it found a campaign that has hit its budget cap.
var increaseBy = 50%
Do note that as this is a percentage, it will have a bigger effect on campaigns with larger budgets. So please put some thought into this.
Next, we'll do three things in the following code:
var overId = []
var overCampaign = [];
var newBudget = [['New Budget']];
for (i in spends){
if (spends[i] > budgets[i]){
overId.push(campaignIds[i]);
overCampaign.push(campaigns[i]);
newBudget.push([budgets[i]*(1 + increaseBy)]); // If it has reached budget cap, increase budget by the defined amount
} else {
newBudget.push(['unchanged']); // Else, update the log that the budget is unchanged
}
}
We'll now record this data into a new column in the log sheet (column D) and sort the data by campaign name so it's more readable.
var newRange = sheet.getRange(2, 4, newBudget.length, 1);
newRange.setValues(newBudget);
// Sorts the sheet so that it's more readable
var sortRange = sheet.getRange(3, 1, pushToSheet.length - 2, 4);
sortRange.sort(1);
If you run or preview the code up to here, you will now see a new column with the new budget after the increment declared earlier.
Here comes the scary part. We're going to allow AdWords Script to make live changes to your campaign.
If you merely want a log sheet and apply the changes manually, please stop here and run with the code you have up till now.
We'll be using the overId array we populated earlier, which has all the IDs of the campaigns that have hit their budget caps, to filter to the relevant campaign to implement the live changes.
Then, we'll again use a campaign iterator object to implement the changes in a while loop.
var overSelector = AdWordsApp.campaigns().withIds(overId);
var overIterator = overSelector.get();
while (overIterator.hasNext()) {
var overCampaignBudget = overIterator.next();
overCampaignBudget.getBudget().setAmount(overCampaignBudget.getBudget()*(1 + increaseBy)) // we increase the budget by the defined amount here
}
You've done it. With this code, you have created an automated method to increase your campaign budget to make sure your key campaigns are fully funded.
However, we still have one more step to go before we're done.
As your hourly log sheet updates every hour, it's best to keep an archive or a snapshot of the sheet when a live campaign change is implemented.
To do that, we'll make a copy of the Hourly Log sheet when the length of overCampaign object is more than 0 (i.e. there was a campaign that has exceeded the budget and we've made a change to it).
if (overCampaign.length > 0){
sheet.copyTo(ss);
var newSheet = ss.getSheetByName('Copy of ' + worksheetName);
newSheet.setName('[LOGSHEET ' + timeNow + ']' );
newSheet.setTabColor("cc0000");
} else {
return;
}
Every time a copy of a worksheet is made, the name of the copied sheet will be in the format "Copy of [original worksheet's name]".
Hence, we've leveraged that to rename it to "[LOGSHEET {current_time}]" and change the tab colour to red.
You're done! Now you have proper logging of the changes that the script has made to your campaign(s).
Apart from having a log sheet, it might be really useful if you and your team get alerted every time a change is made.
We can use the MailApp utility in AdWords Script to send an email to us. It will be sent via the AdWords account email that authorized the script.
First, we create the function to send the email. Please insert the following code outside of the function main() that houses all your codes thus far
function sendEmail(sheetId, mailingList, campaigns, time, worksheetId) {
MailApp.sendEmail({
to: mailingList,
subject: 'Your Campaign(s) Reached the Budget Cap ::: ' + time,
htmlBody: "The following campaigns have hit the budget as of today:<br><br>" + campaigns.toString() + "<br><br>Please refer to <a href='https://docs.google.com/spreadsheets/d/" + sheetId +"/edit#gid=" + worksheetId +"'>the log</a> for more details.",
});
}
Next, we need to call this function from the main code. We can add this code to call this function in the earlier code snippet for "Create an Archived Log Sheet" under the if (overCampaign.length > 0) conditional check:
mailingList = [hello@mydomain.com] // if more than one, split by commas in an array
sendEmail(sheetId, mailingList, overCampaign.join("<br>"), timeNow, newSheet.getSheetId().toString());
This code can be anywhere within the if statement, as its dependencies were already declared before the if statement.
You can format the email better than this. However, as you already have all the data you need in the archived log sheet, you can just direct people to the log sheet via the email using the archive log sheet's ID.
More info:
Like the post? Consider donating to fund the maintenance of this website: