Ook als jij de dagbudgetten van je campagnes netjes hebt ingericht, kan het zo zijn dat Google Ads meer uitgeeft dan jij hebt bedoeld. Google heeft zichzelf namelijk de vrijheid gegeven om 2x zoveel uit te geven als het ingestelde dagbudget van een campagne. Hoewel de uitgaven per maand gemiddeld zullen worden, kan het natuurlijk zo zijn dat je dit graag strict in de hand hebt.
Dit script vergelijkt de daadwerkelijke uitgaven van een campagne met het ingestelde dagbudget. Wanneer er sprake is van een groot verschil van uitgaven ten opzichte van de dag ervoor, de week ervoor of de afgelopen maand, wordt dit weggeschreven in een Google sheet en ontvang je hiervan een mail. Zo ben je snel op de hoogte en kan je je budget beter beheren.
Happy scripting!
INSTRUCTIES VOOR INSTALLATIE:
Maak je geen zorgen als je dit nog nooit eerder hebt gedaan. Je hebt geen programmeervaardigheden nodig. Het is zo simpel als kopiëren en plakken. Volg deze instructies over hoe je Google Ads-scripts installeert.
SPREADSHEET_URL: Maak een nieuwe Google Sheet aan en voeg de URL hier toe.
EMAIL: Vul het e-mailadres in waar je de meldingen op wilt ontvangen.
CAMPAIGNLABEL: Geef campagnes die je niet wilt meenemen dit label mee.
firstRun: Wanneer je het script meerdere keren per dag draait, zet deze dan op 'false'.
dailySpendAlertThreshold: Geef aan wat de afwijking in uitgaven in vergelijking met de dag ervoor mag zijn, voor je een melding ontvangt.
weeklySpendAlertThreshold: Geef aan wat de afwijking in uitgaven in vergelijking met het gemiddelde van de week ervoor mag zijn, voor je een melding ontvangt.
fourWeeklySpendAlertThreshold: Geef aan wat de afwijking in uitgaven in vergelijking met het gemiddelde van de afgelopen maand mag zijn, voor je een melding ontvangt.
The script
// Copyright 2017, Nils Rooijmans, All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @overview:
* For each campaign that is NOT labeled 'noBudgetAlert' this script will compare the anticipated ad spend based on daily budget settings with the actual ad spend.
* In case of big differences (overdelivery by Google) it will report an alert, log the alert in the specified Google Sheet and inform about the alert via email
*
* For the MCC version please contact Nils Rooijmans [nils@nilsrooijmans.com]
*
* @author: Nils Rooijmans [nils@nilsrooijmans.com]
* @version: 1.0
*/
//
var SPREADSHEET_URL = "[REPLACE WITH YOUR SPREADSHEET URL]"; //insert a new blank spreadsheet url, replace everything between and including the square brackets
var EMAIL = "[REPLACE WITH YOUR EMAIL]"; //insert your email, replace everything between and including the square brackets
var CAMPAIGNLABEL = "noBudgetAlert"; //campaign level label for campaigns to ignore
var firstRun = true; // set to false if you schedule the script to run on daily basis, set to true for first run or if you run only once
// Config variables to set the percentage of overdelivery allowed before an alert is sent
var dailySpendAlertThreshold = 0.2; // alert if overdelivery is greater than 20% of daily budget
var weeklySpendAlertThreshold = 0.1; // alert if overdelivery is greater than 10% of 7 times the daily budget (for the 7 days before today)
var fourWeeklySpendAlertThreshold = 0.05; // alert if overdelivery is greater than 5% of 28 times the daily budget (for the 28 days before today)
function main() {
var accountAlert = false;
var campaignAlert_dailyCheck = false;
var campaignAlert_weeklyCheck = false;
var campaignAlert_fourWeeklyCheck = false;
var adSpendYesterday = 0;
var adSpend1to7DaysAgo = 0;
var adSpend1to28DaysAgo = 0;
var differenceDailyCheck = 0;
var differenceWeeklyCheck = 0;
var differenceFourWeeklyCheck = 0;
var d = Utilities.formatDate(new Date(), AdWordsApp.currentAccount().getTimeZone(), "MMM dd,yyyy");
var dayOfTheWeek = new Date(d).getDay();
var dayOfTheMonth = new Date(d).getDate();
//prepare the sheet
var ss = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
var sheet = ss.getActiveSheet();
if (sheet.getRange('A1').isBlank()) {
sheet.appendRow([
"Date",
"Account Name",
"Campaign Name",
"Ad Spend Yesterday",
"Anticipated Spend",
"Difference",
"Ad Spend 1 to 7 Days Ago",
"Anticipated Spend",
"Difference",
"Ad Spend 1 to 28 Days Ago",
"Anticipated Spend",
"Difference"
]);
}
// prepare contents of email
var html = [];
html.push(
"<html>",
"<body>",
"<p>Alerts are logged in sheet: ", SPREADSHEET_URL ,"</p>",
"<p>----------------------------------------------------</p>",
"<p>OVERDELIVERY ALERTS FOR:</P>",
"<P>ACCOUNT - CAMPAIGN</p>",
"<p>----------------------------------------------------</p>"
);
// if not already created, create label used to Ignore campaigns
// this is necessary for the script to run even if no campaign has been labeled
var labelName;
var labelExists = false;
var labelIterator = AdWordsApp.labels().get();
while (labelIterator.hasNext()) {
labelName = labelIterator.next().getName();
if (labelName.localeCompare(CAMPAIGNLABEL) == 0){labelExists = true; break;} else {labelExists = false}
}
if (labelExists == false) {
AdWordsApp.createLabel(CAMPAIGNLABEL);
Logger.log("labelCreated");
} else {
Logger.log("labelExists");
}
// Let's check the campaigns for overdelivery
Logger.log("Checking account: "+AdWordsApp.currentAccount().getName());
var campaignSelector = AdWordsApp.campaigns()
.withCondition("LabelNames CONTAINS_NONE ['" + CAMPAIGNLABEL + "']")
.withCondition("Status = ENABLED")
.forDateRange("YESTERDAY");
var campaignIterator = campaignSelector.get();
while (campaignIterator.hasNext()) {
var campaign = campaignIterator.next();
Logger.log(" Checking Campaign: "+campaign.getName());
var campaignAlert_dailyCheck = false;
var campaignAlert_weeklyCheck = false;
var campaignAlert_fourWeeklyCheck = false;
var anticipatedDailyAdSpend = campaign.getBudget().getAmount();
var anticipatedWeeklyAdSpend = 7 * anticipatedDailyAdSpend;
var anticipatedFourWeeklyAdSpend = 28 * anticipatedDailyAdSpend;
// daily check
//Logger.log("DAILY CHECK");
adSpendYesterday = campaign.getStatsFor("YESTERDAY").getCost();
differenceDailyCheck = (adSpendYesterday-anticipatedDailyAdSpend)/anticipatedDailyAdSpend;
if (differenceDailyCheck > dailySpendAlertThreshold ) {
campaignAlert_dailyCheck = true;
Logger.log("DAILY overdelivery spend alert");
}
// weekly check
if (dayOfTheWeek == 1 || firstRun){ // if not the firstRun this check runs only on mondays
//Logger.log("WEEKLY CHECK");
adSpend1to7DaysAgo = campaign.getStatsFor(dateBefore(7),dateBefore(1)).getCost();
differenceWeeklyCheck = (adSpend1to7DaysAgo-anticipatedWeeklyAdSpend)/anticipatedWeeklyAdSpend;
if (differenceWeeklyCheck > weeklySpendAlertThreshold ) {
campaignAlert_weeklyCheck = true;
Logger.log("WEEKLY overdelivery spend alert");
}
}
// 4 weekly check
if ((dayOfTheWeek == 1 && dayOfTheMonth < 8) || firstRun){ //if not the firstRun this check runs only on the first monday in a month //Logger.log("MONTHLY CHECK"); adSpend1to28DaysAgo = campaign.getStatsFor(dateBefore(28),dateBefore(1)).getCost(); differenceFourWeeklyCheck = (adSpend1to28DaysAgo-anticipatedFourWeeklyAdSpend)/anticipatedFourWeeklyAdSpend; if (differenceFourWeeklyCheck > fourWeeklySpendAlertThreshold) {
campaignAlert_fourWeeklyCheck = true;
Logger.log("4-WEEKLY overdelivery spend alert");
}
}
// add alerts to sheet
if (campaignAlert_dailyCheck||campaignAlert_weeklyCheck||campaignAlert_fourWeeklyCheck) {
accountAlert = true;
sheet.appendRow([
d,
AdWordsApp.currentAccount().getName(),
campaign.getName(),
adSpendYesterday,
anticipatedDailyAdSpend,
(differenceDailyCheck*100).toFixed(1)+"%",
adSpend1to7DaysAgo,
anticipatedWeeklyAdSpend,
(differenceWeeklyCheck*100).toFixed(1)+"%",
adSpend1to28DaysAgo, anticipatedFourWeeklyAdSpend,
(differenceFourWeeklyCheck*100).toFixed(1)+"%"
]);
Logger.log("ALERT ADDED TO SHEET");
if (campaignAlert_dailyCheck) sheet.getRange(sheet.getLastRow(), 6).setFontColor("red");
if (campaignAlert_weeklyCheck) sheet.getRange(sheet.getLastRow(), 9).setFontColor("red");
if (campaignAlert_fourWeeklyCheck) sheet.getRange(sheet.getLastRow(), 12).setFontColor("red");
html.push("<p>" + AdWordsApp.currentAccount().getName() + " | " + campaign.getName() + "</p>");
}
if (accountAlert) { // if there is any alert for any of the campaigns , send email
MailApp.sendEmail(EMAIL, "Overdelivery Alerts", "", {htmlBody: html.join("\n")});
}
}
function dateBefore(days){
var MILLIS_PER_DAY = 1000 * 60 * 60 * 24;
var now = new Date();
var dateBefore = new Date(now.getTime() - days * MILLIS_PER_DAY);
var timeZone = AdWordsApp.currentAccount().getTimeZone();
return Utilities.formatDate(dateBefore, timeZone, 'yyyyMMdd');
}
Show whole script!
Loading Comments
The Experts
Tibbe van AstenTeam Lead Performance Marketing
Nils RooijmansWater Cooler Topics
Martijn KraanFreelance PPC Specialist
Bas BaudoinTeamlead SEA @ Happy Leads
Jermaya LeijenDigital Marketing Strategist
Krzysztof BycinaPPC Specialist from Poland
How about you?JOIN US!
Caring
Adsscripts.com staat voor het delen van kennis. In de huidige markt houden SEA-specialisten de kennis en ervaring graag voor zich. Wij zijn er van overtuigd dat het delen van kennis ervoor kan zorgen dat iedereen beter wordt in haar of zijn werk. Daarom lopen wij hier graag in voorop, door onze kennis over scripts te delen met iedereen.
Wil jij ook graag een bijdrage leveren? Wij staan open voor nieuwe ideeën en feedback op alles wat je op Adsscripts.com vindt.