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.
- data/LICENSE +22 -0
- data/README.rdoc +74 -0
- data/Rakefile +126 -0
- data/VERSION.yml +5 -0
- data/bin/sem +34 -0
- data/config/sem4r.example.yml +51 -0
- data/examples_blog/2009-11-29-hello-world.rb +12 -0
- data/examples_blog/2009-12-12-create-campaign.rb +29 -0
- data/examples_blog/2010-02-06-constants-scope.rb +8 -0
- data/examples_blog/2010-02-07-ad-parameters.rb +47 -0
- data/examples_sem4r/01_get_account.rb +37 -0
- data/examples_sem4r/02_get_info.rb +32 -0
- data/examples_sem4r/03_list_ad.rb +47 -0
- data/examples_sem4r/04_list_keywords.rb +54 -0
- data/examples_sem4r/05_request_report.rb +51 -0
- data/examples_sem4r/05_request_report_2010.rb +40 -0
- data/examples_sem4r/06_create_campaigns.rb +86 -0
- data/examples_sem4r/07_create_campaigns_block.rb +99 -0
- data/examples_sem4r/07_create_campaigns_simple.rb +65 -0
- data/examples_sem4r/08_ad_params.rb +70 -0
- data/examples_sem4r/09_targeting_idea.rb +59 -0
- data/examples_sem4r/10_get_location.rb +28 -0
- data/examples_sem4r/11_submit_bulk_job.rb +82 -0
- data/examples_sem4r/12_list_bulk_job.rb +29 -0
- data/examples_sem4r/30_prune_empty_adgroup.rb +50 -0
- data/examples_sem4r/31_empty_accounts.rb +40 -0
- data/examples_sem4r/example_helper.rb +115 -0
- data/lib/sem4r/account.rb +349 -0
- data/lib/sem4r/ad_extension_override/ad_extension_override_service.rb +30 -0
- data/lib/sem4r/ad_group/ad_group.rb +340 -0
- data/lib/sem4r/ad_group/ad_group_bids.rb +170 -0
- data/lib/sem4r/ad_group/ad_group_service.rb +75 -0
- data/lib/sem4r/ad_group/mobile_ad_image.rb +33 -0
- data/lib/sem4r/ad_group_ad/ad_group_ad.rb +98 -0
- data/lib/sem4r/ad_group_ad/ad_group_ad_operations.rb +38 -0
- data/lib/sem4r/ad_group_ad/ad_group_ad_service.rb +56 -0
- data/lib/sem4r/ad_group_ad/ad_group_mobile_ad.rb +137 -0
- data/lib/sem4r/ad_group_ad/ad_group_text_ad.rb +98 -0
- data/lib/sem4r/ad_group_criterion/ad_group_criterion.rb +144 -0
- data/lib/sem4r/ad_group_criterion/ad_group_criterion_bids.rb +115 -0
- data/lib/sem4r/ad_group_criterion/ad_group_criterion_operations.rb +35 -0
- data/lib/sem4r/ad_group_criterion/ad_group_criterion_service.rb +58 -0
- data/lib/sem4r/ad_group_criterion/criterion.rb +67 -0
- data/lib/sem4r/ad_group_criterion/criterion_keyword.rb +80 -0
- data/lib/sem4r/ad_group_criterion/criterion_placement.rb +66 -0
- data/lib/sem4r/ad_param/ad_param.rb +96 -0
- data/lib/sem4r/ad_param/ad_param_operation.rb +34 -0
- data/lib/sem4r/ad_param/ad_param_service.rb +59 -0
- data/lib/sem4r/adwords.rb +242 -0
- data/lib/sem4r/api_counters.rb +7 -0
- data/lib/sem4r/base.rb +43 -0
- data/lib/sem4r/bulk_mutate_job/bulk_mutate_job.rb +108 -0
- data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_selector.rb +56 -0
- data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_service.rb +57 -0
- data/lib/sem4r/bulk_mutate_job/job_operations.rb +35 -0
- data/lib/sem4r/campaign/campaign.rb +193 -0
- data/lib/sem4r/campaign/campaign_service.rb +91 -0
- data/lib/sem4r/campaign_criterion/campaign_criterion_service.rb +30 -0
- data/lib/sem4r/campaign_target/campaign_target_service.rb +30 -0
- data/lib/sem4r/cli/cli_command.rb +101 -0
- data/lib/sem4r/cli/cli_commands.rb +60 -0
- data/lib/sem4r/cli/cli_common_args.rb +293 -0
- data/lib/sem4r/cli/cli_download_report.rb +81 -0
- data/lib/sem4r/cli/cli_helpers.rb +57 -0
- data/lib/sem4r/cli/cli_ideas.rb +100 -0
- data/lib/sem4r/cli/cli_list_ads.rb +74 -0
- data/lib/sem4r/cli/cli_list_keywords.rb +76 -0
- data/lib/sem4r/cli/cli_request_report.rb +104 -0
- data/lib/sem4r/cli/cli_sem.rb +64 -0
- data/lib/sem4r/common/operation.rb +78 -0
- data/lib/sem4r/credentials.rb +86 -0
- data/lib/sem4r/extensions.rb +62 -0
- data/lib/sem4r/geo_location/geo_location_service.rb +59 -0
- data/lib/sem4r/info/info_service.rb +115 -0
- data/lib/sem4r/report_definition/report_definition.rb +104 -0
- data/lib/sem4r/report_definition/report_definition_operation.rb +34 -0
- data/lib/sem4r/report_definition/report_definition_selector.rb +31 -0
- data/lib/sem4r/report_definition/report_definition_service.rb +55 -0
- data/lib/sem4r/sem4r_error.rb +28 -0
- data/lib/sem4r/services/service.rb +74 -0
- data/lib/sem4r/services/soap_call.rb +100 -0
- data/lib/sem4r/services/soap_connector.rb +284 -0
- data/lib/sem4r/services/soap_error.rb +38 -0
- data/lib/sem4r/services/soap_message_v13.rb +129 -0
- data/lib/sem4r/services/soap_message_v2009.rb +170 -0
- data/lib/sem4r/soap_attributes.rb +141 -0
- data/lib/sem4r/targeting_idea/targeting_idea.rb +158 -0
- data/lib/sem4r/targeting_idea/targeting_idea_selector.rb +200 -0
- data/lib/sem4r/targeting_idea/targeting_idea_service.rb +51 -0
- data/lib/sem4r/v13_account/account_service.rb +54 -0
- data/lib/sem4r/v13_account/billing_address.rb +67 -0
- data/lib/sem4r/v13_report/report.rb +185 -0
- data/lib/sem4r/v13_report/report_job.rb +51 -0
- data/lib/sem4r/v13_report/report_service.rb +89 -0
- data/lib/sem4r/v13_traffic_estimator/traffic_estimator_service.rb +30 -0
- data/lib/sem4r.rb +142 -0
- data/lib/sem4r_cli.rb +40 -0
- data/sem4r.gemspec +247 -0
- data/spec/aggregates_spec_helper.rb +59 -0
- data/spec/fixtures/sem4r.example.yml +26 -0
- data/spec/fixtures/services/ad_group/get-first-req.xml +28 -0
- data/spec/fixtures/services/ad_group/get-first-res.xml +91 -0
- data/spec/fixtures/services/ad_group/get-manual-cpm-bids-req.xml +106 -0
- data/spec/fixtures/services/ad_group/get-manual-cpm-bids-res.xml +75 -0
- data/spec/fixtures/services/ad_group/mutate_add-req.xml +52 -0
- data/spec/fixtures/services/ad_group/mutate_add-res.xml +33 -0
- data/spec/fixtures/services/ad_group_ad/get_mobile_ad-req.xml +28 -0
- data/spec/fixtures/services/ad_group_ad/get_mobile_ad-res.xml +194 -0
- data/spec/fixtures/services/ad_group_ad/get_text_ad-req.xml +29 -0
- data/spec/fixtures/services/ad_group_ad/get_text_ad-res.xml +55 -0
- data/spec/fixtures/services/ad_group_ad/mutate_add_mobile_ad-req.xml +50 -0
- data/spec/fixtures/services/ad_group_ad/mutate_add_mobile_ad-res.xml +42 -0
- data/spec/fixtures/services/ad_group_ad/mutate_add_text_ad-req.xml +37 -0
- data/spec/fixtures/services/ad_group_ad/mutate_add_text_ad-res.xml +32 -0
- data/spec/fixtures/services/ad_group_ad/mutate_add_two_criterions-req.xml +83 -0
- data/spec/fixtures/services/ad_group_ad/mutate_add_two_criterions-res.xml +95 -0
- data/spec/fixtures/services/ad_group_criterion/get-req.xml +28 -0
- data/spec/fixtures/services/ad_group_criterion/get-res.xml +242 -0
- data/spec/fixtures/services/ad_group_criterion/mutate_add_criterion_keyword-req.xml +48 -0
- data/spec/fixtures/services/ad_group_criterion/mutate_add_criterion_keyword-res.xml +47 -0
- data/spec/fixtures/services/ad_group_criterion/mutate_add_criterion_placement-req.xml +35 -0
- data/spec/fixtures/services/ad_group_criterion/mutate_add_criterion_placement-res.xml +32 -0
- data/spec/fixtures/services/ad_group_criterion/mutate_add_negative_keyword-req.xml +37 -0
- data/spec/fixtures/services/ad_group_criterion/mutate_add_negative_keyword-res.xml +51 -0
- data/spec/fixtures/services/ad_param/mutate_set-req.xml +43 -0
- data/spec/fixtures/services/ad_param/mutate_set-res.xml +29 -0
- data/spec/fixtures/services/bulk_mutate_job/get-req.xml +36 -0
- data/spec/fixtures/services/bulk_mutate_job/get-res.xml +54 -0
- data/spec/fixtures/services/bulk_mutate_job/mutate-req.xml +69 -0
- data/spec/fixtures/services/bulk_mutate_job/mutate-res.xml +48 -0
- data/spec/fixtures/services/campaign/get-req.xml +37 -0
- data/spec/fixtures/services/campaign/get-res.xml +1986 -0
- data/spec/fixtures/services/campaign/mutate_add-req.xml +37 -0
- data/spec/fixtures/services/campaign/mutate_add-res.xml +42 -0
- data/spec/fixtures/services/error.xml +28 -0
- data/spec/fixtures/services/info/get_unit_count-req.xml +30 -0
- data/spec/fixtures/services/info/get_unit_count-res.xml +29 -0
- data/spec/fixtures/services/report_definition/mutate_add-req.xml +24 -0
- data/spec/fixtures/services/report_definition/mutate_add-req_orig.xml +45 -0
- data/spec/fixtures/services/targeting_idea/get-req-all-options.xml +57 -0
- data/spec/fixtures/services/targeting_idea/get-req.xml +60 -0
- data/spec/fixtures/services/targeting_idea/get-res.xml +3601 -0
- data/spec/fixtures/services/v13_account/get_account_info-req.xml +23 -0
- data/spec/fixtures/services/v13_account/get_account_info-res.xml +54 -0
- data/spec/fixtures/services/v13_account/get_client_accounts-req.xml +22 -0
- data/spec/fixtures/services/v13_account/get_client_accounts-res.xml +37 -0
- data/spec/fixtures/services/v13_report/get_all_jobs-req.xml +21 -0
- data/spec/fixtures/services/v13_report/get_all_jobs-res.xml +109 -0
- data/spec/fixtures/services/v13_report/schedule_report_job-req.xml +56 -0
- data/spec/fixtures/services/v13_report/schedule_report_job-res.xml +24 -0
- data/spec/sem4r/account_spec.rb +86 -0
- data/spec/sem4r/ad_group/ad_group_bids_spec.rb +67 -0
- data/spec/sem4r/ad_group/ad_group_service_spec.rb +66 -0
- data/spec/sem4r/ad_group/ad_group_spec.rb +212 -0
- data/spec/sem4r/ad_group_ad/ad_group_ad_operation_spec.rb +88 -0
- data/spec/sem4r/ad_group_ad/ad_group_ad_service_spec.rb +55 -0
- data/spec/sem4r/ad_group_ad/ad_group_ad_spec.rb +173 -0
- data/spec/sem4r/ad_group_criterion/ad_group_criterion_bids_spec.rb +60 -0
- data/spec/sem4r/ad_group_criterion/ad_group_criterion_service_spec.rb +55 -0
- data/spec/sem4r/ad_group_criterion/ad_group_criterion_spec.rb +103 -0
- data/spec/sem4r/ad_group_criterion/criterion_spec.rb +85 -0
- data/spec/sem4r/ad_param/ad_param_service_spec.rb +55 -0
- data/spec/sem4r/ad_param/ad_param_spec.rb +59 -0
- data/spec/sem4r/adwords_spec.rb +110 -0
- data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_service_spec.rb +63 -0
- data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_spec.rb +69 -0
- data/spec/sem4r/bulk_mutate_job/job_operation_spec.rb +48 -0
- data/spec/sem4r/campaign/campaign_service_spec.rb +66 -0
- data/spec/sem4r/campaign/campaign_spec.rb +105 -0
- data/spec/sem4r/cli/cli_spec.rb +71 -0
- data/spec/sem4r/credentials_spec.rb +65 -0
- data/spec/sem4r/report_definition/report_definition_service_spec.rb +44 -0
- data/spec/sem4r/report_definition/report_definition_spec.rb +105 -0
- data/spec/sem4r/rexml_parsing_spec.rb +103 -0
- data/spec/sem4r/services/service_spec.rb +36 -0
- data/spec/sem4r/services/soap_call_spec.rb +115 -0
- data/spec/sem4r/services/soap_message_v13_spec.rb +54 -0
- data/spec/sem4r/soap_attributes_spec.rb +116 -0
- data/spec/sem4r/targeting_idea/targeting_idea_selector_spec.rb +120 -0
- data/spec/sem4r/targeting_idea/targeting_idea_service_spec.rb +44 -0
- data/spec/sem4r/targeting_idea/targeting_idea_spec.rb +53 -0
- data/spec/sem4r/v13_account/account_service_spec.rb +60 -0
- data/spec/sem4r/v13_report/report_service_spec.rb +104 -0
- data/spec/sem4r/v13_report/report_spec.rb +79 -0
- data/spec/sem4r_spec_helper.rb +353 -0
- data/spec/spec_helper.rb +12 -0
- metadata +375 -0
|
@@ -0,0 +1,193 @@
|
|
|
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
|
+
|
|
26
|
+
class Campaign < Base
|
|
27
|
+
|
|
28
|
+
enum :Statuses, [
|
|
29
|
+
:ACTIVE,
|
|
30
|
+
:PAUSED,
|
|
31
|
+
:DELETED
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
enum :ServingStatues, [
|
|
35
|
+
:SERVING,
|
|
36
|
+
:NONE,
|
|
37
|
+
:ENDED,
|
|
38
|
+
:PENDING,
|
|
39
|
+
:SUSPENDED
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
attr_reader :id
|
|
43
|
+
attr_reader :account
|
|
44
|
+
|
|
45
|
+
g_accessor :name
|
|
46
|
+
g_accessor :status, {:default => "PAUSED"}
|
|
47
|
+
g_accessor :serving_status
|
|
48
|
+
g_accessor :start_date
|
|
49
|
+
g_accessor :end_date
|
|
50
|
+
|
|
51
|
+
def initialize(account, name = nil, &block)
|
|
52
|
+
super( account.adwords, account.credentials )
|
|
53
|
+
@account = account
|
|
54
|
+
@ad_groups = nil
|
|
55
|
+
self.name = name
|
|
56
|
+
if block_given?
|
|
57
|
+
@inside_initialize = true
|
|
58
|
+
block.arity < 1 ? instance_eval(&block) : block.call(self)
|
|
59
|
+
save
|
|
60
|
+
end
|
|
61
|
+
@inside_initialize = false
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def inside_initialize?
|
|
65
|
+
@inside_initialize
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def to_s
|
|
69
|
+
"#{@id} '#{@name}' (#{@status})"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def to_xml
|
|
73
|
+
<<-EOS
|
|
74
|
+
<name>#{name}</name>
|
|
75
|
+
<status>#{status}</status>
|
|
76
|
+
|
|
77
|
+
<budget>
|
|
78
|
+
<period>DAILY</period>
|
|
79
|
+
<amount xsi:type="Money">
|
|
80
|
+
<microAmount>50000000</microAmount>
|
|
81
|
+
</amount>
|
|
82
|
+
<deliveryMethod>STANDARD</deliveryMethod>
|
|
83
|
+
</budget>
|
|
84
|
+
|
|
85
|
+
<biddingStrategy xsi:type="#{bidding_strategy}"></biddingStrategy>
|
|
86
|
+
|
|
87
|
+
EOS
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
###########################################################################
|
|
91
|
+
|
|
92
|
+
def self.from_element(account, el)
|
|
93
|
+
new(account) do
|
|
94
|
+
@id = el.elements["id"].text.strip.to_i
|
|
95
|
+
name el.elements["name"].text.strip
|
|
96
|
+
status el.elements['status'].text.strip # ACTIVE, PAUSED, DELETED
|
|
97
|
+
serving_status el.elements['servingStatus']
|
|
98
|
+
start_date el.elements['startDate']
|
|
99
|
+
end_date el.elements['endDate']
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def self.create(account, &block)
|
|
104
|
+
new(account, &block).save
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def save
|
|
108
|
+
unless @id
|
|
109
|
+
soap_message = service.campaign.create(credentials, to_xml)
|
|
110
|
+
add_counters( soap_message.counters )
|
|
111
|
+
rval = REXML::XPath.first( soap_message.response, "//mutateResponse/rval")
|
|
112
|
+
id = REXML::XPath.match( rval, "value/id" ).first
|
|
113
|
+
@id = id.text.strip.to_i
|
|
114
|
+
end
|
|
115
|
+
self
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def delete
|
|
119
|
+
soap_message = service.campaign.delete(credentials, @id)
|
|
120
|
+
add_counters( soap_message.counters )
|
|
121
|
+
@id = -1 # logical delete
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
###########################################################################
|
|
125
|
+
|
|
126
|
+
def empty?
|
|
127
|
+
_ad_groups.empty?
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
###########################################################################
|
|
131
|
+
# bidding_strategy
|
|
132
|
+
|
|
133
|
+
# ManualCPC, ManualCPM
|
|
134
|
+
def bidding_strategy(strategy = nil)
|
|
135
|
+
@bidding_strategy = strategy if strategy
|
|
136
|
+
@bidding_strategy ||= "ManualCPC"
|
|
137
|
+
@bidding_strategy
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
###########################################################################
|
|
141
|
+
# ad_group management
|
|
142
|
+
|
|
143
|
+
def ad_group(name = nil, &block)
|
|
144
|
+
save
|
|
145
|
+
ad_group = AdGroup.new(self, name, &block)
|
|
146
|
+
ad_group.save
|
|
147
|
+
@ad_groups ||= []
|
|
148
|
+
@ad_groups.push(ad_group)
|
|
149
|
+
ad_group
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def ad_groups(refresh = false, opts = {})
|
|
153
|
+
if refresh.respond_to?(:keys)
|
|
154
|
+
opts = refresh
|
|
155
|
+
refresh = false
|
|
156
|
+
end
|
|
157
|
+
_ad_groups unless @ad_groups and !refresh
|
|
158
|
+
# statuses = [:ACTIVE, :PAUSED]
|
|
159
|
+
# @ad_groups.select do |ad_group|
|
|
160
|
+
# statuses.include?(ad_group.status)
|
|
161
|
+
# end
|
|
162
|
+
@ad_groups
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def p_ad_groups(refresh = false, opts = {})
|
|
166
|
+
if refresh.respond_to?(:keys)
|
|
167
|
+
opts = refresh
|
|
168
|
+
refresh = false
|
|
169
|
+
end
|
|
170
|
+
cs = ad_groups(refresh, opts)
|
|
171
|
+
puts "#{cs.length} ad_groups"
|
|
172
|
+
cs.each do |ad_group|
|
|
173
|
+
puts ad_group.to_s
|
|
174
|
+
end
|
|
175
|
+
self
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
private
|
|
179
|
+
|
|
180
|
+
def _ad_groups
|
|
181
|
+
soap_message = service.ad_group.all(credentials, @id)
|
|
182
|
+
add_counters( soap_message.counters )
|
|
183
|
+
rval = REXML::XPath.first( soap_message.response, "//getResponse/rval")
|
|
184
|
+
els = REXML::XPath.match( rval, "entries")
|
|
185
|
+
@ad_groups = els.map do |el|
|
|
186
|
+
AdGroup.from_element(self, el)
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
###########################################################################
|
|
191
|
+
|
|
192
|
+
end
|
|
193
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
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
|
+
|
|
26
|
+
class CampaignService
|
|
27
|
+
include SoapCall
|
|
28
|
+
|
|
29
|
+
def initialize(connector)
|
|
30
|
+
@connector = connector
|
|
31
|
+
@service_namespace = "https://adwords.google.com/api/adwords/cm/v201003"
|
|
32
|
+
@header_namespace = @service_namespace
|
|
33
|
+
|
|
34
|
+
@sandbox_service_url = "https://adwords-sandbox.google.com/api/adwords/cm/v201003/CampaignService"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
soap_call_v2009 :all, :mutate => false
|
|
38
|
+
soap_call_v2009 :create
|
|
39
|
+
soap_call_v2009 :delete
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def _all(statuses = [Campaign::ACTIVE, Campaign::PAUSED])
|
|
44
|
+
str = <<-EOFS
|
|
45
|
+
<get xmlns="#{@service_namespace}">
|
|
46
|
+
<selector>
|
|
47
|
+
EOFS
|
|
48
|
+
statuses.each do |s|
|
|
49
|
+
str += "<campaignStatuses>#{s}</campaignStatuses>"
|
|
50
|
+
end
|
|
51
|
+
str += <<-EOFS
|
|
52
|
+
<statsSelector>
|
|
53
|
+
<dateRange>
|
|
54
|
+
<min>20090101</min>
|
|
55
|
+
<max>20091231</max>
|
|
56
|
+
</dateRange>
|
|
57
|
+
</statsSelector>
|
|
58
|
+
</selector>
|
|
59
|
+
</get>
|
|
60
|
+
EOFS
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def _create(xml)
|
|
64
|
+
<<-EOFS
|
|
65
|
+
<mutate xmlns="#{@service_namespace}">
|
|
66
|
+
<operations xsi:type="CampaignOperation">
|
|
67
|
+
<operator>ADD</operator>
|
|
68
|
+
<operand>
|
|
69
|
+
#{xml}
|
|
70
|
+
</operand>
|
|
71
|
+
</operations>
|
|
72
|
+
</mutate>
|
|
73
|
+
EOFS
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def _delete(id)
|
|
77
|
+
<<-EOFS
|
|
78
|
+
<mutate xmlns="#{@service_namespace}">
|
|
79
|
+
<operations xsi:type="CampaignOperation">
|
|
80
|
+
<operator>SET</operator>
|
|
81
|
+
<operand>
|
|
82
|
+
<id>#{id}</id>
|
|
83
|
+
<status>DELETED</status>
|
|
84
|
+
</operand>
|
|
85
|
+
</operations>
|
|
86
|
+
</mutate>
|
|
87
|
+
EOFS
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
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 CampaignCriterionService
|
|
26
|
+
def initialize
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
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 CampaignTargetService
|
|
26
|
+
def initialize
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
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 CliCommand
|
|
28
|
+
|
|
29
|
+
class << self
|
|
30
|
+
|
|
31
|
+
def inherited(base)
|
|
32
|
+
@command_list ||= []
|
|
33
|
+
@command_list << base
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def commands
|
|
37
|
+
return @commands if @commands
|
|
38
|
+
@commands = {}
|
|
39
|
+
@command_list.each { |cmd| @commands[cmd.command] = cmd }
|
|
40
|
+
@commands
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def split_args(argv)
|
|
44
|
+
idx = argv.find_index { |e| commands.key?(e) }
|
|
45
|
+
if idx
|
|
46
|
+
common_args = argv[0,idx]
|
|
47
|
+
command = argv[idx]
|
|
48
|
+
command_args = argv[idx+1..-1]
|
|
49
|
+
return [common_args, command, command_args]
|
|
50
|
+
else
|
|
51
|
+
return [argv, nil, nil]
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def define_command(command_name, description_str, &block)
|
|
56
|
+
|
|
57
|
+
unless block_given?
|
|
58
|
+
raise "define_command: missing block"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
cls = Class.new(CliCommand) do
|
|
62
|
+
def initialize(common_args)
|
|
63
|
+
@common_args = common_args
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def opt_parser(options)
|
|
67
|
+
opt_parser = OptionParser.new
|
|
68
|
+
opt_parser.banner= "#{self.class.description}"
|
|
69
|
+
opt_parser.on("-h", "--help", "show this message") do
|
|
70
|
+
puts opt_parser
|
|
71
|
+
options.exit = true
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
define_method("parse_and_run") do |argv|
|
|
76
|
+
options = OpenStruct.new
|
|
77
|
+
opt_parser(options).parse( argv )
|
|
78
|
+
return false if options.exit
|
|
79
|
+
account = @common_args.account
|
|
80
|
+
unless account
|
|
81
|
+
puts "select an account!"
|
|
82
|
+
false
|
|
83
|
+
else
|
|
84
|
+
return block.call(account)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
s = class << cls; self; end
|
|
90
|
+
s.class_eval do
|
|
91
|
+
define_method("command") { command_name }
|
|
92
|
+
define_method("description") { description_str }
|
|
93
|
+
end
|
|
94
|
+
cls
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
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
|
+
CliListClient = CliCommand.define_command("clients", "list clients account") do |account|
|
|
28
|
+
puts account.adwords.to_s
|
|
29
|
+
puts account.to_s
|
|
30
|
+
account.p_client_accounts
|
|
31
|
+
account.adwords.p_counters
|
|
32
|
+
true
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
CliListReport = CliCommand.define_command("reports", "list reports") do |account|
|
|
36
|
+
report(account.reports, :id, :name, :status)
|
|
37
|
+
account.adwords.p_counters
|
|
38
|
+
true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
CliInfo = CliCommand.define_command("info", "account info") do |account|
|
|
42
|
+
account.p_info
|
|
43
|
+
items = (Account::UsageTypes - [Account::METHOD_COST]).map do |usage_type|
|
|
44
|
+
n = account.year_unit_cost(usage_type)
|
|
45
|
+
# puts "#{usage_type} -> #{n}"
|
|
46
|
+
OpenStruct.new(:usage_type => usage_type, :n => n)
|
|
47
|
+
end
|
|
48
|
+
report(items, :usage_type, :n)
|
|
49
|
+
account.adwords.p_counters
|
|
50
|
+
true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
CliCampaign = CliCommand.define_command("campaigns", "list campaigns") do |account|
|
|
54
|
+
puts "listing campaings in #{account}"
|
|
55
|
+
report( account.campaigns, :id, :name, :status )
|
|
56
|
+
account.adwords.p_counters
|
|
57
|
+
true
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|