The code samples below provide examples of common advanced operations using the AdWords API. Client Library.
Add an ad customizer feed
#!/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 adds an ad customizer feed using Extension Services. Then it adds # an ad that uses the feed to populate dynamic data. require 'adwords_api' require 'date' def add_ad_customizers(feed_name, ad_group_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') feed_item_srv = adwords.service(:FeedItemService, API_VERSION) ad_group_ad_srv = adwords.service(:AdGroupAdService, API_VERSION) # Create a customizer feed. One feed per account can be used for all ads. feed_data = create_customizer_feed(adwords, feed_name) # Now adding feed items -- the values we'd like to place. now_date = Date.today() items_data = [ { :name => 'Mars', :price => '$1234.56', :date => now_date.strftime('%Y%m01 000000'), :ad_group_id => ad_group_ids[0] }, { :name => 'Venus', :price => '$1450.00', :date => now_date.strftime('%Y%m15 000000'), :ad_group_id => ad_group_ids[1] } ] feed_items = items_data.map do |item| { :feed_id => feed_data[:feed_id], :attribute_values => [ { :feed_attribute_id => feed_data[:name_id], :string_value => item[:name] }, { :feed_attribute_id => feed_data[:price_id], :string_value => item[:price] }, { :feed_attribute_id => feed_data[:date_id], :string_value => item[:date] } ] } end feed_items_operations = feed_items.map do |item| {:operator => 'ADD', :operand => item} end response = feed_item_srv.mutate(feed_items_operations) if response and response[:value] response[:value].each do |feed_item| puts 'Feed item with ID %d was added.' % feed_item[:feed_item_id] end else raise new StandardError, 'No feed items were added.' end restrict_feed_item_to_ad_group(adwords, response[:value][0], ad_group_ids[0]) restrict_feed_item_to_ad_group(adwords, response[:value][1], ad_group_ids[1]) # All set! We can now create ads with customizations. expanded_text_ad = { :xsi_type => 'ExpandedTextAd', :headline_part1 => 'Luxury Cruise to {=%s.Name}' % feed_name, :headline_part2 => 'Only {=%s.Price}' % feed_name, :description => 'Offer ends in {=countdown(%s.Date)}!' % feed_name, :final_urls => ['http://www.example.com'] } # We add the same ad to both ad groups. When they serve, they will show # different values, since they match different feed items. operations = ad_group_ids.map do |ad_group_id| { :operator => 'ADD', :operand => { :ad_group_id => ad_group_id, :ad => expanded_text_ad.dup() } } end response = ad_group_ad_srv.mutate(operations) if response and response[:value] ads = response[:value] ads.each do |ad| puts "\tCreated an ad with ID %d, type '%s' and status '%s'" % [ad[:ad][:id], ad[:ad][:ad_type], ad[:status]] end else raise StandardError, 'No ads were added.' end end def create_customizer_feed(adwords, feed_name) ad_customizer_srv = adwords.service(:AdCustomizerFeedService, API_VERSION) feed = { :feed_name => feed_name, :feed_attributes => [ {:name => 'Name', :type => 'STRING'}, {:name => 'Price', :type => 'PRICE'}, {:name => 'Date', :type => 'DATE_TIME'} ] } operation = {:operand => feed, :operator => 'ADD'} added_feed = ad_customizer_srv.mutate([operation])[:value].first() puts "Created ad customizer feed with ID = %d and name = '%s'." % [added_feed[:feed_id], added_feed[:feed_name]] added_feed[:feed_attributes].each do |feed_attribute| puts " ID: %d, name: '%s', type: %s" % [feed_attribute[:id], feed_attribute[:name], feed_attribute[:type]] end return { :feed_id => added_feed[:feed_id], :name_id => added_feed[:feed_attributes][0][:id], :price_id => added_feed[:feed_attributes][1][:id], :date_id => added_feed[:feed_attributes][2][:id] } end def restrict_feed_item_to_ad_group(adwords, feed_item, ad_group_id) # Optional: Restrict this feed item to only serve with ads for the # specified ad group ID. feed_item_target_srv = adwords.service(:FeedItemTargetService, API_VERSION) ad_group_target = { :xsi_type => 'FeedItemAdGroupTarget', :feed_id => feed_item[:feed_id], :feed_item_id => feed_item[:feed_item_id], :ad_group_id => ad_group_id } operation = { :operator => 'ADD', :operand => ad_group_target } retval = feed_item_target_srv.mutate([operation]) new_ad_group_target = retval[:value].first puts ('Feed item target for feed ID %d and feed item ID %d was created to ' + 'restrict serving to ad group ID %d') % [new_ad_group_target[:feed_id], new_ad_group_target[:feed_item_id], new_ad_group_target[:ad_group_id]] end if __FILE__ == $0 API_VERSION = :v201809 begin feed_name = 'INSERT_FEED_NAME_HERE'.to_s ad_group_ids = [ 'INSERT_AD_GROUP_ID_HERE'.to_i, 'INSERT_AD_GROUP_ID_HERE'.to_i ] add_ad_customizers(feed_name, ad_group_ids) # 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 an ad group level bid modifier
#!/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 illustrates how to add an ad group level mobile bid modifier # override for a campaign. require 'adwords_api' def add_ad_group_bid_modifier(ad_group_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') bid_modifier_srv = adwords.service(:AdGroupBidModifierService, API_VERSION) # Mobile criterion ID. criterion_id = 30001 # Prepare to add an ad group level override. operation = { # Use 'ADD' to add a new modifier and 'SET' to update an existing one. A # modifier can be removed with the 'REMOVE' operator. :operator => 'ADD', :operand => { :ad_group_id => ad_group_id, :criterion => { :xsi_type => 'Platform', :id => criterion_id }, :bid_modifier => bid_modifier } } # Add ad group level mobile bid modifier. response = bid_modifier_srv.mutate([operation]) if response and response[:value] modifier = response[:value].first value = modifier[:bid_modifier] || 'unset' puts ('Campaign ID %d, AdGroup ID %d, Criterion ID %d was updated with ' + 'ad group level modifier: %s') % [modifier[:campaign_id], modifier[:ad_group_id], modifier[:criterion][:id], value] else puts 'No modifiers were added.' end end if __FILE__ == $0 API_VERSION = :v201809 begin # ID of an ad group to add an override for. ad_group_id = 'INSERT_AD_GROUP_ID_HERE'.to_i # Bid modifier to override with. bid_modifier = 1.5 add_ad_group_bid_modifier(ad_group_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
Add a page feed specifying URLs for a DSA campaign
#!/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 page feed to specify precisely which URLs to use with # your Dynamic Search Ads campaign. To use a Dynamic Search Ads campaign, run # add_dynamic_search_ads_campaign.rb. To get campaigns, run get_campaigns.rb. require 'adwords_api' def add_dynamic_page_feed(campaign_id, 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') dsa_page_url_label = "discounts" # Get the page feed details. This code example creates a new feed, but you can # fetch and re-use an existing feed. feed_details = create_feed(adwords) create_feed_mapping(adwords, feed_details) create_feed_items(adwords, feed_details, dsa_page_url_label) # Associate the page feed with the campaign. update_campaign_dsa_setting(adwords, campaign_id, feed_details) # Optional: Target web pages matching the feed's label in the ad group. add_dsa_targeting(adwords, ad_group_id, dsa_page_url_label) puts "Dynamic page feed setup is complete for campaign ID %d." % campaign_id end def create_feed(adwords) feed_srv = adwords.service(:FeedService, API_VERSION) url_attribute = { :type => 'URL_LIST', :name => 'Page URL' } label_attribute = { :type => 'STRING_LIST', :name => 'Label' } dsa_page_feed = { :name => 'DSA Feed #%s' % (Time.now.to_f * 1000).to_i, :attributes => [url_attribute, label_attribute], :origin => 'USER' } operation = { :operand => dsa_page_feed, :operator => 'ADD' } new_feed = feed_srv.mutate([operation])[:value].first feed_details = { :feed_id => new_feed[:id], :url_attribute_id => new_feed[:attributes][0][:id], :label_attribute_id => new_feed[:attributes][1][:id] } puts ("Feed with name '%s' and ID %d with urlAttributeId %d and " + "labelAttributeId %d was created.") % [ new_feed[:name], feed_details[:feed_id], feed_details[:url_attribute_id], feed_details[:label_attribute_id] ] return feed_details end def create_feed_mapping(adwords, feed_details) feed_mapping_srv = adwords.service(:FeedMappingService, API_VERSION) url_field_mapping = { :feed_attribute_id => feed_details[:url_attribute_id], :field_id => DSA_PAGE_URLS_FIELD_ID } label_field_mapping = { :feed_attribute_id => feed_details[:label_attribute_id], :field_id => DSA_LABEL_FIELD_ID } feed_mapping = { :criterion_type => DSA_PAGE_FEED_CRITERION_TYPE, :feed_id => feed_details[:feed_id], :attribute_field_mappings => [url_field_mapping, label_field_mapping] } operation = { :operand => feed_mapping, :operator => 'ADD' } new_feed_mapping = feed_mapping_srv.mutate([operation])[:value].first puts ("Feed mapping with ID %d and criterionType %d was saved for feed " + "with ID %d.") % [ new_feed_mapping[:feed_mapping_id], new_feed_mapping[:criterion_type], new_feed_mapping[:feed_id] ] end def create_feed_items(adwords, feed_details, label_name) feed_item_srv = adwords.service(:FeedItemService, API_VERSION) operations = [ create_dsa_url_add_operation( feed_details, 'http://www.example.com/discounts/rental-cars', label_name ), create_dsa_url_add_operation( feed_details, 'http://www.example.com/discounts/hotel-deals', label_name ), create_dsa_url_add_operation( feed_details, 'http://www.example.com/discounts/flight-deals', label_name ) ] result = feed_item_srv.mutate(operations) result[:value].each do |item| puts "Feed item with feed item ID %d was added." % item[:feed_item_id] end end def create_dsa_url_add_operation(feed_details, url, label_name) # Optional: Add the {feeditem} valuetrack parameter to track which page # feed items lead to each click. url = url + '?id={feeditem}' url_attribute_value = { :feed_attribute_id => feed_details[:url_attribute_id], # See https://support.google.com/adwords/answer/7166527 for page feed URL # recommendations and rules. :string_values => [url] } label_attribute_value = { :feed_attribute_id => feed_details[:label_attribute_id], :string_values => [label_name] } feed_item = { :feed_id => feed_details[:feed_id], :attribute_values => [url_attribute_value, label_attribute_value] } operation = { :operand => feed_item, :operator => 'ADD' } return operation end def update_campaign_dsa_setting(adwords, campaign_id, feed_details) campaign_srv = adwords.service(:CampaignService, API_VERSION) selector = { :fields => ['Id', 'Settings'], :predicates => [ {:field => 'CampaignId', :operator => 'IN', :values => [campaign_id]} ] } campaign_page = campaign_srv.get(selector) if campaign_page.nil? or campaign_page[:entries].nil? or campaign_page[:total_num_entries] == 0 raise 'No campaign found with ID: %d' % campaign_id end campaign = campaign_page[:entries].first if campaign[:settings].nil? raise 'Campaign with ID %d is not a DSA campaign.' % campaign_id end dsa_setting = nil campaign[:settings].each do |setting| if setting[:setting_type] == 'DynamicSearchAdsSetting' dsa_setting = setting break end end if dsa_setting.nil? raise 'Campaign with ID %d is not a DSA campaign.' % campaign_id end # Use a page feed to specify precisely which URLs to use with your Dynamic # Search Ads. page_feed = { :feed_ids => [feed_details[:feed_id]] } dsa_setting[:page_feed] = page_feed # Optional: Specify whether only the supplied URLs should be used with your # Dynamic Search Ads. dsa_setting[:use_supplied_urls_only] = true updated_campaign = { :id => campaign_id, :settings => campaign[:settings] } operation = { :operand => updated_campaign, :operator => 'SET' } updated_campaign = campaign_srv.mutate([operation])[:value].first puts "DSA page feed for campaign ID %d was updated with feed ID %d." % [ updated_campaign[:id], feed_details[:feed_id] ] end def add_dsa_targeting(adwords, ad_group_id, dsa_page_url_label) ad_group_criterion_srv = adwords.service(:AdGroupCriterionService, API_VERSION) webpage = { :xsi_type => 'Webpage', :parameter => { :criterion_name => 'Test criterion', :conditions => [{ :operand => 'CUSTOM_LABEL', :argument => dsa_page_url_label }] } } bidding_strategy_configuration = { :bids => [{ :xsi_type => 'CpcBid', :bid => { :micro_amount => 1_500_000 } }] } criterion = { :xsi_type => 'BiddableAdGroupCriterion', :ad_group_id => ad_group_id, :criterion => webpage, :bidding_strategy_configuration => bidding_strategy_configuration } operation = { :operand => criterion, :operator => 'ADD' } new_criterion = ad_group_criterion_srv.mutate([operation])[:value].first puts "Web page criterion with ID %d and status '%s' was created." % [new_criterion[:criterion][:id], new_criterion[:user_status]] end if __FILE__ == $0 API_VERSION = :v201809 # The criterion type to be used for DSA page feeds. DSA page feeds use # criterionType field instead of the placeholderType field unlike most other # feed types. DSA_PAGE_FEED_CRITERION_TYPE = 61 # ID that corresponds to the page URLs. DSA_PAGE_URLS_FIELD_ID = 1 # ID that corresponds to the labels. DSA_LABEL_FIELD_ID = 2 begin campaign_id = 'INSERT_CAMPAIGN_ID_HERE'.to_i ad_group_id = 'INSERT_AD_GROUP_ID_HERE'.to_i add_dynamic_page_feed(campaign_id, 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
Add a DSA campaign
#!/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 Dynamic Search Ads campaign. To get campaigns, run # get_campaigns.rb. require 'date' require 'adwords_api' def add_dynamic_search_ads_campaign() # 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') budget = create_budget(adwords) campaign = create_campaign(adwords, budget) ad_group = create_ad_group(adwords, campaign) create_expanded_dsa(adwords, ad_group) add_web_page_criteria(adwords, ad_group) end def create_budget(adwords) budget_srv = adwords.service(:BudgetService, API_VERSION) shared_budget = { :name => "Interplanetary Cruise #%d" % (Time.now.to_f * 1000).to_i, :amount => { :micro_amount => 50_000_000 }, :delivery_method => 'STANDARD' } budget_operation = { :operand => shared_budget, :operator => 'ADD' } budget = budget_srv.mutate([budget_operation])[:value].first return budget end def create_campaign(adwords, budget) campaign_srv = adwords.service(:CampaignService, API_VERSION) campaign = { :name => "Interplanetary Cruise #%d" % (Time.now.to_f * 1000).to_i, :advertising_channel_type => 'SEARCH', # Recommendation: Set the campaign to PAUSED when creating it to prevent the # ads from immediately serving. Set to ENABLED once you've added targeting # and the ads are ready to serve. :status => 'PAUSED', :bidding_strategy_configuration => { :bidding_strategy_type => 'MANUAL_CPC' }, # Only the budgetId should be sent; all other fields will be ignored by # CampaignService. :budget => { :budget_id => budget[:budget_id] }, :settings => [ :xsi_type => 'DynamicSearchAdsSetting', :domain_name => 'example.com', :language_code => 'en' ], # Optional: Set the start and end dates. :start_date => DateTime.parse((Date.today + 1).to_s).strftime('%Y%m%d'), :end_date => DateTime.parse(Date.today.next_year.to_s).strftime('%Y%m%d') } operation = { :operand => campaign, :operator => 'ADD' } new_campaign = campaign_srv.mutate([operation])[:value].first puts "Campaign with name '%s' and ID %d was added." % [new_campaign[:name], new_campaign[:id]] return new_campaign end def create_ad_group(adwords, campaign) ad_group_srv = adwords.service(:AdGroupService, API_VERSION) ad_group = { # Required: Set the ad group's tpe to Dynamic Search Ads. :ad_group_type => 'SEARCH_DYNAMIC_ADS', :name => "Earth to Mars Cruises #%d" % (Time.now.to_f * 1000).to_i, :campaign_id => campaign[:id], :status => 'PAUSED', # Recommended: Set a tracking URL template for your ad group if you want to # use URL tracking software. :tracking_url_template => 'http://tracker.example.com/traveltracker/{escapedlpurl}', :bidding_strategy_configuration => { :bids => [{ :xsi_type => 'CpcBid', :bid => { :micro_amount => 3_000_000 } }] } } operation = { :operand => ad_group, :operator => 'ADD' } new_ad_group = ad_group_srv.mutate([operation])[:value].first puts "Ad group with name '%s' and ID %d was added." % [new_ad_group[:name], new_ad_group[:id]] return new_ad_group end def create_expanded_dsa(adwords, ad_group) ad_group_ad_srv = adwords.service(:AdGroupAdService, API_VERSION) # Create the expanded Dynamic Search Ad. This ad will have its headline and # final URL auto-generated at serving time according to domain name specific # information provided by DynamicSearchAdsSetting at the campaign level. expanded_dsa = { :xsi_type => 'ExpandedDynamicSearchAd', :description => 'Buy your tickets now!', :description2 => 'Discount ends soon' } ad_group_ad = { :ad_group_id => ad_group[:id], :ad => expanded_dsa, # Optional: Set the status. :status => 'PAUSED' } operation = { :operand => ad_group_ad, :operator => 'ADD' } new_ad_group_ad = ad_group_ad_srv.mutate([operation])[:value].first new_expanded_dsa = new_ad_group_ad[:ad] puts ("Expanded Dynamic Search Ad with ID %d, description '%s', and " + "description 2 '%s' was added.") % [new_expanded_dsa[:id], new_expanded_dsa[:description], new_expanded_dsa[:description2]] end def add_web_page_criteria(adwords, ad_group) ad_group_criterion_srv = adwords.service(:AdGroupCriterionService, API_VERSION) webpage = { :xsi_type => 'Webpage', :parameter => { :criterion_name => 'Special offers', :conditions => [ { :operand => 'URL', :argument => '/specialoffers' }, { :operand => 'PAGE_TITLE', :argument => 'Special Offer' } ] } } biddable_ad_group_criterion = { :xsi_type => 'BiddableAdGroupCriterion', :ad_group_id => ad_group[:id], :criterion => webpage, :user_status => 'PAUSED', # Optional: set a custom bid. :bidding_strategy_configuration => { :bids => [{ :xsi_type => 'CpcBid', :bid => { :micro_amount => 10_000_000 } }] } } operation = { :operand => biddable_ad_group_criterion, :operator => 'ADD' } new_ad_group_criterion = ad_group_criterion_srv.mutate([operation])[:value].first puts "Webpage criterion with ID %d was added to ad group ID %d." % [ new_ad_group_criterion[:criterion][:id], new_ad_group_criterion[:ad_group_id] ] end if __FILE__ == $0 API_VERSION = :v201809 begin add_dynamic_search_ads_campaign() # 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 an expanded text ad with Upgraded URLs
#!/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 code example adds an expanded text ad that uses advanced features of # upgraded URLs. require 'adwords_api' def add_text_ad_with_upgraded_urls(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) expanded_text_ad = { :xsi_type => 'ExpandedTextAd', :headline_part1 => 'Luxury Cruise to Mars', :headline_part2 => 'Visit the Red Planet in style.', :description => 'Low-gravity fun for everyone!', # Specify a list of final URLs. This field cannot be set if :url field # is set. This may be specified at ad, criterion, and feed item levels. :final_urls => [ 'http://www.example.com/cruise/space/', 'http://www.example.com/locations/mars/' ], # Specify a list of final mobile URLs. This field cannot be set if :url # field is set. This may be specificed at ad, criterion, and # feed item levels. :final_mobile_urls => [ 'http://mobile.example.com/cruise/space/', 'http://mobile.example.com/locations/mars/' ] } # Specify a tracking URL for 3rd party tracking provider. You may specify # one at customer, campaign, ad group, ad, criterion, or feed item levels. expanded_text_ad[:tracking_url_template] = 'http://tracker.example.com/' + '?season={_season}&promocode={_promocode}&u={lpurl}' # Since your tracking URL will have two custom parameters, provide their # values too. This can be provided at campaign, ad group, ad, criterion, or # feed item levels. season_parameter = { :key => 'season', :value => 'christmas' } promo_code_parameter = { :key => 'promocode', :value => 'NYC123' } tracking_url_parameters = { :parameters => [season_parameter, promo_code_parameter] } expanded_text_ad[:url_custom_parameters] = tracking_url_parameters operation = { :operator => 'ADD', :operand => {:ad_group_id => ad_group_id, :ad => expanded_text_ad} } # Add ads. response = ad_group_ad_srv.mutate([operation]) if response and response[:value] response[:value].each do |ad| text_ad = ad[:ad] puts "Ad with ID %d was added." % [text_ad[:id]] puts "\tFinal URLs: %s" % [text_ad[:final_urls].join(', ')] puts "\tFinal Mobile URLs: %s" % [text_ad[:final_mobile_urls].join(', ')] puts "\tTracking URL template: %s" % [text_ad[:tracking_url_template]] custom_parameters = text_ad[:url_custom_parameters][:parameters].map do |custom_parameter| "%s=%s" % [custom_parameter[:key], custom_parameter[:value]] end puts "\tCustom parameters: %s" % [custom_parameters.join(', ')] end else raise StandardError, 'No ads were added.' end end if __FILE__ == $0 API_VERSION = :v201809 begin ad_group_id = 'INSERT_AD_GROUP_ID_HERE'.to_i add_text_ad_with_upgraded_urls(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
Add a Gmail ad to an ad group
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright:: Copyright 2018, 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 Gmail ad to a given ad group. The ad group's campaign # needs to have an AdvertisingChannelType of DISPLAY and # AdvertisingChannelSubType of DISPLAY_GMAIL_AD. To get ad groups, run # get_ad_groups.rb. require 'adwords_api' require 'base64' def add_gmail_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) # This ad format does not allow the creation of an image using the # Image.data field. An image must first be created using the MediaService, # and Image.mediaId must be populated when creating the ad. logo_image_id = upload_image(adwords, 'https://goo.gl/mtt54n') logo_image = { :xsi_type => 'Image', :media_id => logo_image_id } marketing_image_id = upload_image(adwords, 'http://goo.gl/3b9Wfh') ad_image = { :xsi_type => 'Image', :media_id => marketing_image_id } teaser = { :headline => 'Dream', :description => 'Create your own adventure', :business_name => 'Interplanetary Ships', :logo_image => logo_image } gmail_ad = { :xsi_type => 'GmailAd', :teaser => teaser, :marketing_image => ad_image, :marketing_image_headline => 'Travel', :marketing_image_description => 'Take to the skies!', :final_urls => ['http://www.example.com'] } ad_group_ad = { :ad_group_id => ad_group_id, :ad => gmail_ad, :status => 'PAUSED' } operation = { :operator => 'ADD', :operand => ad_group_ad } result = ad_group_ad_srv.mutate([operation]) result[:value].each do |ad_group_ad| puts 'A Gmail ad with id %d and short headline "%s" was added.' % [ad_group_ad[:ad][:id], ad_group_ad[:ad][:teaser][:headline]] end end def upload_image(adwords, url) media_srv = adwords.service(:MediaService, API_VERSION) image_data = AdsCommon::Http.get(url, adwords.config) base64_image_data = Base64.encode64(image_data) image = { :xsi_type => 'Image', :data => base64_image_data, :type => 'IMAGE' } response = media_srv.upload([image]) return response.first[:media_id] end if __FILE__ == $0 API_VERSION = :v201809 begin ad_group_id = 'INSERT_AD_GROUP_ID_HERE'.to_i add_gmail_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
Add an HTML 5 ad to an ad group
#!/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 example adds an HTML5 ad to a given ad group. # To get ad groups, run basic_operations/get_ad_groups.rb. require 'adwords_api' require 'base64' def add_html5_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) # The HTML5 zip file contains all the HTML, CSS, and images needed for the # HTML5 ad. For help on creating an HTML5 zip file, check out Google Web # Designer (https://www.google.com/webdesigner). html5_url = 'http://goo.gl/9Y7qI2' html5_data = AdsCommon::Http.get(html5_url, adwords.config) html5_data_base64 = Base64.encode64(html5_data) # Create a media bundle containing the zip file with all the HTML5 # components. media_bundle = { :xsi_type => 'MediaBundle', :data => html5_data_base64, :entry_point => 'carousel/index.html', :type => 'MEDIA_BUNDLE' } # Create the template elements for the ad. You can refer to # https://developers.google.com/adwords/api/docs/appendix/templateads # for the list of available template fields. ad_data = { :unique_name => 'adData', :fields => [ { :name => 'Custom_layout', :field_media => media_bundle, :type => 'MEDIA_BUNDLE' }, { :name => 'layout', :field_text => 'Custom', :type => 'ENUM' } ] } html5_ad = { :xsi_type => 'TemplateAd', :name => 'Ad for HTML5', :template_id => 419, :final_urls => ['http://example.com/html5'], :display_url => 'www.example.com/html5', :dimensions => { :width => 300, :height => 250 }, :template_elements => [ad_data] } ad_group_ad = { :ad_group_id => ad_group_id, :ad => html5_ad, :status => 'PAUSED' } operation = { :operator => 'ADD', :operand => ad_group_ad } response = ad_group_ad_srv.mutate([operation]) if response and !response.empty? response[:value].each do |ad_group_ad| puts "New HTML5 ad with ID %d and display url '%s' was added." % [ad_group_ad[:ad][:id], ad_group_ad[:ad][:display_url]] end else puts "No HTML5 ads were added." end end if __FILE__ == $0 API_VERSION = :v201809 begin # Ad group ID to add text ads to. ad_group_id = 'INSERT_AD_GROUP_ID_HERE'.to_i add_html5_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
Add a multi-asset responsive display ad to an ad group
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright 2018 Google LLC # # 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 responsive display ad (MultiAssetResponsiveDisplayAd) # to an ad group. Image assets are uploaded using AssetService. To get # ad groups, run get_ad_groups.rb. require 'adwords_api' def add_multi_asset_responsive_display_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_srv = adwords.service(:AdGroupAdService, API_VERSION) # Create the ad. ad = { :xsi_type => 'MultiAssetResponsiveDisplayAd', :headlines => [ { # Text assets can be specified directly in the asset field # when creating the ad. :asset => { :xsi_type => 'TextAsset', :asset_text => 'Travel to Mars' } }, { :asset => { :xsi_type => 'TextAsset', :asset_text => 'Travel to Jupiter' } }, { :asset => { :xsi_type => 'TextAsset', :asset_text => 'Travel to Pluto' } } ], :descriptions => [ { :asset => { :xsi_type => 'TextAsset', :asset_text => 'Visit the planet in a luxury spaceship.' } }, { :asset => { :xsi_type => 'TextAsset', :asset_text => 'See the planet in style.' } } ], :business_name => 'Galactic Luxury Cruises', :long_headline => { :asset => { :xsi_type => 'TextAsset', :asset_text => 'Visit the planet in a luxury spaceship.' } }, # This ad format does not allow the creation of an image asset by setting # the asset.imageData field. An image asset must first be created using the # AssetService, and asset.assetId must be populated when creating the ad. :marketing_images => [ { :asset => { :xsi_type => 'ImageAsset', :asset_id => upload_image_asset('https://goo.gl/3b9Wfh') } } ], :square_marketing_images => [ { :asset => { :xsi_type => 'ImageAsset', :asset_id => upload_image_asset('https://goo.gl/mtt54n') } } ], :final_urls => [ 'http://www.example.com' ], :call_to_action_text => 'Shop Now', :main_color => '#0000ff', :accent_color => '#ffff00', :allow_flexible_color => false, :format_setting => 'NON_NATIVE', :dynamic_settings_price_prefix => 'as low as', :dynamic_settings_promo_text => 'Free shipping!', :logo_images => [ { :asset => { :xsi_type => 'ImageAsset', :asset_id => upload_image_asset('https://goo.gl/mtt54n') } } ], } # Create the ad group ad. ad_group_ad = { :xsi_type => 'AdGroupAd', :ad => ad, :ad_group_id => ad_group_id }; # Create the operation. ad_group_operation = {:operator => 'ADD', :operand => ad_group_ad} begin # Make the mutate request. result = ad_group_srv.mutate([ad_group_operation]) # Display the results if result[:value].length > 0 result[:value].each do |entry| new_ad = entry[:ad] puts ('Responsive display ad v2 with ID "%s" ' + 'and short headline "%s" was added.') % [new_ad[:id], new_ad[:long_headline][:asset][:asset_text]] end else puts 'No responsive display ad v2 were created.' end rescue Exception => e puts 'Failed to create responsive display ad v2.' end end def upload_image_asset(image_url, adwords_api_instance) asset_srv = adwords_api_instance.service(:AssetService, API_VERSION) # The image needs to be in a BASE64 encoded form image_data = AdsCommon::Http.get(image_url, adwords_api_instance.config) image_data_base64 = Base64.encode64(image_data) # Create the image asset image_asset = { :xsi_type => 'ImageAsset', # Optional: Provide a unique friendly name to identify your asset. If you # specify the assetName field, then both the asset name and the image being # uploaded should be unique, and should not match another ACTIVE asset in # this customer account. # :asset_name => 'Image asset %s' % (Time.new.to_f * 1000).to_i, :image_data => image_data_base64 } # Create the operation. asset_operation = {:operator => 'ADD', :operand => image_asset} # Make the mutate request. result = asset_srv.mutate([asset_operation]) # return the generated Id result[:value].first[:asset_id] end if __FILE__ == $0 API_VERSION = :v201809 begin ad_group_id = 'INSERT_AD_GROUP_ID_HERE'.to_i add_multi_asset_responsive_display_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
Add a responsive display ad
#!/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 code example adds an image representing the ad using the MediaService and # then adds a responsive display ad to a given ad group. # To get ad groups, run basic_operations/get_ad_groups.rb. require 'adwords_api' require 'base64' def add_responsive_display_ad(adwords, ad_group_id) ad_group_ad_srv = adwords.service(:AdGroupAdService, API_VERSION) # This ad format does not allow the creation of an image using the Image.data # field. An image must first be created using the MediaService, and # Image.mediaId must be populated when creating the ad. ad_image = upload_image(adwords, 'https://goo.gl/3b9Wfh') # Create the responsive display ad. responsive_display_ad = { :xsi_type => 'ResponsiveDisplayAd', # This ad format does not allow the creation of an image using the # Image.data field. An image must first be created using the MediaService, # and Image.mediaId must be populated when creating the ad. :marketing_image => {:media_id => ad_image[:media_id]}, :short_headline => 'Travel', :long_headline => 'Traver the World', :description => 'Take to the air!', :business_name => 'Interplanetary Cruises', :final_urls => ['http://www.example.com/'], # Optional: Set call to action text. :call_to_action_text => 'Shop Now' # Whitelisted accounts only: Set color settings using hexadecimal values. # Set 'allow_flexible_color' to false if you want your ads to render by # always using your colors strictly. #:main_color => '#0000ff', #:accent_color => '#ffff00', #:allow_flexible_color => false, # Whitelisted accounts only: Set the format setting that the ad will be # served in. #:format_setting => 'NON_NATIVE' } # Optional: Create a square marketing image using MediaService, and set it to # the ad. square_image = upload_image(adwords, 'https://goo.gl/mtt54n') responsive_display_ad[:square_marketing_image] = { :media_id => square_image[:media_id] } # Optional: Set dynamic display ad settings, composed of landscape logo image, # promotion text, and price prefix. logo_image = upload_image(adwords, 'https://goo.gl/dEvQeF') responsive_display_ad[:dynamic_display_ad_settings] = { :landscape_logo_image => {:media_id => logo_image[:media_id]}, :price_prefix => 'as low as', :promo_text => 'Free shipping!' } # Create an ad group ad for the responsive display ad. responsive_display_ad_group_ad = { :ad_group_id => ad_group_id, :ad => responsive_display_ad, # Additional propertires (non-required). :status => 'PAUSED' } # Create operation. responsive_display_ad_group_ad_operations = { :operator => 'ADD', :operand => responsive_display_ad_group_ad } # Add the responsive display ad. result = ad_group_ad_srv.mutate([responsive_display_ad_group_ad_operations]) # Display results. if result && result[:value] result[:value].each do |ad_group_ad| puts ("New responsive display ad with id %d and short headline '%s' was" + "added.") % [ad_group_ad[:ad][:id], ad_group_ad[:ad][:short_headline]] end else puts 'No responsive display ads were added.' end end def upload_image(adwords, image_url) media_srv = adwords.service(:MediaService, API_VERSION) # Create an image. raw_image_data = AdsCommon::Http.get(image_url, adwords.config) image = { :xsi_type => 'Image', :data => Base64.encode64(raw_image_data), :type => 'IMAGE' } # Upload the image. response = media_srv.upload([image]) if response and !response.empty? return response.first else raise StandardError, 'Could not upload image, aborting.' end end if __FILE__ == $0 API_VERSION = :v201809 begin # 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 ID to add text ads to. ad_group_id = 'INSERT_AD_GROUP_ID_HERE'.to_i add_responsive_display_ad(adwords, 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
Add a Shopping dynamic remarketing campaign
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright:: Copyright 2018, 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 Shopping dynamic remarketing campaign for the Display # Network via the following steps: # * Creates a new Display Network campaign. # * Links the campaign with Merchant Center. # * Links the user list to the ad group. # * Creates a responsive display ad to render the dynamic text. require 'adwords_api' def add_shopping_dynamic_remarketing_campaign(merchant_id, budget_id, user_list_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 = create_campaign(adwords, merchant_id, budget_id) puts "Campaign with name '%s' and ID %d was added." % [campaign[:name], campaign[:id]] ad_group = create_ad_group(adwords, campaign) puts "Ad group with name '%s' and ID :%d was added." % [ad_group[:name], ad_group[:id]] ad_group_ad = create_ad(adwords, ad_group) puts "Responsive display ad with ID %d was added." % ad_group_ad[:ad][:id] attach_user_list(adwords, ad_group, user_list_id) puts "User list with ID %d was attached to ad group with ID %d." % [user_list_id, ad_group[:id]] end def create_campaign(adwords, merchant_id, budget_id) campaign_srv = adwords.service(:CampaignService, API_VERSION) campaign = { :name => 'Shopping campaign #%d' % (Time.new.to_f * 1000).to_i, # Dynamic remarketing campaigns are only available on the Google Display # Network :advertising_channel_type => 'DISPLAY', :status => 'PAUSED', :budget => { :budget_id => budget_id }, # This example uses a Manual CPC bidding strategy, but you should select the # strategy that best aligns with your sales goals. More details here: # https://support.google.com/adwords/answer/2472725 :bidding_strategy_configuration => { :bidding_strategy_type => 'MANUAL_CPC' }, :settings => [{ :xsi_type => 'ShoppingSetting', # Campaigns with numerically higher priorities take precedence over those # with lower priorities. :campaign_priority => 0, # Set the Merchant Center account ID from which to source products. :merchant_id => merchant_id, # Display Network campaigns do not support partition by country. The only # supported value is "ZZ". This signals that products from all countries # are available in the campaign. The actual products which serve are based # on the products tagged in the user list entry. :sales_country => 'ZZ', # Optional: Enable local inventory ads (items for sale in physical # stores.) :enable_local => true }] } operation = { :operator => 'ADD', :operand => campaign } result = campaign_srv.mutate([operation]) return result[:value].first end def create_ad_group(adwords, campaign) ad_group_srv = adwords.service(:AdGroupService, API_VERSION) ad_group = { :name => 'Dynamic remarketing ad group', :campaign_id => campaign[:id], :status => 'ENABLED' } operation = { :operator => 'ADD', :operand => ad_group } result = ad_group_srv.mutate([operation]) return result[:value].first end def create_ad(adwords, ad_group) ad_srv = adwords.service(:AdGroupAdService, API_VERSION) optional_media_id = upload_image(adwords, 'https://goo.gl/mtt54n') ad = { :xsi_type => 'ResponsiveDisplayAd', # This ad format does not allow the creation of an image using the # Image.data field. An image must first be created using the MediaService, # and Image.mediaId must be populated when creating the ad. :marketing_image => { :xsi_type => 'Image', :media_id => upload_image(adwords, 'https://goo.gl/3b9Wfh') }, :short_headline => 'Travel', :long_headline => 'Travel the World', :description => 'Take to the air!', :business_name => 'Interplanetary Cruises', :final_urls => ['http://www.example.com'], # Optional: Call to action text. # Valid texts: https://support.google.com/adwords/answer/7005917 :call_to_action_text => 'Apply Now', # Optional: Set dynamic display ad settings, composed of landscape logo # image, promotion text, and price prefix. :dynamic_display_ad_settings => create_dynamic_display_ad_settings(adwords), # Optional: Create a logo image and set it to the ad. :logo_image => { :xsi_type => 'Image', :media_id => optional_media_id }, # Optional: Create a square marketing image and set it to the ad. :square_marketing_image => { :xsi_type => 'Image', :media_id => optional_media_id }, # Whitelisted accounts only: Set color settings using hexadecimal values. # Set allowFlexibleColor to false if you want your ads to render by always # using your colors strictly. # :main_color => '#0000ff', # :accent_color => '#ffff00', # :allow_flexible_color => false, # Whitelisted accounts only: Set the format setting that the ad will be # served in. # :format_setting => 'NON_NATIVE' } ad_group_ad = { :ad => ad, :ad_group_id => ad_group[:id] } operation = { :operator => 'ADD', :operand => ad_group_ad } result = ad_srv.mutate([operation]) return result[:value].first end def attach_user_list(adwords, ad_group, user_list_id) ad_group_criterion_srv = adwords.service(:AdGroupCriterionService, API_VERSION) user_list = { :xsi_type => 'CriterionUserList', :user_list_id => user_list_id } ad_group_criterion = { :xsi_type => 'BiddableAdGroupCriterion', :criterion => user_list, :ad_group_id => ad_group[:id] } operation = { :operator => 'ADD', :operand => ad_group_criterion } result = ad_group_criterion_srv.mutate([operation]) end def upload_image(adwords, url) media_srv = adwords.service(:MediaService, API_VERSION) image_data = AdsCommon::Http.get(url, adwords.config) base64_image_data = Base64.encode64(image_data) image = { :xsi_type => 'Image', :data => base64_image_data, :type => 'IMAGE' } response = media_srv.upload([image]) return response.first[:media_id] end def create_dynamic_display_ad_settings(adwords) logo = { :xsi_type => 'Image', :media_id => upload_image(adwords, 'https://goo.gl/dEvQeF') } dynamic_settings = { :landscape_logo_image => logo, :price_prefix => 'as low as', :promo_text => 'Free shipping!' } return dynamic_settings end if __FILE__ == $0 API_VERSION = :v201809 begin merchant_id = 'INSERT_MERCHANT_CENTER_ID_HERE'.to_i budget_id = 'INSERT_BUDGET_ID_HERE'.to_i user_list_id = 'INSERT_USER_LIST_ID_HERE'.to_i add_shopping_dynamic_remarketing_campaign(merchant_id, budget_id, user_list_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 universal app 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 adds a universal app campaign. # # To get campaigns, run get_campaigns.rb. To upload image assets for this # campaign, run upload_image.rb. require 'adwords_api' require 'date' def add_universal_app_campaigns() # 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) budget_srv = adwords.service(:BudgetService, API_VERSION) # Create a budget. budget = { :name => 'Interplanetary budget #%d' % (Time.new.to_f * 1000).to_i, :amount => {:micro_amount => 50000000}, :delivery_method => 'STANDARD', # Universal app campaigns don't support shared budgets. :is_explicitly_shared => false } budget_operation = {:operator => 'ADD', :operand => budget} # Add the budget. return_budget = budget_srv.mutate([budget_operation]) budget_id = return_budget[:value].first[:budget_id] # Create campaigns. universal_app_campaign = { :name => "Interplanetary Cruise #%d" % (Time.new.to_f * 1000).to_i, # Recommendation: Set the campaign to PAUSED when creating it to stop the # ads from immediately serving. Set it to ENABLED once you've added # targeting and the ads are ready to serve. :status => 'PAUSED', # Set the advertising channel and subchannel types for universal app # campaigns. :advertising_channel_type => 'MULTI_CHANNEL', :advertising_channel_sub_type => 'UNIVERSAL_APP_CAMPAIGN', # Set the campaign's bidding strategy. Universal app campaigns only support # the TARGET_CPA bidding strategy. :bidding_strategy_configuration => { :bidding_scheme => { :xsi_type => 'TargetCpaBiddingScheme', :target_cpa => { :micro_amount => 1000000 } } }, # Budget (required) - note only the budget ID is required. :budget => {:budget_id => budget_id}, # Optional fields: :start_date => DateTime.parse((Date.today + 1).to_s).strftime('%Y%m%d'), :end_date => DateTime.parse((Date.today + 365).to_s).strftime('%Y%m%d') } universal_app_setting = { # Set the campaign's assets and ad text ideas. These values will be used to # generate ads. :xsi_type => 'UniversalAppCampaignSetting', :app_id => 'com.labpixies.colordrips', :app_vendor => 'VENDOR_GOOGLE_MARKET', :description1 => 'A cool puzzle game', :description2 => 'Remove connected blocks', :description3 => '3 difficulty levels', :description4 => '4 colorful fun skins' # Optional: You can set up to 20 image assets for your campaign. See # upload_image.rb for an example on how to upload images. # # :image_media_ids => [INSERT_IMGAGE_MEDIA_ID(s)_HERE] } # Optimize this campaign for getting new users for your app. universal_app_setting[:universal_app_bidding_strategy_goal_type] = 'OPTIMIZE_FOR_INSTALL_CONVERSION_VOLUME' # Optional: If you select OPTIMIZE_FOR_IN_APP_CONVERSION_VOLUME goal type, # then also specify your in-app conversion types so AdWords can focus your # campaign on people who are most likely to complete the corresponding in-app # actions. # Conversion type IDs can be retrieved using ConversionTrackerService.get. # # universal_app_campaign[:selective_optimization] = { # :conversion_type_ids => [INSERT_CONVERSION_TYPE_ID(s)_HERE] # } # Optional: Set the campaign settings for Advanced location options. geo_setting = { :xsi_type => 'GeoTargetTypeSetting', :positive_geo_target_type => 'DONT_CARE', :negative_geo_target_type => 'DONT_CARE' } universal_app_campaign[:settings] = [ universal_app_setting, geo_setting ] # Construct the operation and add the campaign. operations = [{ :operator => 'ADD', :operand => universal_app_campaign }] campaigns = campaign_srv.mutate(operations)[:value] if campaigns campaigns.each do |campaign| puts "Universal app campaign with name '%s' and ID %d was added." % [campaign[:name], campaign[:id]] set_campaign_targeting_criteria(adwords, campaign) end else raise new StandardError, 'No universal app campaigns were added.' end end def set_campaign_targeting_criteria(adwords, campaign) campaign_criterion_service = adwords.service(:CampaignCriterionService, API_VERSION) criteria = [ { :xsi_type => 'Location', :id => 21137 # California }, { :xsi_type => 'Location', :id => 2484 # Mexico }, { :xsi_type => 'Language', :id => 1000 # English }, { :xsi_type => 'Language', :id => 1003 # Spanish } ] operations = criteria.map do |criterion| { :operator => 'ADD', :operand => { :campaign_id => campaign[:id], :criterion => criterion } } end response = campaign_criterion_service.mutate(operations) if response and response[:value] # Display the added campaign targets. response[:value].each do |criterion| puts 'Campaign criteria of type "%s" and id %d was added.' % [ criterion[:criterion][:criterion_type], criterion[:criterion][:id] ] end end end if __FILE__ == $0 API_VERSION = :v201809 begin add_universal_app_campaigns() # 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 negative broad match keywords list and attach it to a campaign
#!/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 creates a shared list of negative broad match keywords, it then # attaches them to a campaign. require 'adwords_api' require 'date' def create_and_attach_shared_keyword_set(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') shared_set_srv = adwords.service(:SharedSetService, API_VERSION) shared_criterion_srv = adwords.service(:SharedCriterionService, API_VERSION) campaign_shared_set_srv = adwords.service(:CampaignSharedSetService, API_VERSION) # Keywords to create a shared set of. keywords = ['mars cruise', 'mars hotels'] # Create shared negative keyword set. shared_set = { :name => 'API Negative keyword list - %d' % (Time.new.to_f * 1000).to_i, :type => 'NEGATIVE_KEYWORDS' } # Add shared set. response = shared_set_srv.mutate([ {:operator => 'ADD', :operand => shared_set} ]) if response and response[:value] shared_set = response[:value].first shared_set_id = shared_set[:shared_set_id] puts "Shared set with ID %d and name '%s' was successfully added." % [shared_set_id, shared_set[:name]] else raise StandardError, 'No shared set was added' end # Add negative keywords to shared set. shared_criteria = keywords.map do |keyword| { :criterion => { :xsi_type => 'Keyword', :text => keyword, :match_type => 'BROAD' }, :negative => true, :shared_set_id => shared_set_id } end operations = shared_criteria.map do |criterion| {:operator => 'ADD', :operand => criterion} end response = shared_criterion_srv.mutate(operations) if response and response[:value] response[:value].each do |shared_criterion| puts "Added shared criterion ID %d '%s' to shared set with ID %d." % [shared_criterion[:criterion][:id], shared_criterion[:criterion][:text], shared_criterion[:shared_set_id]] end else raise StandardError, 'No shared keyword was added' end # Attach the articles to the campaign. campaign_set = { :campaign_id => campaign_id, :shared_set_id => shared_set_id } response = campaign_shared_set_srv.mutate([ {:operator => 'ADD', :operand => campaign_set} ]) if response and response[:value] campaign_shared_set = response[:value].first puts 'Shared set ID %d was attached to campaign ID %d' % [campaign_shared_set[:shared_set_id], campaign_shared_set[:campaign_id]] else raise StandardError, 'No campaign shared set was added' end end if __FILE__ == $0 API_VERSION = :v201809 begin # Campaign ID to attach shared keyword set to. campaign_id = 'INSERT_CAMPAIGN_ID_HERE'.to_i create_and_attach_shared_keyword_set(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
Find and remove shared sets and shared set criteria
#!/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 demonstrates how to find shared sets, shared set criterions and # how to remove them. require 'adwords_api' def find_and_remove_criteria_from_shared_set(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') campaign_shared_set_srv = adwords.service(:CampaignSharedSetService, API_VERSION) shared_criterion_srv = adwords.service(:SharedCriterionService, API_VERSION) shared_set_ids = [] criterion_ids = [] # First, retrieve all shared sets associated with the campaign. # Create selector for shared sets to: # - filter by campaign ID, # - filter by shared set type. selector = { :fields => ['SharedSetId', 'CampaignId', 'SharedSetName', 'SharedSetType', 'Status'], :predicates => [ {:field => 'CampaignId', :operator => 'EQUALS', :values => [campaign_id]}, {:field => 'SharedSetType', :operator => 'IN', :values => ['NEGATIVE_KEYWORDS', 'NEGATIVE_PLACEMENTS']} ], :paging => { :start_index => 0, :number_results => PAGE_SIZE } } # Set initial values. offset, page = 0, {} begin page = campaign_shared_set_srv.get(selector) if page[:entries] page[:entries].each do |shared_set| puts "Campaign shared set ID %d and name '%s'" % [shared_set[:shared_set_id], shared_set[:shared_set_name]] shared_set_ids << shared_set[:shared_set_id] end # Increment values to request the next page. offset += PAGE_SIZE selector[:paging][:start_index] = offset end end while page[:total_num_entries] > offset # Next, Retrieve criterion IDs for all found shared sets. selector = { :fields => ['SharedSetId', 'Id', 'KeywordText', 'KeywordMatchType', 'PlacementUrl'], :predicates => [ {:field => 'SharedSetId', :operator => 'IN', :values => shared_set_ids} ], :paging => { :start_index => 0, :number_results => PAGE_SIZE } } # Set initial values. offset, page = 0, {} begin page = shared_criterion_srv.get(selector) if page[:entries] page[:entries].each do |shared_criterion| if shared_criterion[:criterion][:type] == 'KEYWORD' puts "Shared negative keyword with ID %d and text '%s' was found." % [shared_criterion[:criterion][:id], shared_criterion[:criterion][:text]] elsif shared_criterion[:criterion][:type] == 'PLACEMENT' puts "Shared negative placement with ID %d and url '%s' was found." % [shared_criterion[:criterion][:id], shared_criterion[:criterion][:url]] else puts 'Shared criterion with ID %d was found.' % [shared_criterion[:criterion][:id]] end criterion_ids << { :shared_set_id => shared_criterion[:shared_set_id], :criterion_id => shared_criterion[:criterion][:id] } end # Increment values to request the next page. offset += PAGE_SIZE selector[:paging][:start_index] = offset end end while page[:total_num_entries] > offset # Finally, remove the criteria. operations = criterion_ids.map do |criterion| { :operator => 'REMOVE', :operand => { :criterion => {:id => criterion[:criterion_id]}, :shared_set_id => criterion[:shared_set_id] } } end response = shared_criterion_srv.mutate(operations) if response and response[:value] response[:value].each do |criterion| puts "Criterion ID %d was successfully removed from shared set ID %d." % [criterion[:criterion][:id], criterion[:shared_set_id]] end else puts 'No shared criteria were removed.' end end if __FILE__ == $0 API_VERSION = :v201809 PAGE_SIZE = 500 begin # ID of a campaign to remove shared criteria from. campaign_id = 'INSERT_CAMPAIGN_ID_HERE'.to_i find_and_remove_criteria_from_shared_set(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 ad group level bid modifiers
#!/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 illustrates how to retrieve ad group level bid modifiers for a # campaign. require 'adwords_api' def get_ad_group_bid_modifiers(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') bid_modifier_srv = adwords.service(:AdGroupBidModifierService, API_VERSION) # Get all ad group bid modifiers for the campaign. selector = { :fields => ['CampaignId', 'AdGroupId', 'Id', 'BidModifier'], :predicates => [ {:field => 'CampaignId', :operator => 'EQUALS', :values => [campaign_id]} ], :paging => { :start_index => 0, :number_results => PAGE_SIZE } } # Set initial values. offset, page = 0, {} begin page = bid_modifier_srv.get(selector) if page[:entries] page[:entries].each do |modifier| value = modifier[:bid_modifier] || 'unset' puts ('Campaign ID %d, AdGroup ID %d, Criterion ID %d has ad group ' + 'level modifier: %s') % [modifier[:campaign_id], modifier[:ad_group_id], modifier[:criterion][:id], value] end # Increment values to request the next page. offset += PAGE_SIZE selector[:paging][:start_index] = offset else puts 'No ad group level bid overrides returned.' end end while page[:total_num_entries] > offset end if __FILE__ == $0 API_VERSION = :v201809 PAGE_SIZE = 500 begin # ID of a campaign to pull overrides for. campaign_id = 'INSERT_CAMPAIGN_ID_HERE'.to_i get_ad_group_bid_modifiers(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
Add a portfolio bidding strategy to 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 adds a Portfolio Bidding Strategy and uses it to construct a # campaign. require 'adwords_api' require 'date' def use_portfolio_bidding_strategy() # 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') budget_srv = adwords.service(:BudgetService, API_VERSION) bidding_srv = adwords.service(:BiddingStrategyService, API_VERSION) campaign_srv = adwords.service(:CampaignService, API_VERSION) # Create a budget, which can be shared by multiple campaigns. budget = { :name => 'Interplanetary budget #%d' % (Time.new.to_f * 1000).to_i, :amount => {:micro_amount => 50000000}, :delivery_method => 'STANDARD', :is_explicitly_shared => true } return_budget = budget_srv.mutate([ {:operator => 'ADD', :operand => budget}]) budget_id = return_budget[:value].first[:budget_id] # Create a portfolio bidding strategy. portfolio_bidding_strategy = { :name => 'Maximize Clicks #%d' % (Time.new.to_f * 1000).to_i, :bidding_scheme => { :xsi_type => 'TargetSpendBiddingScheme', # Optionally set additional bidding scheme parameters. :bid_ceiling => {:micro_amount => 20000000}, :spend_target => {:micro_amount => 40000000} } } return_strategy = bidding_srv.mutate([ {:operator => 'ADD', :operand => portfolio_bidding_strategy}]) bidding_strategy = return_strategy[:value].first puts ("Portfolio bidding strategy with name '%s' and ID %d of type '%s'" + ' was created') % [bidding_strategy[:name], bidding_strategy[:id], bidding_strategy[:type]] # Create campaigns. campaigns = [ { :name => "Interplanetary Cruise #%d" % (Time.new.to_f * 1000).to_i, # 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', :bidding_strategy_configuration => { :bidding_strategy_id => bidding_strategy[:id] }, # Budget (required) - note only the budget ID is required. :budget => {:budget_id => budget_id}, :advertising_channel_type => 'SEARCH', :network_setting => { :target_google_search => true, :target_search_network => true, :target_content_network => true } }, { :name => "Interplanetary Cruise banner #%d" % (Time.new.to_f * 1000).to_i, :status => 'PAUSED', :bidding_strategy_configuration => { :bidding_strategy_id => bidding_strategy[:id] }, :budget => {:budget_id => budget_id}, :advertising_channel_type => 'DISPLAY', :network_setting => { :target_google_search => false, :target_search_network => false, :target_content_network => true } } ] # Prepare for adding campaign. operations = campaigns.map do |campaign| {:operator => 'ADD', :operand => campaign} end # Add campaign. response = campaign_srv.mutate(operations) if response and response[:value] response[:value].each do |campaign| puts "Campaign with name '%s' and ID %d was added." % [campaign[:name], campaign[:id]] end else raise new StandardError, 'No campaigns were added.' end end if __FILE__ == $0 API_VERSION = :v201809 begin use_portfolio_bidding_strategy() # 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