Skip to content

Instantly share code, notes, and snippets.

@siliconvallaeys
Last active January 14, 2020 03:19
Show Gist options
  • Save siliconvallaeys/461dd2fc26c5f57d5b17836bc81613be to your computer and use it in GitHub Desktop.
Save siliconvallaeys/461dd2fc26c5f57d5b17836bc81613be to your computer and use it in GitHub Desktop.
AdWords Budgets By ZIP Code for Franchises
// Limit Monthly Cost By Postal Codes in a Campaign
//
// Copyright 2017 - Optmyzr Inc - All Rights Reserved
// Visit www.optmyzr.com for more AdWords Scripts and PPC Management Tools and Reports
//
//
// Purpose of the script:
// ---------------------
// To allow you to set a broad location target to capture more traffic in a regionwhile at the same time
// letting you limit the monthly cost for locations within the target region.
// When a target budget is exceeded, the location's bid adjustment is set to -90%.
// -90% modifiers for locations included in this script's settings are reset to 0% bid modifier the next month.
//
// Example Use Case:
// -----------------
// Run a campaign for multiple franchise locations in one city but limit the maximum cost for each zip code
// to ensure a more fair distribution of ad budget for the franchisees.
//
//
// 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.
// ---------------------
// UPDATE THESE SETTINGS
// ---------------------
// Change this to the name of the campaign you'd like to manage
// To manage multiple campaigns, create multiple versions of this script or contact support@optmyzr.com
CAMPAIGN_NAME_IS = "Optimization- New"; //The name of the campaign to manage. This is case sensitive
// Change this to a list of postal codes with a maximum budget for the month.
// These locations should be inside a targeted region but they don't have to be specifically added as targets.
// For example, if you target New York City, you do not have to specifically target zip code 10001 as this falls inside NYC.
// If you do NOT have the postal code as a specific target in the campaign, you will need to add its corresponding Google
// location targeting ID for the value of adWordsID. You can find the values for adWordsId here: https://goo.gl/2BXevL
// example: {"postalCode": "98040", "budget" : 100, "adWordsId" : "9033282"}
LOCATION_BUDGET_TARGETS = [
{"postalCode": "98040", "budget" : 100, "adWordsId" : "9033282"},
{"postalCode" : "94022", "budget" : 100, "adWordsId" : "9031912"},
{"postalCode" : "75044", "budget" : 100, "adWordsId" : "9026815"}
];
function main() {
// Go through the list of budgets set up in the script
Logger.log("These are the budgets you've specified in the settings for this script.");
Logger.log("LOCATION\t BUDGET");
var locationsWithBudgets = new Array();
var locationsWithAdWordsId = new Array();
for (var i = 0; i < LOCATION_BUDGET_TARGETS.length; i++) {
var budgetLine = LOCATION_BUDGET_TARGETS[i];
var location = budgetLine.postalCode;
var budgetAmount = budgetLine.budget;
var adWordsLocationId = budgetLine.adWordsId;
Logger.log(location + "\t\t " + budgetAmount);
locationsWithBudgets[location] = budgetAmount;
locationsWithAdWordsId[location] = adWordsLocationId;
}
Logger.log("");
if(CAMPAIGN_NAME_IS.indexOf("'") != -1) {
var needle = '"' + CAMPAIGN_NAME_IS + '"';
} else {
var needle = "'" + CAMPAIGN_NAME_IS + "'";
}
// Not sure what locations your ad is showing in? Uncomment the following line of code to see your spend by location in a spreadsheet
// exportLocationsToSheet();
evaluateLocationCosts(locationsWithBudgets, locationsWithAdWordsId, needle);
}
function getTargetedLocations(campaignName, locationsWithBudgets) {
var locationIds = new Array();
var campaignIterator = AdWordsApp.campaigns()
.withCondition('Name = ' + campaignName)
.get();
if (campaignIterator.hasNext()) {
var campaign = campaignIterator.next();
var locationIterator = campaign.targeting().targetedLocations().get();
while (locationIterator.hasNext()) {
var targetedLocation = locationIterator.next();
var targetId = targetedLocation.getId();
var entityType = targetedLocation.getEntityType();
var locationName = targetedLocation.getName();
if(locationsWithBudgets[locationName]) {
//Logger.log("this location has a budget");
locationIds[locationName] = targetId;
} else {
//Logger.log("this targeted location doesn't have a budget in this script");
}
/*Logger.log('Location name: ' +
targetedLocation.getName() + ', country code: ' +
targetedLocation.getCountryCode() + ', bid modifier: ' +
targetedLocation.getBidModifier() + " id: " + targetId + " entityType: " + entityType);
*/
}
}
return locationIds;
}
function exportLocationsToSheet() {
var spreadsheet = SpreadsheetApp.create('GEO_PERFORMANCE_REPORT');
var report = AdWordsApp.report(
'SELECT CampaignName, Clicks, Impressions, Cost, MostSpecificCriteriaId, CountryCriteriaId, IsTargetingLocation ' +
'FROM GEO_PERFORMANCE_REPORT ' +
'WHERE Impressions > 1 ' +
'AND CampaignName = "' + CAMPAIGN_NAME_IS + '" ' +
'DURING THIS_MONTH');
report.exportToSheet(spreadsheet.getActiveSheet());
Logger.log("Locations where your ad is running: " + spreadsheet.getUrl() + "\n");
}
function evaluateLocationCosts(locationsWithBudgets, locationsWithAdWordsId, campaignName) {
var locationIds = getTargetedLocations(campaignName, locationsWithBudgets);
var campaignIterator = AdWordsApp.campaigns()
.withCondition('Name = ' + campaignName)
.get();
if (campaignIterator.hasNext()) {
var campaign = campaignIterator.next();
}
Logger.log("Evaluating costs for locations with a budget cap...");
var report = AdWordsApp.report(
'SELECT CampaignName, Clicks, Impressions, Cost, MostSpecificCriteriaId, CountryCriteriaId, RegionCriteriaId, MetroCriteriaId, CityCriteriaId ' +
'FROM GEO_PERFORMANCE_REPORT ' +
'WHERE Impressions > 1 ' +
'AND CampaignName = "' + CAMPAIGN_NAME_IS + '" ' +
'DURING THIS_MONTH');
var rows = report.rows();
while(rows.hasNext()) {
var row = rows.next();
var mostSpecific = row['MostSpecificCriteriaId'];
var cost = row['Cost'];
if(locationsWithBudgets[mostSpecific] > 0) {
if(cost < locationsWithBudgets[mostSpecific]) {
Logger.log(mostSpecific + ": $" + cost + " does NOT exceed budget.");
var locationId = locationIds[mostSpecific];
if(locationId) {
//Logger.log("id: " + locationId);
var ids = [locationId];
// Update an existing location target
var locationTargetIter = campaign.targeting().targetedLocations().withIds(ids).get();
if(locationTargetIter.hasNext()) {
var locationTarget = locationTargetIter.next();
var bidModifier = locationTarget.getBidModifier();
if(bidModifier == 0.1) {
locationTarget.setBidModifier(1);
Logger.log(" Bid modifier removed");
} else {
Logger.log(" Bid modifier exists but is not -90% so leaving as-is");
}
}
}
} else {
Logger.log(mostSpecific + ": $" + cost + " EXCEEDS budget.");
var locationId = locationIds[mostSpecific];
if(locationId) {
//Logger.log("id: " + locationId);
var ids = [locationId];
// Update an existing location target
var locationTargetIter = campaign.targeting().targetedLocations().withIds(ids).get();
if(locationTargetIter.hasNext()) {
var locationTarget = locationTargetIter.next();
locationTarget.setBidModifier(0.1);
Logger.log(" Bid modifier set to -90%");
}
} else {
// Create a new location target
var locationId = parseInt(locationsWithAdWordsId[mostSpecific]);
//Logger.log("user provided location ID: " + locationId);
campaign.addLocation({
id: locationId,
bidModifier: 0.1,
});
Logger.log(" Location target added and bid modifier set to -90%");
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment