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