Automating Google Ads Management with Google Apps Script
Introduction:
In the realm of online advertising, effective campaign management is crucial for success. Google Ads provides a powerful platform for advertisers, and with the help of Google Apps Script, you can streamline and automate various aspects of your advertising campaigns. In this blog post, we’ll walk through the process of setting up and using a Google Apps Script tailored for Google Ads.
Setting Up Google Apps Script for Google Ads:
- Access Google Apps Script:
- Open Google Apps Script by visiting script.google.com.
- Create a new project to get started.
2.Enable Google Ads API:
- In the Google Apps Script project, go to Resources > Advanced Google Services.
- Enable the Google Ads API.
3. Authorizing the Script:
- Authorize the script to access your Google Ads account by running a function in the script that requires authorization.
- Follow the prompts to grant the necessary permissions.
4. Adding Google Ads Library:
- In the Google Apps Script project, go to Resources > Libraries.
- Add the Google Ads API library using the key.
Exploring the Google Ads Script
Now that the setup is complete, let’s delve into the different components of the provided Google Ads Script.
Part 1: Retrieving Campaign Data
Function: get_data_from_spreadsheet:
/**
* Retrieves campaign data from a specified Google Sheet.
* Extracts relevant information such as campaign name, type, start and end dates, and budget.
* Assumes the data is organized in columns with the following structure:
* | Campaign Name | Campaign Type | Start Date | End Date | Budget |
* |---------------|---------------|------------|------------|----------|
* | Example_Camp1 | Search | YYYYMMDD | YYYYMMDD | 100.0 |
* | Example_Camp2 | Display | YYYYMMDD | YYYYMMDD | 200.0 |
* @returns {Object} An object containing campaign data indexed by campaign name.
*/
function get_data_from_spreadsheet() {
var data = {};
var ss = SpreadsheetApp.openByUrl(spreadsheet_url);
var range = ss.getSheetByName(sheet_name).getRange('A:E');
var headers = range.getValues()[0];
for (var i = 1; i < range.getNumRows(); i++) {
if (range.getCell(i, 1).getValue() !== "") {
var campaign_name = range.getCell(i, 1).getValue();
var start_date = date_formater(add_day(range.getCell(i, 3).getValue()));
var end_date = date_formater(add_day(range.getCell(i, 4).getValue()));
var budget = range.getCell(i, 5).getValue();
data[campaign_name] = {
campaign_name: campaign_name,
campaign_type: range.getCell(i, 2).getValue(),
start_date: start_date,
end_date: end_date,
budget: budget
};
}
}
return data;
}- This function retrieves campaign data from a specified Google Sheet.
- It extracts relevant information such as campaign name, type, start and end dates, and budget.
Part 2: Monitoring Daily Spend
Function: check_yesterday_spend:
function check_yesterday_spend(campaign_list) {
var campaigns_not_spending = [];
for (var campaign_name in campaign_list) {
var yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
yesterday = date_formater(yesterday);
var yesterday_spend = check_campaign_spend(campaign_name, yesterday, yesterday);
var daily_budget = get_campaign_daily_budget(campaign_name);
if (yesterday_spend > 0) {
update_spend_column(campaign_name, yesterday_spend);
}
if (yesterday_spend < 0.7 * daily_budget) {
campaigns_not_spending.push(campaign_name);
}
}
if (campaigns_not_spending.length > 0 && (hour > 7 && hour < 9)) {
var msg = "The following campaign(s) spent yesterday less than " + percentage_alert * 100 + "% of daily budget:<br/>" + campaigns_not_spending.toString().split(",").join("<br/>");
sendEmailWithGmailAPI(notification_mail, "Google Ads Script Alert", msg);
}
}- Checks the previous day’s spend for each campaign.
- If the spend is below a specified percentage of the daily budget, an email alert is triggered.
- Updates the Google Sheet with the spend information.
Part 3: Total Spend and Budget Management
Function: check_total_spend:
function check_total_spend(campaign_list) {
for (var campaign_name in campaign_list) {
var today = new Date();
today = date_formater(today);
var start_date = campaign_list[campaign_name].start_date;
var budget = campaign_list[campaign_name].budget;
var total_spend = check_campaign_spend(campaign_name, start_date, today);
if (total_spend > budget || today > campaign_list[campaign_name].end_date) {
pause_campaign(campaign_name);
}
if (total_spend <= budget && today <= campaign_list[campaign_name].end_date) {
if (is_campaign_paused(campaign_name)) {
enable_campaign(campaign_name);
}
}
}
}- Monitors the total spend for each campaign.
- Pauses campaigns that exceed their budget or reach the end date.
- If the campaign is paused, an email alert is triggered.
Function: calculate_daily_budget:
/**
* Calculates and sets the daily budget for each campaign based on remaining budget and days left.
* @param {Object} campaign_list - An object containing campaign data indexed by campaign name.
*/
function calculate_daily_budget(campaign_list) {
for (var campaign_name in campaign_list) {
var yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
yesterday = date_formater(yesterday);
var today = new Date();
today = date_formater(today);
var start_date = campaign_list[campaign_name].start_date;
var end_date = campaign_list[campaign_name].end_date;
var budget = campaign_list[campaign_name].budget;
var total_spend_until_yesterday = check_campaign_spend(campaign_name, start_date, yesterday);
var days_left = date_diff(end_date, yesterday);
var daily_budget = Math.floor((budget - total_spend_until_yesterday) * 10 / (days_left)) / 10;
set_daily_budget(campaign_name, daily_budget);
}
}- Calculates and sets the daily budget for each campaign based on remaining budget and days left.
Part 4: Campaign State Management
Functions: enable_campaign and is_campaign_paused:
function enable_campaign(name) {
const campaignIterator = AdsApp.campaigns().withCondition(`Name = "${name}"`).get();
if (campaignIterator.hasNext()) {
const campaign = campaignIterator.next();
campaign.enable();
} else {
throw new Error(`No campaign named "${name}" found`);
}
}
function is_campaign_paused(campaign_name) {
var campaigns = AdsApp.campaigns().withCondition('Name = "' + campaign_name + '"').get();
if (campaigns.hasNext()) {
var cmp = campaigns.next();
return cmp.isPaused();
} else {
return false;
}
}enable_campaignactivates a paused campaign.is_campaign_pausedchecks if a campaign is currently paused.
Function: pause_campaign:
function pause_campaign(name) {
const campaignIterator = AdsApp.campaigns().withCondition(`campaign.name = "${name}"`).get();
if (campaignIterator.hasNext()) {
const campaign = campaignIterator.next();
campaign.pause();
} else {
throw new Error(`No campaign named "${name}" found`);
}
}- Pauses a campaign if certain conditions are met.
Part 5: Date and Budget Helper Functions
Functions: date_formater, add_day, date_diff:
function date_formater(full_date) {
var the_date = new Date(full_date);
var year = (the_date.getFullYear()).toString();
var month = (the_date.getMonth() + 1).toString();
if (month < 10) { month = "0" + month; }
var day = (the_date.getDate()).toString();
if (day < 10) { day = "0" + day; }
return (year + month + day);
}
function add_day(date) {
var new_date = new Date(date);
new_date.setDate(new_date.getDate() + 1);
return new_date;
}
function date_diff(later_date, early_date) {
later_date = new Date([later_date.slice(0, 4), "-", later_date.slice(4, 6), "-", later_date.slice(6, 8)].join(''));
early_date = new Date([early_date.slice(0, 4), "-", early_date.slice(4, 6), "-", early_date.slice(6, 8)].join(''));
var one_day = 1000 * 60 * 60 * 24;
var result = Math.round(later_date - early_date) / (one_day);
return result.toFixed(0);
}- These functions assist in formatting dates, adding days to a date, and calculating the difference in days between two dates.
Part 6: Checking and Pausing Unlisted Campaigns
Function: check_and_pause_unlisted_campaigns:
function check_and_pause_unlisted_campaigns(spreadsheetCampaigns) {
if (!Array.isArray(spreadsheetCampaigns)) {
Logger.log("Error: spreadsheetCampaigns is not an array");
return false;
}
var unlistedCampaigns = [];
for (var campaignIterator of [AdsApp.campaigns().withCondition("Status = ENABLED").get()]) {
while (campaignIterator.hasNext()) {
var campaign = campaignIterator.next();
var campaignName = campaign.getName();
if (spreadsheetCampaigns.indexOf(campaignName) === -1) {
pause_campaign(campaignName);
unlistedCampaigns.push(campaignName);
}
}
}
if (unlistedCampaigns.length > 0 && (hour > 7 && hour < 9)) {
var msg = "The following campaign(s) are not listed in the spreadsheet and have been paused:<br/>" + unlistedCampaigns.join("<br/>");
MailApp.sendEmail({ to: notification_mail, subject: "Google Ads Script Alert", htmlBody: msg });
}
return unlistedCampaigns.length > 0;
}- Checks for campaigns not listed in the provided spreadsheet.
- Pauses unlisted campaigns and sends an email alert.
Conclusion
By leveraging the power of Google Apps Script, this automation script enhances the management of Google Ads campaigns. From monitoring daily spend to dynamically adjusting budgets, this script offers a comprehensive solution for advertisers looking to optimize their campaigns efficiently. Feel free to customize and adapt the script to fit your specific advertising needs.
Get Affan Ahmed Usmani’s stories in your inbox
Join Medium for free to get updates from this writer.
Happy automating!
Practicle Implementation of the code at the link below :







