bing-ads 0.1.11 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 423587915177b9c676bd2534087b0a8f233cbbc9
4
- data.tar.gz: 5377b102e6a1512fbd268c97bada27af95482184
3
+ metadata.gz: 69fd2b5280eafbb14724463be4492828935ebbc4
4
+ data.tar.gz: 0fa11c1a1c80a3788b42637248340933455488d9
5
5
  SHA512:
6
- metadata.gz: 56a1313389de341e937e47b94ec8fec9be888f619a547000bbfc305f28dd78de618b5578b8e6f345e7117ca2dc89a6f2693cca82ea9c43666283bf9344e2be33
7
- data.tar.gz: 5dbd8a412d30767047a3a7dc6380fdb134f240d543ba121653f7857d0247e22470ae2ae8ca8cee07f660b1bfc07fcdd2ef2d9c772048c67b1b7d292cf968dfda
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
- Not yet supported
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
- Not yet supported. Use: https://github.com/FindHotel/bing-ads-reporting
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.
@@ -7,6 +7,7 @@ require 'savon'
7
7
 
8
8
  require 'bing/ads/api/errors'
9
9
  require 'bing/ads/api/soap_client'
10
+ require 'bing/ads/api/http_client'
10
11
  require 'bing/ads/api/v11'
11
12
  require 'bing/ads/api/v11/constants'
12
13
  require 'bing/ads/api/v11/data'
@@ -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
@@ -2,3 +2,4 @@ require_relative './data/ad_group'
2
2
  require_relative './data/expanded_text_ad'
3
3
  require_relative './data/campaign'
4
4
  require_relative './data/keyword'
5
+ require_relative './data/report_request'
@@ -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
@@ -2,3 +2,4 @@ require_relative './services/base'
2
2
  require_relative './services/bulk'
3
3
  require_relative './services/campaign_management'
4
4
  require_relative './services/customer_management'
5
+ require_relative './services/reporting'
@@ -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
- fault_detail = error.to_hash[:fault][:detail]
55
- if fault_detail.key?(:api_fault_detail)
56
- handle_soap_fault(operation, fault_detail, :api_fault_detail)
57
- elsif fault_detail.key?(:ad_api_fault_detail)
58
- handle_soap_fault(operation, fault_detail, :ad_api_fault_detail)
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 (#{fault_detail.keys.join(', ')}) while calling #{operation}. #{error.message}"
67
+ "SOAP error (#{fault.keys.join(', ')}) while calling #{operation}. #{error.message}"
67
68
  end
68
69
  end
69
70
  rescue Savon::HTTPError => error
@@ -23,6 +23,8 @@ module Bing
23
23
  response_body.slice(:errors, :percent_complete, :request_status, :result_file_url)
24
24
  end
25
25
 
26
+ # TODO operations: https://msdn.microsoft.com/en-us/library/bing-ads-bulk-service-operations.aspx
27
+
26
28
  private
27
29
 
28
30
  def service_name
@@ -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
@@ -1,5 +1,5 @@
1
1
  module Bing
2
2
  module Ads
3
- VERSION = '0.1.11'
3
+ VERSION = '0.2.0'
4
4
  end
5
5
  end
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.1.11
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-09-12 00:00:00.000000000 Z
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.12
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