Last active
January 14, 2020 03:19
-
-
Save siliconvallaeys/461dd2fc26c5f57d5b17836bc81613be to your computer and use it in GitHub Desktop.
AdWords Budgets By ZIP Code for Franchises
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 [email protected] | |
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