The code samples below provide examples of common optimization functions using the AdWords API. Client Library.
Get keyword traffic estimates
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright:: Copyright 2011, Google Inc. All Rights Reserved. # # License:: 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. # # This example gets keyword traffic estimates. require 'adwords_api' def estimate_keyword_traffic() # AdwordsApi::Api will read a config file from ENV['HOME']/adwords_api.yml # when called without parameters. adwords = AdwordsApi::Api.new # To enable logging of SOAP requests, set the log_level value to 'DEBUG' in # the configuration file or provide your own logger: # adwords.logger = Logger.new('adwords_xml.log') traffic_estimator_srv = adwords.service(:TrafficEstimatorService, API_VERSION) # Create keywords. Up to 2000 keywords can be passed in a single request. keywords = [ # The 'xsi_type' field allows you to specify the xsi:type of the object # being created. It's only necessary when you must provide an explicit # type that the client library can't infer. {:xsi_type => 'Keyword', :text => 'mars cruise', :match_type => 'BROAD'}, {:xsi_type => 'Keyword', :text => 'cheap cruise', :match_type => 'PHRASE'}, {:xsi_type => 'Keyword', :text => 'cruise', :match_type => 'EXACT'}, {:xsi_type => 'Keyword', :text => 'moon walk', :match_type => 'BROAD'} ] # Create a keyword estimate request for each keyword. keyword_requests = keywords.map {|keyword| {:keyword => keyword}} # Negative keywords don't return estimates, but adjust the estimates of the # other keywords in the hypothetical ad group. To specify a negative keyword # set the is_negative field to true. keyword_requests[3][:is_negative] = true # Create ad group estimate requests. ad_group_request = { :keyword_estimate_requests => keyword_requests, :max_cpc => { :micro_amount => 1000000 } } # Create campaign estimate requests. campaign_request = { :ad_group_estimate_requests => [ad_group_request], # Set targeting criteria. Only locations and languages are supported. :criteria => [ {:xsi_type => 'Location', :id => 2840}, # United States {:xsi_type => 'Language', :id => 1000} # English ] } # Create a selector. selector = { :campaign_estimate_requests => [campaign_request], # Optional: Request a list of campaign level estimates segmented by # platform. :platform_estimate_requested => true } # Execute the request. response = traffic_estimator_srv.get(selector) # Display traffic estimates. if response and response[:campaign_estimates] and response[:campaign_estimates].size > 0 campaign_estimate = response[:campaign_estimates].first unless campaign_estimate[:platform_estimates].nil? # Display the campaign level estimates segmented by platform. campaign_estimate[:platform_estimates].each do |platform_estimate| platform_message = ('Results for the platform with ID %d and name ' + '"%s":') % [platform_estimate[:platform][:id], platform_estimate[:platform][:platform_name]] display_mean_estimates( platform_message, platform_estimate[:min_estimate], platform_estimate[:max_estimate] ) end end # Display the keyword estimates. keyword_estimates = campaign_estimate[:ad_group_estimates].first[:keyword_estimates] keyword_estimates.each_with_index do |keyword_estimate, index| next if keyword_requests[index][:is_negative] keyword = keyword_requests[index][:keyword] keyword_message = ('Results for the keyword with text "%s" and match ' + 'type "%s":') % [keyword[:text], keyword[:match_type]] display_mean_estimates( keyword_message, keyword_estimate[:min], keyword_estimate[:max] ) end else puts 'No traffic estimates were returned.' end end def display_mean_estimates(message, min_estimate, max_estimate) mean_average_cpc = nil unless min_estimate[:average_cpc].nil? || max_estimate[:average_cpc].nil? mean_average_cpc = calculate_mean( min_estimate[:average_cpc][:micro_amount], max_estimate[:average_cpc][:micro_amount] ) end mean_average_position = calculate_mean( min_estimate[:average_position], max_estimate[:average_position] ) mean_clicks = calculate_mean( min_estimate[:clicks_per_day], max_estimate[:clicks_per_day] ) mean_total_cost = nil unless min_estimate[:total_cost].nil? || max_estimate[:total_cost].nil? mean_total_cost = calculate_mean( min_estimate[:total_cost][:micro_amount], max_estimate[:total_cost][:micro_amount] ) end puts message puts "\tEstimated average CPC: %s" % format_mean(mean_average_cpc) puts "\tEstimated ad position: %s" % format_mean(mean_average_position) puts "\tEstimated daily clicks: %s" % format_mean(mean_clicks) puts "\tEstimated daily cost: %s" % format_mean(mean_total_cost) end def format_mean(mean) return "nil" if mean.nil? return "%.2f" % (mean / 1000000) end def calculate_mean(min_money, max_money) return nil if min_money.nil? || max_money.nil? return (min_money.to_f + max_money.to_f) / 2.0 end if __FILE__ == $0 API_VERSION = :v201809 begin estimate_keyword_traffic() # Authorization error. rescue AdsCommon::Errors::OAuth2VerificationRequired => e puts "Authorization credentials are not valid. Edit adwords_api.yml for " + "OAuth2 client ID and secret and run misc/setup_oauth2.rb example " + "to retrieve and store OAuth2 tokens." puts "See this wiki page for more details:\n\n " + 'https://github.com/googleads/google-api-ads-ruby/wiki/OAuth2' # HTTP errors. rescue AdsCommon::Errors::HttpError => e puts "HTTP Error: %s" % e # API errors. rescue AdwordsApi::Errors::ApiException => e puts "Message: %s" % e.message puts 'Errors:' e.errors.each_with_index do |error, index| puts "\tError [%d]:" % (index + 1) error.each do |field, value| puts "\t\t%s: %s" % [field, value] end end end end
Get all mobile bid modifier landscapes for a campaign
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright:: Copyright 2016, Google Inc. All Rights Reserved. # # License:: 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. # # This example gets all available campaign criterion bid modifier landscapes # for a given campaign. # To get campaigns, run basic_operations/get_campaigns.rb. require 'adwords_api' def get_campaign_criterion_bid_modifier_simulations(campaign_id) # AdwordsApi::Api will read a config file from ENV['HOME']/adwords_api.yml # when called without parameters. adwords = AdwordsApi::Api.new # To enable logging of SOAP requests, set the log_level value to 'DEBUG' in # the configuration file or provide your own logger: # adwords.logger = Logger.new('adwords_xml.log') data_srv = adwords.service(:DataService, API_VERSION) selector = { :fields => [ 'CampaignId', 'CriterionId', 'StartDate', 'EndDate', 'BidModifier', 'LocalClicks', 'LocalCost', 'LocalImpressions', 'TotalLocalImpressions', 'TotalLocalClicks', 'TotalLocalCost', 'RequiredBudget' ], :predicates => [ {:field => 'CampaignId', :operator => 'IN', :values => [campaign_id]} ], :paging => { :start_index => 0, :number_results => PAGE_SIZE } } landscape_points_in_previous_page = 0 start_index = 0 begin # Offset the start index by the number of landscape points in the last # retrieved page, NOT the number of entries (bid landscapes) in the page. start_index += landscape_points_in_previous_page selector[:paging][:start_index] = start_index # Reset the count of landscape points in preparation for processing the # next page. landscape_points_in_previous_page = 0 # Request the next page of bid landscapes. page = data_srv.get_campaign_criterion_bid_landscape(selector) if page[:entries] page[:entries].each do |bid_modifier_landscape| puts ("Found campaign-level criterion bid modifier landscapes for " + "criterion with id '%d', start date '%s', end date '%s', and " + "landscape points:") % [ bid_modifier_landscape[:criterion_id], bid_modifier_landscape[:start_date], bid_modifier_landscape[:end_date] ] bid_modifier_landscape[:landscape_points].each do |landscape_point| landscape_points_in_previous_page += 1 puts (" bid modifier: %f => clicks: %d, cost: %d, impressions: %d" + " total clicks: %d, total cost: %d, total impressions: %d" + " and required budget: %f") % [ landscape_point[:bid_modifier], landscape_point[:clicks], landscape_point[:cost][:micro_amount], landscape_point[:impressions], landscape_point[:total_local_clicks], landscape_point[:total_local_cost][:micro_amount], landscape_point[:total_local_impressions], landscape_point[:required_budget][:micro_amount] ] end puts end end end while landscape_points_in_previous_page >= PAGE_SIZE end if __FILE__ == $0 API_VERSION = :v201809 PAGE_SIZE = 100 begin campaign_id = 'INSERT_CAMPAIGN_ID_HERE'.to_i get_campaign_criterion_bid_modifier_simulations(campaign_id) # Authorization error. rescue AdsCommon::Errors::OAuth2VerificationRequired => e puts "Authorization credentials are not valid. Edit adwords_api.yml for " + "OAuth2 client ID and secret and run misc/setup_oauth2.rb example " + "to retrieve and store OAuth2 tokens." puts "See this wiki page for more details:\n\n " + 'https://github.com/googleads/google-api-ads-ruby/wiki/OAuth2' # HTTP errors. rescue AdsCommon::Errors::HttpError => e puts "HTTP Error: %s" % e # API errors. rescue AdwordsApi::Errors::ApiException => e puts "Message: %s" % e.message puts 'Errors:' e.errors.each_with_index do |error, index| puts "\tError [%d]:" % (index + 1) error.each do |field, value| puts "\t\t%s: %s" % [field, value] end end end end
Get a bid landscape for an ad group and criterion
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright:: Copyright 2011, Google Inc. All Rights Reserved. # # License:: 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. # # This example gets bid landscapes for a keyword. To get keywords, run # get_keywords.rb. require 'adwords_api' def get_criterion_bid_landscapes(ad_group_id, keyword_id) # AdwordsApi::Api will read a config file from ENV['HOME']/adwords_api.yml # when called without parameters. adwords = AdwordsApi::Api.new # To enable logging of SOAP requests, set the log_level value to 'DEBUG' in # the configuration file or provide your own logger: # adwords.logger = Logger.new('adwords_xml.log') data_srv = adwords.service(:DataService, API_VERSION) # Get keyword bid landscape. query_builder = adwords.service_query_builder do |b| b.select(%w[ AdGroupId CriterionId StartDate EndDate Bid BiddableConversions BiddableConversionsValue LocalClicks LocalCost LocalImpressions ]) b.where('AdGroupId').equal_to(ad_group_id) b.where('CriterionId').equal_to(keyword_id) b.limit(0, PAGE_SIZE) end query = query_builder.build loop do # Request the next page of bid landscapes. page = data_srv.query_criterion_bid_landscape(query.to_s) if page and page[:entries] puts "Bid landscape(s) retrieved: %d." % [page[:entries].length] page[:entries].each do |bid_landscape| puts ("Retrieved keyword bid landscape with ad group ID %d" + ", keyword ID %d, start date '%s', end date '%s'" + ", with landscape points:") % [bid_landscape[:ad_group_id], bid_landscape[:criterion_id], bid_landscape[:start_date], bid_landscape[:end_date]] bid_landscape[:landscape_points].each do |point| landscape_points_in_previous_page += 1 puts ("\t%d => clicks: %d, cost: %d, impressions: %d, biddable " + "conversions: %.2f, biddable conversions value: %.2f") % [point[:bid][:micro_amount], point[:clicks], point[:cost][:micro_amount], point[:impressions], point[:biddable_conversions], point[:biddable_conversions_value]] end end end break unless query.has_next_landscape_page(page) query.next_page() end end if __FILE__ == $0 API_VERSION = :v201809 PAGE_SIZE = 100 begin ad_group_id = 'INSERT_ADGROUP_ID_HERE'.to_i keyword_id = 'INSERT_KEYWORD_ID_HERE'.to_i get_criterion_bid_landscapes(ad_group_id, keyword_id) # Authorization error. rescue AdsCommon::Errors::OAuth2VerificationRequired => e puts "Authorization credentials are not valid. Edit adwords_api.yml for " + "OAuth2 client ID and secret and run misc/setup_oauth2.rb example " + "to retrieve and store OAuth2 tokens." puts "See this wiki page for more details:\n\n " + 'https://github.com/googleads/google-api-ads-ruby/wiki/OAuth2' # HTTP errors. rescue AdsCommon::Errors::HttpError => e puts "HTTP Error: %s" % e # API errors. rescue AdwordsApi::Errors::ApiException => e puts "Message: %s" % e.message puts 'Errors:' e.errors.each_with_index do |error, index| puts "\tError [%d]:" % (index + 1) error.each do |field, value| puts "\t\t%s: %s" % [field, value] end end end end
Get keywords related to a seed keyword
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright:: Copyright 2011, Google Inc. All Rights Reserved. # # License:: 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. # # This example retrieves keywords that are related to a given keyword. require 'adwords_api' def get_keyword_ideas(keyword_text, ad_group_id) # AdwordsApi::Api will read a config file from ENV['HOME']/adwords_api.yml # when called without parameters. adwords = AdwordsApi::Api.new # To enable logging of SOAP requests, set the log_level value to 'DEBUG' in # the configuration file or provide your own logger: # adwords.logger = Logger.new('adwords_xml.log') targeting_idea_srv = adwords.service(:TargetingIdeaService, API_VERSION) # Construct selector object. selector = { :idea_type => 'KEYWORD', :request_type => 'IDEAS' } selector[:requested_attribute_types] = [ 'KEYWORD_TEXT', 'SEARCH_VOLUME', 'AVERAGE_CPC', 'COMPETITION', 'CATEGORY_PRODUCTS_AND_SERVICES', ] selector[:paging] = { :start_index => 0, :number_results => PAGE_SIZE } search_parameters = [] search_parameters << { # The 'xsi_type' field allows you to specify the xsi:type of the object # being created. It's only necessary when you must provide an explicit # type that the client library can't infer. :xsi_type => 'RelatedToQuerySearchParameter', :queries => [keyword_text] } search_parameters << { # Language setting (optional). # The ID can be found in the documentation: # https://developers.google.com/adwords/api/docs/appendix/languagecodes # Only one LanguageSearchParameter is allowed per request. :xsi_type => 'LanguageSearchParameter', :languages => [{:id => 1000}] } search_parameters << { # Network search parameter (optional). :xsi_type => 'NetworkSearchParameter', :network_setting => { :target_google_search => true, :target_search_network => false, :target_content_network => false, :target_partner_search_network => false } } unless ad_group_id.nil? search_parameters << { :xsi_type => 'SeedAdGroupIdSearchParameter', :ad_group_id => ad_group_id } end selector[:search_parameters] = search_parameters # Define initial values. offset = 0 results = [] begin # Perform request. If this loop executes too many times in quick suggestion, # you may get a RateExceededError. See here for more info on handling these: # https://developers.google.com/adwords/api/docs/guides/rate-limits page = targeting_idea_srv.get(selector) results += page[:entries] if page and page[:entries] # Prepare next page request. offset += PAGE_SIZE selector[:paging][:start_index] = offset end while offset < page[:total_num_entries] # Display results. results.each do |result| data = result[:data] keyword = data['KEYWORD_TEXT'][:value] average_cpc = data['AVERAGE_CPC'][:value] competition = data['COMPETITION'][:value] products_and_services = data['CATEGORY_PRODUCTS_AND_SERVICES'][:value] average_monthly_searches = data['SEARCH_VOLUME'][:value] puts ("Keyword with text '%s', average monthly search volume %d, " + "average CPC %d, and competition %.2f was found with categories: %s") % [ keyword, average_monthly_searches, average_cpc[:micro_amount], competition, products_and_services ] end puts "Total keywords related to '%s': %d." % [keyword_text, results.length] end if __FILE__ == $0 API_VERSION = :v201809 PAGE_SIZE = 100 begin keyword_text = 'INSERT_KEYWORD_TEXT_HERE' # Optional: ad_group_id = 'INSERT_AD_GROUP_ID_HERE' ad_group_id = nil if ad_group_id == 'INSERT_AD_GROUP_ID_HERE' get_keyword_ideas(keyword_text, ad_group_id) # Authorization error. rescue AdsCommon::Errors::OAuth2VerificationRequired => e puts "Authorization credentials are not valid. Edit adwords_api.yml for " + "OAuth2 client ID and secret and run misc/setup_oauth2.rb example " + "to retrieve and store OAuth2 tokens." puts "See this wiki page for more details:\n\n " + 'https://github.com/googleads/google-api-ads-ruby/wiki/OAuth2' # HTTP errors. rescue AdsCommon::Errors::HttpError => e puts "HTTP Error: %s" % e # API errors. rescue AdwordsApi::Errors::ApiException => e puts "Message: %s" % e.message puts 'Errors:' e.errors.each_with_index do |error, index| puts "\tError [%d]:" % (index + 1) error.each do |field, value| puts "\t\t%s: %s" % [field, value] end end end end