The code samples below provide examples for managing campaigns using the AdWords API. Client Library.
Add a campaign group and set its performance target
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright:: Copyright 2017, 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 code example adds a campaign group and sets a performance target for that # group. To get campaigns, run get_campaigns.rb. To download reports, run # download_criteria_report_with_awql.rb. require 'date' require 'adwords_api' def add_campaign_groups_and_performance_targets(campaign_ids) # 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') campaign_group = create_campaign_group(adwords) add_campaigns_to_group(adwords, campaign_group, campaign_ids) create_performance_target(adwords, campaign_group) end def create_campaign_group(adwords) campaign_group_srv = adwords.service(:CampaignGroupService, API_VERSION) campaign_group = { :name => "Mars campaign group #%d" % (Time.new.to_f * 1000).to_i } operation = { :operand => campaign_group, :operator => 'ADD' } new_campaign_group = campaign_group_srv.mutate([operation])[:value].first puts "Campaign group with ID %d and name '%s' was created." % [ new_campaign_group[:id], new_campaign_group[:name] ] return new_campaign_group end def add_campaigns_to_group(adwords, campaign_group, campaign_ids) campaign_srv = adwords.service(:CampaignService, API_VERSION) operations = campaign_ids.map do |campaign_id| { :operand => { :id => campaign_id, :campaign_group_id => campaign_group[:id] }, :operator => 'SET' } end return_value = campaign_srv.mutate(operations) puts ("The following campaign IDs were added to the campaign group with " + " ID %d:") % campaign_group[:id] return_value[:value].each do |campaign| puts "\t%d" % campaign[:id] end end def create_performance_target(adwords, campaign_group) campaign_group_performance_target_srv = adwords.service( :CampaignGroupPerformanceTargetService, API_VERSION) campaign_group_performance_target = { :campaign_group_id => campaign_group[:id], :performance_target => { # Keep the CPC for the campaigns <=$3. :efficiency_target_type => 'CPC_LESS_THAN_OR_EQUAL_TO', :efficiency_target_value => 3_000_000, # Keep the maximum spend under $50. :spend_target_type => 'MAXIMUM', :spend_target => { :micro_amount => 50_000_000 }, # Aim for at least 3000 clicks. :volume_target_value => 3000, :volume_goal_type => 'MAXIMIZE_CLICKS', # Start the performance target today, and run it for the next 90 days. :start_date => DateTime.parse((Date.today).to_s).strftime('%Y%m%d'), :end_date => DateTime.parse((Date.today + 90).to_s).strftime('%Y%m%d') } } operation = { :operand => campaign_group_performance_target, :operator => 'ADD' } new_campaign_group_performance_target = campaign_group_performance_target_srv.mutate([operation])[:value].first puts ("Campaign group performance target with ID %s was added for campaign " + "group ID %d") % [new_campaign_group_performance_target[:id], new_campaign_group_performance_target[:campaign_group_id]] end if __FILE__ == $0 API_VERSION = :v201809 begin campaign_id_1 = 'INSERT_CAMPAIGN_ID_1_HERE'.to_i campaign_id_2 = 'INSERT_CAMPAIGN_ID_2_HERE'.to_i add_campaign_groups_and_performance_targets([campaign_id_1, campaign_id_2]) # 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
Add a label to multiple campaigns
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright:: Copyright 2014, 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 adds a label to multiple campaigns. require 'adwords_api' def add_campaign_labels(campaign_ids, label_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') campaign_srv = adwords.service(:CampaignService, API_VERSION) operations = campaign_ids.map do |campaign_id| { :operator => 'ADD', :operand => {:campaign_id => campaign_id, :label_id => label_id} } end response = campaign_srv.mutate_label(operations) if response and response[:value] response[:value].each do |campaign_label| puts "Campaign label for campaign ID %d and label ID %d was added.\n" % [campaign_label[:campaign_id], campaign_label[:label_id]] end end end if __FILE__ == $0 API_VERSION = :v201809 begin campaign_id_1 = 'INSERT_CAMPAIGN_ID_1_HERE'.to_i campaign_id_2 = 'INSERT_CAMPAIGN_ID_2_HERE'.to_i label_id = 'INSERT_LABEL_ID_HERE'.to_i add_campaign_labels([campaign_id_1, campaign_id_2], label_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
Add a campaign using BatchJobService
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright:: Copyright 2015, 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 code sample illustrates how to use BatchJobService to create a complete # campaign, including ad groups and keywords. require 'adwords_api' def add_complete_campaigns_using_batch_job() # 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') batch_job_srv = adwords.service(:BatchJobService, API_VERSION) batch_job_utils = adwords.batch_job_utils(API_VERSION) # Create a BatchJob. add_op = { :operator => 'ADD', :operand => {} } response = batch_job_srv.mutate([add_op]) batch_job = response[:value].first # Get the upload URL from the new job. upload_url = batch_job[:upload_url][:url] puts "Created BatchJob with ID %d, status '%s', and upload URL %s." % [batch_job[:id], batch_job[:status], upload_url] # Create a temporary ID generator that will produce a sequence of descending # negative numbers. temp_id_generator = TempIdGenerator.new() # Create an array of hashed operations generated from the batch_job_utils. operations = [] # Create an operation to create a new budget. budget_operation = build_budget_operation(temp_id_generator) operations << budget_operation # Create operations to create new campaigns. campaign_operations = build_campaign_operations( temp_id_generator, budget_operation) operations += campaign_operations # Create operations to create new negative keyword criteria for each # campaign. operations += build_campaign_criterion_operations(campaign_operations) # Create operations to create new ad groups. ad_group_operations = build_ad_group_operations( temp_id_generator, campaign_operations) operations += ad_group_operations # Create operations to create new ad group criteria (keywords). operations += build_ad_group_criterion_operations(ad_group_operations) # Create operations to create new ad group ads (text ads). operations += build_ad_group_ad_operations(ad_group_operations) # Use the batch_job_utils to upload all operations. batch_job_utils.upload_operations(operations, upload_url) puts "Uploaded %d operations for batch job with ID %d." % [operations.size, batch_job[:id]] # Poll for completion of the batch job using an exponential back off. poll_attempts = 0 is_pending = true selector = { :fields => ['Id', 'Status', 'DownloadUrl', 'ProcessingErrors', 'ProgressStats'], :predicates => [{ :field => 'Id', :operator => 'IN', :values => [batch_job[:id]] }] } begin sleep_seconds = 30 * (2 ** poll_attempts) puts "Sleeping for %d seconds" % sleep_seconds sleep(sleep_seconds) batch_job = batch_job_srv.get(selector)[:entries].first puts "Batch job ID %d has status '%s'." % [batch_job[:id], batch_job[:status]] poll_attempts += 1 is_pending = PENDING_STATUSES.include?(batch_job[:status]) end while is_pending and poll_attempts < MAX_POLL_ATTEMPTS if is_pending raise StandardError, "Job is still in pending state after polling %d times." % MAX_POLL_ATTEMPTS end unless batch_job[:processing_errors].nil? batch_job[:processing_errors].each_with_index do |processing_error, i| puts ("Processing error [%d]: errorType=%s, trigger=%s, errorString=%s" + "fieldPath=%s, reason=%s") % [i, processing_error[:api_error_type], processing_error[:trigger], processing_error[:error_string], processing_error[:field_path], processing_error[:reason]] end end unless batch_job[:download_url].nil? or batch_job[:download_url][:url].nil? mutate_response = batch_job_utils.get_job_results( batch_job[:download_url][:url]) puts "Downloaded results from '%s':" % batch_job[:download_url][:url] mutate_response.each do |mutate_result| outcome = "FAILURE" outcome = "SUCCESS" if mutate_result[:error_list].nil? puts " Operation [%d] - %s" % [mutate_result[:index], outcome] end end end # Custom class to generate temporary negative IDs for created entities to # reference each other. class TempIdGenerator def initialize() @counter = -1 end def next() ret = @counter @counter -= 1 return ret end end def get_time_microseconds() return (Time.now.to_f * 1000000).to_i end def build_budget_operation(temp_id_generator) budget = { :budget_id => temp_id_generator.next, :name => "Interplanetary Cruise %d" % get_time_microseconds(), :amount => { :micro_amount => 50000000 }, :delivery_method => 'STANDARD' } budget_operation = { # The xsi_type of the operation can usually be guessed by the API because # a given service only handles one type of operation. However, batch jobs # process operations of different types, so the xsi_type must always be # explicitly defined for these operations. :xsi_type => 'BudgetOperation', :operator => 'ADD', :operand => budget } return budget_operation end def build_campaign_operations(temp_id_generator, budget_operation) budget_id = budget_operation[:operand][:budget_id] operations = [] NUMBER_OF_CAMPAIGNS_TO_ADD.times do campaign = { :name => "Batch Campaign %s" % get_time_microseconds(), # Recommendation: Set the campaign to PAUSED when creating it to stop the # ads from immediately serving. Set to ENABLED once you've added # targeting and the ads are ready to serve. :status => 'PAUSED', :id => temp_id_generator.next, :advertising_channel_type => 'SEARCH', :budget => { :budget_id => budget_id }, :bidding_strategy_configuration => { :bidding_strategy_type => 'MANUAL_CPC', # You can optionally provide a bidding scheme in place of the type. :bidding_scheme => { :xsi_type => 'ManualCpcBiddingScheme' } } } operation = { :xsi_type => 'CampaignOperation', :operator => 'ADD', :operand => campaign } operations << operation end return operations end def build_campaign_criterion_operations(campaign_operations) operations = [] campaign_operations.each do |campaign_operation| keyword = { :xsi_type => 'Keyword', :match_type => 'BROAD', :text => 'venus' } negative_criterion = { :xsi_type => 'NegativeCampaignCriterion', :campaign_id => campaign_operation[:operand][:id], :criterion => keyword } operation = { :xsi_type => 'CampaignCriterionOperation', :operator => 'ADD', :operand => negative_criterion } operations << operation end return operations end def build_ad_group_operations(temp_id_generator, campaign_operations) operations = [] campaign_operations.each do |campaign_operation| NUMBER_OF_ADGROUPS_TO_ADD.times do ad_group = { :campaign_id => campaign_operation[:operand][:id], :id => temp_id_generator.next, :name => "Batch Ad Group %s" % get_time_microseconds(), :bidding_strategy_configuration => { :bids => [ { :xsi_type => 'CpcBid', :bid => {:micro_amount => 10000000} } ] } } operation = { :xsi_type => 'AdGroupOperation', :operator => 'ADD', :operand => ad_group } operations << operation end end return operations end def build_ad_group_criterion_operations(ad_group_operations) operations = [] ad_group_operations.each do |ad_group_operation| NUMBER_OF_KEYWORDS_TO_ADD.times do |i| text = "mars%d" % i # Make 50% of keywords invalid to demonstrate error handling. text = text + "!!!" if i % 2 == 0 keyword = { :xsi_type => 'Keyword', :text => text, :match_type => 'BROAD' } biddable_criterion = { :xsi_type => 'BiddableAdGroupCriterion', :ad_group_id => ad_group_operation[:operand][:id], :criterion => keyword } operation = { :xsi_type => 'AdGroupCriterionOperation', :operator => 'ADD', :operand => biddable_criterion } operations << operation end end return operations end def build_ad_group_ad_operations(ad_group_operations) operations = [] ad_group_operations.each do |ad_group_operation| text_ad = { :xsi_type => 'ExpandedTextAd', :headline_part1 => 'Luxury Cruise to Mars', :headling_part2 => 'Visit the Red Planet in style.', :description => 'Low-gravity fun for everyone!', :final_urls => ['http://www.example.com/1'] } ad_group_ad = { :ad_group_id => ad_group_operation[:operand][:id], :ad => text_ad } operation = { :xsi_type => 'AdGroupAdOperation', :operator => 'ADD', :operand => ad_group_ad } operations << operation end return operations end if __FILE__ == $0 API_VERSION = :v201809 NUMBER_OF_CAMPAIGNS_TO_ADD = 2 NUMBER_OF_ADGROUPS_TO_ADD = 2 NUMBER_OF_KEYWORDS_TO_ADD = 5 MAX_POLL_ATTEMPTS = 5 PENDING_STATUSES = ['ACTIVE', 'AWAITING_FILE', 'CANCELING'] begin add_complete_campaigns_using_batch_job() # 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
Create a draft and access its 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 illustrates how to create a draft and access its associated # draft campaign. # # See the Campaign Drafts and Experiments guide for more information: # https://developers.google.com/adwords/api/docs/guides/campaign-drafts-experiments require 'adwords_api' require 'date' def add_draft(base_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') draft_srv = adwords.service(:DraftService, API_VERSION) draft = { :base_campaign_id => base_campaign_id, :draft_name => 'Test Draft #%d' % (Time.new.to_f * 1000).to_i } draft_operation = {:operator => 'ADD', :operand => draft} draft_result = draft_srv.mutate([draft_operation]) draft = draft_result[:value].first draft_id = draft[:draft_id] draft_campaign_id = draft[:draft_campaign_id] puts "Draft with id %d and base campaign %d and draft campaign %d created" % [draft_id, draft[:base_campaign_id], draft_campaign_id] # Once the draft is created, you can modify the draft campaign as if it # were a real campaign. For example, you may add criteria, adjust bids, # or even include additional ads. Adding a criterion is shown here. campaign_criterion_srv = adwords.service(:CampaignCriterionService, API_VERSION) criterion = { :xsi_type => 'Language', :id => 1003 # Spanish } criterion_operation = { # Make sure to use the draft_campaign_id when modifying the virtual draft # campaign. :operator => 'ADD', :operand => { :campaign_id => draft_campaign_id, :criterion => criterion } } criterion_result = campaign_criterion_srv.mutate([criterion_operation]) criterion = criterion_result[:value].first puts "Draft updated to include criteria in campaign %d" % draft_campaign_id end if __FILE__ == $0 API_VERSION = :v201809 begin base_campaign_id = 'INSERT_BASE_CAMPAIGN_ID_HERE'.to_i add_draft(base_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
Upload keywords incrementally using BatchJobService
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright:: Copyright 2015, 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 illustrates how to perform multiple requests using the # BatchJobService using incremental uploads. require 'adwords_api' def add_keywords_using_incremental_batch_job(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') batch_job_srv = adwords.service(:BatchJobService, API_VERSION) batch_job_utils = adwords.batch_job_utils(API_VERSION) # Create a BatchJob. add_op = { :operator => 'ADD', :operand => {} } response = batch_job_srv.mutate([add_op]) batch_job = response[:value].first # Get the upload URL from the new job. upload_url = batch_job[:upload_url][:url] puts "Created BatchJob with ID %d, status '%s', and upload URL %s." % [batch_job[:id], batch_job[:status], upload_url] # Upload #1 incremental_helper = batch_job_utils.start_incremental_upload(upload_url) operations = create_keyword_operations(ad_group_id) incremental_helper.upload(operations) # Upload #2 operations = create_keyword_operations(ad_group_id) incremental_helper.upload(operations) # Upload #3 operations = create_keyword_operations(ad_group_id) incremental_helper.upload(operations, true) # Poll for completion of the batch job using an exponential back off. poll_attempts = 0 is_pending = true cancel_requested = false selector = { :fields => ['Id', 'Status', 'DownloadUrl', 'ProcessingErrors', 'ProgressStats'], :predicates => [{ :field => 'Id', :operator => 'IN', :values => [batch_job[:id]] }] } begin sleep_seconds = 30 * (2 ** poll_attempts) puts "Sleeping for %d seconds" % sleep_seconds sleep(sleep_seconds) batch_job = batch_job_srv.get(selector)[:entries].first puts "Batch job ID %d has status '%s'." % [batch_job[:id], batch_job[:status]] poll_attempts += 1 is_pending = PENDING_STATUSES.include?(batch_job[:status]) if is_pending && !cancel_requested && poll_attempts == MAX_POLL_ATTEMPTS batch_job[:status] = 'CANCELING' set_op = { :operator => 'SET', :operand => batch_job } # Only request cancellation once per job. cancel_requested = true begin batch_job = batch_job_srv.mutate([set_op])[:value].first puts "Requested cancellation of batch job with ID %d" % batch_job[:id] rescue AdwordsApi::Errors::ApiException => e if !e.message.nil? && e.message.include?('INVALID_STATE_CHANGE') puts ("Attempt to cancel batch job with ID %d was rejected " + "because the job already completed or was canceled.") % batch_job[:id] next end raise e end end end while is_pending and poll_attempts < MAX_POLL_ATTEMPTS if is_pending raise StandardError, "Job is still in pending state after polling %d times." % MAX_POLL_ATTEMPTS end if batch_job[:status] == 'CANCELED' puts "Job was canceled before completion." return end unless batch_job[:processing_errors].nil? batch_job[:processing_errors].each_with_index do |processing_error, i| puts ("Processing error [%d]: errorType=%s, trigger=%s, errorString=%s" + "fieldPath=%s, reason=%s") % [i, processing_error[:api_error_type], processing_error[:trigger], processing_error[:error_string], processing_error[:field_path], processing_error[:reason]] end end unless batch_job[:download_url].nil? or batch_job[:download_url][:url].nil? mutate_response = batch_job_utils.get_job_results( batch_job[:download_url][:url]) puts "Downloaded results from '%s':" % batch_job[:download_url][:url] mutate_response.each do |mutate_result| outcome = "FAILURE" outcome = "SUCCESS" if mutate_result[:error_list].nil? puts " Operation [%d] - %s" % [mutate_result[:index], outcome] end end end def create_keyword_operations(ad_group_id) operations = [] KEYWORD_COUNT.times do |i| text = "keyword %d" % i # Make 10% of keywords invalid to demonstrate error handling. text = text + "!!!" if i % 10 == 0 keyword = { :xsi_type => 'Keyword', :text => text, :match_type => 'BROAD' } biddable_criterion = { :xsi_type => 'BiddableAdGroupCriterion', :ad_group_id => ad_group_id, :criterion => keyword } operation = { :xsi_type => 'AdGroupCriterionOperation', :operator => 'ADD', :operand => biddable_criterion } operations << operation end return operations end if __FILE__ == $0 API_VERSION = :v201809 KEYWORD_COUNT = 100 MAX_POLL_ATTEMPTS = 5 PENDING_STATUSES = ['ACTIVE', 'AWAITING_FILE', 'CANCELING'] begin ad_group_id = 'INSERT_AD_GROUP_ID_HERE'.to_i add_keywords_using_incremental_batch_job(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
Create a trial
#!/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 illustrates how to create a trial and wait for it to complete. # # See the Campaign Drafts and Experiments guide for more information: # https://developers.google.com/adwords/api/docs/guides/campaign-drafts-experiments require 'adwords_api' require 'date' def add_trial(draft_id, base_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') trial_srv = adwords.service(:TrialService, API_VERSION) trial_async_error_srv = adwords.service(:TrialAsyncErrorService, API_VERSION) trial = { :draft_id => draft_id, :base_campaign_id => base_campaign_id, :name => 'Test Trial #%d' % (Time.new.to_f * 1000).to_i, :traffic_split_percent => 50, :traffic_split_type => 'RANDOM_QUERY' } trial_operation = {:operator => 'ADD', :operand => trial} trial_result = trial_srv.mutate([trial_operation]) trial_id = trial_result[:value].first[:id] # Since creating a trial is asynchronous, we have to poll it to wait for # it to finish. selector = { :fields => ['Id', 'Status', 'BaseCampaignId', 'TrialCampaignId'], :predicates => [ :field => 'Id', :operator => 'IN', :values => [trial_id] ] } poll_attempts = 0 is_pending = true trial = nil begin sleep_seconds = 30 * (2 ** poll_attempts) puts "Sleeping for %d seconds" % sleep_seconds sleep(sleep_seconds) trial = trial_srv.get(selector)[:entries].first puts "Trial ID %d has status '%s'" % [trial[:id], trial[:status]] poll_attempts += 1 is_pending = (trial[:status] == 'CREATING') end while is_pending and poll_attempts < MAX_POLL_ATTEMPTS if trial[:status] == 'ACTIVE' # The trial creation was successful. puts "Trial created with id %d and trial campaign id %d" % [trial[:id], trial[:trial_campaign_id]] elsif trial[:status] == 'CREATION_FAILED' # The trial creation failed, and errors can be fetched from the # TrialAsyncErrorService. selector = { :fields => ['TrialId', 'AsyncError'], :predicates => [ {:field => 'TrialId', :operator => 'IN', :values => [trial[:id]]} ] } errors = trial_async_error_srv.get(selector)[:entries] if errors.nil? puts "Could not retrieve errors for trial %d" % trial[:id] else puts "Could not create trial due to the following errors:" errors.each_with_index do |error, i| puts "Error #%d: %s" % [i, error[:async_error]] end end else # Most likely, the trial is still being created. You can continue polling, # but we have limited the number of attempts in the example. puts ("Timed out waiting to create trial from draft %d with base " + "campaign %d") % [draft_id, base_campaign_id] end end if __FILE__ == $0 API_VERSION = :v201809 MAX_POLL_ATTEMPTS = 6 begin draft_id = 'INSERT_DRAFT_ID_HERE'.to_i base_campaign_id = 'INSERT_BASE_CAMPAIGN_ID_HERE'.to_i add_trial(draft_id, base_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 all disapproved ads in an ad group
#!/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 illustrates how to retrieve all the disapproved ads in a given # ad group. require 'adwords_api' def get_all_disapproved_ads(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') ad_group_ad_srv = adwords.service(:AdGroupAdService, API_VERSION) # Get all the ads in this ad group. selector = { :fields => ['Id', 'PolicySummary'], :ordering => [{:field => 'Id', :sort_order => 'ASCENDING'}], :predicates => [ {:field => 'AdGroupId', :operator => 'IN', :values => [ad_group_id]}, { :field => 'CombinedApprovalStatus', :operator => 'IN', :values => ['DISAPPROVED'] } ], :paging => { :start_index => 0, :number_results => PAGE_SIZE } } # Set the initial values. offset, page = 0, {} disapproved_ads_count = 0 # Look through all ads to find ones that are disapproved. begin page = ad_group_ad_srv.get(selector) if page[:entries] page[:entries].each do |ad_group_ad| policy_summary = ad_group_ad[:policy_summary] disapproved_ads_count += 1 puts ("Ad with ID %d and type '%s' was disapproved with the " + "following policy topic entries:") % [ad_group_ad[:ad][:id], ad_group_ad[:ad][:ad_type]] policy_summary[:policy_topic_entries].each do |policy_topic_entry| puts " topic id: %s, topic name: '%s', Help Center URL: '%s'" % [ policy_topic_entry[:policy_topic_id], policy_topic_entry[:policy_topic_name], policy_topic_entry[:policy_topic_help_center_url] ] unless policy_topic_entry[:policy_topic_evidences].nil? policy_topic_entry[:policy_topic_evidences].each do |evidence| puts " evidence type: '%s'" % evidence[:policy_topic_evidence_type] unless evidence[:evidence_text_list].nil? evidence[:evidence_text_list].each_with_index do |text, i| puts " evidence text[%d]: '%s'" % [i, text] end end end end end end end offset += PAGE_SIZE selector[:paging][:start_index] = offset end while page[:total_num_entries] > offset puts "%d disapproved ads were found." % disapproved_ads_count end if __FILE__ == $0 API_VERSION = :v201809 PAGE_SIZE = 100 begin # ID of an ad group to get disapproved ads for. ad_group_id = 'INSERT_AD_GROUP_ID_HERE'.to_i get_all_disapproved_ads(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
Get all disapproved ads in an ad group using AWQL
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright:: Copyright 2012, 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 illustrates how to retrieve all the disapproved ads in a given # ad group with AWQL. require 'adwords_api' def get_all_disapproved_ads_with_awql(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') ad_group_ad_srv = adwords.service(:AdGroupAdService, API_VERSION) # Get all the ads in this ad group. query_builder = adwords.service_query_builder do |b| b.select('Id', 'PolicySummary') b.where('AdGroupId').equal_to(ad_group_id) b.where('CombinedApprovalStatus').equal_to('DISAPPROVED') b.order_by_asc('Id') b.limit(0, PAGE_SIZE) end query = query_builder.build # Set the initial values. disapproved_ads_count = 0 # Look through all ads to find ones that are disapproved. loop do page_query = query.to_s page = ad_group_ad_srv.query(page_query) if page[:entries] page[:entries].each do |ad_group_ad| policy_summary = ad_group_ad[:policy_summary] disapproved_ads_count += 1 puts ("Ad with ID %d and type '%s' was disapproved with the " + "following policy topic entries:") % [ad_group_ad[:ad][:id], ad_group_ad[:ad][:ad_type]] policy_summary[:policy_topic_entries].each do |policy_topic_entry| puts " topic id: %s, topic name: '%s', Help Center URL: '%s'" % [ policy_topic_entry[:policy_topic_id], policy_topic_entry[:policy_topic_name], policy_topic_entry[:policy_topic_help_center_url] ] unless policy_topic_entry[:policy_topic_evidences].nil? policy_topic_entry[:policy_topic_evidences].each do |evidence| puts " evidence type: '%s'" % evidence[:policy_topic_evidence_type] unless evidence[:evidence_text_list].nil? evidence[:evidence_text_list].each_with_index do |text, i| puts " evidence text[%d]: '%s'" % [i, text] end end end end end end end break unless query.has_next(page) query.next_page end puts "%d disapproved ads were found." % disapproved_ads_count end if __FILE__ == $0 API_VERSION = :v201809 PAGE_SIZE = 100 begin # ID of an ad group to get disapproved ads for. ad_group_id = 'INSERT_AD_GROUP_ID_HERE'.to_i get_all_disapproved_ads_with_awql(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
Get all campaigns with a specific label
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright:: Copyright 2014, 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 campaigns with a specific label. To add a label # to campaigns, run add_campaign_labels.rb. require 'adwords_api' def get_campaigns_by_label(label_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') campaign_srv = adwords.service(:CampaignService, API_VERSION) # Get all the ad groups for this campaign. selector = { :fields => ['Id', 'Name', 'Labels'], :ordering => [{:field => 'Name', :sort_order => 'ASCENDING'}], :predicates => [ { :field => 'Labels', # Labels filtering is performed by ID. You can use CONTAINS_ANY to # select campaigns with any of the label IDs, CONTAINS_ALL to select # campaigns with all of the label IDs, or CONTAINS_NONE to select # campaigns with none of the label IDs. :operator => 'CONTAINS_ANY', :values => [label_id] } ], :paging => { :start_index => 0, :number_results => PAGE_SIZE } } # Set initial values. offset, page = 0, {} begin page = campaign_srv.get(selector) if page[:entries] page[:entries].each do |campaign| label_string = campaign[:labels].map do |label| '%d/"%s"' % [label[:id], label[:name]] end.join(', ') puts 'Campaign found with name "%s" and ID %d and labels: %s.' % [campaign[:name], campaign[:id], label_string] end # Increment values to request the next page. offset += PAGE_SIZE selector[:paging][:start_index] = offset end end while page[:total_num_entries] > offset end if __FILE__ == $0 API_VERSION = :v201809 PAGE_SIZE = 500 begin # Label ID to get campaigns for. label_id = 'INSERT_LABEL_ID_HERE'.to_i get_campaigns_by_label(label_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
Graduate a trial
#!/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 illustrates how to graduate a trial. # # See the Campaign Drafts and Experiments guide for more information: # https://developers.google.com/adwords/api/docs/guides/campaign-drafts-experiments require 'adwords_api' require 'date' def graduate_trial(trial_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') trial_srv = adwords.service(:TrialService, API_VERSION) budget_srv = adwords.service(:BudgetService, API_VERSION) # To graduate a trial, you must specify a different budget from the base # campaign. The base campaign (in order to have had a trial based on it) # must have a non-shared budget, so it cannot be shared with the new # independent campaign created by graduation. budget = { :name => 'Budget #%d' % (Time.new.to_f * 1000).to_i, :amount => {:micro_amount => 50000000}, :delivery_method => 'STANDARD' } budget_operation = {:operator => 'ADD', :operand => budget} # Add budget. return_budget = budget_srv.mutate([budget_operation]) budget_id = return_budget[:value].first[:budget_id] trial = { :id => trial_id, :budget_id => budget_id, :status => 'GRADUATED' } trial_operation = {:operator => 'SET', :operand => trial} # Update the trial. return_trial = trial_srv.mutate([trial_operation]) trial = return_trial[:value].first # Graduation is a synchronous operation, so the campaign is already ready. # If you promote instead, make sure to see the polling scheme demonstrated # in add_trial.rb to wait for the asynchronous operation to finish. puts ("Trial ID %d graduated. Campaign %d was given a new budget ID %d and" + "is no longer dependent on this trial.") % [trial[:id], trial[:trial_campaign_id], budget_id] end if __FILE__ == $0 API_VERSION = :v201809 begin trial_id = 'INSERT_TRIAL_ID_HERE'.to_i graduate_trial(trial_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
Set ad parameters for a keyword ad group 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 illustrates how to create a text ad with ad parameters. To add an # ad group, run add_ad_group.rb. To add a keyword, run add_keywords.rb. require 'adwords_api' def set_ad_parameters(ad_group_id, criterion_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') ad_group_ad_srv = adwords.service(:AdGroupAdService, API_VERSION) ad_param_srv = adwords.service(:AdParamService, API_VERSION) # Prepare for adding ad. ad_operation = { :operator => 'ADD', :operand => { :ad_group_id => ad_group_id, :ad => { # 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 => 'TextAd', :headline => 'Luxury Mars Cruises', :description1 => 'Low-gravity fun for {param1:cheap}.', :description2 => 'Only {param2:a few} seats left!', :final_urls => ['http://www.example.com'], :display_url => 'www.example.com' } } } # Add ad. response = ad_group_ad_srv.mutate([ad_operation]) ad = response[:value].first[:ad] puts "Text ad ID %d was successfully added." % ad[:id] # Prepare for setting ad parameters. price_operation = { :operator => 'SET', :operand => { :ad_group_id => ad_group_id, :criterion_id => criterion_id, :param_index => 1, :insertion_text => '$100' } } seat_operation = { :operator => 'SET', :operand => { :ad_group_id => ad_group_id, :criterion_id => criterion_id, :param_index => 2, :insertion_text => '50' } } # Set ad parameters. response = ad_param_srv.mutate([price_operation, seat_operation]) puts 'Parameters were successfully updated.' end if __FILE__ == $0 API_VERSION = :v201809 begin # IDs of ad group and criterion to set ad parameter for. ad_group_id = 'INSERT_AD_GROUP_ID_HERE'.to_i criterion_id = 'INSERT_CRITERION_ID_HERE'.to_i set_ad_parameters(ad_group_id, criterion_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
Set a bid modifier on a campaign
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright:: Copyright 2013, 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 sets a bid modifier for the mobile platform on given campaign. # To get campaigns, run get_campaigns.rb. require 'adwords_api' def set_criterion_bid_modifier(campaign_id, bid_modifier) # 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') campaign_criterion_srv = adwords.service(:CampaignCriterionService, API_VERSION) # Create campaign criterion with modified bid. campaign_criterion = { :campaign_id => campaign_id, # Mobile platform. The ID can be found in the documentation. # https://developers.google.com/adwords/api/docs/appendix/platforms :criterion => { :xsi_type => 'Platform', :id => 30001 }, :bid_modifier => bid_modifier } # Create operation. operation = { :operator => 'SET', :operand => campaign_criterion } response = campaign_criterion_srv.mutate([operation]) if response and response[:value] criteria = response[:value] criteria.each do |campaign_criterion| criterion = campaign_criterion[:criterion] puts ("Campaign criterion with campaign ID %d, criterion ID %d was " + "updated with bid modifier %f.") % [campaign_criterion[:campaign_id], criterion[:id], campaign_criterion[:bid_modifier]] end else puts 'No criteria were returned.' end end if __FILE__ == $0 API_VERSION = :v201809 begin # ID of a campaign to use mobile bid modifier for. campaign_id = 'INSERT_CAMPAIGN_ID_HERE'.to_i # Bid modifier to set. bid_modifier = 1.5 set_criterion_bid_modifier(campaign_id, bid_modifier) # 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
Validate text ad through setValidateOnly header
#!/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 shows how to use the 'validate only' header. No objects will be # created, but exceptions will still be thrown. require 'adwords_api' def validate_text_ad(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') ad_group_ad_srv = adwords.service(:AdGroupAdService, API_VERSION) # Enable 'validate only' option. adwords.validate_only = true # Prepare for adding text ad. operation = { :operator => 'ADD', :operand => { :ad_group_id => ad_group_id, :ad => { :xsi_type => 'ExpandedTextAd', :headline_part1 => 'Luxury Cruise to Mars', :headline_part2 => 'Visit the Red Planet in style.', :description => 'Low-gravity fun for everyone!', :final_urls => ['http://www.example.com'] } } } # Validate text ad add operation. response = ad_group_ad_srv.mutate([operation]) if response and response[:value] ad = response[:value].first puts "Unexpected ad creation! Name '%s', ID %d and status '%s'." % [campaign[:name], campaign[:id], campaign[:status]] else puts 'Text ad validated, no error thrown and no ad created.' end # Now let's check an invalid ad using extra punctuation to trigger an error. operation[:operand][:ad][:headline_part1] = 'Luxury Cruise to Mars!!!!!' # Validate text ad add operation. begin response = ad_group_ad_srv.mutate([operation]) if response and response[:value] ad = response[:value].first raise StandardError, ("Unexpected ad creation! Name '%s', ID %d and " + "status '%s'.") % [campaign[:name], campaign[:id], campaign[:status]] end rescue AdwordsApi::Errors::ApiException => e puts "Validation correctly failed with an exception: %s" % e.class end end if __FILE__ == $0 API_VERSION = :v201809 begin ad_group_id = 'INSERT_AD_GROUP_ID_HERE'.to_i validate_text_ad(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