bing-ads-api 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +92 -0
- data/Rakefile +38 -0
- data/lib/bing-ads-api.rb +38 -0
- data/lib/bing-ads-api.yml +345 -0
- data/lib/bing-ads-api/api_exception.rb +42 -0
- data/lib/bing-ads-api/client_proxy.rb +131 -0
- data/lib/bing-ads-api/config.rb +75 -0
- data/lib/bing-ads-api/constants.rb +133 -0
- data/lib/bing-ads-api/data/ad.rb +119 -0
- data/lib/bing-ads-api/data/ad_group.rb +121 -0
- data/lib/bing-ads-api/data/campaign.rb +40 -0
- data/lib/bing-ads-api/data/report_request.rb +78 -0
- data/lib/bing-ads-api/data/report_request_status.rb +48 -0
- data/lib/bing-ads-api/data/reporting/account_performance_report_request.rb +176 -0
- data/lib/bing-ads-api/data/reporting/campaign_performance_report_request.rb +186 -0
- data/lib/bing-ads-api/data/reporting/helpers/column_helper.rb +65 -0
- data/lib/bing-ads-api/data/reporting/helpers/filter_helper.rb +124 -0
- data/lib/bing-ads-api/data/reporting/helpers/scope_helper.rb +51 -0
- data/lib/bing-ads-api/data/reporting/helpers/time_helper.rb +69 -0
- data/lib/bing-ads-api/data/reporting/performance_report_request.rb +78 -0
- data/lib/bing-ads-api/data_object.rb +35 -0
- data/lib/bing-ads-api/fault/ad_api_error.rb +15 -0
- data/lib/bing-ads-api/fault/ad_api_fault_detail.rb +67 -0
- data/lib/bing-ads-api/fault/api_fault_detail.rb +97 -0
- data/lib/bing-ads-api/fault/application_fault.rb +18 -0
- data/lib/bing-ads-api/fault/batch_error.rb +47 -0
- data/lib/bing-ads-api/fault/operation_error.rb +22 -0
- data/lib/bing-ads-api/fault/partial_errors.rb +75 -0
- data/lib/bing-ads-api/service.rb +174 -0
- data/lib/bing-ads-api/service/campaign_management.rb +483 -0
- data/lib/bing-ads-api/service/reporting.rb +101 -0
- data/lib/bing-ads-api/soap_hasheable.rb +143 -0
- data/lib/bing-ads-api/version.rb +6 -0
- data/lib/locales/es.yml +174 -0
- data/lib/tasks/bing-ads-api_tasks.rake +4 -0
- data/test/bing-ads-api_test.rb +134 -0
- data/test/campaign_management_test.rb +463 -0
- data/test/data_object_test.rb +46 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +56 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +58 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +29 -0
- data/test/dummy/log/test.log +3264 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/report_request_test.rb +312 -0
- data/test/reporting_test.rb +145 -0
- data/test/test_helper.rb +11 -0
- metadata +205 -0
@@ -0,0 +1,174 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
|
3
|
+
module BingAdsApi
|
4
|
+
|
5
|
+
# Public : Base class for service object
|
6
|
+
#
|
7
|
+
# Author:: jlopezn@neonline.cl
|
8
|
+
#
|
9
|
+
class Service
|
10
|
+
|
11
|
+
attr_accessor :client_proxy, :environment
|
12
|
+
|
13
|
+
# Default logger for services
|
14
|
+
LOGGER = Logger.new(STDOUT)
|
15
|
+
|
16
|
+
# Public : Constructor
|
17
|
+
#
|
18
|
+
# Author:: jlopezn@neonline.cl
|
19
|
+
#
|
20
|
+
# === Parameters
|
21
|
+
# * +options+ - Hash with autentication and environment settings
|
22
|
+
#
|
23
|
+
# === Options
|
24
|
+
# * environment - +:production+ or +:sandbox+
|
25
|
+
# * username - Bing Ads username
|
26
|
+
# * passwrod - Bing Ads user's sign-in password
|
27
|
+
# * developer_token - client application's developer access token
|
28
|
+
# * customer_id - identifier for the customer that owns the account
|
29
|
+
# * account_id - identifier of the account that own the entities in the request
|
30
|
+
# * proxy - Hash with any Client Proxy additional options (such as header, logger or enconding)
|
31
|
+
#
|
32
|
+
# === Examples
|
33
|
+
# service = BingAdsApi::Service.new(
|
34
|
+
# :environment => :sandbox,
|
35
|
+
# :username => 'username',
|
36
|
+
# :password => 'pass',
|
37
|
+
# :developer_token => 'SOME_TOKEN',
|
38
|
+
# :account_id => 123456,
|
39
|
+
# :customer_id => 654321,
|
40
|
+
# :proxy => {:logger => Rails.logger}
|
41
|
+
# )
|
42
|
+
# # => <Service>
|
43
|
+
def initialize(options={})
|
44
|
+
|
45
|
+
# Service Environment
|
46
|
+
self.environment = options[:environment]
|
47
|
+
|
48
|
+
# ClientProxy settings
|
49
|
+
clientProxySettings = {
|
50
|
+
:username => options[:username],
|
51
|
+
:password => options[:password],
|
52
|
+
:developer_token => options[:developer_token],
|
53
|
+
:account_id => options[:account_id],
|
54
|
+
:customer_id => options[:customer_id],
|
55
|
+
:wsdl_url => options[:wdsl] || solve_wsdl_url
|
56
|
+
}
|
57
|
+
|
58
|
+
# Additionsl ClientProxy settings
|
59
|
+
clientProxySettings[:proxy] = options[:proxy] if options[:proxy]
|
60
|
+
|
61
|
+
# ClientProxy creation
|
62
|
+
self.client_proxy = BingAdsApi::ClientProxy.new(clientProxySettings)
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
# Public : This is a utility wrapper for calling services into the
|
67
|
+
# +ClientProxy+. This methods handle all the +Savon::Client+ Exceptions
|
68
|
+
# and returns a Hash with the call response
|
69
|
+
#
|
70
|
+
# Author:: jlopezn@neonline.cl
|
71
|
+
#
|
72
|
+
# === Parameters
|
73
|
+
# +operation+ - name of the operation to be called
|
74
|
+
# +message+ - hash with the parameters to the operation
|
75
|
+
#
|
76
|
+
# === Examples
|
77
|
+
# service.call(:some_operation, {key: value})
|
78
|
+
# # => <Hash>
|
79
|
+
#
|
80
|
+
# Returns:: Hash with the result of the service call
|
81
|
+
# Raises:: ServiceError if the SOAP call, the ClientProxy fails or the response is invalid
|
82
|
+
def call(operation, message, &block)
|
83
|
+
raise "You must provide an operation" if operation.nil?
|
84
|
+
begin
|
85
|
+
LOGGER.debug "BingAdsApi Service"
|
86
|
+
LOGGER.debug " Calling #{operation.to_s}"
|
87
|
+
LOGGER.debug " Message: #{message}"
|
88
|
+
response = self.client_proxy.call(operation.to_sym,
|
89
|
+
message: message)
|
90
|
+
|
91
|
+
LOGGER.debug "response header:"
|
92
|
+
LOGGER.debug "\t#{response.header}"
|
93
|
+
|
94
|
+
LOGGER.info "Operation #{operation.to_s} call success"
|
95
|
+
return response.hash
|
96
|
+
rescue Savon::SOAPFault => error
|
97
|
+
LOGGER.error "SOAP Error calling #{operation.to_s}: #{error.http.code}"
|
98
|
+
fault_detail = error.to_hash[:fault][:detail]
|
99
|
+
if fault_detail.key?(:api_fault_detail)
|
100
|
+
api_fault_detail = BingAdsApi::ApiFaultDetail.new(fault_detail[:api_fault_detail])
|
101
|
+
raise BingAdsApi::ApiException.new(
|
102
|
+
api_fault_detail, "SOAP Error calling #{operation.to_s}")
|
103
|
+
elsif fault_detail.key?(:ad_api_fault_detail)
|
104
|
+
ad_api_fault_detail = BingAdsApi::AdApiFaultDetail.new(fault_detail[:ad_api_fault_detail])
|
105
|
+
raise BingAdsApi::ApiException.new(
|
106
|
+
ad_api_fault_detail, "SOAP Error calling #{operation.to_s}")
|
107
|
+
else
|
108
|
+
raise
|
109
|
+
end
|
110
|
+
rescue Savon::HTTPError => error
|
111
|
+
LOGGER.error "Http Error calling #{operation.to_s}: #{error.http.code}"
|
112
|
+
raise
|
113
|
+
rescue Savon::InvalidResponseError => error
|
114
|
+
LOGGER.error "Invalid server reponse calling #{operation.to_s}"
|
115
|
+
raise
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
# Public : Extracts the actual response from the entire response hash.
|
121
|
+
# For example, if you specify 'AddCampaigns', this method will return
|
122
|
+
# the content of 'AddCampaignsResponse' tag as a Hash
|
123
|
+
#
|
124
|
+
# Author:: jlopezn@neonline.cl
|
125
|
+
#
|
126
|
+
# === Parameters
|
127
|
+
# response - The complete response hash received from a Operation call
|
128
|
+
# method - Name of the method of with the 'reponse' tag is require
|
129
|
+
#
|
130
|
+
# === Examples
|
131
|
+
# service.get_response_hash(Hash, 'add_campaigns')
|
132
|
+
# # => Hash
|
133
|
+
#
|
134
|
+
# Returns:: Hash with the inner structure of the method response hash
|
135
|
+
# Raises:: exception
|
136
|
+
def get_response_hash(response, method)
|
137
|
+
return response[:envelope][:body]["#{method}_response".to_sym]
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
# Private : This method must be overriden by specific services.
|
143
|
+
# Returns:: the service name
|
144
|
+
#
|
145
|
+
# Author:: jlopezn@neonline.cl
|
146
|
+
#
|
147
|
+
# Examples
|
148
|
+
# get_service_name
|
149
|
+
# # => "service_name"
|
150
|
+
#
|
151
|
+
# Returns:: String with the service name
|
152
|
+
# Raises:: exception if the specific Service class hasn't overriden this method
|
153
|
+
def get_service_name
|
154
|
+
raise "Should return the a service name from config.wsdl keys"
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
# Private : Solves the service WSDL URL based on his service name
|
159
|
+
# and environment values
|
160
|
+
#
|
161
|
+
# Author:: jlopezn@neonline.cl
|
162
|
+
#
|
163
|
+
# Examples
|
164
|
+
# solve_wsdl_url
|
165
|
+
# # => "https://bing.wsdl.url.com"
|
166
|
+
#
|
167
|
+
# Returns:: String with the Service url
|
168
|
+
def solve_wsdl_url
|
169
|
+
config = BingAdsApi::Config.instance
|
170
|
+
return config.service_wsdl(environment, get_service_name)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
@@ -0,0 +1,483 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module BingAdsApi
|
3
|
+
|
4
|
+
|
5
|
+
# Public : This class represents the Campaign Management Services
|
6
|
+
# defined in the Bing Ads API, to manage advertising campaigns
|
7
|
+
#
|
8
|
+
# Author:: jlopezn@neonline.cl
|
9
|
+
#
|
10
|
+
# Examples
|
11
|
+
# options = {
|
12
|
+
# :environment => :sandbox,
|
13
|
+
# :username => "username",
|
14
|
+
# :password => "pass",
|
15
|
+
# :developer_token => "SOME_TOKEN",
|
16
|
+
# :customer_id => "1234567",
|
17
|
+
# :account_id => "9876543" }
|
18
|
+
# service = BingAdsApi::CampaignManagement.new(options)
|
19
|
+
class CampaignManagement < BingAdsApi::Service
|
20
|
+
|
21
|
+
|
22
|
+
# Public : Constructor
|
23
|
+
#
|
24
|
+
# Author:: jlopezn@neonline.cl
|
25
|
+
#
|
26
|
+
# options - Hash with the parameters for the client proxy and the environment
|
27
|
+
#
|
28
|
+
# Examples
|
29
|
+
# options = {
|
30
|
+
# :environment => :sandbox,
|
31
|
+
# :username => "username",
|
32
|
+
# :password => "password",
|
33
|
+
# :developer_token => "DEV_TOKEN",
|
34
|
+
# :customer_id => "123456",
|
35
|
+
# :account_id => "654321"
|
36
|
+
# }
|
37
|
+
# service = BingAdsApi::CampaignManagement.new(options)
|
38
|
+
def initialize(options={})
|
39
|
+
super(options)
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
#########################
|
44
|
+
## Operations Wrappers ##
|
45
|
+
#########################
|
46
|
+
|
47
|
+
# Public : Returns all the campaigns found in the specified account
|
48
|
+
#
|
49
|
+
# Author:: jlopezn@neonline.cl
|
50
|
+
#
|
51
|
+
# === Parameters
|
52
|
+
# account_id - account who owns the campaigns
|
53
|
+
#
|
54
|
+
# === Examples
|
55
|
+
# campaign_management_service.get_campaigns_by_account_id(1)
|
56
|
+
# # => Array[BingAdsApi::Campaign]
|
57
|
+
#
|
58
|
+
# Returns:: Array of BingAdsApi::Campaign
|
59
|
+
#
|
60
|
+
# Raises:: exception
|
61
|
+
def get_campaigns_by_account_id(account_id)
|
62
|
+
response = call(:get_campaigns_by_account_id,
|
63
|
+
{account_id: account_id})
|
64
|
+
response_hash = get_response_hash(response, __method__)
|
65
|
+
campaigns = response_hash[:campaigns][:campaign].map do |camp_hash|
|
66
|
+
BingAdsApi::Campaign.new(camp_hash)
|
67
|
+
end
|
68
|
+
return campaigns
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
# Public : Adds a campaign to the specified account
|
73
|
+
#
|
74
|
+
# Author:: jlopezn@neonline.cl
|
75
|
+
#
|
76
|
+
# === Parameters
|
77
|
+
# account_id - account who will own the newly campaigns
|
78
|
+
# campaigns - An array of BingAdsApi::Campaign
|
79
|
+
#
|
80
|
+
# === Examples
|
81
|
+
# service.add_campaigns(1, [<BingAdsApi::Campaign>])
|
82
|
+
# # => <Hash>
|
83
|
+
#
|
84
|
+
# Returns:: hash with the 'add_campaigns_response' structure
|
85
|
+
#
|
86
|
+
# Raises:: exception
|
87
|
+
def add_campaigns(account_id, campaigns)
|
88
|
+
|
89
|
+
camps = []
|
90
|
+
if campaigns.is_a? Array
|
91
|
+
camps = campaigns.map{ |camp| camp.to_hash(:camelcase) }
|
92
|
+
elsif campaigns.is_a? BingAdsApi::Campaign
|
93
|
+
camps = campaigns.to_hash
|
94
|
+
else
|
95
|
+
raise "campaigns must be an array of BingAdsApi::Campaigns"
|
96
|
+
end
|
97
|
+
message = {
|
98
|
+
:account_id => account_id,
|
99
|
+
:campaigns => {:campaign => camps} }
|
100
|
+
puts message
|
101
|
+
response = call(:add_campaigns, message)
|
102
|
+
return get_response_hash(response, __method__)
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
# Public : Updates on or more campaigns for the specified account
|
107
|
+
#
|
108
|
+
# Author:: jlopezn@neonline.cl
|
109
|
+
#
|
110
|
+
# === Parameters
|
111
|
+
# account_id - account who own the updated campaigns
|
112
|
+
# campaigns - Array with the campaigns to be updated
|
113
|
+
#
|
114
|
+
# === Examples
|
115
|
+
# service_update_campaigns(1, [<BingAdsApi::Campaign])
|
116
|
+
# # => true
|
117
|
+
#
|
118
|
+
# Returns:: boolean. true if the update was successful. false otherwise
|
119
|
+
#
|
120
|
+
# Raises:: exception
|
121
|
+
def update_campaigns(account_id, campaigns)
|
122
|
+
camps = []
|
123
|
+
if campaigns.is_a? Array
|
124
|
+
camps = campaigns.map do |camp|
|
125
|
+
camp.to_hash(:camelcase)
|
126
|
+
end
|
127
|
+
elsif campaigns.is_a? BingAdsApi::Campaign
|
128
|
+
camps = campaigns.to_hash
|
129
|
+
else
|
130
|
+
raise "campaigns must be an array of BingAdsApi::Campaigns"
|
131
|
+
end
|
132
|
+
message = {
|
133
|
+
:account_id => account_id,
|
134
|
+
:campaigns => {:campaign => camps} }
|
135
|
+
puts message
|
136
|
+
response = call(:update_campaigns, message)
|
137
|
+
return get_response_hash(response, __method__)
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
# Public : Returns all the ad groups that belongs to the
|
143
|
+
# specified campaign
|
144
|
+
#
|
145
|
+
# Author:: jlopezn@neonline.cl
|
146
|
+
#
|
147
|
+
# === Parameters
|
148
|
+
# campaign_id - campaign id
|
149
|
+
#
|
150
|
+
# === Examples
|
151
|
+
# service.get_ad_groups_by_campaign_id(1)
|
152
|
+
# # => Array[AdGroups]
|
153
|
+
#
|
154
|
+
# Returns:: Array with all the ad groups present in campaign_id
|
155
|
+
#
|
156
|
+
# Raises:: exception
|
157
|
+
def get_ad_groups_by_campaign_id(campaign_id)
|
158
|
+
response = call(:get_ad_groups_by_campaign_id,
|
159
|
+
{campaign_id: campaign_id})
|
160
|
+
response_hash = get_response_hash(response, __method__)
|
161
|
+
ad_groups = response_hash[:ad_groups][:ad_group].map do |ad_group_hash|
|
162
|
+
BingAdsApi::AdGroup.new(ad_group_hash)
|
163
|
+
end
|
164
|
+
return ad_groups
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
# Public : Returns the specified ad groups that belongs to the
|
169
|
+
# specified campaign
|
170
|
+
#
|
171
|
+
# Author:: jlopezn@neonline.cl
|
172
|
+
#
|
173
|
+
# === Parameters
|
174
|
+
# campaign_id - campaign id
|
175
|
+
# ad_groups_ids - array with ids from ad groups
|
176
|
+
#
|
177
|
+
# === Examples
|
178
|
+
# service.get_ad_groups_by_ids(1, [1,2,3])
|
179
|
+
# # => Array[AdGroups]
|
180
|
+
#
|
181
|
+
# Returns:: Array with the ad groups specified in the ad_groups_ids array
|
182
|
+
#
|
183
|
+
# Raises:: exception
|
184
|
+
def get_ad_groups_by_ids(campaign_id, ad_groups_ids)
|
185
|
+
|
186
|
+
message = {
|
187
|
+
:campaign_id => campaign_id,
|
188
|
+
:ad_group_ids => {"ins1:long" => ad_groups_ids} }
|
189
|
+
response = call(:get_ad_groups_by_ids, message)
|
190
|
+
response_hash = get_response_hash(response, __method__)
|
191
|
+
ad_groups = response_hash[:ad_groups][:ad_group].map do |ad_group_hash|
|
192
|
+
BingAdsApi::AdGroup.new(ad_group_hash)
|
193
|
+
end
|
194
|
+
return ad_groups
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
# Public : Adds 1 or more AdGroups to a Campaign
|
200
|
+
#
|
201
|
+
# Author:: jlopezn@neonline.cl
|
202
|
+
#
|
203
|
+
# === Parameters
|
204
|
+
# campaing_id - the campaign id where the ad groups will be added
|
205
|
+
# ad_groups - Array[BingAdsApi::AdGroup] ad groups to be added
|
206
|
+
#
|
207
|
+
# === Examples
|
208
|
+
# service.add_ad_groups(1, [<BingAdsApi::AdGroup>])
|
209
|
+
# # => <Hash>
|
210
|
+
#
|
211
|
+
# Returns:: Hash with the 'add_ad_groups_response' structure
|
212
|
+
#
|
213
|
+
# Raises:: exception
|
214
|
+
def add_ad_groups(campaign_id, ad_groups)
|
215
|
+
|
216
|
+
groups = []
|
217
|
+
if ad_groups.is_a? Array
|
218
|
+
groups = ad_groups.map{ |gr| gr.to_hash(:camelcase) }
|
219
|
+
elsif ad_groups.is_a? BingAdsApi::AdGroup
|
220
|
+
groups = ad_groups.to_hash
|
221
|
+
else
|
222
|
+
raise "ad_groups must be an array of BingAdsApi::AdGroup"
|
223
|
+
end
|
224
|
+
message = {
|
225
|
+
:campaign_id => campaign_id,
|
226
|
+
:ad_groups => {:ad_group => groups} }
|
227
|
+
puts message
|
228
|
+
response = call(:add_ad_groups, message)
|
229
|
+
return get_response_hash(response, __method__)
|
230
|
+
end
|
231
|
+
|
232
|
+
|
233
|
+
# Public : Updates on or more ad groups in a specified campaign
|
234
|
+
#
|
235
|
+
# Author:: jlopezn@neonline.cl
|
236
|
+
#
|
237
|
+
# === Parameters
|
238
|
+
# campaign_id - campaign who owns the updated ad groups
|
239
|
+
#
|
240
|
+
# === Examples
|
241
|
+
# service.update_ad_groups(1, [<BingAdsApi::AdGroup])
|
242
|
+
# # => true
|
243
|
+
#
|
244
|
+
# Returns:: boolean. true if the updates is successfull. false otherwise
|
245
|
+
#
|
246
|
+
# Raises:: exception
|
247
|
+
def update_ad_groups(campaign_id, ad_groups)
|
248
|
+
groups = []
|
249
|
+
if ad_groups.is_a? Array
|
250
|
+
groups = ad_groups.map{ |gr| gr.to_hash(:camelcase) }
|
251
|
+
elsif ad_groups.is_a? BingAdsApi::AdGroup
|
252
|
+
groups = ad_groups.to_hash(:camelcase)
|
253
|
+
else
|
254
|
+
raise "ad_groups must be an array or instance of BingAdsApi::AdGroup"
|
255
|
+
end
|
256
|
+
message = {
|
257
|
+
:campaign_id => campaign_id,
|
258
|
+
:ad_groups => {:ad_group => groups} }
|
259
|
+
puts message
|
260
|
+
response = call(:update_ad_groups, message)
|
261
|
+
return get_response_hash(response, __method__)
|
262
|
+
end
|
263
|
+
|
264
|
+
|
265
|
+
# Public : Obtains all the ads associated to the specified ad group
|
266
|
+
#
|
267
|
+
# Author:: jlopezn@neonline.cl
|
268
|
+
#
|
269
|
+
# === Parameters
|
270
|
+
# ad_group_id - long with the ad group id
|
271
|
+
#
|
272
|
+
# === Examples
|
273
|
+
# service.get_ads_by_ad_group_id(1)
|
274
|
+
# # => [<BingAdsApi::Ad]
|
275
|
+
#
|
276
|
+
# Returns:: An array of BingAdsApi::Ad
|
277
|
+
#
|
278
|
+
# Raises:: exception
|
279
|
+
def get_ads_by_ad_group_id(ad_group_id)
|
280
|
+
response = call(:get_ads_by_ad_group_id,
|
281
|
+
{ad_group_id: ad_group_id})
|
282
|
+
response_hash = get_response_hash(response, __method__)
|
283
|
+
|
284
|
+
if response_hash[:ads][:ad].is_a?(Array)
|
285
|
+
ads = response_hash[:ads][:ad].map do |ad_hash|
|
286
|
+
initialize_ad(ad_hash)
|
287
|
+
end
|
288
|
+
else
|
289
|
+
ads = [ initialize_ad(response_hash[:ads][:ad]) ]
|
290
|
+
end
|
291
|
+
return ads
|
292
|
+
end
|
293
|
+
|
294
|
+
|
295
|
+
# Public : Obtains the ads indicated in ad_ids associated to the specified ad group
|
296
|
+
#
|
297
|
+
# Author:: jlopezn@neonline.cl
|
298
|
+
#
|
299
|
+
# === Parameters
|
300
|
+
# ad_group_id - long with the ad group id
|
301
|
+
# ads_id - an Array io ads ids, that are associated to the ad_group_id provided
|
302
|
+
#
|
303
|
+
# === Examples
|
304
|
+
# service.get_ads_by_ids(1, [1,2,3])
|
305
|
+
# # => [<BingAdsApi::Ad>]
|
306
|
+
#
|
307
|
+
# Returns:: An array of BingAdsApi::Ad
|
308
|
+
#
|
309
|
+
# Raises:: exception
|
310
|
+
def get_ads_by_ids(ad_group_id, ad_ids)
|
311
|
+
|
312
|
+
|
313
|
+
message = {
|
314
|
+
:ad_group_id => ad_group_id,
|
315
|
+
:ad_ids => {"ins1:long" => ad_ids} }
|
316
|
+
response = call(:get_ads_by_ids, message)
|
317
|
+
response_hash = get_response_hash(response, __method__)
|
318
|
+
|
319
|
+
if response_hash[:ads][:ad].is_a?(Array)
|
320
|
+
ads = response_hash[:ads][:ad].map do |ad_hash|
|
321
|
+
initialize_ad(ad_hash)
|
322
|
+
end
|
323
|
+
else
|
324
|
+
ads = [ initialize_ad(response_hash[:ads][:ad]) ]
|
325
|
+
end
|
326
|
+
return ads
|
327
|
+
end
|
328
|
+
|
329
|
+
|
330
|
+
# Public : Add ads into a specified ad group
|
331
|
+
#
|
332
|
+
# Author:: jlopezn@neonline.cl
|
333
|
+
#
|
334
|
+
# === Parameters
|
335
|
+
# ad_group_id - a number with the id where the ads should be added
|
336
|
+
# ads - an array of BingAdsApi::Ad instances
|
337
|
+
#
|
338
|
+
# === Examples
|
339
|
+
# # if the operation returns partial errors
|
340
|
+
# service.add_ads(1, [BingAdsApi::Ad])
|
341
|
+
# # => {:ad_ids => [], :partial_errors => BingAdsApi::PartialErrors }
|
342
|
+
#
|
343
|
+
# # if the operation doesn't return partial errors
|
344
|
+
# service.add_ads(1, [BingAdsApi::Ad])
|
345
|
+
# # => {:ad_ids => [] }
|
346
|
+
#
|
347
|
+
# Returns:: Hash with the AddAdsResponse structure.
|
348
|
+
# If the operation returns 'PartialErrors' key,
|
349
|
+
# this methods returns those errors as an BingAdsApi::PartialErrors
|
350
|
+
# instance
|
351
|
+
#
|
352
|
+
# Raises:: exception
|
353
|
+
def add_ads(ad_group_id, ads)
|
354
|
+
|
355
|
+
ads_for_soap = []
|
356
|
+
if ads.is_a? Array
|
357
|
+
ads_for_soap = ads.map{ |ad| ad_to_hash(ad, :camelcase) }
|
358
|
+
elsif ads.is_a? BingAdsApi::Ad
|
359
|
+
ads_for_soap = ad_to_hash(ads, :camelcase)
|
360
|
+
else
|
361
|
+
raise "ads must be an array or instance of BingAdsApi::Ad"
|
362
|
+
end
|
363
|
+
message = {
|
364
|
+
:ad_group_id => ad_group_id,
|
365
|
+
:ads => {:ad => ads_for_soap} }
|
366
|
+
puts message
|
367
|
+
response = call(:add_ads, message)
|
368
|
+
|
369
|
+
response_hash = get_response_hash(response, __method__)
|
370
|
+
|
371
|
+
# Checks if there are partial errors in the request
|
372
|
+
if response_hash[:partial_errors].key?(:batch_error)
|
373
|
+
partial_errors = BingAdsApi::PartialErrors.new(
|
374
|
+
response_hash[:partial_errors])
|
375
|
+
response_hash[:partial_errors] = partial_errors
|
376
|
+
else
|
377
|
+
response_hash.delete(:partial_errors)
|
378
|
+
end
|
379
|
+
|
380
|
+
return response_hash
|
381
|
+
end
|
382
|
+
|
383
|
+
|
384
|
+
# Public : Updates ads for the specified ad group
|
385
|
+
#
|
386
|
+
# Author:: jlopezn@neonline.cl
|
387
|
+
#
|
388
|
+
# === Parameters
|
389
|
+
# ad_group_id - long with the ad group id
|
390
|
+
# ads - array of BingAdsApi::Ad subclasses instances to update
|
391
|
+
#
|
392
|
+
# === Examples
|
393
|
+
# service.update_ads(1, [<BingAdsApi::Ad>])
|
394
|
+
# # => Hash
|
395
|
+
#
|
396
|
+
# Returns:: Hash with the UpdateAddsResponse structure
|
397
|
+
#
|
398
|
+
# Raises:: exception
|
399
|
+
def update_ads(ad_group_id, ads)
|
400
|
+
|
401
|
+
ads_for_soap = []
|
402
|
+
if ads.is_a? Array
|
403
|
+
ads_for_soap = ads.map{ |ad| ad_to_hash(ad, :camelcase) }
|
404
|
+
elsif ads.is_a? BingAdsApi::Ad
|
405
|
+
ads_for_soap = ad_to_hash(ads, :camelcase)
|
406
|
+
else
|
407
|
+
raise "ads must be an array or instance of BingAdsApi::Ad"
|
408
|
+
end
|
409
|
+
message = {
|
410
|
+
:ad_group_id => ad_group_id,
|
411
|
+
:ads => {:ad => ads_for_soap} }
|
412
|
+
puts message
|
413
|
+
response = call(:update_ads, message)
|
414
|
+
|
415
|
+
response_hash = get_response_hash(response, __method__)
|
416
|
+
|
417
|
+
# Checks if there are partial errors in the request
|
418
|
+
if response_hash[:partial_errors].key?(:batch_error)
|
419
|
+
partial_errors = BingAdsApi::PartialErrors.new(
|
420
|
+
response_hash[:partial_errors])
|
421
|
+
response_hash[:partial_errors] = partial_errors
|
422
|
+
else
|
423
|
+
response_hash.delete(:partial_errors)
|
424
|
+
end
|
425
|
+
|
426
|
+
return response_hash
|
427
|
+
end
|
428
|
+
|
429
|
+
|
430
|
+
private
|
431
|
+
def get_service_name
|
432
|
+
"campaign_management"
|
433
|
+
end
|
434
|
+
|
435
|
+
# Private : Returns an instance of any of the subclases of BingAdsApi::Ad based on the '@i:type' value in the hash
|
436
|
+
#
|
437
|
+
# Author:: jlopezn@neonline.cl
|
438
|
+
#
|
439
|
+
# ad_hash - Hash returned by the SOAP request with the Ad attributes
|
440
|
+
#
|
441
|
+
# Examples
|
442
|
+
# initialize_ad({:device_preference=>"0", :editorial_status=>"Active",
|
443
|
+
# :forward_compatibility_map=>{:"@xmlns:a"=>"http://schemas.datacontract.org/2004/07/System.Collections.Generic"},
|
444
|
+
# :id=>"1", :status=>"Active", :type=>"Text",
|
445
|
+
# :destination_url=>"www.some-url.com", :display_url=>"http://www.some-url.com",
|
446
|
+
# :text=>"My Page", :title=>"My Page",
|
447
|
+
# :"@i:type"=>"TextAd"})
|
448
|
+
# # => BingAdsApi::TextAd
|
449
|
+
#
|
450
|
+
# Returns:: BingAdsApi::Ad subclass instance
|
451
|
+
def initialize_ad(ad_hash)
|
452
|
+
ad = BingAdsApi::Ad.new(ad_hash)
|
453
|
+
case ad_hash["@i:type".to_sym]
|
454
|
+
when "TextAd"
|
455
|
+
ad = BingAdsApi::TextAd.new(ad_hash)
|
456
|
+
when "MobileAd"
|
457
|
+
ad = BingAdsApi::MobileAd.new(ad_hash)
|
458
|
+
when "ProductAd"
|
459
|
+
ad = BingAdsApi::ProductAd.new(ad_hash)
|
460
|
+
end
|
461
|
+
return ad
|
462
|
+
end
|
463
|
+
|
464
|
+
|
465
|
+
# Private : Helper method to correctly assemble the Ad XML for SOAP requests
|
466
|
+
#
|
467
|
+
# Author:: jlopezn@neonline.cl
|
468
|
+
#
|
469
|
+
# ad - BingAdsApi::Ad subclass instance
|
470
|
+
#
|
471
|
+
# Examples
|
472
|
+
# ad_to_hash(BingAdsApi::Ad, :camelcase)
|
473
|
+
# # => Hash
|
474
|
+
#
|
475
|
+
# Returns:: The same hash that ad.to_hash returns plus the needed key for the Ad Type
|
476
|
+
def ad_to_hash(ad, keys)
|
477
|
+
hash = ad.to_hash(keys)
|
478
|
+
hash["@xsi:type"] = self.client_proxy.class::NAMESPACE.to_s + ":" + ad.class.to_s.demodulize
|
479
|
+
return hash
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
483
|
+
end
|