This guide describes location targeting, and how you can use the Google Ads API to add, retrieve, and update location targeting for your campaigns.
Why is geo targeting important?
Location targeting allows you to serve ads to users in a particular geographical region. For example, assume you're advertising for a chain of supermarkets. Without location targeting, your ads would show in all regions worldwide, and your ads might receive clicks from users in regions where you have no supermarket locations. This generates cost while providing no possibility of a return on the investment. With location targeting, your campaigns show ads only in regions where you have open supermarkets. This approach also allows you to directly target customers searching locally for supermarkets.
The Google Ads API allows you to target your ads by country, region, or proximity around a specific geographical point.
Learn more about Targeting ads to geographic locations.
Geo target campaigns for a region
You can target campaigns to any geographical region for which Google Ads
supports location targeting, for instance, a country, a state, a city, or a
postal region. Each targetable location is uniquely identified by a Criterion
ID. You can look up a criterion ID using
GeoTargetConstantService.SuggestGeoTargetConstants
.
The resource_name
of each GeoTargetConstant
is
of the form geoTargetConstants/{Criterion ID}
. For example, the
resource_name
value of New York state is geoTargetConstants/21167
.
You can add geo targets to your campaigns using the
CampaignCriterionService
. The following
code snippet shows how to target your campaign with a criterion ID.
Java
private static CampaignCriterion buildLocationIdCriterion( long locationId, String campaignResourceName) { Builder criterionBuilder = CampaignCriterion.newBuilder().setCampaign(StringValue.of(campaignResourceName)); criterionBuilder .getLocationBuilder() .setGeoTargetConstant( StringValue.of(GeoTargetConstantName.format(String.valueOf(locationId)))); return criterionBuilder.build(); }
C#
private CampaignCriterion buildLocationCriterion(long locationId, string campaignResourceName) { GeoTargetConstantName location = new GeoTargetConstantName(locationId.ToString()); return new CampaignCriterion() { Campaign = campaignResourceName, Location = new LocationInfo() { GeoTargetConstant = location.ToString() } }; }
PHP
private static function createLocationCampaignCriterionOperation( int $locationId, string $campaignResourceName ) { // Constructs a campaign criterion for the specified campaign ID using the specified // location ID. $campaignCriterion = new CampaignCriterion([ // Creates a location using the specified location ID. 'location' => new LocationInfo([ 'geo_target_constant' => new StringValue( // Besides using location ID, you can also search by location names using // GeoTargetConstantServiceClient::suggestGeoTargetConstants() and directly // apply GeoTargetConstant::$resourceName here. An example can be found // in GetGeoTargetConstantByNames.php. ['value' => ResourceNames::forGeoTargetConstant($locationId)] ) ]), 'campaign' => new StringValue(['value' => $campaignResourceName]) ]); return new CampaignCriterionOperation(['create' => $campaignCriterion]); }
Python
def create_location_op(client, customer_id, campaign_id, location_id): campaign_service = client.get_service('CampaignService', version='v2') geo_target_constant_service = client.get_service('GeoTargetConstantService', version='v2') # Create the campaign criterion. campaign_criterion_operation = client.get_type('CampaignCriterionOperation', version='v2') campaign_criterion = campaign_criterion_operation.create campaign_criterion.campaign.value = campaign_service.campaign_path( customer_id, campaign_id) # Besides using location_id, you can also search by location names from # GeoTargetConstantService.suggest_geo_target_constants() and directly # apply GeoTargetConstant.resource_name here. An example can be found # in get_geo_target_constant_by_names.py. campaign_criterion.location.geo_target_constant.value = ( geo_target_constant_service.geo_target_constant_path(location_id)) return campaign_criterion_operation
Ruby
def create_location(client, customer_id, campaign_id, location_id) client.operation.create_resource.campaign_criterion do |criterion| criterion.campaign = client.path.campaign(customer_id, campaign_id) criterion.location = client.resource.location_info do |li| # Besides using location_id, you can also search by location names from # GeoTargetConstantService.suggest_geo_target_constants() and directly # apply GeoTargetConstant.resource_name here. An example can be found # in get_geo_target_constant_by_names.rb. li.geo_target_constant = client.path.geo_target_constant(location_id) end end end
Google may occasionally phase out some location criteria for various reasons:
the location may be restructured into smaller or larger areas, geo-political
changes, etc. Refer to the status
field of a
GeoTargetConstant object to determine if a location is
ENABLED
or
REMOVAL_PLANNED
.
Read more about
how location targets are phased out.
Look up by location name
You can also look up the criterion ID by location name using
GeoTargetConstantService.SuggestGeoTargetConstants
.
The following code example shows how to look up a location criterion ID by
location name.
Java
private void runExample(GoogleAdsClient googleAdsClient) { GeoTargetConstantServiceClient geoTargetClient = googleAdsClient.getLatestVersion().createGeoTargetConstantServiceClient(); SuggestGeoTargetConstantsRequest.Builder requestBuilder = SuggestGeoTargetConstantsRequest.newBuilder(); // Locale is using ISO 639-1 format. If an invalid locale is given, 'en' is used by default. requestBuilder.setLocale(StringValue.of("en")); // A list of country codes can be referenced here: // https://developers.google.com/adwords/api/docs/appendix/geotargeting requestBuilder.setCountryCode(StringValue.of("FR")); requestBuilder .getLocationNamesBuilder() .addAllNames( Stream.of("Paris", "Quebec", "Spain", "Deutschland") .map(StringValue::of) .collect(Collectors.toList())); SuggestGeoTargetConstantsResponse response = geoTargetClient.suggestGeoTargetConstants(requestBuilder.build()); for (GeoTargetConstantSuggestion suggestion : response.getGeoTargetConstantSuggestionsList()) { System.out.printf( "%s (%s,%s,%s,%s) is found in locale (%s) with reach (%d) for search term (%s).%n", suggestion.getGeoTargetConstant().getResourceName(), suggestion.getGeoTargetConstant().getName().getValue(), suggestion.getGeoTargetConstant().getCountryCode().getValue(), suggestion.getGeoTargetConstant().getTargetType().getValue(), suggestion.getGeoTargetConstant().getStatus().name(), suggestion.getLocale().getValue(), suggestion.getReach().getValue(), suggestion.getSearchTerm().getValue()); } }
C#
public void Run(GoogleAdsClient client) { // Get the GeoTargetConstantServiceClient. GeoTargetConstantServiceClient geoService = client.GetService(Services.V2.GeoTargetConstantService); // Locale is using ISO 639-1 format. If an invalid locale is given, // 'en' is used by default. string locale = "en"; // A list of country codes can be referenced here: // https://developers.google.com/adwords/api/docs/appendix/geotargeting string countryCode = "FR"; String[] locations = { "Paris", "Quebec", "Spain", "Deutschland" }; SuggestGeoTargetConstantsRequest request = new SuggestGeoTargetConstantsRequest() { Locale = locale, CountryCode = countryCode, LocationNames = new SuggestGeoTargetConstantsRequest.Types.LocationNames() }; request.LocationNames.Names.AddRange(locations); try { SuggestGeoTargetConstantsResponse response = geoService.SuggestGeoTargetConstants(request); foreach (GeoTargetConstantSuggestion suggestion in response.GeoTargetConstantSuggestions) { Console.WriteLine( $"{suggestion.GeoTargetConstant.ResourceName} " + $"({suggestion.GeoTargetConstant.Name}, " + $"{suggestion.GeoTargetConstant.CountryCode}, " + $"{suggestion.GeoTargetConstant.TargetType}, " + $"{suggestion.GeoTargetConstant.Status}) is found in locale " + $"({suggestion.Locale}) with reach ({suggestion.Reach.Value}) " + $"for search term ({suggestion.SearchTerm})."); } } catch (GoogleAdsException e) { Console.WriteLine("Failure:"); Console.WriteLine($"Message: {e.Message}"); Console.WriteLine($"Failure: {e.Failure}"); Console.WriteLine($"Request ID: {e.RequestId}"); } }
PHP
public static function runExample( GoogleAdsClient $googleAdsClient, array $locationNames, string $locale, string $countryCode ) { $geoTargetConstantServiceClient = $googleAdsClient->getGeoTargetConstantServiceClient(); $names = []; foreach ($locationNames as $locationName) { $names[] = new StringValue(['value' => $locationName]); } $response = $geoTargetConstantServiceClient->suggestGeoTargetConstants( new StringValue(['value' => $locale]), new StringValue(['value' => $countryCode]), ['locationNames' => new LocationNames(['names' => $names])] ); // Iterates over all geo target constant suggestion objects and prints the requested field // values for each one. foreach ($response->getGeoTargetConstantSuggestions() as $geoTargetConstantSuggestion) { /** @var GeoTargetConstantSuggestion $geoTargetConstantSuggestion */ printf( "Found '%s' ('%s','%s','%s',%s) in locale '%s' with reach %d" . " for the search term '%s'.%s", $geoTargetConstantSuggestion->getGeoTargetConstant()->getResourceName(), $geoTargetConstantSuggestion->getGeoTargetConstant()->getNameUnwrapped(), $geoTargetConstantSuggestion->getGeoTargetConstant()->getCountryCodeUnwrapped(), $geoTargetConstantSuggestion->getGeoTargetConstant()->getTargetTypeUnwrapped(), GeoTargetConstantStatus::name( $geoTargetConstantSuggestion->getGeoTargetConstant()->getStatus() ), $geoTargetConstantSuggestion->getLocaleUnwrapped(), $geoTargetConstantSuggestion->getReachUnwrapped(), $geoTargetConstantSuggestion->getSearchTermUnwrapped(), PHP_EOL ); } }
Python
def main(client): gtc_service = client.get_service('GeoTargetConstantService', version='v2') location_names = ( client.get_type('SuggestGeoTargetConstantsRequest', version='v2').LocationNames()) for location in ['Paris', 'Quebec', 'Spain', 'Deutschland']: location_name = location_names.names.add() location_name.value = location # Locale is using ISO 639-1 format. If an invalid locale is given, # 'en' is used by default. locale = client.get_type('StringValue', version='v2') locale.value = 'en' # A list of country codes can be referenced here: # https://developers.google.com/adwords/api/docs/appendix/geotargeting country_code = client.get_type('StringValue', version='v2') country_code.value = 'FR' results = gtc_service.suggest_geo_target_constants( locale, country_code, location_names=location_names) geo_target_constant_status_enum = client.get_type( 'GeoTargetConstantStatusEnum').GeoTargetConstantStatus try: for suggestion in results.geo_target_constant_suggestions: geo_target_constant = suggestion.geo_target_constant print('%s (%s, %s, %s, %s) is found in locale (%s) with reach (%d) ' 'from search term (%s).' % (geo_target_constant.resource_name, geo_target_constant.name.value, geo_target_constant.country_code.value, geo_target_constant.target_type.value, geo_target_constant_status_enum.Name( geo_target_constant.status), suggestion.locale.value, suggestion.reach.value, suggestion.search_term.value)) except google.ads.google_ads.errors.GoogleAdsException as ex: print('Request with ID "%s" failed with status "%s" and includes the ' 'following errors:' % (ex.request_id, ex.error.code().name)) for error in ex.failure.errors: print('\tError with message "%s".' % error.message) if error.location: for field_path_element in error.location.field_path_elements: print('\t\tOn field: %s' % field_path_element.field_name) sys.exit(1)
Ruby
def get_geo_target_constant_by_names() # GoogleAdsClient will read a config file from # ENV['HOME']/google_ads_config.rb when called without parameters client = Google::Ads::GoogleAds::GoogleAdsClient.new gtc_service = client.service.geo_target_constant location_names = client.resource.location_names do |ln| ['Paris', 'Quebec', 'Spain', 'Deutschland'].each do |name| ln.names << name end end # Locale is using ISO 639-1 format. If an invalid locale is given, # 'en' is used by default. locale = 'en' # A list of country codes can be referenced here: # https://developers.google.com/adwords/api/docs/appendix/geotargeting country_code = 'FR' response = gtc_service.suggest_geo_target_constants(locale, country_code, location_names: location_names) response.geo_target_constant_suggestions.each do |suggestion| puts sprintf("%s (%s,%s,%s,%s) is found in locale (%s) with reach (%d)" \ " from search term (%s).", suggestion.geo_target_constant.resource_name, suggestion.geo_target_constant.name, suggestion.geo_target_constant.country_code, suggestion.geo_target_constant.target_type, suggestion.geo_target_constant.status, suggestion.locale, suggestion.reach, suggestion.search_term) end end
The code example above generates the following output:
geoTargetConstants/21167 (New York,US,State,ENABLED) is found in locale (en) with reach (32900000) from search term (New York).
Target campaigns for proximity to a location
There are times when you might want to target even more precisely than a city or
country. For example, you may want to advertise your supermarkets within 10
kilometers of your shop location. In such cases, you can use
proximity targeting.
The code to create a proximity target is similar to adding a location target,
except that you have to create a ProximityInfo
object instead of a
LocationInfo
object.
Java
private static CampaignCriterion buildProximityLocation(String campaignResourceName) { Builder builder = CampaignCriterion.newBuilder().setCampaign(StringValue.of(campaignResourceName)); ProximityInfo.Builder proximityBuilder = builder.getProximityBuilder(); proximityBuilder.setRadius(DoubleValue.of(10.0)).setRadiusUnits(ProximityRadiusUnits.MILES); AddressInfo.Builder addressBuilder = proximityBuilder.getAddressBuilder(); addressBuilder .setStreetAddress(StringValue.of("38 avenue de l'Opéra")) .setCityName(StringValue.of("Paris")) .setPostalCode(StringValue.of("75002")) .setCountryCode(StringValue.of("FR")); return builder.build(); }
C#
private CampaignCriterion buildProximityCriterion(string campaignResourceName) { ProximityInfo proximity = new ProximityInfo() { Address = new AddressInfo() { StreetAddress = "38 avenue de l'Opéra", CityName = "Paris", PostalCode = "75002", CountryCode = "FR" }, Radius = 10d, // Default is kilometers. RadiusUnits = ProximityRadiusUnits.Miles }; return new CampaignCriterion() { Campaign = campaignResourceName, Proximity = proximity }; }
PHP
private static function createProximityCampaignCriterionOperation(string $campaignResourceName) { // Constructs a campaign criterion as a proximity. $campaignCriterion = new CampaignCriterion([ 'proximity' => new ProximityInfo([ 'address' => new AddressInfo([ 'street_address' => new StringValue(['value' => '38 avenue de l\'Opéra']), 'city_name' => new StringValue(['value' => 'Paris']), 'postal_code' => new StringValue(['value' => '75002']), 'country_code' => new StringValue(['value' => 'FR']), ]), 'radius' => new DoubleValue(['value' => 10.0]), // Default is kilometers. 'radius_units' => ProximityRadiusUnits::MILES ]), 'campaign' => new StringValue(['value' => $campaignResourceName]) ]); return new CampaignCriterionOperation(['create' => $campaignCriterion]); }
Python
def create_location_op(client, customer_id, campaign_id, location_id): campaign_service = client.get_service('CampaignService', version='v2') geo_target_constant_service = client.get_service('GeoTargetConstantService', version='v2') # Create the campaign criterion. campaign_criterion_operation = client.get_type('CampaignCriterionOperation', version='v2') campaign_criterion = campaign_criterion_operation.create campaign_criterion.campaign.value = campaign_service.campaign_path( customer_id, campaign_id) # Besides using location_id, you can also search by location names from # GeoTargetConstantService.suggest_geo_target_constants() and directly # apply GeoTargetConstant.resource_name here. An example can be found # in get_geo_target_constant_by_names.py. campaign_criterion.location.geo_target_constant.value = ( geo_target_constant_service.geo_target_constant_path(location_id)) return campaign_criterion_operation
Ruby
def create_proximity(client, customer_id, campaign_id) client.operation.create_resource.campaign_criterion do |criterion| criterion.campaign = client.path.campaign(customer_id, campaign_id) criterion.proximity = client.resource.proximity_info do |proximity| proximity.address = client.resource.address_info do |address| address.street_address = "38 avenue de l'Opéra" address.city_name = "Paris" address.postal_code = "75002" address.country_code = "FR" end proximity.radius = 10 proximity.radius_units = :MILES end end end
Retrieve geo targets
You can retrieve the geo targets for a campaign using the
GoogleAdsService.Search
. You can filter your
results in the WHERE
clause.
SELECT
campaign_criterion.campaign,
campaign_criterion.location.geo_target_constant,
campaign_criterion.proximity.geo_point.longitude_in_micro_degrees,
campaign_criterion.proximity.geo_point.latitude_in_micro_degrees,
campaign_criterion.proximity.radius,
campaign_criterion.negative
FROM campaign_criterion
WHERE
campaign_criterion.campaign = 'customers/{customer_id}/campaigns/{campaign_id}'
AND campaign_criterion.type IN (LOCATION, PROXIMITY)
Update geo targets
To update location targets for a campaign, you need to retrieve the list of
existing geo targets and compare it with the list of new targets. You can then
use the remove
operation to remove the targets you don't need, and the
create
operation to add the new geo targets you need (but are missing in the
existing campaign).
Exclude geo targets
You can also exclude LocationInfo
, but not
ProximityInfo
. This feature is most useful if you want
to target a region, but exclude a sub-region (for example, to target the entire
United States, except for New York City). To exclude a region, set the
negative
field in CampaignCriterion
to be
true
.
Target multiple geographic regions
Using a LocationGroup
, you can enable a campaign to
target multiple geographic regions. A region is centered on the locations
defined by the location extensions of the campaign, or by an optional
Feed
.
The radius defined on the LocationGroup
ascribes a circular region around each
location, and consists of a radius
object, length, and radius_units
, which
can be either meters or miles
(LocationGroupRadiusUnitsEnum
).
The locations in a LocationGroup
can be filtered by a list of geotargeting
criterion IDs prescribed in the
geo_target_constant
field. If defined, no locations that exist outside of
the given critera IDs will be targeted.
Here are some tips when creating a LocationGroup
:
LocationGroup.feed
must be theresource_name
of aFeed
(if aFeed
is being used).LocationGroup.feed
can only be mutated onCREATE
actions. You cannot mutate this field onUPDATE
actions.A
RESOURCE_NOT_FOUND
error can occur when adding aFeed
to aLocationGroup
due to any of the following causes:- The
Feed
does not exist. - The
Feed
is inactive. - The
Feed
does not have attributes mapped to location campaign critera.
- The
Whether or not a Feed
can be used for a LocationGroup
can be determined by
looking at its FeedMapping
entries—at least one
FeedMapping
should have a criterion_type
of LOCATION_EXTENSION_TARGETING
.
Here is a GAQL query that returns the feeds with the proper feed-mapping
criterion type:
SELECT
feed.id,
feed_mapping.criterion_type
FROM feed_mapping
WHERE
feed.id = <feed id>
AND feed_mapping.criterion_type = LOCATION_EXTENSION_TARGETING