bing-ads-api 0.1.0
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/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
|