soapy_bing 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/lib/soapy_bing/ads/bulk/campaigns.rb +61 -0
  4. data/lib/soapy_bing/ads/bulk/parsers/csv_parser.rb +35 -0
  5. data/lib/soapy_bing/ads/bulk/parsers.rb +2 -0
  6. data/lib/soapy_bing/ads/bulk.rb +3 -0
  7. data/lib/soapy_bing/ads/reports/base.rb +1 -19
  8. data/lib/soapy_bing/ads.rb +9 -0
  9. data/lib/soapy_bing/helpers/zip_downloader.rb +26 -0
  10. data/lib/soapy_bing/helpers.rb +1 -1
  11. data/lib/soapy_bing/soap/request/download_campaigns_by_account_ids_request.rb +17 -0
  12. data/lib/soapy_bing/soap/request/get_bulk_download_status_request.rb +17 -0
  13. data/lib/soapy_bing/soap/request.rb +2 -0
  14. data/lib/soapy_bing/soap/response/download_campaigns_by_account_ids_response.rb +12 -0
  15. data/lib/soapy_bing/soap/response/get_accounts_info_response.rb +1 -1
  16. data/lib/soapy_bing/soap/response/get_ad_groups_by_campaign_id_response.rb +1 -1
  17. data/lib/soapy_bing/soap/response/get_ads_by_ad_group_id_response.rb +1 -1
  18. data/lib/soapy_bing/soap/response/get_bulk_download_status_response.rb +12 -0
  19. data/lib/soapy_bing/soap/response/get_targets_by_campaign_ids_response.rb +1 -1
  20. data/lib/soapy_bing/soap/response/payload.rb +13 -1
  21. data/lib/soapy_bing/soap/response/report_status.rb +1 -1
  22. data/lib/soapy_bing/soap/response/submit_generate_report_response.rb +1 -1
  23. data/lib/soapy_bing/soap/response.rb +2 -0
  24. data/lib/soapy_bing/soap/template_renderer.rb +1 -1
  25. data/lib/soapy_bing/soap/templates/download_campaigns_by_account_ids.xml.erb +22 -0
  26. data/lib/soapy_bing/soap/templates/{get_accounts_info.erb.xml → get_accounts_info.xml.erb} +0 -0
  27. data/lib/soapy_bing/soap/templates/{get_ad_groups_by_campaign_id.erb.xml → get_ad_groups_by_campaign_id.xml.erb} +0 -0
  28. data/lib/soapy_bing/soap/templates/{get_ads_by_ad_group_id.erb.xml → get_ads_by_ad_group_id.xml.erb} +0 -0
  29. data/lib/soapy_bing/soap/templates/get_bulk_download_status.xml.erb +15 -0
  30. data/lib/soapy_bing/soap/templates/{get_targets_by_campaign_ids.erb.xml → get_targets_by_campaign_ids.xml.erb} +0 -0
  31. data/lib/soapy_bing/soap/templates/{poll_generate_report.erb.xml → poll_generate_report.xml.erb} +0 -0
  32. data/lib/soapy_bing/soap/templates/{submit_generate_report.erb.xml → submit_generate_report.xml.erb} +0 -0
  33. data/lib/soapy_bing/version.rb +1 -1
  34. data/spec/fixtures/bulk/campaigns.csv +8 -0
  35. data/spec/fixtures/bulk/campaigns.json +1108 -0
  36. data/spec/fixtures/helpers/hello.zip +0 -0
  37. data/spec/fixtures/soap_templates/{simple.erb.xml → simple.xml.erb} +0 -0
  38. data/spec/fixtures/vcr_cassettes/SoapyBing_Ads_Bulk_Campaigns/_result_file_url/returns_result_file_url.yml +216 -0
  39. data/spec/integration/soapy_bing/ads/bulk/campaigns_spec.rb +35 -0
  40. data/spec/soapy_bing/ads/bulk/parsers/csv_parser_spec.rb +22 -0
  41. data/spec/soapy_bing/helpers/zip_downloader_spec.rb +16 -0
  42. data/spec/soapy_bing/soap/response/payload_spec.rb +26 -4
  43. data/spec/soapy_bing/soap/template_renderer_spec.rb +2 -2
  44. metadata +35 -13
  45. data/lib/soapy_bing/helpers/ssl_version.rb +0 -18
  46. data/spec/soapy_bing/helpers/ssl_version_spec.rb +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6afe9e7e07f2ae7766ed8bf8ede8fd09bb44d959
4
- data.tar.gz: 471bcd556c53589f2e2721507f85a4e582d29fbc
3
+ metadata.gz: 050d78288c2a6684ef1755104627587ba44f6263
4
+ data.tar.gz: 84eca8e11161bd4645d2d8ba35a7e42defdf281d
5
5
  SHA512:
6
- metadata.gz: 1097d26a4f5a57076061b4a550a9c0cdfdc8579bc0315d86e444c07d0d3690c743ed36e8c94b33a19f4a8f423bfd0af4452eebce034dfad243861534b642e0d1
7
- data.tar.gz: 3f3b44dec28fc377efc7cb813efef0d69847b6e5fb6eff01a717b6244cf42da59293d17d0f63f286d5d564735de65f284d5e059df4997d24923c095e5f1c1ad8
6
+ metadata.gz: b39872dacbc8cc83a41293ba31cbdbb98ddc22902093f361064b6218224e105c63a4f5e8baf7b86d3867dc10d6bd2dd9a4d5bce5e8a4c62428ab98a97287777a
7
+ data.tar.gz: b45e9ef2c03f630a262ef99f67e6267deb3354fd082a601bddbabd111973a69788a81dd03a391342d953b8dc431e4997ccea03110f5adad8f3d3c5a31a4e52a0
data/.gitignore CHANGED
@@ -5,3 +5,4 @@ Gemfile.lock
5
5
  .env.local
6
6
  .env.development
7
7
  .bundle
8
+ /pkg
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+ module SoapyBing
3
+ class Ads
4
+ module Bulk
5
+ class Campaigns
6
+ DEFAULT_ENTITIES = %w(CampaignTargets Ads).freeze
7
+ POLLING_TRIES = 30
8
+ NotCompleted = Class.new(StandardError)
9
+
10
+ attr_reader :oauth_credentials, :account, :entities, :status
11
+
12
+ def initialize(options)
13
+ @oauth_credentials = options.fetch(:oauth_credentials)
14
+ @account = options.fetch(:account)
15
+ @entities = options.fetch(:entities) || DEFAULT_ENTITIES
16
+ end
17
+
18
+ def rows
19
+ @rows ||= Parsers::CSVParser.new(Helpers::ZipDownloader.new(result_file_url).read).rows
20
+ end
21
+
22
+ def result_file_url
23
+ @result_file_url ||= begin
24
+ wait_status_complete
25
+ status['ResultFileUrl']
26
+ end
27
+ end
28
+
29
+ def fetch_status
30
+ @status = Soap::Request::GetBulkDownloadStatusRequest
31
+ .new(context: context.merge(request_id: download_request_id))
32
+ .perform
33
+ .payload
34
+ end
35
+
36
+ private
37
+
38
+ def wait_status_complete
39
+ Retryable.retryable(tries: POLLING_TRIES, on: NotCompleted) do
40
+ fetch_status
41
+ raise NotCompleted if status['RequestStatus'] != 'Completed'
42
+ end
43
+ end
44
+
45
+ def download_request_id
46
+ @download_request_id ||= Soap::Request::DownloadCampaignsByAccountIdsRequest
47
+ .new(context: context.merge(entities: entities))
48
+ .perform
49
+ .payload
50
+ end
51
+
52
+ def context
53
+ {
54
+ account: account,
55
+ authentication_token: oauth_credentials.access_token
56
+ }
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ require 'csv'
3
+
4
+ module SoapyBing
5
+ class Ads
6
+ module Bulk
7
+ module Parsers
8
+ class CSVParser
9
+ def initialize(raw)
10
+ @raw = raw
11
+ end
12
+
13
+ def rows
14
+ @rows ||= begin
15
+ header, *body = extract_csv_payload
16
+ body.map { |row| header.zip(row).to_h }
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :raw
23
+
24
+ def extract_csv_payload
25
+ text = raw.dup
26
+ text.force_encoding(Encoding::UTF_8).encode! unless text.encoding == Encoding::UTF_8
27
+ text.sub!(/^\xEF\xBB\xBF/, '') # cleanup BOM
28
+
29
+ CSV.parse(text)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,2 @@
1
+ # frozen_string_literal: true
2
+ require 'soapy_bing/ads/bulk/parsers/csv_parser'
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+ require 'soapy_bing/ads/bulk/parsers'
3
+ require 'soapy_bing/ads/bulk/campaigns'
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require 'ostruct'
3
- require 'uri'
4
- require 'httparty'
5
- require 'zip'
6
3
 
7
4
  module SoapyBing
8
5
  class Ads
@@ -10,7 +7,6 @@ module SoapyBing
10
7
  class Base
11
8
  class UnknownParserError < StandardError; end
12
9
  include Helpers::ClassName
13
- include Helpers::SSLVersion
14
10
 
15
11
  DEFAULT_REPORT_SETTINGS = {
16
12
  format: 'Csv',
@@ -29,7 +25,7 @@ module SoapyBing
29
25
  end
30
26
 
31
27
  def rows
32
- @rows ||= parser_class.new(report_body).rows
28
+ @rows ||= parser_class.new(Helpers::ZipDownloader.new(download_url).read).rows
33
29
  end
34
30
 
35
31
  private
@@ -56,20 +52,6 @@ module SoapyBing
56
52
  }
57
53
  end
58
54
 
59
- def report_body
60
- @report_body ||=
61
- Zip::InputStream.open(download_io) do |archive_io|
62
- file_io = archive_io.get_next_entry.get_input_stream
63
- file_io.read
64
- end
65
- end
66
-
67
- def download_io
68
- https = URI.parse(download_url).scheme == 'https'
69
- request_options = https ? { ssl_version: ssl_version } : {}
70
- StringIO.new HTTParty.get(download_url, request_options).body
71
- end
72
-
73
55
  def request_id
74
56
  @request_id ||=
75
57
  Soap::Request::SubmitGenerateReportRequest
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require 'soapy_bing/ads/reports'
3
+ require 'soapy_bing/ads/bulk'
3
4
 
4
5
  module SoapyBing
5
6
  class Ads
@@ -20,6 +21,14 @@ module SoapyBing
20
21
  )
21
22
  end
22
23
 
24
+ def bulk_campaigns(entities = nil)
25
+ Bulk::Campaigns.new(
26
+ oauth_credentials: oauth_credentials,
27
+ account: account,
28
+ entities: entities
29
+ )
30
+ end
31
+
23
32
  def get_ad_groups_by_campaign_id(campaign_id)
24
33
  do_request(Soap::Request::GetAdGroupsByCampaignIdRequest, campaign_id: campaign_id)
25
34
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ require 'httparty'
3
+ require 'zip'
4
+
5
+ module SoapyBing
6
+ module Helpers
7
+ class ZipDownloader
8
+ def initialize(url)
9
+ @url = url
10
+ end
11
+
12
+ def read
13
+ Zip::InputStream.open(download_io) do |archive_io|
14
+ file_io = archive_io.get_next_entry.get_input_stream
15
+ file_io.read
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def download_io
22
+ StringIO.new HTTParty.get(@url).body
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
  require 'soapy_bing/helpers/class_name'
3
- require 'soapy_bing/helpers/ssl_version'
3
+ require 'soapy_bing/helpers/zip_downloader'
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ module SoapyBing
3
+ module Soap
4
+ module Request
5
+ class DownloadCampaignsByAccountIdsRequest < Base
6
+ API_BASE_URL = 'https://bulk.api.bingads.microsoft.com'
7
+ API_VERSION = 10
8
+ API_ENDPOINT =
9
+ "#{API_BASE_URL}/Api/Advertiser/CampaignManagement/V#{API_VERSION}/BulkService.svc"
10
+
11
+ def perform
12
+ Response::DownloadCampaignsByAccountIdsResponse.new(post(API_ENDPOINT))
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ module SoapyBing
3
+ module Soap
4
+ module Request
5
+ class GetBulkDownloadStatusRequest < Base
6
+ API_BASE_URL = 'https://bulk.api.bingads.microsoft.com'
7
+ API_VERSION = 10
8
+ API_ENDPOINT =
9
+ "#{API_BASE_URL}/Api/Advertiser/CampaignManagement/V#{API_VERSION}/BulkService.svc"
10
+
11
+ def perform
12
+ Response::GetBulkDownloadStatusResponse.new(post(API_ENDPOINT))
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -6,3 +6,5 @@ require 'soapy_bing/soap/request/get_ad_groups_by_campaign_id_request'
6
6
  require 'soapy_bing/soap/request/get_ads_by_ad_group_id_request'
7
7
  require 'soapy_bing/soap/request/get_targets_by_campaign_ids_request'
8
8
  require 'soapy_bing/soap/request/get_accounts_info_request'
9
+ require 'soapy_bing/soap/request/download_campaigns_by_account_ids_request'
10
+ require 'soapy_bing/soap/request/get_bulk_download_status_request'
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module SoapyBing
3
+ module Soap
4
+ module Response
5
+ class DownloadCampaignsByAccountIdsResponse < Base
6
+ def extract_payload
7
+ response['DownloadRequestId']
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -4,7 +4,7 @@ module SoapyBing
4
4
  module Response
5
5
  class GetAccountsInfoResponse < Base
6
6
  def extract_payload
7
- Array.wrap(body['Envelope']['Body'][class_name]['AccountsInfo']['AccountInfo'])
7
+ Array.wrap(response['AccountsInfo']['AccountInfo'])
8
8
  end
9
9
  end
10
10
  end
@@ -4,7 +4,7 @@ module SoapyBing
4
4
  module Response
5
5
  class GetAdGroupsByCampaignIdResponse < Base
6
6
  def extract_payload
7
- Array.wrap(body['Envelope']['Body'][class_name]['AdGroups']['AdGroup'])
7
+ Array.wrap(response['AdGroups']['AdGroup'])
8
8
  end
9
9
  end
10
10
  end
@@ -4,7 +4,7 @@ module SoapyBing
4
4
  module Response
5
5
  class GetAdsByAdGroupIdResponse < Base
6
6
  def extract_payload
7
- Array.wrap(body['Envelope']['Body'][class_name]['Ads']['Ad'])
7
+ Array.wrap(response['Ads']['Ad'])
8
8
  end
9
9
  end
10
10
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module SoapyBing
3
+ module Soap
4
+ module Response
5
+ class GetBulkDownloadStatusResponse < Base
6
+ def extract_payload
7
+ response.slice('PercentComplete', 'RequestStatus', 'ResultFileUrl')
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -4,7 +4,7 @@ module SoapyBing
4
4
  module Response
5
5
  class GetTargetsByCampaignIdsResponse < Base
6
6
  def extract_payload
7
- Array.wrap(body['Envelope']['Body'][class_name]['Targets']['Target']).first
7
+ Array.wrap(response['Targets']['Target']).first
8
8
  end
9
9
  end
10
10
  end
@@ -3,13 +3,25 @@ module SoapyBing
3
3
  module Soap
4
4
  module Response
5
5
  module Payload
6
+ Fault = Class.new(StandardError)
7
+
6
8
  def payload
7
- @payload ||= extract_payload
9
+ @payload ||= check_errors_and_extract_payload
10
+ end
11
+
12
+ def check_errors_and_extract_payload
13
+ fault = body.dig('Envelope', 'Body', 'Fault')
14
+ raise Fault, fault.to_s if fault
15
+ extract_payload
8
16
  end
9
17
 
10
18
  def extract_payload
11
19
  raise NotImplementedError
12
20
  end
21
+
22
+ def response
23
+ @response ||= body.dig('Envelope', 'Body', class_name)
24
+ end
13
25
  end
14
26
  end
15
27
  end
@@ -14,7 +14,7 @@ module SoapyBing
14
14
  end
15
15
 
16
16
  def report_status
17
- body['Envelope']['Body'][class_name]['ReportRequestStatus']
17
+ response['ReportRequestStatus']
18
18
  end
19
19
 
20
20
  def error?
@@ -4,7 +4,7 @@ module SoapyBing
4
4
  module Response
5
5
  class SubmitGenerateReportResponse < Base
6
6
  def extract_payload
7
- body['Envelope']['Body'][class_name]['ReportRequestId']
7
+ response['ReportRequestId']
8
8
  end
9
9
  end
10
10
  end
@@ -10,3 +10,5 @@ require 'soapy_bing/soap/response/get_ad_groups_by_campaign_id_response'
10
10
  require 'soapy_bing/soap/response/get_ads_by_ad_group_id_response'
11
11
  require 'soapy_bing/soap/response/get_targets_by_campaign_ids_response'
12
12
  require 'soapy_bing/soap/response/get_accounts_info_response'
13
+ require 'soapy_bing/soap/response/download_campaigns_by_account_ids_response'
14
+ require 'soapy_bing/soap/response/get_bulk_download_status_response'
@@ -15,7 +15,7 @@ module SoapyBing
15
15
  private
16
16
 
17
17
  def read(name)
18
- File.read(File.join(TEMPLATE_PATH, "#{name}.erb.xml"))
18
+ File.read(File.join(TEMPLATE_PATH, "#{name}.xml.erb"))
19
19
  end
20
20
  end
21
21
  end
@@ -0,0 +1,22 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <s:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
3
+ <s:Header xmlns="https://bingads.microsoft.com/CampaignManagement/v10">
4
+ <Action mustUnderstand="1">DownloadCampaignsByAccountIds</Action>
5
+ <AuthenticationToken i:nil="false"><%= authentication_token %></AuthenticationToken>
6
+ <CustomerAccountId i:nil="false"><%= account.account_id %></CustomerAccountId>
7
+ <CustomerId i:nil="false"><%= account.customer_id %></CustomerId>
8
+ <DeveloperToken i:nil="false"><%= account.developer_token %></DeveloperToken>
9
+ </s:Header>
10
+ <s:Body>
11
+ <DownloadCampaignsByAccountIdsRequest xmlns="https://bingads.microsoft.com/CampaignManagement/v10">
12
+ <AccountIds i:nil="false" xmlns:a1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
13
+ <a1:long><%= account.account_id %></a1:long>
14
+ </AccountIds>
15
+ <CompressionType i:nil="false">Zip</CompressionType>
16
+ <DataScope>EntityData</DataScope>
17
+ <DownloadFileType i:nil="false">Csv</DownloadFileType>
18
+ <Entities><%= entities.join(' ') %></Entities>
19
+ <FormatVersion i:nil="false">4.0</FormatVersion>
20
+ </DownloadCampaignsByAccountIdsRequest>
21
+ </s:Body>
22
+ </s:Envelope>
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <s:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
3
+ <s:Header xmlns="https://bingads.microsoft.com/CampaignManagement/v10">
4
+ <Action mustUnderstand="1">GetBulkDownloadStatus</Action>
5
+ <AuthenticationToken i:nil="false"><%= authentication_token %></AuthenticationToken>
6
+ <CustomerAccountId i:nil="false"><%= account.account_id %></CustomerAccountId>
7
+ <CustomerId i:nil="false"><%= account.customer_id %></CustomerId>
8
+ <DeveloperToken i:nil="false"><%= account.developer_token %></DeveloperToken>
9
+ </s:Header>
10
+ <s:Body>
11
+ <GetBulkDownloadStatusRequest xmlns="https://bingads.microsoft.com/CampaignManagement/v10">
12
+ <RequestId i:nil="false"><%= request_id %></RequestId>
13
+ </GetBulkDownloadStatusRequest>
14
+ </s:Body>
15
+ </s:Envelope>
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module SoapyBing
3
- VERSION = '0.2.0'
3
+ VERSION = '0.3.0'
4
4
  end
@@ -0,0 +1,8 @@
1
+ Type,Status,Id,Parent Id,Sub Type,Campaign,Ad Group,Website,Sync Time,Client Id,Modified Time,Tracking Template,Custom Parameter,Final Url,Mobile Final Url,Time Zone,Budget Id,Budget Name,Budget,Budget Type,Bid Strategy Type,KeywordVariantMatchEnabled,Campaign Type,Priority,Start Date,End Date,Network Distribution,Pricing Model,Ad Rotation,Search Network,Search Bid,Content Network,Content Bid,Language,Title,Text,Display Url,Destination Url,Business Name,Phone Number,Promotion,Editorial Status,Editorial Location,Editorial Term,Editorial Reason Code,Editorial Appeal Status,Device Preference,Ad Format Preference,Title Part 1,Title Part 2,Path 1,Path 2,Keyword,Match Type,Bid,Param1,Param2,Param3,Target,Physical Intent,Bid Adjustment,Radius Target Id,Name,OS Names,Radius,Unit,Business Id,From Hour,From Minute,To Hour,To Minute,Version,Ad Schedule,Use Searcher Time Zone,Sitelink Extension Order,Sitelink Extension Link Text,Sitelink Extension Destination Url,Sitelink Extension Description1,Sitelink Extension Description2,Geo Code Status,Map Icon,Business Icon,Address Line 1,Address Line 2,Postal Code,City,State Or Province Code,Province Name,Latitude,Longitude,Country Code,Call Only,Call Tracking Enabled,Toll Free,Alternative Text,Media Ids,Publisher Countries,Store Id,Product Condition 1,Product Value 1,Product Condition 2,Product Value 2,Product Condition 3,Product Value 3,Product Condition 4,Product Value 4,Product Condition 5,Product Value 5,Product Condition 6,Product Value 6,Product Condition 7,Product Value 7,Callout Text,Action Text,Action Link Url,Is Exact,Source,Url,Structured Snippet Header,Structured Snippet Values,Spend,Impressions,Clicks,CTR,Avg CPC,Avg CPM,Avg position,Conversions,CPA,Quality Score,Keyword Relevance,Landing Page Relevance,Landing Page User Experience,App Platform,App Id,Tracking Enabled,App Status,Error,Error Number,Field Path,Is Excluded,Parent Criterion Id,Remarketing List,Remarketing List Id,Scope,Membership Duration,UET Tag Id,Description,Remarketing Targeting Setting,Domain Language,Dynamic Ad Target Condition 1,Dynamic Ad Target Condition 2,Dynamic Ad Target Condition 3,Dynamic Ad Target Value 1,Dynamic Ad Target Value 2,Dynamic Ad Target Value 3
2
+ Format Version,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
3
+ Account,,2000001,9000001,,,,,09/09/2016 14:28:40,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
4
+ Text Ad,Active,4000000075,1900000096,,saga_FR_exact,lost saga,,,,12/13/2014 16:32:34.413,,,,,,,,,,,,,,,,,,,,,,,,Joue á Lost Saga,MMO de combat gratuit. Inscris-toi et joue gratuitement !,saga.nexoneu.com,t.ad2games.com/k?w=59594_240806755&p=27871&c5=direct&c6=saga_FR_exact&c7=MV&c8=SEM_bing&ex=12007,,,,Active,,,,,All,All,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
5
+ Text Ad,Paused,7000000082,2800000068,,B. BB_game_US_alpha,1. Game Online,,,,02/25/2015 14:22:42.380,,,,,,,,,,,,,,,,,,,,,,,,Game Online MMORPG,"Explore a vast, expanding universe. Register now and play for free!",example.com,example.com/?E=Wu%2byxu8PC76sbG%2beMQchUHtUq0rOvXqJ&s1=game_US_alpha&s2={keyword},,,,Active,,,,,All,All,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
6
+ Text Ad,Paused,7000000083,2800000068,,B. BB_game_US_alpha,1. Game Online,,,,02/25/2015 14:22:42.380,,,,,,,,,,,,,,,,,,,,,,,,Play Game Online,"Explore a vast, expanding universe. Register now and play for free!",example.com,example.com/?E=Wu%2byxu8PC76sbG%2beMQchUHtUq0rOvXqJ&s1=game_US_alpha&s2={keyword},,,,Active,,,,,All,All,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
7
+ Campaign Location Target,Active,450000052,90000073,Country,saga_FR_exact,,,,,05/06/2014 14:18:49.787,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,FR,PeopleInOrSearchingForOrViewingPages,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
8
+ Campaign Location Target,Active,450000024,91000058,Country,B. BB_game_US_alpha,,,,,03/25/2015 00:07:29.180,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,US,PeopleInOrSearchingForOrViewingPages,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,