Recommendations can improve your campaigns in a few ways:
- Introduce new and relevant features
- Get more out of your budget with improved bids, keywords, and ads
- Increase the overall performance and efficiency of your campaigns
To increase optimization scores, you can use the
RecommendationService
to retrieve
recommendations, and then apply or dismiss them accordingly.
Optimization score
Optimization score is an
estimate of how well your Google Ads account is set to perform and is available
at the Customer
and
Campaign
levels.
The
Customer.optimization_score_weight
is only available for non-manager accounts and is used to compute the overall
optimization score of multiple accounts. Retrieve the optimization score and
optimization score weight of the accounts and multiply them together
(Customer.optimization_score * Customer.optimization_score_weight
) to compute
the overall optimization score.
There are optimization-related metrics available for customer
and campaign
reports:
- The
metrics.optimization_score_url
provides a deep link into the account to view information on the related recommendations in the Google Ads UI. - The
metrics.optimization_score_uplift
tells how much the optimization score would increase if all related recommendations are applied. It's an estimate based on all available recommendations as a whole, not just the sum of the uplift scores for each recommendation.
To group and order the returned recommendations, you can segment both of these
metrics by recommendation type using segments.recommendation_type
in your
query.
Recommendation types
The Google Ads API fully supports the following recommendation types:
RecommendationType | Description |
---|---|
CAMPAIGN_BUDGET |
Fix campaigns limited by budget |
KEYWORD |
Add new keywords |
TEXT_AD |
Add ad suggestions |
TARGET_CPA_OPT_IN |
Bid with Target CPA |
MAXIMIZE_CONVERSIONS_OPT_IN |
Bid with Maximize Conversions |
ENHANCED_CPC_OPT_IN |
Bid with Enhanced CPC |
SEARCH_PARTNERS_OPT_IN |
Expand reach with Google search partners |
MAXIMIZE_CLICKS_OPT_IN |
Bid with Maximize Clicks |
OPTIMIZE_AD_ROTATION |
Use optimized ad rotations |
CALLOUT_EXTENSION (deprecated) |
Deprecated, use CALLOUT_ASSET instead |
SITELINK_EXTENSION (deprecated) |
Deprecated, use SITELINK_ASSET instead |
CALL_EXTENSION (deprecated) |
Deprecated, use CALL_ASSET instead |
KEYWORD_MATCH_TYPE (deprecated) |
Deprecated, use USE_BROAD_MATCH_KEYWORD instead |
MOVE_UNUSED_BUDGET |
Move unused to constrained budgets |
TARGET_ROAS_OPT_IN |
Bid with Target ROAS |
FORECASTING_CAMPAIGN_BUDGET |
Fix campaigns that are expected to become limited by budget in the future |
RESPONSIVE_SEARCH_AD |
Add new responsive search ad |
MARGINAL_ROI_CAMPAIGN_BUDGET |
Adjust campaign budget to increase ROI |
USE_BROAD_MATCH_KEYWORD |
Use broad match for conversion-based campaigns with automated bidding |
RESPONSIVE_SEARCH_AD_ASSET |
Add responsive search ad assets to an ad |
UPGRADE_SMART_SHOPPING_CAMPAIGN_TO_PERFORMANCE_MAX |
Upgrade a Smart Shopping campaign to a Performance Max campaign |
RESPONSIVE_SEARCH_AD_IMPROVE_AD_STRENGTH |
Improve the strength of a responsive search ad |
DISPLAY_EXPANSION_OPT_IN |
Update a campaign to use Display Expansion |
UPGRADE_LOCAL_CAMPAIGN_TO_PERFORMANCE_MAX |
Upgrade a legacy local campaign to a Performance Max campaign |
RAISE_TARGET_CPA_BID_TOO_LOW |
Recommendation to raise target CPA when it is too low and there are very few or no conversions |
FORECASTING_SET_TARGET_ROAS |
Recommendation to raise the budget in advance of a seasonal event that is forecasted to increase traffic, and change bidding strategy from maximize conversion value to target ROAS |
CALLOUT_ASSET |
Add callout assets to campaign or customer level |
SITELINK_ASSET |
Add sitelink assets to campaign or customer level |
CALL_ASSET |
Add call assets to campaign or customer level |
SHOPPING_ADD_AGE_GROUP |
Add the age group attribute to offers that are demoted because of a missing age group |
SHOPPING_ADD_COLOR |
Add a color to offers that are demoted because of a missing color |
SHOPPING_ADD_GENDER |
Add a gender to offers that are demoted because of a missing gender |
SHOPPING_ADD_GTIN |
Add a GTIN (Global Trade Item Number) to offers that are demoted because of a missing GTIN |
SHOPPING_ADD_MORE_IDENTIFIERS |
Add more identifiers to offers that are demoted because of missing identifiers |
SHOPPING_ADD_SIZE |
Add the size to offers that are demoted because of a missing size |
SHOPPING_ADD_PRODUCTS_TO_CAMPAIGN |
Add products for a campaign to serve |
SHOPPING_FIX_DISAPPROVED_PRODUCTS |
Fix disapproved products |
SHOPPING_TARGET_ALL_OFFERS |
Create a catch-all campaign that targets all offers |
SHOPPING_FIX_SUSPENDED_MERCHANT_CENTER_ACCOUNT |
Fix Merchant Center account suspension issues |
SHOPPING_FIX_MERCHANT_CENTER_ACCOUNT_SUSPENSION_WARNING |
Fix Merchant Center account suspension warning issues |
SHOPPING_MIGRATE_REGULAR_SHOPPING_CAMPAIGN_OFFERS_TO_PERFORMANCE_MAX |
Migrate offers targeted by Regular Shopping Campaigns to existing Performance Max campaigns |
Handle unsupported types
Retrieve recommendations
Like most other entities in the Google Ads API, Recommendation
objects are fetched by using the
GoogleAdsService.SearchStream
with a Google Ads Query Language query.
For each type of recommendation, the recommendation details are provided in a
specific recommendation
field
with a specific type:
Code example
The following sample code retrieves all available and dismissed recommendations
of type TEXT_AD
from an account and prints some of their details:
Java
private void runExample(GoogleAdsClient googleAdsClient, long customerId) { try (GoogleAdsServiceClient googleAdsServiceClient = googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) { String query = "SELECT recommendation.type, " + "recommendation.campaign, " + "recommendation.text_ad_recommendation " + "FROM recommendation " + "WHERE recommendation.type = TEXT_AD"; // Creates a request that will retrieve all recommendations using pages of the // specified page size. SearchGoogleAdsRequest request = SearchGoogleAdsRequest.newBuilder() .setCustomerId(Long.toString(customerId)) .setPageSize(PAGE_SIZE) .setQuery(query) .build(); // Issues the search request. SearchPagedResponse searchPagedResponse = googleAdsServiceClient.search(request); // Iterates over all rows in all pages and prints the requested field values for the // recommendation in each row. for (GoogleAdsRow googleAdsRow : searchPagedResponse.iterateAll()) { Recommendation recommendation = googleAdsRow.getRecommendation(); Ad recommendedAd = recommendation.getTextAdRecommendation().getAd(); System.out.printf( "Recommendation ('%s') was found for campaign '%s':%n", recommendation.getResourceName(), recommendation.getCampaign()); if (recommendedAd.hasExpandedTextAd()) { ExpandedTextAdInfo eta = recommendedAd.getExpandedTextAd(); System.out.printf( "\tHeadline 1 = '%s'%n" + "\tHeadline 2 = '%s'%n" + "\tDescription = '%s'%n", eta.getHeadlinePart1(), eta.getHeadlinePart2(), eta.getDescription()); } if (recommendedAd.getDisplayUrl() != null) { System.out.printf("\tDisplay URL = '%s'%n", recommendedAd.getDisplayUrl()); } for (String url : recommendedAd.getFinalUrlsList()) { System.out.printf("\tFinal URL = '%s'%n", url); } for (String url : recommendedAd.getFinalMobileUrlsList()) { System.out.printf("\tFinal Mobile URL = '%s'%n", url); } } } }
C#
public void Run(GoogleAdsClient client, long customerId) { // Get the GoogleAdsServiceClient . GoogleAdsServiceClient service = client.GetService(Services.V13.GoogleAdsService); string query = @"SELECT recommendation.type, recommendation.campaign, recommendation.text_ad_recommendation FROM recommendation WHERE recommendation.type = TEXT_AD"; // Create a request that will retrieve all recommendations using pages of the // specified page size. SearchGoogleAdsRequest request = new SearchGoogleAdsRequest() { CustomerId = customerId.ToString(), PageSize = PAGE_SIZE, Query = query }; try { // Issue the search request. PagedEnumerable<SearchGoogleAdsResponse, GoogleAdsRow> searchPagedResponse = service.Search(customerId.ToString(), query); // Iterates over all rows in all pages and prints the requested field values // for the recommendation in each row. foreach (GoogleAdsRow googleAdsRow in searchPagedResponse) { Recommendation recommendation = googleAdsRow.Recommendation; // ... } } catch (GoogleAdsException e) { Console.WriteLine("Failure:"); Console.WriteLine($"Message: {e.Message}"); Console.WriteLine($"Failure: {e.Failure}"); Console.WriteLine($"Request ID: {e.RequestId}"); throw; } }
PHP
public static function runExample(GoogleAdsClient $googleAdsClient, int $customerId) { $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient(); // Creates a query that retrieves recommendations for text ads. $query = 'SELECT recommendation.type, recommendation.campaign, ' . 'recommendation.text_ad_recommendation ' . 'FROM recommendation ' . 'WHERE recommendation.type = TEXT_AD'; // Issues a search request by specifying page size. $response = $googleAdsServiceClient->search($customerId, $query, ['pageSize' => self::PAGE_SIZE]); // Iterates over all rows in all pages and prints the requested field values for // the recommendation in each row. foreach ($response->iterateAllElements() as $googleAdsRow) { /** @var GoogleAdsRow $googleAdsRow */ $recommendation = $googleAdsRow->getRecommendation(); printf( "Recommendation with resource name '%s' was found for campaign " . "with resource name '%s':%s", $recommendation->getResourceName(), $recommendation->getCampaign(), PHP_EOL ); $recommendedAd = $recommendation->getTextAdRecommendation()->getAd(); if (!is_null($recommendedAd->getExpandedTextAd())) { $recommendedExpandedTextAd = $recommendedAd->getExpandedTextAd(); printf( "\tHeadline part 1 is '%s'.%s", $recommendedExpandedTextAd->getHeadlinePart1(), PHP_EOL ); printf( "\tHeadline part 2 is '%s'.%s", $recommendedExpandedTextAd->getHeadlinePart2(), PHP_EOL ); printf( "\tDescription is '%s'%s", $recommendedExpandedTextAd->getDescription(), PHP_EOL ); } if (!is_null($recommendedAd->getDisplayUrl())) { printf("\tDisplay URL is '%s'.%s", $recommendedAd->getDisplayUrl(), PHP_EOL); } foreach ($recommendedAd->getFinalUrls() as $finalUrl) { /** @var string $finalUrl */ printf("\tFinal URL is '%s'.%s", $finalUrl, PHP_EOL); } foreach ($recommendedAd->getFinalMobileUrls() as $finalMobileUrl) { /** @var string $finalMobileUrl */ printf("\tFinal Mobile URL is '%s'.%s", $finalMobileUrl, PHP_EOL); } } }
Python
def main(client, customer_id): ga_service = client.get_service("GoogleAdsService") query = """ SELECT recommendation.type, recommendation.campaign, recommendation.text_ad_recommendation FROM recommendation WHERE recommendation.type = TEXT_AD""" search_request = client.get_type("SearchGoogleAdsStreamRequest") search_request.customer_id = customer_id search_request.query = query stream = ga_service.search_stream(request=search_request) for batch in stream: for row in batch.results: recommendation = row.recommendation recommended_ad = recommendation.text_ad_recommendation.ad print( f'Recommendation ("{recommendation.resource_name}") ' f'was found for campaign "{recommendation.campaign}".' ) if recommended_ad.display_url: print(f'\tDisplay URL = "{recommended_ad.display_url}"') for url in recommended_ad.final_urls: print(f'\tFinal URL = "{url}"') for url in recommended_ad.final_mobile_urls: print(f'\tFinal Mobile URL = "{url}"')
Ruby
def get_text_ad_recommendations(customer_id) # GoogleAdsClient will read a config file from # ENV['HOME']/google_ads_config.rb when called without parameters client = Google::Ads::GoogleAds::GoogleAdsClient.new ga_service = client.service.google_ads query = <<~QUERY SELECT recommendation.type, recommendation.campaign, recommendation.text_ad_recommendation FROM recommendation WHERE recommendation.type = TEXT_AD QUERY response = ga_service.search( customer_id: customer_id, query: query, page_size: PAGE_SIZE, ) response.each do |row| recommendation = row.recommendation recommended_ad = recommendation.text_ad_recommendation.ad puts "Recommendation ('#{recommendation.resource_name}') was found for "\ "campaign '#{recommendation.campaign}'." if recommended_ad.expanded_text_ad eta = recommended_ad.expanded_text_ad puts "\tHeadline 1 = '#{eta.headline_part1}'\n\tHeadline2 = '#{eta.headline_part2}'\n" + "\tDescription = '#{eta.description}'" end if recommended_ad.display_url puts "\tDisplay URL = '#{recommended_ad.display_url}'" end recommended_ad.final_urls.each do |url| puts "\tFinal Url = '#{url}'" end recommended_ad.final_mobile_urls.each do |url| puts "\tFinal Mobile Url = '#{url}'" end end end
Perl
sub get_text_ad_recommendations { my ($api_client, $customer_id) = @_; # Creates the search query. my $search_query = "SELECT recommendation.type, recommendation.campaign, " . "recommendation.text_ad_recommendation " . "FROM recommendation WHERE recommendation.type = TEXT_AD"; # Create a search Google Ads request that will retrieve all recommendations for # text ads using pages of the specified page size. my $search_request = Google::Ads::GoogleAds::V13::Services::GoogleAdsService::SearchGoogleAdsRequest ->new({ customerId => $customer_id, query => $search_query, pageSize => PAGE_SIZE }); # Get the GoogleAdsService. my $google_ads_service = $api_client->GoogleAdsService(); my $iterator = Google::Ads::GoogleAds::Utils::SearchGoogleAdsIterator->new({ service => $google_ads_service, request => $search_request }); # Iterate over all rows in all pages and print the requested field values for # the recommendation in each row. while ($iterator->has_next) { my $google_ads_row = $iterator->next; my $recommendation = $google_ads_row->{recommendation}; printf "Recommendation '%s' was found for campaign '%s':\n", $recommendation->{resourceName}, $recommendation->{campaign}; my $recommended_ad = $recommendation->{textAdRecommendation}{ad}; if ($recommended_ad->{expandedTextAd}) { my $recommended_expanded_text_ad = $recommended_ad->{expandedTextAd}; printf "\tHeadline part 1 is '%s'.\n" . "\tHeadline part 2 is '%s'.\n" . "\tDescription is '%s'.\n", $recommended_expanded_text_ad->{headlinePart1}, $recommended_expanded_text_ad->{headlinePart2}, $recommended_expanded_text_ad->{description}; } if ($recommended_ad->{displayUrl}) { printf "\tDisplay URL is '%s'.\n", $recommended_ad->{displayUrl}; } foreach my $final_url (@{$recommended_ad->{finalUrls}}) { printf "\tFinal URL is '%s'.\n", $final_url; } foreach my $final_mobile_url (@{$recommended_ad->{finalMobileUrls}}) { printf "\tFinal Mobile URL is '%s'.\n", $final_mobile_url; } } return 1; }
Take action
Any retrieved recommendation can be applied or dismissed.
Depending on the recommendation type, recommendations can change on a daily
basis or even multiple times a day. When that happens, a recommendation
object's resource_name
can
become obsolete after the recommendation is retrieved.
It is good practice to take action on recommendations shortly after retrieval.
Apply recommendations
Setting accounts for auto-applying
recommendations is not
supported in the Google Ads API, however, you can implement similar behavior for the
recommendation types that are fully supported by the Google Ads API. Refer to the
DetectAndApplyRecommendations
code
example to learn more.
You can apply active or dismissed recommendations with the
ApplyRecommendation
method of the
RecommendationService
.
Recommendation types can have mandatory or optional parameters. Most recommendations come with recommended values that are used by default; see recommendation details.
Use the
apply_parameters
field of
ApplyRecommendationOperation
to
apply recommendations with specific parameter values. Each suitable
recommendation type has its own field. Any recommendation type missing from the
table does not use these parameter values.
Code example
The following code example illustrates how to apply a recommendation with the recommended apply parameters:
Java
private void runExample( GoogleAdsClient googleAdsClient, long customerId, String recommendationId) { String recommendationResourceName = ResourceNames.recommendation(customerId, recommendationId); ApplyRecommendationOperation.Builder operationBuilder = ApplyRecommendationOperation.newBuilder().setResourceName(recommendationResourceName); // Each recommendation types has optional parameters to override the recommended values. // This is an example to override a recommended ad when a TextAdRecommendation is applied. // Please read // https://developers.google.com/google-ads/api/reference/rpc/latest/ApplyRecommendationOperation // for details. // Note that additional import statements are needed for this example to work. And also, please // replace INSERT_AD_ID_HERE with a valid ad ID below. // // Ad overrideAd = Ad.newBuilder().setId(Long.parseLong("INSERT_AD_ID_HERE")).build(); // operationBuilder.setTextAd(TextAdParameters.newBuilder(). // setAd(overrideAd).build()).build(); List<ApplyRecommendationOperation> operations = new ArrayList<>(); operations.add(operationBuilder.build()); try (RecommendationServiceClient recommendationServiceClient = googleAdsClient.getLatestVersion().createRecommendationServiceClient()) { ApplyRecommendationResponse response = recommendationServiceClient.applyRecommendation(Long.toString(customerId), operations); System.out.printf("Applied %d recommendation:%n", response.getResultsCount()); for (ApplyRecommendationResult result : response.getResultsList()) { System.out.println(result.getResourceName()); } } }
C#
public void Run(GoogleAdsClient client, long customerId, long recommendationId) { // Get the RecommendationServiceClient. RecommendationServiceClient service = client.GetService( Services.V13.RecommendationService); ApplyRecommendationOperation operation = new ApplyRecommendationOperation() { ResourceName = ResourceNames.Recommendation(customerId, recommendationId), // Each recommendation types has optional parameters to override the recommended // values. For example, you can override a recommended ad when a // TextAdRecommendation is applied, as shown below. // Please read https://developers.google.com/google-ads/api/reference/rpc/latest/ApplyRecommendationOperation // for details. // TextAd = new TextAdParameters() { // Ad = new Ad() { // Id = long.Parse("INSERT_AD_ID_HERE") // } // } }; try { ApplyRecommendationResponse response = service.ApplyRecommendation( customerId.ToString(), new ApplyRecommendationOperation[] { operation }); Console.WriteLine($"Applied {0} recommendation(s):", response.Results.Count); foreach (ApplyRecommendationResult result in response.Results) { Console.WriteLine($"- {result.ResourceName}"); } } catch (GoogleAdsException e) { Console.WriteLine("Failure:"); Console.WriteLine($"Message: {e.Message}"); Console.WriteLine($"Failure: {e.Failure}"); Console.WriteLine($"Request ID: {e.RequestId}"); throw; } }
PHP
public static function runExample( GoogleAdsClient $googleAdsClient, int $customerId, string $recommendationId ) { $recommendationResourceName = ResourceNames::forRecommendation($customerId, $recommendationId); $applyRecommendationOperation = new ApplyRecommendationOperation(); $applyRecommendationOperation->setResourceName($recommendationResourceName); // Each recommendation type has optional parameters to override the recommended values. // This is an example to override a recommended ad when a TextAdRecommendation is applied. // For details, please read // https://developers.google.com/google-ads/api/reference/rpc/latest/ApplyRecommendationOperation. /* $overridingAd = new Ad([ 'id' => 'INSERT_AD_ID_AS_INTEGER_HERE' ]); $applyRecommendationOperation->setTextAd(new TextAdParameters(['ad' => $overridingAd])); */ // Issues a mutate request to apply the recommendation. $recommendationServiceClient = $googleAdsClient->getRecommendationServiceClient(); $response = $recommendationServiceClient->applyRecommendation( $customerId, [$applyRecommendationOperation] ); /** @var Recommendation $appliedRecommendation */ $appliedRecommendation = $response->getResults()[0]; printf( "Applied recommendation with resource name: '%s'.%s", $appliedRecommendation->getResourceName(), PHP_EOL ); }
Python
def main(client, customer_id, recommendation_id): recommendation_service = client.get_service("RecommendationService") apply_recommendation_operation = client.get_type( "ApplyRecommendationOperation" ) apply_recommendation_operation.resource_name = recommendation_service.recommendation_path( customer_id, recommendation_id ) # This is where we override the recommended ad when a TextAdRecommendation is applied. # override_ad = client.get_type("Ad") # override_ad.resource_name = "INSERT_AD_ID_HERE" # apply_recommendation_operation.text_ad.ad = override_ad recommendation_response = recommendation_service.apply_recommendation( customer_id=customer_id, operations=[apply_recommendation_operation] ) print( "Applied recommendation with resource name: " f"'{recommendation_response.results[0].resource_name}'" )
Ruby
def apply_recommendation(customer_id, recommendation_id) # GoogleAdsClient will read a config file from # ENV['HOME']/google_ads_config.rb when called without parameters client = Google::Ads::GoogleAds::GoogleAdsClient.new recommendation_resource = client.path.recommendation(customer_id, recommendation_id) apply_recommendation_operation = client.operation.apply_recommendation apply_recommendation_operation.resource_name = recommendation_resource # Each recommendation type has optional parameters to override the recommended # values. This is an example to override a recommended ad when a # TextAdRecommendation is applied. # For details, please read # https://developers.google.com/google-ads/api/reference/rpc/google.ads.google_ads.v1.services#google.ads.google_ads.v1.services.ApplyRecommendationOperation # # text_ad_parameters = client.resource.text_ad_parameters do |tap| # tap.ad = client.resource.ad do |ad| # ad.id = "INSERT_AD_ID_AS_INTEGER_HERE" # end # end # apply_recommendation_operation.text_ad = text_ad_parameters # Issues a mutate request to apply the recommendation. recommendation_service = client.service.recommendation response = recommendation_service.apply_recommendation( customer_id: customer_id, operations: [apply_recommendation_operation], ) applied_recommendation = response.results.first puts "Applied recommendation with resource name: '#{applied_recommendation.resource_name}'." end
Perl
sub apply_recommendation { my ($api_client, $customer_id, $recommendation_id) = @_; my $recommendation_resource_name = Google::Ads::GoogleAds::V13::Utils::ResourceNames::recommendation( $customer_id, $recommendation_id); # Create an apply recommendation operation. my $apply_recommendation_operation = Google::Ads::GoogleAds::V13::Services::RecommendationService::ApplyRecommendationOperation ->new({ resourceName => $recommendation_resource_name }); # Each recommendation type has optional parameters to override the recommended values. # This is an example to override a recommended ad when a TextAdRecommendation is applied. # For details, please read # https://developers.google.com/google-ads/api/reference/rpc/latest/ApplyRecommendationOperation. # # my $overriding_ad = Google::Ads::GoogleAds::V13::Resources::Ad->new({ # id => "INSERT_AD_ID_AS_INTEGER_HERE" # }); # my $text_ad_parameters = # Google::Ads::GoogleAds::V13::Services::RecommendationService::TextAdParameters # ->new({ad => $overriding_ad}); # $apply_recommendation_operation->{textAd} = $text_ad_parameters; # Apply the recommendation. my $apply_recommendation_response = $api_client->RecommendationService()->apply({ customerId => $customer_id, operations => [$apply_recommendation_operation]}); printf "Applied recommendation with resource name: '%s'.\n", $apply_recommendation_response->{results}[0]{resourceName}; return 1; }
Watch these videos to learn more
Apply parameters
Bulk
Errors
Tests
Dismiss recommendations
Video: Dismiss recommendations
You can dismiss recommendations with the
RecommendationService
. The code
structure is similar to applying recommendations, but instead you use
DismissRecommendationOperation
and
RecommendationService.DismissRecommendation
.