sem4r 0.1.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 (187) hide show
  1. data/LICENSE +22 -0
  2. data/README.rdoc +74 -0
  3. data/Rakefile +126 -0
  4. data/VERSION.yml +5 -0
  5. data/bin/sem +34 -0
  6. data/config/sem4r.example.yml +51 -0
  7. data/examples_blog/2009-11-29-hello-world.rb +12 -0
  8. data/examples_blog/2009-12-12-create-campaign.rb +29 -0
  9. data/examples_blog/2010-02-06-constants-scope.rb +8 -0
  10. data/examples_blog/2010-02-07-ad-parameters.rb +47 -0
  11. data/examples_sem4r/01_get_account.rb +37 -0
  12. data/examples_sem4r/02_get_info.rb +32 -0
  13. data/examples_sem4r/03_list_ad.rb +47 -0
  14. data/examples_sem4r/04_list_keywords.rb +54 -0
  15. data/examples_sem4r/05_request_report.rb +51 -0
  16. data/examples_sem4r/05_request_report_2010.rb +40 -0
  17. data/examples_sem4r/06_create_campaigns.rb +86 -0
  18. data/examples_sem4r/07_create_campaigns_block.rb +99 -0
  19. data/examples_sem4r/07_create_campaigns_simple.rb +65 -0
  20. data/examples_sem4r/08_ad_params.rb +70 -0
  21. data/examples_sem4r/09_targeting_idea.rb +59 -0
  22. data/examples_sem4r/10_get_location.rb +28 -0
  23. data/examples_sem4r/11_submit_bulk_job.rb +82 -0
  24. data/examples_sem4r/12_list_bulk_job.rb +29 -0
  25. data/examples_sem4r/30_prune_empty_adgroup.rb +50 -0
  26. data/examples_sem4r/31_empty_accounts.rb +40 -0
  27. data/examples_sem4r/example_helper.rb +115 -0
  28. data/lib/sem4r/account.rb +349 -0
  29. data/lib/sem4r/ad_extension_override/ad_extension_override_service.rb +30 -0
  30. data/lib/sem4r/ad_group/ad_group.rb +340 -0
  31. data/lib/sem4r/ad_group/ad_group_bids.rb +170 -0
  32. data/lib/sem4r/ad_group/ad_group_service.rb +75 -0
  33. data/lib/sem4r/ad_group/mobile_ad_image.rb +33 -0
  34. data/lib/sem4r/ad_group_ad/ad_group_ad.rb +98 -0
  35. data/lib/sem4r/ad_group_ad/ad_group_ad_operations.rb +38 -0
  36. data/lib/sem4r/ad_group_ad/ad_group_ad_service.rb +56 -0
  37. data/lib/sem4r/ad_group_ad/ad_group_mobile_ad.rb +137 -0
  38. data/lib/sem4r/ad_group_ad/ad_group_text_ad.rb +98 -0
  39. data/lib/sem4r/ad_group_criterion/ad_group_criterion.rb +144 -0
  40. data/lib/sem4r/ad_group_criterion/ad_group_criterion_bids.rb +115 -0
  41. data/lib/sem4r/ad_group_criterion/ad_group_criterion_operations.rb +35 -0
  42. data/lib/sem4r/ad_group_criterion/ad_group_criterion_service.rb +58 -0
  43. data/lib/sem4r/ad_group_criterion/criterion.rb +67 -0
  44. data/lib/sem4r/ad_group_criterion/criterion_keyword.rb +80 -0
  45. data/lib/sem4r/ad_group_criterion/criterion_placement.rb +66 -0
  46. data/lib/sem4r/ad_param/ad_param.rb +96 -0
  47. data/lib/sem4r/ad_param/ad_param_operation.rb +34 -0
  48. data/lib/sem4r/ad_param/ad_param_service.rb +59 -0
  49. data/lib/sem4r/adwords.rb +242 -0
  50. data/lib/sem4r/api_counters.rb +7 -0
  51. data/lib/sem4r/base.rb +43 -0
  52. data/lib/sem4r/bulk_mutate_job/bulk_mutate_job.rb +108 -0
  53. data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_selector.rb +56 -0
  54. data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_service.rb +57 -0
  55. data/lib/sem4r/bulk_mutate_job/job_operations.rb +35 -0
  56. data/lib/sem4r/campaign/campaign.rb +193 -0
  57. data/lib/sem4r/campaign/campaign_service.rb +91 -0
  58. data/lib/sem4r/campaign_criterion/campaign_criterion_service.rb +30 -0
  59. data/lib/sem4r/campaign_target/campaign_target_service.rb +30 -0
  60. data/lib/sem4r/cli/cli_command.rb +101 -0
  61. data/lib/sem4r/cli/cli_commands.rb +60 -0
  62. data/lib/sem4r/cli/cli_common_args.rb +293 -0
  63. data/lib/sem4r/cli/cli_download_report.rb +81 -0
  64. data/lib/sem4r/cli/cli_helpers.rb +57 -0
  65. data/lib/sem4r/cli/cli_ideas.rb +100 -0
  66. data/lib/sem4r/cli/cli_list_ads.rb +74 -0
  67. data/lib/sem4r/cli/cli_list_keywords.rb +76 -0
  68. data/lib/sem4r/cli/cli_request_report.rb +104 -0
  69. data/lib/sem4r/cli/cli_sem.rb +64 -0
  70. data/lib/sem4r/common/operation.rb +78 -0
  71. data/lib/sem4r/credentials.rb +86 -0
  72. data/lib/sem4r/extensions.rb +62 -0
  73. data/lib/sem4r/geo_location/geo_location_service.rb +59 -0
  74. data/lib/sem4r/info/info_service.rb +115 -0
  75. data/lib/sem4r/report_definition/report_definition.rb +104 -0
  76. data/lib/sem4r/report_definition/report_definition_operation.rb +34 -0
  77. data/lib/sem4r/report_definition/report_definition_selector.rb +31 -0
  78. data/lib/sem4r/report_definition/report_definition_service.rb +55 -0
  79. data/lib/sem4r/sem4r_error.rb +28 -0
  80. data/lib/sem4r/services/service.rb +74 -0
  81. data/lib/sem4r/services/soap_call.rb +100 -0
  82. data/lib/sem4r/services/soap_connector.rb +284 -0
  83. data/lib/sem4r/services/soap_error.rb +38 -0
  84. data/lib/sem4r/services/soap_message_v13.rb +129 -0
  85. data/lib/sem4r/services/soap_message_v2009.rb +170 -0
  86. data/lib/sem4r/soap_attributes.rb +141 -0
  87. data/lib/sem4r/targeting_idea/targeting_idea.rb +158 -0
  88. data/lib/sem4r/targeting_idea/targeting_idea_selector.rb +200 -0
  89. data/lib/sem4r/targeting_idea/targeting_idea_service.rb +51 -0
  90. data/lib/sem4r/v13_account/account_service.rb +54 -0
  91. data/lib/sem4r/v13_account/billing_address.rb +67 -0
  92. data/lib/sem4r/v13_report/report.rb +185 -0
  93. data/lib/sem4r/v13_report/report_job.rb +51 -0
  94. data/lib/sem4r/v13_report/report_service.rb +89 -0
  95. data/lib/sem4r/v13_traffic_estimator/traffic_estimator_service.rb +30 -0
  96. data/lib/sem4r.rb +142 -0
  97. data/lib/sem4r_cli.rb +40 -0
  98. data/sem4r.gemspec +247 -0
  99. data/spec/aggregates_spec_helper.rb +59 -0
  100. data/spec/fixtures/sem4r.example.yml +26 -0
  101. data/spec/fixtures/services/ad_group/get-first-req.xml +28 -0
  102. data/spec/fixtures/services/ad_group/get-first-res.xml +91 -0
  103. data/spec/fixtures/services/ad_group/get-manual-cpm-bids-req.xml +106 -0
  104. data/spec/fixtures/services/ad_group/get-manual-cpm-bids-res.xml +75 -0
  105. data/spec/fixtures/services/ad_group/mutate_add-req.xml +52 -0
  106. data/spec/fixtures/services/ad_group/mutate_add-res.xml +33 -0
  107. data/spec/fixtures/services/ad_group_ad/get_mobile_ad-req.xml +28 -0
  108. data/spec/fixtures/services/ad_group_ad/get_mobile_ad-res.xml +194 -0
  109. data/spec/fixtures/services/ad_group_ad/get_text_ad-req.xml +29 -0
  110. data/spec/fixtures/services/ad_group_ad/get_text_ad-res.xml +55 -0
  111. data/spec/fixtures/services/ad_group_ad/mutate_add_mobile_ad-req.xml +50 -0
  112. data/spec/fixtures/services/ad_group_ad/mutate_add_mobile_ad-res.xml +42 -0
  113. data/spec/fixtures/services/ad_group_ad/mutate_add_text_ad-req.xml +37 -0
  114. data/spec/fixtures/services/ad_group_ad/mutate_add_text_ad-res.xml +32 -0
  115. data/spec/fixtures/services/ad_group_ad/mutate_add_two_criterions-req.xml +83 -0
  116. data/spec/fixtures/services/ad_group_ad/mutate_add_two_criterions-res.xml +95 -0
  117. data/spec/fixtures/services/ad_group_criterion/get-req.xml +28 -0
  118. data/spec/fixtures/services/ad_group_criterion/get-res.xml +242 -0
  119. data/spec/fixtures/services/ad_group_criterion/mutate_add_criterion_keyword-req.xml +48 -0
  120. data/spec/fixtures/services/ad_group_criterion/mutate_add_criterion_keyword-res.xml +47 -0
  121. data/spec/fixtures/services/ad_group_criterion/mutate_add_criterion_placement-req.xml +35 -0
  122. data/spec/fixtures/services/ad_group_criterion/mutate_add_criterion_placement-res.xml +32 -0
  123. data/spec/fixtures/services/ad_group_criterion/mutate_add_negative_keyword-req.xml +37 -0
  124. data/spec/fixtures/services/ad_group_criterion/mutate_add_negative_keyword-res.xml +51 -0
  125. data/spec/fixtures/services/ad_param/mutate_set-req.xml +43 -0
  126. data/spec/fixtures/services/ad_param/mutate_set-res.xml +29 -0
  127. data/spec/fixtures/services/bulk_mutate_job/get-req.xml +36 -0
  128. data/spec/fixtures/services/bulk_mutate_job/get-res.xml +54 -0
  129. data/spec/fixtures/services/bulk_mutate_job/mutate-req.xml +69 -0
  130. data/spec/fixtures/services/bulk_mutate_job/mutate-res.xml +48 -0
  131. data/spec/fixtures/services/campaign/get-req.xml +37 -0
  132. data/spec/fixtures/services/campaign/get-res.xml +1986 -0
  133. data/spec/fixtures/services/campaign/mutate_add-req.xml +37 -0
  134. data/spec/fixtures/services/campaign/mutate_add-res.xml +42 -0
  135. data/spec/fixtures/services/error.xml +28 -0
  136. data/spec/fixtures/services/info/get_unit_count-req.xml +30 -0
  137. data/spec/fixtures/services/info/get_unit_count-res.xml +29 -0
  138. data/spec/fixtures/services/report_definition/mutate_add-req.xml +24 -0
  139. data/spec/fixtures/services/report_definition/mutate_add-req_orig.xml +45 -0
  140. data/spec/fixtures/services/targeting_idea/get-req-all-options.xml +57 -0
  141. data/spec/fixtures/services/targeting_idea/get-req.xml +60 -0
  142. data/spec/fixtures/services/targeting_idea/get-res.xml +3601 -0
  143. data/spec/fixtures/services/v13_account/get_account_info-req.xml +23 -0
  144. data/spec/fixtures/services/v13_account/get_account_info-res.xml +54 -0
  145. data/spec/fixtures/services/v13_account/get_client_accounts-req.xml +22 -0
  146. data/spec/fixtures/services/v13_account/get_client_accounts-res.xml +37 -0
  147. data/spec/fixtures/services/v13_report/get_all_jobs-req.xml +21 -0
  148. data/spec/fixtures/services/v13_report/get_all_jobs-res.xml +109 -0
  149. data/spec/fixtures/services/v13_report/schedule_report_job-req.xml +56 -0
  150. data/spec/fixtures/services/v13_report/schedule_report_job-res.xml +24 -0
  151. data/spec/sem4r/account_spec.rb +86 -0
  152. data/spec/sem4r/ad_group/ad_group_bids_spec.rb +67 -0
  153. data/spec/sem4r/ad_group/ad_group_service_spec.rb +66 -0
  154. data/spec/sem4r/ad_group/ad_group_spec.rb +212 -0
  155. data/spec/sem4r/ad_group_ad/ad_group_ad_operation_spec.rb +88 -0
  156. data/spec/sem4r/ad_group_ad/ad_group_ad_service_spec.rb +55 -0
  157. data/spec/sem4r/ad_group_ad/ad_group_ad_spec.rb +173 -0
  158. data/spec/sem4r/ad_group_criterion/ad_group_criterion_bids_spec.rb +60 -0
  159. data/spec/sem4r/ad_group_criterion/ad_group_criterion_service_spec.rb +55 -0
  160. data/spec/sem4r/ad_group_criterion/ad_group_criterion_spec.rb +103 -0
  161. data/spec/sem4r/ad_group_criterion/criterion_spec.rb +85 -0
  162. data/spec/sem4r/ad_param/ad_param_service_spec.rb +55 -0
  163. data/spec/sem4r/ad_param/ad_param_spec.rb +59 -0
  164. data/spec/sem4r/adwords_spec.rb +110 -0
  165. data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_service_spec.rb +63 -0
  166. data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_spec.rb +69 -0
  167. data/spec/sem4r/bulk_mutate_job/job_operation_spec.rb +48 -0
  168. data/spec/sem4r/campaign/campaign_service_spec.rb +66 -0
  169. data/spec/sem4r/campaign/campaign_spec.rb +105 -0
  170. data/spec/sem4r/cli/cli_spec.rb +71 -0
  171. data/spec/sem4r/credentials_spec.rb +65 -0
  172. data/spec/sem4r/report_definition/report_definition_service_spec.rb +44 -0
  173. data/spec/sem4r/report_definition/report_definition_spec.rb +105 -0
  174. data/spec/sem4r/rexml_parsing_spec.rb +103 -0
  175. data/spec/sem4r/services/service_spec.rb +36 -0
  176. data/spec/sem4r/services/soap_call_spec.rb +115 -0
  177. data/spec/sem4r/services/soap_message_v13_spec.rb +54 -0
  178. data/spec/sem4r/soap_attributes_spec.rb +116 -0
  179. data/spec/sem4r/targeting_idea/targeting_idea_selector_spec.rb +120 -0
  180. data/spec/sem4r/targeting_idea/targeting_idea_service_spec.rb +44 -0
  181. data/spec/sem4r/targeting_idea/targeting_idea_spec.rb +53 -0
  182. data/spec/sem4r/v13_account/account_service_spec.rb +60 -0
  183. data/spec/sem4r/v13_report/report_service_spec.rb +104 -0
  184. data/spec/sem4r/v13_report/report_spec.rb +79 -0
  185. data/spec/sem4r_spec_helper.rb +353 -0
  186. data/spec/spec_helper.rb +12 -0
  187. metadata +375 -0
@@ -0,0 +1,200 @@
1
+ # -------------------------------------------------------------------------
2
+ # Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+ # -------------------------------------------------------------------------
24
+
25
+ module Sem4r
26
+
27
+ class RelatedToKeywordSearchParameter
28
+ include SoapAttributes
29
+
30
+ g_accessor :text
31
+ g_accessor :match_type
32
+
33
+ def initialize(&block)
34
+ if block_given?
35
+ block.arity < 1 ? instance_eval(&block) : block.call(self)
36
+ end
37
+ end
38
+
39
+ def to_xml
40
+ <<-EOS
41
+ <s:searchParameters xsi:type="s:RelatedToKeywordSearchParameter">
42
+ <s:keywords xsi:type="Keyword">
43
+ <Criterion.Type>Keyword</Criterion.Type>
44
+ <text>#{text}</text>
45
+ <matchType>#{match_type}</matchType>
46
+ </s:keywords>
47
+ </s:searchParameters>
48
+ EOS
49
+ end
50
+ end
51
+
52
+ class ExcludedKeywordSearchParameter
53
+ include SoapAttributes
54
+
55
+ g_accessor :text
56
+ g_accessor :match_type
57
+
58
+ def initialize(&block)
59
+ if block_given?
60
+ block.arity < 1 ? instance_eval(&block) : block.call(self)
61
+ end
62
+ end
63
+
64
+ def to_xml
65
+ <<-EOS
66
+ <s:searchParameters xsi:type="s:ExcludedKeywordSearchParameter">
67
+ <s:keywords xsi:type="Keyword">
68
+ <Criterion.Type>Keyword</Criterion.Type>
69
+ <text>#{text}</text>
70
+ <matchType>#{match_type}</matchType>
71
+ </s:keywords>
72
+ </s:searchParameters>
73
+ EOS
74
+ end
75
+ end
76
+
77
+ class KeywordMatchTypeSearchParameter
78
+ include SoapAttributes
79
+
80
+ g_set_accessor :match_type
81
+
82
+ def initialize(&block)
83
+ if block_given?
84
+ block.arity < 1 ? instance_eval(&block) : block.call(self)
85
+ end
86
+ end
87
+
88
+ def to_xml
89
+ xml = ""
90
+ xml << '<s:searchParameters xsi:type="s:KeywordMatchTypeSearchParameter">'
91
+ match_types.each do |t|
92
+ xml << "<s:keywordMatchTypes>#{t}</s:keywordMatchTypes>"
93
+ end
94
+ xml << '</s:searchParameters>'
95
+ end
96
+ end
97
+
98
+ class CountryTargetSearchParameter
99
+ include SoapAttributes
100
+
101
+ g_set_accessor :country_code
102
+
103
+ def initialize(&block)
104
+ if block_given?
105
+ block.arity < 1 ? instance_eval(&block) : block.call(self)
106
+ end
107
+ end
108
+
109
+ def to_xml
110
+ xml = ""
111
+ xml << '<s:searchParameters xsi:type="s:CountryTargetSearchParameter">'
112
+ country_codes.each do |t|
113
+ # tag contryCode is into the cm namespace (sem4r main namespace)
114
+ # tag contryTarget is into o namespace (sem4r service namespace)
115
+ xml << "<s:countryTargets><countryCode>#{t}</countryCode></s:countryTargets>"
116
+ end
117
+ xml << '</s:searchParameters>'
118
+ end
119
+ end
120
+
121
+ class TargetingIdeaSelector
122
+ include SoapAttributes
123
+
124
+ enum :IdeaTypes, [:KEYWORD, :PLACEMENT]
125
+ enum :RequestTypes, [:IDEAS, :STATS]
126
+
127
+ g_accessor :idea_type, { :values_in => :IdeaTypes }
128
+ g_accessor :request_type
129
+ g_accessor :requested_attributes
130
+ g_accessor :start_index
131
+ g_accessor :number_results
132
+
133
+ def initialize(&block)
134
+ @search_parameters = []
135
+ if block_given?
136
+ block.arity < 1 ? instance_eval(&block) : block.call(self)
137
+ end
138
+ end
139
+
140
+ # TODO: synthetize following methods with metaprogramming
141
+ def related_to_keyword_search_parameter(&block)
142
+ @search_parameters << RelatedToKeywordSearchParameter.new(&block)
143
+ end
144
+
145
+ def excluded_keyword_search_parameter(&block)
146
+ @search_parameters << ExcludedKeywordSearchParameter.new(&block)
147
+ end
148
+
149
+ def keyword_match_type_search_parameter(&block)
150
+ @search_parameters << KeywordMatchTypeSearchParameter.new(&block)
151
+ end
152
+
153
+ def country_target_search_parameter(&block)
154
+ @search_parameters << CountryTargetSearchParameter.new(&block)
155
+ end
156
+
157
+ def to_xml
158
+ xml=<<-EOFS
159
+ <s:selector>
160
+ <s:ideaType>#{@idea_type}</s:ideaType>
161
+ <s:requestType>#{@request_type}</s:requestType>
162
+ EOFS
163
+ xml += @search_parameters.collect{ |sp| sp.to_xml }.join()
164
+ if requested_attributes
165
+ requested_attributes.each do |requested_attribute|
166
+ xml += <<-EOS
167
+ <s:requestedAttributeTypes>#{requested_attribute.to_s.upcase}</s:requestedAttributeTypes>
168
+ EOS
169
+ end
170
+ end
171
+ xml+=<<-EOFS
172
+ <s:paging>
173
+ <startIndex>#{start_index || 0}</startIndex>
174
+ <numberResults>#{number_results || 100}</numberResults>
175
+ </s:paging>
176
+ </s:selector>
177
+ EOFS
178
+ xml
179
+
180
+ end
181
+ # <n3:selector>
182
+ #
183
+ # <n3:ideaType>KEYWORD</n3:ideaType>
184
+ # <n3:requestType>IDEAS</n3:requestType>
185
+ #
186
+ #
187
+ #
188
+ #
189
+ # <n3:paging xmlns:n6="https://adwords.google.com/api/adwords/cm/v200909">
190
+ # <n6:startIndex>0</n6:startIndex>
191
+ # <n6:numberResults>100</n6:numberResults>
192
+ # </n3:paging>
193
+ #
194
+ # </n3:selector>
195
+ #
196
+
197
+ ##########################################################################
198
+
199
+ end
200
+ end
@@ -0,0 +1,51 @@
1
+ # -------------------------------------------------------------------
2
+ # Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ # -------------------------------------------------------------------
23
+
24
+ module Sem4r
25
+ class TargetingIdeaService
26
+ include SoapCall
27
+
28
+ def initialize(connector)
29
+ @connector = connector
30
+
31
+ @header_namespace = "https://adwords.google.com/api/adwords/cm/v201003"
32
+ @service_namespace = "https://adwords.google.com/api/adwords/o/v201003"
33
+
34
+ @sandbox_service_url = "https://adwords-sandbox.google.com/api/adwords/o/v201003/TargetingIdeaService"
35
+ @production_service_url = "https://adwords.google.com/api/adwords/o/v201003/TargetingIdeaService"
36
+ end
37
+
38
+ soap_call_v2009 :get, :mutate => false
39
+
40
+ ################
41
+
42
+ private
43
+
44
+ def _get(xml)
45
+ <<-EOFS
46
+ <s:get>#{xml}</s:get>
47
+ EOFS
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,54 @@
1
+ # -------------------------------------------------------------------
2
+ # Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ # -------------------------------------------------------------------
23
+
24
+ module Sem4r
25
+ class AccountService
26
+ include SoapCall
27
+
28
+ def initialize(connector)
29
+ @connector = connector
30
+ @sandbox_service_url = "https://sandbox.google.com/api/adwords/v13/AccountService"
31
+ @production_service_url = "https://adwords.google.com/api/adwords/v13/AccountService"
32
+ end
33
+
34
+ soap_call_v13 :account_info, :mutate => false
35
+ soap_call_v13 :client_accounts, :mutate => false
36
+
37
+ private
38
+
39
+ def _account_info
40
+ <<-EOFS
41
+ <getAccountInfo xmlns="https://adwords.google.com/api/adwords/v13">
42
+ </getAccountInfo>
43
+ EOFS
44
+ end
45
+
46
+ def _client_accounts
47
+ <<-EOFS
48
+ <getClientAccounts xmlns="https://adwords.google.com/api/adwords/v13">
49
+ </getClientAccounts>
50
+ EOFS
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,67 @@
1
+ # -------------------------------------------------------------------------
2
+ # Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+ # -------------------------------------------------------------------------
24
+
25
+ module Sem4r
26
+ class BillingAddress
27
+ include SoapAttributes
28
+
29
+ g_accessor :company_name
30
+ g_accessor :address_line1
31
+ g_accessor :address_line2
32
+ g_accessor :city
33
+
34
+ def initialize(&block)
35
+ if block_given?
36
+ block.arity < 1 ? instance_eval(&block) : block.call(self)
37
+ end
38
+ end
39
+
40
+ # <billingAddress>
41
+ # <addressLine1>1600 Amphitheatre Parkway</addressLine1>
42
+ # <addressLine2>Building #42</addressLine2>
43
+ # <city>Mountain View</city>
44
+ # <companyName>Some Company</companyName>
45
+ # <countryCode>US</countryCode>
46
+ # <emailAddress>Some@email</emailAddress>
47
+ # <faxNumber>4085551213</faxNumber>
48
+ # <name>Some contact</name>
49
+ # <phoneNumber>4085551212</phoneNumber>
50
+ # <postalCode>94043</postalCode>
51
+ # <state>CA</state>
52
+ # </billingAddress>
53
+ def self.from_element(el)
54
+ new do
55
+ company_name el.elements["companyName"].text.strip
56
+ address_line1 el.elements["addressLine1"].text.strip
57
+ address_line2 el.elements["addressLine2"].text.strip
58
+ city el.elements["city"].text.strip
59
+ end
60
+ end
61
+
62
+ def to_s
63
+ "#{@company_name} #{@address_line1} #{@address_line2} #{@city}"
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,185 @@
1
+ # -------------------------------------------------------------------
2
+ # Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ # -------------------------------------------------------------------
23
+
24
+ module Sem4r
25
+ class Report < Base
26
+
27
+ enum :AggregationTypes, [
28
+ :Summary,
29
+ :Daily, :Weekly, :Monthly, :Quarterly, :Yearly,
30
+ :DayOfWeek,
31
+ :HourlyByDate, :HourlyRegardlessDate,
32
+ :Campaign, :AdGroup, :Keyword,
33
+ :Creative
34
+ ]
35
+
36
+ enum :Columns, [
37
+ :Campaign,
38
+ :AdGroup,
39
+ :Keyword,
40
+ :KeywordTypeDisplay]
41
+
42
+ enum :ReportTypes, [
43
+ :Account, # Account Performance
44
+ :AdGroup, # Ad Group Performance
45
+ :Campaign, # Campaign Performance
46
+ :Demographic, # Demographic Performance
47
+ :ContentPlacement, # Placement Performance
48
+ :Creative, # Ad Performance
49
+ :Geographic, # Geographic Performance
50
+ :Keyword, # Placement / Keyword Performance
51
+ :Query, # Search Query Performance
52
+ :ReachAndFrequency, # Reach and Frequency Performance
53
+ :Structure, # Account Structure
54
+ :Url # URL Performance
55
+ ]
56
+
57
+ enum :Statuses, [ :Pending, :InProgress, :Completed, :Failed ]
58
+
59
+ ###########################################################################
60
+
61
+ attr_reader :id
62
+ attr_reader :account
63
+
64
+ g_accessor :name
65
+
66
+ g_accessor :start_day
67
+ g_accessor :end_day
68
+
69
+ def days(start_day, end_day)
70
+ self.start_day start_day
71
+ self.end_day end_day
72
+ end
73
+
74
+ g_accessor :aggregation
75
+ g_accessor :type
76
+ g_accessor :cross_client, {:default => false}
77
+ g_accessor :zero_impression, {:default => false}
78
+
79
+ g_reader :status
80
+
81
+ g_set_accessor :column
82
+
83
+ ###########################################################################
84
+
85
+ def initialize(account, &block)
86
+ super( account.adwords, account.credentials )
87
+ @account = account
88
+ if block_given?
89
+ block.arity < 1 ? instance_eval(&block) : block.call(self)
90
+ end
91
+ end
92
+
93
+ def to_s
94
+ "#{id} '#{name}' #{status}"
95
+ end
96
+
97
+ def xml(t)
98
+ t.name name
99
+ t.selectedReportType type
100
+ t.startDay start_day
101
+ t.endDay end_day
102
+ t.aggregationTypes aggregation
103
+
104
+ t.crossClient cross_client
105
+ t.includeZeroImpression zero_impression
106
+
107
+ columns.each do |column|
108
+ t.selectedColumns column
109
+ end
110
+ end
111
+
112
+ def to_xml
113
+ builder = Builder::XmlMarkup.new
114
+ builder.job("xsi:type" => "DefinedReportJob") do |t|
115
+ xml(t)
116
+ # job.name name
117
+ # job.selectedReportType type
118
+ # job.startDay start_day
119
+ # job.endDay end_day
120
+ # job.aggregationTypes aggregation
121
+ #
122
+ # job.crossClient cross_client
123
+ # job.includeZeroImpression zero_impression
124
+ #
125
+ # columns.each do |column|
126
+ # job.selectedColumns column
127
+ # end
128
+ end
129
+ end
130
+
131
+ def self.from_element(account, el)
132
+ new(account) do
133
+ @id = el.elements["id"].text.strip.to_i # id is read only
134
+ name el.elements["name"].text.strip
135
+ start_day el.elements["startDay"].text.strip
136
+ end_day el.elements["endDay"].text.strip
137
+ @status = el.elements["status"].text.strip # status is read only
138
+ end
139
+ end
140
+
141
+ ############################################################################
142
+
143
+ def status(refresh = false)
144
+ return @status unless refresh
145
+ soap_message = service.report.status(credentials, @id)
146
+ add_counters( soap_message.counters )
147
+ el = REXML::XPath.first( soap_message.response, "//getReportJobStatusResponse/getReportJobStatusReturn")
148
+ @status = el.text
149
+ end
150
+
151
+ # Validate the report definition to make sure it is valid.
152
+ # If it is not, an AdWords::Error::ApiError will be thrown.
153
+ def validate
154
+ begin
155
+ service.report.validate(credentials, to_xml)
156
+ return true
157
+ rescue SoapError => e
158
+ puts e
159
+ end
160
+ return false
161
+ end
162
+
163
+ def schedule
164
+ soap_message = service.report.schedule(credentials, to_xml)
165
+ add_counters( soap_message.counters )
166
+ el = REXML::XPath.first( soap_message.response, "//scheduleReportJobResponse/scheduleReportJobReturn")
167
+ @id = el.text
168
+ # puts "requested report assigned job nr. #{@job_id}"
169
+ ReportJob.new(self, @id)
170
+ end
171
+
172
+ def url
173
+ soap_message = service.report.url(credentials, @id)
174
+ add_counters( soap_message.counters )
175
+ el = REXML::XPath.first( soap_message.response, "//getReportDownloadUrlResponse/getReportDownloadUrlReturn")
176
+ url = el.text
177
+ url
178
+ end
179
+
180
+ def download(path_name)
181
+ service.report.download(url, path_name)
182
+ end
183
+
184
+ end
185
+ end
@@ -0,0 +1,51 @@
1
+ # -------------------------------------------------------------------
2
+ # Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ # -------------------------------------------------------------------
23
+
24
+ module Sem4r
25
+ class ReportJob < Base
26
+
27
+ def initialize(report, job_id)
28
+ super( report.adwords, report.credentials )
29
+ @job_id = job_id
30
+ end
31
+
32
+ def wait(sleep_interval = 10, &block)
33
+ status = nil
34
+ while status != "Completed" && status != 'Failed'
35
+ sleep(sleep_interval)
36
+ status = self.status
37
+ block.call(self, status) if block
38
+ end
39
+ raise Sem4Error, "Report failed" if status == 'Failed'
40
+ end
41
+
42
+ def status
43
+ soap_message = service.report.status(credentials, @job_id)
44
+ add_counters( soap_message.counters )
45
+ el = REXML::XPath.first( soap_message.response, "//getReportJobStatusResponse/getReportJobStatusReturn")
46
+ status = el.text
47
+ status
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,89 @@
1
+ # -------------------------------------------------------------------
2
+ # Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ # -------------------------------------------------------------------
23
+
24
+ module Sem4r
25
+ class ReportService
26
+
27
+ include SoapCall
28
+
29
+ def initialize(connector)
30
+ @connector = connector
31
+ @namespace = "https://adwords.google.com/api/adwords/v13"
32
+
33
+ @sandbox_service_url = "https://sandbox.google.com/api/adwords/v13/ReportService"
34
+ @production_service_url = "https://adwords.google.com/api/adwords/v13/ReportService"
35
+ end
36
+
37
+ soap_call_v13 :all, :mutate => false
38
+ soap_call_v13 :validate, :mutate => false
39
+ soap_call_v13 :schedule, :mutate => false
40
+ soap_call_v13 :status, :mutate => false
41
+ soap_call_v13 :url, :mutate => false
42
+
43
+ ################
44
+
45
+ def download(url, path_name)
46
+ @connector.download(url, path_name)
47
+ end
48
+
49
+ private
50
+
51
+ def _all
52
+ <<-EOFS
53
+ <getAllJobs xmlns:n1="#{@namespace}">
54
+ </getAllJobs>
55
+ EOFS
56
+ end
57
+
58
+ def _validate(job_xml)
59
+ soap_body_content = "<validateReportJob xmlns=\"#{@namespace}\">"
60
+ soap_body_content += job_xml
61
+ soap_body_content += "</validateReportJob>"
62
+ soap_body_content
63
+ end
64
+
65
+ def _schedule(job_xml)
66
+ soap_body_content = "<scheduleReportJob xmlns=\"#{@namespace}\">"
67
+ soap_body_content += job_xml
68
+ soap_body_content += "</scheduleReportJob>"
69
+ soap_body_content
70
+ end
71
+
72
+ def _status(job_id)
73
+ <<-EOFS
74
+ <getReportJobStatus xmlns:n1="#{@namespace}">
75
+ <reportJobId>#{job_id}</reportJobId>
76
+ </getReportJobStatus>
77
+ EOFS
78
+ end
79
+
80
+ def _url(job_id)
81
+ <<-EOFS
82
+ <getReportDownloadUrl xmlns="#{@namespace}">
83
+ <reportJobId>#{job_id}</reportJobId>
84
+ </getReportDownloadUrl>
85
+ EOFS
86
+ end
87
+
88
+ end
89
+ end