google-adwords-api 0.18.0 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +8 -0
  3. data/examples/v201509/basic_operations/add_ad_groups.rb +4 -2
  4. data/examples/v201509/remarketing/add_crm_based_user_list.rb +2 -4
  5. data/examples/v201509/{advanced_operations → remarketing}/upload_offline_conversions.rb +6 -21
  6. data/examples/v201601/account_management/create_account.rb +88 -0
  7. data/examples/v201601/account_management/get_account_changes.rb +139 -0
  8. data/examples/v201601/account_management/get_account_hierarchy.rb +132 -0
  9. data/examples/v201601/advanced_operations/add_ad_customizers.rb +184 -0
  10. data/examples/v201601/advanced_operations/add_ad_group_bid_modifier.rb +101 -0
  11. data/examples/v201601/advanced_operations/add_click_to_download_ad.rb +133 -0
  12. data/examples/v201601/advanced_operations/add_html5_ad.rb +137 -0
  13. data/examples/v201601/advanced_operations/add_keywords_using_incremental_batch_job.rb +179 -0
  14. data/examples/v201601/advanced_operations/add_text_ad_with_upgraded_urls.rb +134 -0
  15. data/examples/v201601/advanced_operations/create_and_attach_shared_keyword_set.rb +141 -0
  16. data/examples/v201601/advanced_operations/find_and_remove_criteria_from_shared_set.rb +174 -0
  17. data/examples/v201601/advanced_operations/get_ad_group_bid_modifiers.rb +102 -0
  18. data/examples/v201601/advanced_operations/use_shared_bidding_strategy.rb +147 -0
  19. data/examples/v201601/basic_operations/add_ad_groups.rb +142 -0
  20. data/examples/v201601/basic_operations/add_campaigns.rb +139 -0
  21. data/examples/v201601/basic_operations/add_keywords.rb +114 -0
  22. data/examples/v201601/basic_operations/add_text_ads.rb +109 -0
  23. data/examples/v201601/basic_operations/get_ad_groups.rb +102 -0
  24. data/examples/v201601/basic_operations/get_campaigns.rb +97 -0
  25. data/examples/v201601/basic_operations/get_campaigns_with_awql.rb +89 -0
  26. data/examples/v201601/basic_operations/get_keywords.rb +109 -0
  27. data/examples/v201601/basic_operations/get_text_ads.rb +110 -0
  28. data/examples/v201601/basic_operations/pause_ad.rb +88 -0
  29. data/examples/v201601/basic_operations/remove_ad.rb +89 -0
  30. data/examples/v201601/basic_operations/remove_ad_group.rb +85 -0
  31. data/examples/v201601/basic_operations/remove_campaign.rb +87 -0
  32. data/examples/v201601/basic_operations/remove_keyword.rb +94 -0
  33. data/examples/v201601/basic_operations/update_ad_group.rb +85 -0
  34. data/examples/v201601/basic_operations/update_campaign.rb +86 -0
  35. data/examples/v201601/basic_operations/update_keyword.rb +106 -0
  36. data/examples/v201601/campaign_management/add_campaign_labels.rb +82 -0
  37. data/examples/v201601/campaign_management/add_complete_campaigns_using_batch_job.rb +356 -0
  38. data/examples/v201601/campaign_management/add_experiment.rb +162 -0
  39. data/examples/v201601/campaign_management/add_keywords_in_bulk.rb +153 -0
  40. data/examples/v201601/campaign_management/get_all_disapproved_ads.rb +97 -0
  41. data/examples/v201601/campaign_management/get_all_disapproved_ads_with_awql.rb +89 -0
  42. data/examples/v201601/campaign_management/get_campaigns_by_label.rb +108 -0
  43. data/examples/v201601/campaign_management/promote_experiment.rb +81 -0
  44. data/examples/v201601/campaign_management/set_ad_parameters.rb +118 -0
  45. data/examples/v201601/campaign_management/set_criterion_bid_modifier.rb +104 -0
  46. data/examples/v201601/campaign_management/validate_text_ad.rb +110 -0
  47. data/examples/v201601/error_handling/handle_partial_failures.rb +130 -0
  48. data/examples/v201601/error_handling/handle_policy_violation_error.rb +141 -0
  49. data/examples/v201601/extensions/add_google_my_business_location_extensions.rb +193 -0
  50. data/examples/v201601/extensions/add_site_links.rb +164 -0
  51. data/examples/v201601/extensions/add_site_links_using_feeds.rb +281 -0
  52. data/examples/v201601/migration/migrate_to_extension_settings.rb +386 -0
  53. data/examples/v201601/migration/upgrade_ad_url.rb +93 -0
  54. data/examples/v201601/misc/get_all_images_and_videos.rb +104 -0
  55. data/examples/v201601/misc/setup_oauth2.rb +84 -0
  56. data/examples/v201601/misc/upload_image.rb +93 -0
  57. data/examples/v201601/misc/upload_media_bundle.rb +90 -0
  58. data/examples/v201601/misc/use_oauth2_jwt.rb +93 -0
  59. data/examples/v201601/misc/use_runtime_config.rb +92 -0
  60. data/examples/v201601/optimization/estimate_keyword_traffic.rb +146 -0
  61. data/examples/v201601/optimization/get_keyword_bid_simulations.rb +95 -0
  62. data/examples/v201601/optimization/get_keyword_ideas.rb +126 -0
  63. data/examples/v201601/remarketing/add_audience.rb +118 -0
  64. data/examples/v201601/remarketing/add_conversion_tracker.rb +97 -0
  65. data/examples/v201601/remarketing/add_crm_based_user_list.rb +119 -0
  66. data/examples/v201601/remarketing/add_rule_based_user_lists.rb +167 -0
  67. data/examples/v201601/remarketing/upload_offline_conversions.rb +98 -0
  68. data/examples/v201601/reporting/download_criteria_report.rb +92 -0
  69. data/examples/v201601/reporting/download_criteria_report_with_awql.rb +93 -0
  70. data/examples/v201601/reporting/get_report_fields.rb +75 -0
  71. data/examples/v201601/reporting/parallel_report_download.rb +166 -0
  72. data/examples/v201601/reporting/stream_criteria_report_results.rb +97 -0
  73. data/examples/v201601/shopping_campaigns/add_product_partition_tree.rb +267 -0
  74. data/examples/v201601/shopping_campaigns/add_product_scope.rb +129 -0
  75. data/examples/v201601/shopping_campaigns/add_shopping_campaign.rb +129 -0
  76. data/examples/v201601/shopping_campaigns/get_product_category_taxonomy.rb +115 -0
  77. data/examples/v201601/targeting/add_campaign_targeting_criteria.rb +180 -0
  78. data/examples/v201601/targeting/add_demographic_targeting_criteria.rb +112 -0
  79. data/examples/v201601/targeting/get_campaign_targeting_criteria.rb +106 -0
  80. data/examples/v201601/targeting/get_targetable_languages_and_carriers.rb +89 -0
  81. data/examples/v201601/targeting/lookup_location.rb +108 -0
  82. data/lib/adwords_api/api_config.rb +90 -4
  83. data/lib/adwords_api/batch_job_utils.rb +29 -17
  84. data/lib/adwords_api/incremental_upload_helper.rb +5 -1
  85. data/lib/adwords_api/report_stream.rb +7 -8
  86. data/lib/adwords_api/report_utils.rb +4 -4
  87. data/lib/adwords_api/v201601/account_label_service.rb +46 -0
  88. data/lib/adwords_api/v201601/account_label_service_registry.rb +46 -0
  89. data/lib/adwords_api/v201601/ad_customizer_feed_service.rb +46 -0
  90. data/lib/adwords_api/v201601/ad_customizer_feed_service_registry.rb +46 -0
  91. data/lib/adwords_api/v201601/ad_group_ad_service.rb +70 -0
  92. data/lib/adwords_api/v201601/ad_group_ad_service_registry.rb +46 -0
  93. data/lib/adwords_api/v201601/ad_group_bid_modifier_service.rb +54 -0
  94. data/lib/adwords_api/v201601/ad_group_bid_modifier_service_registry.rb +46 -0
  95. data/lib/adwords_api/v201601/ad_group_criterion_service.rb +62 -0
  96. data/lib/adwords_api/v201601/ad_group_criterion_service_registry.rb +46 -0
  97. data/lib/adwords_api/v201601/ad_group_extension_setting_service.rb +54 -0
  98. data/lib/adwords_api/v201601/ad_group_extension_setting_service_registry.rb +46 -0
  99. data/lib/adwords_api/v201601/ad_group_feed_service.rb +54 -0
  100. data/lib/adwords_api/v201601/ad_group_feed_service_registry.rb +46 -0
  101. data/lib/adwords_api/v201601/ad_group_service.rb +62 -0
  102. data/lib/adwords_api/v201601/ad_group_service_registry.rb +46 -0
  103. data/lib/adwords_api/v201601/ad_param_service.rb +46 -0
  104. data/lib/adwords_api/v201601/ad_param_service_registry.rb +46 -0
  105. data/lib/adwords_api/v201601/adwords_user_list_service.rb +54 -0
  106. data/lib/adwords_api/v201601/adwords_user_list_service_registry.rb +46 -0
  107. data/lib/adwords_api/v201601/batch_job_service.rb +54 -0
  108. data/lib/adwords_api/v201601/batch_job_service_registry.rb +46 -0
  109. data/lib/adwords_api/v201601/bidding_strategy_service.rb +54 -0
  110. data/lib/adwords_api/v201601/bidding_strategy_service_registry.rb +46 -0
  111. data/lib/adwords_api/v201601/budget_order_service.rb +54 -0
  112. data/lib/adwords_api/v201601/budget_order_service_registry.rb +46 -0
  113. data/lib/adwords_api/v201601/budget_service.rb +54 -0
  114. data/lib/adwords_api/v201601/budget_service_registry.rb +46 -0
  115. data/lib/adwords_api/v201601/campaign_criterion_service.rb +54 -0
  116. data/lib/adwords_api/v201601/campaign_criterion_service_registry.rb +46 -0
  117. data/lib/adwords_api/v201601/campaign_extension_setting_service.rb +54 -0
  118. data/lib/adwords_api/v201601/campaign_extension_setting_service_registry.rb +46 -0
  119. data/lib/adwords_api/v201601/campaign_feed_service.rb +54 -0
  120. data/lib/adwords_api/v201601/campaign_feed_service_registry.rb +46 -0
  121. data/lib/adwords_api/v201601/campaign_service.rb +62 -0
  122. data/lib/adwords_api/v201601/campaign_service_registry.rb +46 -0
  123. data/lib/adwords_api/v201601/campaign_shared_set_service.rb +54 -0
  124. data/lib/adwords_api/v201601/campaign_shared_set_service_registry.rb +46 -0
  125. data/lib/adwords_api/v201601/constant_data_service.rb +110 -0
  126. data/lib/adwords_api/v201601/constant_data_service_registry.rb +46 -0
  127. data/lib/adwords_api/v201601/conversion_tracker_service.rb +54 -0
  128. data/lib/adwords_api/v201601/conversion_tracker_service_registry.rb +46 -0
  129. data/lib/adwords_api/v201601/customer_extension_setting_service.rb +54 -0
  130. data/lib/adwords_api/v201601/customer_extension_setting_service_registry.rb +46 -0
  131. data/lib/adwords_api/v201601/customer_feed_service.rb +54 -0
  132. data/lib/adwords_api/v201601/customer_feed_service_registry.rb +46 -0
  133. data/lib/adwords_api/v201601/customer_service.rb +54 -0
  134. data/lib/adwords_api/v201601/customer_service_registry.rb +46 -0
  135. data/lib/adwords_api/v201601/customer_sync_service.rb +38 -0
  136. data/lib/adwords_api/v201601/customer_sync_service_registry.rb +47 -0
  137. data/lib/adwords_api/v201601/data_service.rb +78 -0
  138. data/lib/adwords_api/v201601/data_service_registry.rb +46 -0
  139. data/lib/adwords_api/v201601/experiment_service.rb +46 -0
  140. data/lib/adwords_api/v201601/experiment_service_registry.rb +46 -0
  141. data/lib/adwords_api/v201601/feed_item_service.rb +54 -0
  142. data/lib/adwords_api/v201601/feed_item_service_registry.rb +46 -0
  143. data/lib/adwords_api/v201601/feed_mapping_service.rb +54 -0
  144. data/lib/adwords_api/v201601/feed_mapping_service_registry.rb +46 -0
  145. data/lib/adwords_api/v201601/feed_service.rb +54 -0
  146. data/lib/adwords_api/v201601/feed_service_registry.rb +46 -0
  147. data/lib/adwords_api/v201601/label_service.rb +54 -0
  148. data/lib/adwords_api/v201601/label_service_registry.rb +46 -0
  149. data/lib/adwords_api/v201601/location_criterion_service.rb +46 -0
  150. data/lib/adwords_api/v201601/location_criterion_service_registry.rb +46 -0
  151. data/lib/adwords_api/v201601/managed_customer_service.rb +78 -0
  152. data/lib/adwords_api/v201601/managed_customer_service_registry.rb +46 -0
  153. data/lib/adwords_api/v201601/media_service.rb +54 -0
  154. data/lib/adwords_api/v201601/media_service_registry.rb +46 -0
  155. data/lib/adwords_api/v201601/mutate_job_service.rb +54 -0
  156. data/lib/adwords_api/v201601/mutate_job_service_registry.rb +46 -0
  157. data/lib/adwords_api/v201601/offline_conversion_feed_service.rb +38 -0
  158. data/lib/adwords_api/v201601/offline_conversion_feed_service_registry.rb +46 -0
  159. data/lib/adwords_api/v201601/report_definition_service.rb +38 -0
  160. data/lib/adwords_api/v201601/report_definition_service_registry.rb +46 -0
  161. data/lib/adwords_api/v201601/shared_criterion_service.rb +54 -0
  162. data/lib/adwords_api/v201601/shared_criterion_service_registry.rb +46 -0
  163. data/lib/adwords_api/v201601/shared_set_service.rb +54 -0
  164. data/lib/adwords_api/v201601/shared_set_service_registry.rb +46 -0
  165. data/lib/adwords_api/v201601/targeting_idea_service.rb +38 -0
  166. data/lib/adwords_api/v201601/targeting_idea_service_registry.rb +46 -0
  167. data/lib/adwords_api/v201601/traffic_estimator_service.rb +38 -0
  168. data/lib/adwords_api/v201601/traffic_estimator_service_registry.rb +46 -0
  169. data/lib/adwords_api/version.rb +1 -1
  170. data/test/adwords_api/test_batch_job_utils.rb +11 -2
  171. metadata +163 -5
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env ruby
2
+ # Encoding: utf-8
3
+ #
4
+ # Copyright:: Copyright 2011, Google Inc. All Rights Reserved.
5
+ #
6
+ # License:: Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15
+ # implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ # This example updates the bid of a keyword. To create a keyword, run
20
+ # add_keywords.rb.
21
+
22
+ require 'adwords_api'
23
+
24
+ def update_keyword(ad_group_id, criterion_id)
25
+ # AdwordsApi::Api will read a config file from ENV['HOME']/adwords_api.yml
26
+ # when called without parameters.
27
+ adwords = AdwordsApi::Api.new
28
+
29
+ # To enable logging of SOAP requests, set the log_level value to 'DEBUG' in
30
+ # the configuration file or provide your own logger:
31
+ # adwords.logger = Logger.new('adwords_xml.log')
32
+
33
+ ad_group_criterion_srv =
34
+ adwords.service(:AdGroupCriterionService, API_VERSION)
35
+
36
+ # Prepare for updating a keyword.
37
+ operation = {
38
+ :operator => 'SET',
39
+ :operand => {
40
+ # The 'xsi_type' field allows you to specify the xsi:type of the object
41
+ # being created. It's only necessary when you must provide an explicit
42
+ # type that the client library can't infer.
43
+ :xsi_type => 'BiddableAdGroupCriterion',
44
+ :ad_group_id => ad_group_id,
45
+ :criterion => {
46
+ :id => criterion_id
47
+ },
48
+ :bidding_strategy_configuration => {
49
+ :bids => [
50
+ {
51
+ :xsi_type => 'CpcBid',
52
+ :bid => {:micro_amount => 1000000}
53
+ }
54
+ ]
55
+ }
56
+ }
57
+ }
58
+
59
+ # Update criterion.
60
+ response = ad_group_criterion_srv.mutate([operation])
61
+ if response and response[:value]
62
+ ad_group_criterion = response[:value].first
63
+ puts "Keyword ID %d was successfully updated, current bids are:" %
64
+ ad_group_criterion[:criterion][:id]
65
+ ad_group_criterion[:bidding_strategy_configuration][:bids].each do |bid|
66
+ puts "\tType: '%s', value: %d" %
67
+ [bid[:bids_type], bid[:bid][:micro_amount]]
68
+ end
69
+ else
70
+ puts 'No keywords were updated.'
71
+ end
72
+ end
73
+
74
+ if __FILE__ == $0
75
+ API_VERSION = :v201601
76
+
77
+ begin
78
+ # IDs of a criterion to update and its ad group.
79
+ ad_group_id = 'INSERT_AD_GROUP_ID_HERE'.to_i
80
+ criterion_id = 'INSERT_CRITERION_ID_HERE'.to_i
81
+ update_keyword(ad_group_id, criterion_id)
82
+
83
+ # Authorization error.
84
+ rescue AdsCommon::Errors::OAuth2VerificationRequired => e
85
+ puts "Authorization credentials are not valid. Edit adwords_api.yml for " +
86
+ "OAuth2 client ID and secret and run misc/setup_oauth2.rb example " +
87
+ "to retrieve and store OAuth2 tokens."
88
+ puts "See this wiki page for more details:\n\n " +
89
+ 'https://github.com/googleads/google-api-ads-ruby/wiki/OAuth2'
90
+
91
+ # HTTP errors.
92
+ rescue AdsCommon::Errors::HttpError => e
93
+ puts "HTTP Error: %s" % e
94
+
95
+ # API errors.
96
+ rescue AdwordsApi::Errors::ApiException => e
97
+ puts "Message: %s" % e.message
98
+ puts 'Errors:'
99
+ e.errors.each_with_index do |error, index|
100
+ puts "\tError [%d]:" % (index + 1)
101
+ error.each do |field, value|
102
+ puts "\t\t%s: %s" % [field, value]
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+ # Encoding: utf-8
3
+ #
4
+ # Copyright:: Copyright 2014, Google Inc. All Rights Reserved.
5
+ #
6
+ # License:: Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15
+ # implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ # This example adds a label to multiple campaigns.
20
+
21
+ require 'adwords_api'
22
+
23
+ def add_campaign_labels(campaign_ids, label_id)
24
+ # AdwordsApi::Api will read a config file from ENV['HOME']/adwords_api.yml
25
+ # when called without parameters.
26
+ adwords = AdwordsApi::Api.new
27
+
28
+ # To enable logging of SOAP requests, set the log_level value to 'DEBUG' in
29
+ # the configuration file or provide your own logger:
30
+ # adwords.logger = Logger.new('adwords_xml.log')
31
+
32
+ campaign_srv = adwords.service(:CampaignService, API_VERSION)
33
+
34
+ operations = campaign_ids.map do |campaign_id|
35
+ {
36
+ :operator => 'ADD',
37
+ :operand => {:campaign_id => campaign_id, :label_id => label_id}
38
+ }
39
+ end
40
+
41
+ response = campaign_srv.mutate_label(operations)
42
+ if response and response[:value]
43
+ response[:value].each do |campaign_label|
44
+ puts "Campaign label for campaign ID %d and label ID %d was added.\n" %
45
+ [campaign_label[:campaign_id], campaign_label[:label_id]]
46
+ end
47
+ end
48
+ end
49
+
50
+ if __FILE__ == $0
51
+ API_VERSION = :v201601
52
+
53
+ begin
54
+ campaign_id_1 = 'INSERT_CAMPAIGN_ID_1_HERE'.to_i
55
+ campaign_id_2 = 'INSERT_CAMPAIGN_ID_2_HERE'.to_i
56
+ label_id = 'INSERT_LABEL_ID_HERE'.to_i
57
+ add_campaign_labels([campaign_id_1, campaign_id_2], label_id)
58
+
59
+ # Authorization error.
60
+ rescue AdsCommon::Errors::OAuth2VerificationRequired => e
61
+ puts "Authorization credentials are not valid. Edit adwords_api.yml for " +
62
+ "OAuth2 client ID and secret and run misc/setup_oauth2.rb example " +
63
+ "to retrieve and store OAuth2 tokens."
64
+ puts "See this wiki page for more details:\n\n " +
65
+ 'https://github.com/googleads/google-api-ads-ruby/wiki/OAuth2'
66
+
67
+ # HTTP errors.
68
+ rescue AdsCommon::Errors::HttpError => e
69
+ puts "HTTP Error: %s" % e
70
+
71
+ # API errors.
72
+ rescue AdwordsApi::Errors::ApiException => e
73
+ puts "Message: %s" % e.message
74
+ puts 'Errors:'
75
+ e.errors.each_with_index do |error, index|
76
+ puts "\tError [%d]:" % (index + 1)
77
+ error.each do |field, value|
78
+ puts "\t\t%s: %s" % [field, value]
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,356 @@
1
+ #!/usr/bin/env ruby
2
+ # Encoding: utf-8
3
+ #
4
+ # Copyright:: Copyright 2015, Google Inc. All Rights Reserved.
5
+ #
6
+ # License:: Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15
+ # implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ # This code sample illustrates how to use BatchJobService to create a complete
20
+ # campaign, including ad groups and keywords.
21
+
22
+ require 'adwords_api'
23
+
24
+ def add_complete_campaigns_using_batch_job()
25
+ # AdwordsApi::Api will read a config file from ENV['HOME']/adwords_api.yml
26
+ # when called without parameters.
27
+ adwords = AdwordsApi::Api.new
28
+
29
+ # To enable logging of SOAP requests, set the log_level value to 'DEBUG' in
30
+ # the configuration file or provide your own logger:
31
+ # adwords.logger = Logger.new('adwords_xml.log')
32
+
33
+ batch_job_srv = adwords.service(:BatchJobService, API_VERSION)
34
+ batch_job_utils = adwords.batch_job_utils(API_VERSION)
35
+
36
+ # Create a BatchJob.
37
+ add_op = {
38
+ :operator => 'ADD',
39
+ :operand => {}
40
+ }
41
+
42
+ response = batch_job_srv.mutate([add_op])
43
+ batch_job = response[:value].first
44
+
45
+ # Get the upload URL from the new job.
46
+ upload_url = batch_job[:upload_url][:url]
47
+ puts "Created BatchJob with ID %d, status '%s', and upload URL %s." %
48
+ [batch_job[:id], batch_job[:status], upload_url]
49
+
50
+ # Create a temporary ID generator that will produce a sequence of descending
51
+ # negative numbers.
52
+ temp_id_generator = TempIdGenerator.new()
53
+
54
+ # Create an array of hashed operations generated from the batch_job_utils.
55
+ operations = []
56
+
57
+ # Create an operation to create a new budget.
58
+ budget_operation = build_budget_operation(temp_id_generator)
59
+ operations << budget_operation
60
+
61
+ # Create operations to create new campaigns.
62
+ campaign_operations = build_campaign_operations(
63
+ temp_id_generator, budget_operation)
64
+ operations += campaign_operations
65
+
66
+ # Create operations to create new negative keyword criteria for each
67
+ # campaign.
68
+ operations += build_campaign_criterion_operations(campaign_operations)
69
+
70
+ # Create operations to create new ad groups.
71
+ ad_group_operations = build_ad_group_operations(
72
+ temp_id_generator, campaign_operations)
73
+ operations += ad_group_operations
74
+
75
+ # Create operations to create new ad group criteria (keywords).
76
+ operations += build_ad_group_criterion_operations(ad_group_operations)
77
+
78
+ # Create operations to create new ad group ads (text ads).
79
+ operations += build_ad_group_ad_operations(ad_group_operations)
80
+
81
+ # Use the batch_job_utils to upload all operations.
82
+ batch_job_utils.upload_operations(operations, upload_url)
83
+ puts "Uploaded %d operations for batch job with ID %d." %
84
+ [operations.size, batch_job[:id]]
85
+
86
+ # Poll for completion of the batch job using an exponential back off.
87
+ poll_attempts = 0
88
+ is_pending = true
89
+ selector = {
90
+ :fields => ['Id', 'Status', 'DownloadUrl', 'ProcessingErrors',
91
+ 'ProgressStats'],
92
+ :predicates => [{
93
+ :field => 'Id',
94
+ :operator => 'IN',
95
+ :values => [batch_job[:id]]
96
+ }]
97
+ }
98
+
99
+ begin
100
+ sleep_seconds = 30 * (2 ** poll_attempts)
101
+ puts "Sleeping for %d seconds" % sleep_seconds
102
+ sleep(sleep_seconds)
103
+
104
+ batch_job = batch_job_srv.get(selector)[:entries].first
105
+
106
+ puts "Batch job ID %d has status '%s'." %
107
+ [batch_job[:id], batch_job[:status]]
108
+
109
+ poll_attempts += 1
110
+ is_pending = PENDING_STATUSES.include?(batch_job[:status])
111
+ end while is_pending and poll_attempts < MAX_POLL_ATTEMPTS
112
+
113
+ if is_pending
114
+ raise StandardError,
115
+ "Job is still in pending state after polling %d times." %
116
+ MAX_POLL_ATTEMPTS
117
+ end
118
+
119
+ unless batch_job[:processing_errors].nil?
120
+ batch_job[:processing_errors].each_with_index do |processing_error, i|
121
+ puts ("Processing error [%d]: errorType=%s, trigger=%s, errorString=%s" +
122
+ "fieldPath=%s, reason=%s") % [i, processing_error[:api_error_type],
123
+ processing_error[:trigger], processing_error[:error_string],
124
+ processing_error[:field_path], processing_error[:reason]]
125
+ end
126
+ end
127
+
128
+ unless batch_job[:download_url].nil? or batch_job[:download_url][:url].nil?
129
+ mutate_response = batch_job_utils.get_job_results(
130
+ batch_job[:download_url][:url])
131
+ puts "Downloaded results from '%s':" % batch_job[:download_url][:url]
132
+ mutate_response.each do |mutate_result|
133
+ outcome = "FAILURE"
134
+ outcome = "SUCCESS" if mutate_result[:error_list].nil?
135
+ puts " Operation [%d] - %s" % [mutate_result[:index], outcome]
136
+ end
137
+ end
138
+ end
139
+
140
+ # Custom class to generate temporary negative IDs for created entities to
141
+ # reference each other.
142
+ class TempIdGenerator
143
+ def initialize()
144
+ @counter = -1
145
+ end
146
+
147
+ def next()
148
+ ret = @counter
149
+ @counter -= 1
150
+ return ret
151
+ end
152
+ end
153
+
154
+ def get_time_microseconds()
155
+ return (Time.now.to_f * 1000000).to_i
156
+ end
157
+
158
+ def build_budget_operation(temp_id_generator)
159
+ budget = {
160
+ :budget_id => temp_id_generator.next,
161
+ :name => "Interplanetary Cruise %d" % get_time_microseconds(),
162
+ :amount => {
163
+ :micro_amount => 50000000
164
+ },
165
+ :delivery_method => 'STANDARD',
166
+ :period => 'DAILY'
167
+ }
168
+ budget_operation = {
169
+ # The xsi_type of the operation can usually be guessed by the API because
170
+ # a given service only handles one type of operation. However, batch jobs
171
+ # process operations of different types, so the xsi_type must always be
172
+ # explicitly defined for these operations.
173
+ :xsi_type => 'BudgetOperation',
174
+ :operator => 'ADD',
175
+ :operand => budget
176
+ }
177
+ return budget_operation
178
+ end
179
+
180
+ def build_campaign_operations(temp_id_generator, budget_operation)
181
+ budget_id = budget_operation[:operand][:budget_id]
182
+
183
+ operations = []
184
+ NUMBER_OF_CAMPAIGNS_TO_ADD.times do
185
+ campaign = {
186
+ :name => "Batch Campaign %s" % get_time_microseconds(),
187
+ :status => 'PAUSED',
188
+ :id => temp_id_generator.next,
189
+ :advertising_channel_type => 'SEARCH',
190
+ :budget => {
191
+ :budget_id => budget_id
192
+ },
193
+ :bidding_strategy_configuration => {
194
+ :bidding_strategy_type => 'MANUAL_CPC',
195
+ # You can optionally provide a bidding scheme in place of the type.
196
+ :bidding_scheme => {
197
+ :xsi_type => 'ManualCpcBiddingScheme',
198
+ :enhanced_cpc_enabled => false
199
+ }
200
+ }
201
+ }
202
+ operation = {
203
+ :xsi_type => 'CampaignOperation',
204
+ :operator => 'ADD',
205
+ :operand => campaign
206
+ }
207
+ operations << operation
208
+ end
209
+
210
+ return operations
211
+ end
212
+
213
+ def build_campaign_criterion_operations(campaign_operations)
214
+ operations = []
215
+ campaign_operations.each do |campaign_operation|
216
+ keyword = {
217
+ :xsi_type => 'Keyword',
218
+ :match_type => 'BROAD',
219
+ :text => 'venus'
220
+ }
221
+ negative_criterion = {
222
+ :xsi_type => 'NegativeCampaignCriterion',
223
+ :campaign_id => campaign_operation[:operand][:id],
224
+ :criterion => keyword
225
+ }
226
+ operation = {
227
+ :xsi_type => 'CampaignCriterionOperation',
228
+ :operator => 'ADD',
229
+ :operand => negative_criterion
230
+ }
231
+ operations << operation
232
+ end
233
+
234
+ return operations
235
+ end
236
+
237
+ def build_ad_group_operations(temp_id_generator, campaign_operations)
238
+ operations = []
239
+ campaign_operations.each do |campaign_operation|
240
+ NUMBER_OF_ADGROUPS_TO_ADD.times do
241
+ ad_group = {
242
+ :campaign_id => campaign_operation[:operand][:id],
243
+ :id => temp_id_generator.next,
244
+ :name => "Batch Ad Group %s" % get_time_microseconds(),
245
+ :bidding_strategy_configuration => {
246
+ :bids => [
247
+ {
248
+ :xsi_type => 'CpcBid',
249
+ :bid => {:micro_amount => 10000000}
250
+ }
251
+ ]
252
+ }
253
+ }
254
+ operation = {
255
+ :xsi_type => 'AdGroupOperation',
256
+ :operator => 'ADD',
257
+ :operand => ad_group
258
+ }
259
+ operations << operation
260
+ end
261
+ end
262
+
263
+ return operations
264
+ end
265
+
266
+ def build_ad_group_criterion_operations(ad_group_operations)
267
+ operations = []
268
+ ad_group_operations.each do |ad_group_operation|
269
+ NUMBER_OF_KEYWORDS_TO_ADD.times do |i|
270
+ text = "mars%d" % i
271
+
272
+ # Make 50% of keywords invalid to demonstrate error handling.
273
+ text = text + "!!!" if i % 2 == 0
274
+ keyword = {
275
+ :xsi_type => 'Keyword',
276
+ :text => text,
277
+ :match_type => 'BROAD'
278
+ }
279
+ biddable_criterion = {
280
+ :xsi_type => 'BiddableAdGroupCriterion',
281
+ :ad_group_id => ad_group_operation[:operand][:id],
282
+ :criterion => keyword
283
+ }
284
+ operation = {
285
+ :xsi_type => 'AdGroupCriterionOperation',
286
+ :operator => 'ADD',
287
+ :operand => biddable_criterion
288
+ }
289
+ operations << operation
290
+ end
291
+ end
292
+
293
+ return operations
294
+ end
295
+
296
+ def build_ad_group_ad_operations(ad_group_operations)
297
+ operations = []
298
+ ad_group_operations.each do |ad_group_operation|
299
+ text_ad = {
300
+ :xsi_type => 'TextAd',
301
+ :headline => 'Luxury Cruise to Mars',
302
+ :description1 => 'Visit the Red Planet in style.',
303
+ :description2 => 'Low-gravity fun for everyone!',
304
+ :display_url => 'www.example.com',
305
+ :final_urls => ['http://www.example.com/1']
306
+ }
307
+ ad_group_ad = {
308
+ :ad_group_id => ad_group_operation[:operand][:id],
309
+ :ad => text_ad
310
+ }
311
+ operation = {
312
+ :xsi_type => 'AdGroupAdOperation',
313
+ :operator => 'ADD',
314
+ :operand => ad_group_ad
315
+ }
316
+ operations << operation
317
+ end
318
+
319
+ return operations
320
+ end
321
+
322
+ if __FILE__ == $0
323
+ API_VERSION = :v201601
324
+ NUMBER_OF_CAMPAIGNS_TO_ADD = 2
325
+ NUMBER_OF_ADGROUPS_TO_ADD = 2
326
+ NUMBER_OF_KEYWORDS_TO_ADD = 5
327
+ MAX_POLL_ATTEMPTS = 5
328
+ PENDING_STATUSES = ['ACTIVE', 'AWAITING_FILE']
329
+
330
+ begin
331
+ add_complete_campaigns_using_batch_job()
332
+
333
+ # Authorization error.
334
+ rescue AdsCommon::Errors::OAuth2VerificationRequired => e
335
+ puts "Authorization credentials are not valid. Edit adwords_api.yml for " +
336
+ "OAuth2 client ID and secret and run misc/setup_oauth2.rb example " +
337
+ "to retrieve and store OAuth2 tokens."
338
+ puts "See this wiki page for more details:\n\n " +
339
+ 'https://github.com/googleads/google-api-ads-ruby/wiki/OAuth2'
340
+
341
+ # HTTP errors.
342
+ rescue AdsCommon::Errors::HttpError => e
343
+ puts "HTTP Error: %s" % e
344
+
345
+ # API errors.
346
+ rescue AdwordsApi::Errors::ApiException => e
347
+ puts "Message: %s" % e.message
348
+ puts 'Errors:'
349
+ e.errors.each_with_index do |error, index|
350
+ puts "\tError [%d]:" % (index + 1)
351
+ error.each do |field, value|
352
+ puts "\t\t%s: %s" % [field, value]
353
+ end
354
+ end
355
+ end
356
+ end