bing-ads 0.1.11 → 0.2.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.
- checksums.yaml +4 -4
- data/README.md +109 -4
- data/lib/bing/ads.rb +1 -0
- data/lib/bing/ads/api/errors.rb +3 -0
- data/lib/bing/ads/api/http_client.rb +22 -0
- data/lib/bing/ads/api/v11/data.rb +1 -0
- data/lib/bing/ads/api/v11/data/report_request.rb +106 -0
- data/lib/bing/ads/api/v11/services.rb +1 -0
- data/lib/bing/ads/api/v11/services/base.rb +7 -6
- data/lib/bing/ads/api/v11/services/bulk.rb +2 -0
- data/lib/bing/ads/api/v11/services/reporting.rb +51 -0
- data/lib/bing/ads/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 69fd2b5280eafbb14724463be4492828935ebbc4
|
4
|
+
data.tar.gz: 0fa11c1a1c80a3788b42637248340933455488d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c07d81eb68e2f058b0ec7a1ca6fca6a426e89c61f4efad82d8f12a8ead814c1771859f74ac3b7ec5dc114e36ca067f302baa4352dc511e3f567c8dbb64501a32
|
7
|
+
data.tar.gz: b7ed4a73f67e5daa38b16e12512e49322cc5b74f05ce7b4645a72c419dde7f961a9ad8452e48b82ee18406cfe9840496d7f121a0d4e78d24cd910158599fe6ad
|
data/README.md
CHANGED
@@ -312,16 +312,121 @@ response = service.delete_keywords(ad_group_id, keyword_ids_to_delete)
|
|
312
312
|
```
|
313
313
|
|
314
314
|
### Bulk Service
|
315
|
-
|
315
|
+
#### Initialization
|
316
|
+
```ruby
|
317
|
+
# Authentication token is not supported in sandbox, use `username` and `password` instead
|
318
|
+
# https://msdn.microsoft.com/en-us/library/dn277356.aspx
|
319
|
+
|
320
|
+
options = {
|
321
|
+
environment: :sandbox,
|
322
|
+
authentication_token: '39b290146bea6ce975c37cfc23',
|
323
|
+
developer_token: 'BBD37VB98',
|
324
|
+
customer_id: '21027149',
|
325
|
+
account_id: '5278183',
|
326
|
+
# client_settings: { logger: LOGGER::STDOUT }
|
327
|
+
}
|
328
|
+
|
329
|
+
service = Bing::Ads::API::V11::Services::Bulk.new(options)
|
330
|
+
```
|
331
|
+
|
332
|
+
#### Submit a request for a URL where a bulk upload file may be posted.
|
333
|
+
```ruby
|
334
|
+
response = service.get_bulk_upload_url
|
335
|
+
|
336
|
+
# @return
|
337
|
+
# {
|
338
|
+
# request_id: 4981237213
|
339
|
+
# upload_url: '-'
|
340
|
+
# }
|
341
|
+
```
|
342
|
+
|
343
|
+
#### Get the status and completion percentage of a bulk upload request.
|
344
|
+
```ruby
|
345
|
+
response = service.get_bulk_upload_status(request_id)
|
346
|
+
|
347
|
+
# @return
|
348
|
+
# {
|
349
|
+
# errors: [],
|
350
|
+
# percent_complete: 100,
|
351
|
+
# request_status: '-',
|
352
|
+
# result_file_url: '-'
|
353
|
+
# }
|
354
|
+
```
|
316
355
|
|
317
356
|
### Reporting Service
|
318
|
-
|
357
|
+
|
358
|
+
#### Initialization
|
359
|
+
```ruby
|
360
|
+
# Authentication token is not supported in sandbox, use `username` and `password` instead
|
361
|
+
# https://msdn.microsoft.com/en-us/library/dn277356.aspx
|
362
|
+
|
363
|
+
options = {
|
364
|
+
environment: :sandbox,
|
365
|
+
authentication_token: '39b290146bea6ce975c37cfc23',
|
366
|
+
developer_token: 'BBD37VB98',
|
367
|
+
customer_id: '21027149',
|
368
|
+
# client_settings: { logger: LOGGER::STDOUT }
|
369
|
+
}
|
370
|
+
|
371
|
+
service = Bing::Ads::API::V11::Services::Reporting.new(options)
|
372
|
+
```
|
373
|
+
|
374
|
+
#### Submit Generate Report
|
375
|
+
To get reports from Bing, you must first submit a report generation request.
|
376
|
+
|
377
|
+
The method `submit_generate_report` receive two params as input, first the `report_type` and then a hash with the report options.
|
378
|
+
|
379
|
+
Example:
|
380
|
+
|
381
|
+
```ruby
|
382
|
+
response = service.submit_generate_report(:keyword_performance, {
|
383
|
+
exclude_column_headers: false,
|
384
|
+
exclude_report_footer: false,
|
385
|
+
exclude_report_header: false,
|
386
|
+
language: 'English',
|
387
|
+
format: 'Tsv',
|
388
|
+
report_name: 'keyword_performance_report',
|
389
|
+
return_only_complete_data: false,
|
390
|
+
aggregation: 'Daily',
|
391
|
+
columns: [:destination_url, :average_cpc],
|
392
|
+
from_date: '2017-10-23',
|
393
|
+
to_date: '2017-10-25'
|
394
|
+
account_ids: [144012349, 224002158]
|
395
|
+
})
|
396
|
+
```
|
397
|
+
|
398
|
+
The required options depend on the report type you are using.
|
399
|
+
|
400
|
+
Response example:
|
401
|
+
|
402
|
+
```ruby
|
403
|
+
{:report_request_id=>"30000000999745662", :@xmlns=>"https://bingads.microsoft.com/Reporting/v11"}
|
404
|
+
```
|
405
|
+
|
406
|
+
#### Poll Generate Report
|
407
|
+
|
408
|
+
To retrieve the report generated you have a few options:
|
409
|
+
|
410
|
+
You can check if the report is ready and then get the url:
|
411
|
+
```ruby
|
412
|
+
service.report_url(report_request_id) if service.report_ready?(report_request_id)
|
413
|
+
```
|
414
|
+
|
415
|
+
Or you can download the body of the report when it's ready. (and then write to a file for example)
|
416
|
+
```ruby
|
417
|
+
service.report_body(report_request_id) if service.report_ready?(report_request_id)
|
418
|
+
```
|
419
|
+
|
420
|
+
You can also get the entire poll_generate_reportl report object:
|
421
|
+
```ruby
|
422
|
+
service.poll_generate_report(report_request_id)
|
423
|
+
```
|
319
424
|
|
320
425
|
### Errors raised
|
321
|
-
* `Bing::Ads::API::Errors::AuthenticationParamsMissing`
|
322
|
-
No username/password or authentication_token.
|
426
|
+
* `Bing::Ads::API::Errors::AuthenticationParamsMissing` No username/password or authentication_token.
|
323
427
|
* `Bing::Ads::API::Errors::AuthenticationTokenExpired` Authentication token needs to be refreshed.
|
324
428
|
* `Bing::Ads::API::Errors::LimitError` An API limit has been exceeded on a specific request. Check message for details.
|
429
|
+
* `Bing::Ads::API::Errors::DownloadError` Error when downloading a report body.
|
325
430
|
|
326
431
|
## Development
|
327
432
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/bing/ads.rb
CHANGED
data/lib/bing/ads/api/errors.rb
CHANGED
@@ -11,6 +11,9 @@ module Bing
|
|
11
11
|
# Bing::Ads::API::Errors::UnhandledSOAPFault
|
12
12
|
class UnhandledSOAPFault < RuntimeError; end;
|
13
13
|
|
14
|
+
# Bing::Ads::API::Errors::DownloadError
|
15
|
+
class DownloadError < RuntimeError; end;
|
16
|
+
|
14
17
|
# Bing::Ads::API::Errors::LimitError
|
15
18
|
class LimitError < RuntimeError
|
16
19
|
def initialize(operation, limit, type)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Bing
|
2
|
+
module Ads
|
3
|
+
module API
|
4
|
+
# Bing::Ads::API::HttpClient
|
5
|
+
class HttpClient
|
6
|
+
API_CALL_RETRY_COUNT = 3
|
7
|
+
|
8
|
+
def self.download(url, retry_count = API_CALL_RETRY_COUNT)
|
9
|
+
1.upto(retry_count + 1) do |retry_index|
|
10
|
+
response = Net::HTTP.get_response(URI(url))
|
11
|
+
if response.is_a?(Net::HTTPSuccess)
|
12
|
+
break response.body
|
13
|
+
else
|
14
|
+
next if retry_index <= retry_count
|
15
|
+
raise Bing::Ads::API::Errors::DownloadError, "#{response.code} #{response.msg}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module Bing
|
2
|
+
module Ads
|
3
|
+
module API
|
4
|
+
module V11
|
5
|
+
module Data
|
6
|
+
# Bing::Ads::API::V11::Data::ReportRequest
|
7
|
+
class ReportRequest
|
8
|
+
|
9
|
+
# @order
|
10
|
+
# https://msdn.microsoft.com/en-us/library/bing-ads-reporting-reportrequest.aspx
|
11
|
+
KEYS_ORDER = [
|
12
|
+
:exclude_column_headers,
|
13
|
+
:exclude_report_footer,
|
14
|
+
:exclude_report_header,
|
15
|
+
:format,
|
16
|
+
:language,
|
17
|
+
:report_name,
|
18
|
+
:return_only_complete_data,
|
19
|
+
:aggregation,
|
20
|
+
:columns,
|
21
|
+
:filter,
|
22
|
+
:scope,
|
23
|
+
:time
|
24
|
+
]
|
25
|
+
|
26
|
+
class << self
|
27
|
+
def prepare(type, report_request_raw)
|
28
|
+
report_request_raw[:columns] = prepare_columns(
|
29
|
+
columns: report_request_raw[:columns],
|
30
|
+
type: type.to_s.classify
|
31
|
+
)
|
32
|
+
|
33
|
+
report_request_raw[:scope] = prepare_scope(
|
34
|
+
account_ids: report_request_raw[:account_ids]
|
35
|
+
)
|
36
|
+
|
37
|
+
report_request_raw[:time] = prepare_time_period(
|
38
|
+
from_date: report_request_raw[:from_date],
|
39
|
+
to_date: report_request_raw[:to_date]
|
40
|
+
)
|
41
|
+
|
42
|
+
report_request_raw.except!(:from_date, :to_date, :account_ids)
|
43
|
+
|
44
|
+
report_request = Bing::Ads::Utils.sort_keys(report_request_raw, KEYS_ORDER)
|
45
|
+
namespace_identifier = Bing::Ads::API::V11::NAMESPACE_IDENTIFIER
|
46
|
+
{
|
47
|
+
report_request: Bing::Ads::Utils.camelcase_keys(report_request),
|
48
|
+
:attributes! => {
|
49
|
+
report_request: {
|
50
|
+
"xmlns:i" => "http://www.w3.org/2001/XMLSchema-instance",
|
51
|
+
"i:type" => "#{namespace_identifier}:#{type.to_s.classify}ReportRequest"
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def prepare_columns(type:, columns:)
|
60
|
+
{
|
61
|
+
"#{type}ReportColumn" => columns.map(&:to_s).map(&:camelcase)
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def prepare_scope(account_ids:)
|
66
|
+
account_ids_elements =
|
67
|
+
if account_ids.nil?
|
68
|
+
nil
|
69
|
+
else
|
70
|
+
{
|
71
|
+
'a1:long' => account_ids,
|
72
|
+
'@xmlns:a1' => 'http://schemas.microsoft.com/2003/10/Serialization/Arrays'
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
{
|
77
|
+
account_ids: account_ids_elements,
|
78
|
+
ad_groups: nil,
|
79
|
+
campaigns: nil
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
def prepare_time_period(from_date:, to_date:)
|
84
|
+
from_date = Date.parse(from_date)
|
85
|
+
to_date = Date.parse(to_date)
|
86
|
+
|
87
|
+
{
|
88
|
+
custom_date_range_end: {
|
89
|
+
day: to_date.day,
|
90
|
+
month: to_date.month,
|
91
|
+
year: to_date.year
|
92
|
+
},
|
93
|
+
custom_date_range_start: {
|
94
|
+
day: from_date.day,
|
95
|
+
month: from_date.month,
|
96
|
+
year: from_date.year
|
97
|
+
}
|
98
|
+
}
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -51,11 +51,12 @@ module Bing
|
|
51
51
|
response = soap_client.call(operation: operation.to_sym, payload: payload)
|
52
52
|
return response.hash
|
53
53
|
rescue Savon::SOAPFault => error
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
54
|
+
fault = error.to_hash[:fault]
|
55
|
+
|
56
|
+
if fault.dig(:detail, :api_fault_detail)
|
57
|
+
handle_soap_fault(operation, fault[:detail], :api_fault_detail)
|
58
|
+
elsif fault.dig(:detail, :ad_api_fault_detail)
|
59
|
+
handle_soap_fault(operation, fault[:detail], :ad_api_fault_detail)
|
59
60
|
else
|
60
61
|
if retries_made < retry_attempts
|
61
62
|
sleep(2**retries_made)
|
@@ -63,7 +64,7 @@ module Bing
|
|
63
64
|
retry
|
64
65
|
else
|
65
66
|
raise Bing::Ads::API::Errors::UnhandledSOAPFault,
|
66
|
-
"SOAP error (#{
|
67
|
+
"SOAP error (#{fault.keys.join(', ')}) while calling #{operation}. #{error.message}"
|
67
68
|
end
|
68
69
|
end
|
69
70
|
rescue Savon::HTTPError => error
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Bing
|
2
|
+
module Ads
|
3
|
+
module API
|
4
|
+
module V11
|
5
|
+
module Services
|
6
|
+
# Bing::Ads::API::V11::Services::CampaignManagement
|
7
|
+
class Reporting < Base
|
8
|
+
def initialize(options = {})
|
9
|
+
super(options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def submit_generate_report(type, report_options)
|
13
|
+
payload = Bing::Ads::API::V11::Data::ReportRequest.prepare(type, report_options)
|
14
|
+
response = call(:submit_generate_report, payload)
|
15
|
+
response_body = response_body(response, __method__)
|
16
|
+
response_body
|
17
|
+
end
|
18
|
+
|
19
|
+
def poll_generate_report(report_request_id)
|
20
|
+
response = call(:poll_generate_report, report_request_id: report_request_id)
|
21
|
+
response_body = response_body(response, __method__)
|
22
|
+
response_body
|
23
|
+
end
|
24
|
+
|
25
|
+
def report_ready?(report_request_id)
|
26
|
+
polled = poll_generate_report(report_request_id)
|
27
|
+
status = polled.dig(:report_request_status, :status)
|
28
|
+
raise "Report status: Error for ID: #{report_request_id}" if status == "Error"
|
29
|
+
status == "Success"
|
30
|
+
end
|
31
|
+
|
32
|
+
def report_url(report_request_id)
|
33
|
+
polled = poll_generate_report(report_request_id)
|
34
|
+
polled.dig(:report_request_status, :report_download_url)
|
35
|
+
end
|
36
|
+
|
37
|
+
def report_body(report_request_id)
|
38
|
+
HttpClient.download(report_url(report_request_id))
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def service_name
|
44
|
+
'reporting'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/bing/ads/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bing-ads
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- oss92
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: savon
|
@@ -117,6 +117,7 @@ files:
|
|
117
117
|
- bing-ads.gemspec
|
118
118
|
- lib/bing/ads.rb
|
119
119
|
- lib/bing/ads/api/errors.rb
|
120
|
+
- lib/bing/ads/api/http_client.rb
|
120
121
|
- lib/bing/ads/api/soap_client.rb
|
121
122
|
- lib/bing/ads/api/v11.rb
|
122
123
|
- lib/bing/ads/api/v11/constants.rb
|
@@ -130,11 +131,13 @@ files:
|
|
130
131
|
- lib/bing/ads/api/v11/data/campaign.rb
|
131
132
|
- lib/bing/ads/api/v11/data/expanded_text_ad.rb
|
132
133
|
- lib/bing/ads/api/v11/data/keyword.rb
|
134
|
+
- lib/bing/ads/api/v11/data/report_request.rb
|
133
135
|
- lib/bing/ads/api/v11/services.rb
|
134
136
|
- lib/bing/ads/api/v11/services/base.rb
|
135
137
|
- lib/bing/ads/api/v11/services/bulk.rb
|
136
138
|
- lib/bing/ads/api/v11/services/campaign_management.rb
|
137
139
|
- lib/bing/ads/api/v11/services/customer_management.rb
|
140
|
+
- lib/bing/ads/api/v11/services/reporting.rb
|
138
141
|
- lib/bing/ads/utils.rb
|
139
142
|
- lib/bing/ads/version.rb
|
140
143
|
homepage: https://github.com/FindHotel/bing-ads
|
@@ -157,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
157
160
|
version: '0'
|
158
161
|
requirements: []
|
159
162
|
rubyforge_project:
|
160
|
-
rubygems_version: 2.6.
|
163
|
+
rubygems_version: 2.6.13
|
161
164
|
signing_key:
|
162
165
|
specification_version: 4
|
163
166
|
summary: Enhances the experience of developing Bing Ads applications with Ruby
|