bluekai 0.0.1
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 +7 -0
- data/.gitignore +23 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +44 -0
- data/Rakefile +2 -0
- data/bluekai.gemspec +28 -0
- data/circle.yml +3 -0
- data/lib/bluekai.rb +7 -0
- data/lib/bluekai/client.rb +407 -0
- data/lib/bluekai/error.rb +4 -0
- data/lib/bluekai/version.rb +3 -0
- data/spec/fixtures/signatures/1952b4f61dbd2187b5589dfc390af2ee985ca6f43020081d420f5d9ca025532e +1 -0
- data/spec/fixtures/signatures/26d52d2e4c2d42ba54ec6b4de9e67d9b566aeb8224c28261d1d133b7fb3c3436 +1 -0
- data/spec/fixtures/signatures/2db01e685f73149994efc9824c10fa91e704fb7256d748c4305101513444f49f +1 -0
- data/spec/fixtures/signatures/391112d6698e9864c1d9b37f92ab7e6db690a7e84949378ee272b011f3b82fc0 +1 -0
- data/spec/fixtures/signatures/3c33aa44e5fbea304ffda0390ac2e413a02d187d5425f67c3edab34684b2b18f +1 -0
- data/spec/fixtures/signatures/691325444d07bf08ce72b95283f8a8fd74e19f6963263e5367772b7633cbeab0 +1 -0
- data/spec/fixtures/signatures/78f40f967bf9cb1ae030412e7c28267a8050926a538226c685fb2dec6f23b44a +1 -0
- data/spec/fixtures/signatures/847da153b01c0ea4e3beeeb00f5552c3dd773227ee5aeaf5c9ff9a620adae324 +1 -0
- data/spec/fixtures/signatures/a49b4d9ac5b30c91f95a907b887f9b8eaf5c7856b844c49d2b937c00d88af63d +1 -0
- data/spec/fixtures/signatures/a6d578d433ca6f7c84ce9da14c415b3d302bf1da2b87f7666c637419fb784f57 +1 -0
- data/spec/fixtures/signatures/d30077840edb2b580c1c9a4a6659989b8342cfdc439ceef0c984672849288243 +1 -0
- data/spec/fixtures/signatures/d3c90cbaf307901dff229713b703217d7460f3c50400aa981ac20088f58343ad +1 -0
- data/spec/fixtures/vcr_cassettes/Bluekai_Client/_ping/when_we_get_a_pong_from_bluekai/.yml +30 -0
- data/spec/fixtures/vcr_cassettes/Bluekai_Client/creates_a_category.yml +49 -0
- data/spec/fixtures/vcr_cassettes/Bluekai_Client/creates_a_rule.yml +57 -0
- data/spec/fixtures/vcr_cassettes/Bluekai_Client/lists_10_phint_rules.yml +194 -0
- data/spec/fixtures/vcr_cassettes/Bluekai_Client/lists_4_categories.yml +3569 -0
- data/spec/fixtures/vcr_cassettes/Bluekai_Client/lists_Bluekai_taxonomy_nodes.yml +161267 -0
- data/spec/fixtures/vcr_cassettes/Bluekai_Client/performs_a_ping.yml +36 -0
- data/spec/fixtures/vcr_cassettes/Bluekai_Client/reads_a_category_and_its_reach.yml +2459 -0
- data/spec/fixtures/vcr_cassettes/Bluekai_Client/reads_a_rule.yml +56 -0
- data/spec/fixtures/vcr_cassettes/Bluekai_Client/updates_a_category.yml +48 -0
- data/spec/fixtures/vcr_cassettes/Bluekai_Client/updates_a_rule.yml +57 -0
- data/spec/lib/bluekai/client_integration_spec.rb +153 -0
- data/spec/lib/bluekai/client_spec.rb +19 -0
- data/spec/spec_helper.rb +108 -0
- metadata +193 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 68f6e5115ea82ddcda1d0ad4780f27fd0b33d73e
|
4
|
+
data.tar.gz: acd51bbeef54aac2ce754571fbb6fe3cd592707a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8460428509ffdac8f0b0994f4be95fa89982e967d67d7342a5b9a796729e6672f2aa879e1b247798b65a8afabff27be2e3f757da0e4b8a97fd76127c44843b80
|
7
|
+
data.tar.gz: e35bbd450af7dc97de6489f679c8fbfa6415e483d967dcb322088d49db60f757a816aa42ccf98276588d64588fc8b4226ea1a46dcc32ec59d1a7c631ee8a6b72
|
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
23
|
+
.env
|
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.0
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 ad2games GmbH
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# Bluekai
|
2
|
+
[](http://rubygems.org/gems/bluekai)
|
3
|
+
[](https://circleci.com/gh/ad2games/bluekai)
|
4
|
+
[](https://codeclimate.com/repos/5523e6d8695680516e00144d/feed)
|
5
|
+
[](https://codeclimate.com/repos/5523e6d8695680516e00144d/feed)
|
6
|
+
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
gem 'bluekai'
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install bluekai
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
Before you start, please ensure the following variables are correctly set in your environment: `ENV['BLUEKAI_DOMAIN']`, `ENV['BLUEKAI_API_USER_KEY']`, `ENV['BLUEKAI_API_PRIVATE_KEY']` and `ENV['BLUEKAI_PARTNER_ID']`
|
25
|
+
|
26
|
+
|
27
|
+
List all self-classification categories
|
28
|
+
```ruby
|
29
|
+
Bluekai::Client.new.category_list({})
|
30
|
+
```
|
31
|
+
Read category parameters including estimated reach (estimated number of unique users
|
32
|
+
based on 30-day inventory) on desktop
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
Bluekai::Client.new.category_read({category_id: 421426, stats: 'true', device_type: 'desktop'})
|
36
|
+
```
|
37
|
+
|
38
|
+
## Contributing
|
39
|
+
|
40
|
+
1. Fork it ( https://github.com/[my-github-username]/bluekai/fork )
|
41
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
42
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
43
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
44
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bluekai.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'bluekai/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "bluekai"
|
8
|
+
spec.version = Bluekai::VERSION
|
9
|
+
spec.authors = ["ad2games GmbH"]
|
10
|
+
spec.email = ["developers@ad2games.com"]
|
11
|
+
spec.summary = "Simple client for the BlueKai API"
|
12
|
+
spec.description = "Simple client for the BlueKai API (services.bluekai.com)"
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'httparty'
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency 'vcr'
|
26
|
+
spec.add_development_dependency 'webmock'
|
27
|
+
spec.add_development_dependency 'rspec'
|
28
|
+
end
|
data/circle.yml
ADDED
data/lib/bluekai.rb
ADDED
@@ -0,0 +1,407 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'base64'
|
3
|
+
require 'httparty'
|
4
|
+
require 'cgi'
|
5
|
+
|
6
|
+
module Bluekai
|
7
|
+
# A simple BlueKai client
|
8
|
+
class Client
|
9
|
+
attr_reader :domain, :api_user_key
|
10
|
+
|
11
|
+
def initialize(opts = {})
|
12
|
+
@domain = opts.fetch(:domain, ENV['BLUEKAI_DOMAIN']) ||
|
13
|
+
fail(Error, 'BlueKai domain missing')
|
14
|
+
@api_user_key = opts.fetch(:api_user_key, ENV['BLUEKAI_API_USER_KEY']) ||
|
15
|
+
fail(Error, 'BlueKai API user key missing')
|
16
|
+
@api_private_key = opts.fetch(:api_private_key, ENV['BLUEKAI_API_PRIVATE_KEY']) ||
|
17
|
+
fail(Error, 'BlueKai API private key missing')
|
18
|
+
@partner_id = opts.fetch(:partner_id, ENV['BLUEKAI_PARTNER_ID']) ||
|
19
|
+
fail(Error, 'BlueKai PartnerID missing')
|
20
|
+
@opts = opts
|
21
|
+
end
|
22
|
+
|
23
|
+
def ping
|
24
|
+
request('GET', '/Services/WS/Ping', {}).to_i == 200 rescue false
|
25
|
+
end
|
26
|
+
|
27
|
+
# Public: Lists categories in the BlueKai taxonomy. API definition
|
28
|
+
# can be found here https://kb.bluekai.com/display/PD/Taxonomy+API
|
29
|
+
#
|
30
|
+
# parentId - integer
|
31
|
+
# fullPath - {0,1}
|
32
|
+
# bkSize - {0,1} Enter 1 to include the inventory of unique users in
|
33
|
+
# the BlueKai network for each category.
|
34
|
+
# intlDataCountryId - {-1..24} for country index see
|
35
|
+
# (https://kb.bluekai.com/display/PD/Taxonomy+API)
|
36
|
+
# device_code - {0 = Desktop + Mobile,1 = Desktop, 2 = Mobile}
|
37
|
+
# showBuyable - {0,1}
|
38
|
+
# showLeafStatus - {0,1}
|
39
|
+
# description - {0,1}
|
40
|
+
# vertical - {0,1}
|
41
|
+
# showReceivedAudienceCategories - {0,1}
|
42
|
+
# showCategoryPriceAtDate - {'YYYY-MM-DD'}
|
43
|
+
#
|
44
|
+
# Returns array of taxonomy nodes.
|
45
|
+
def taxonomy(query = {})
|
46
|
+
request('GET', '/Services/WS/Taxonomy', query)[:nodeList]
|
47
|
+
end
|
48
|
+
|
49
|
+
####
|
50
|
+
#### Categories
|
51
|
+
####
|
52
|
+
#### API definition can be found here
|
53
|
+
#### https://kb.bluekai.com/display/PD/Self-Classification+Category+API
|
54
|
+
####
|
55
|
+
|
56
|
+
# Public: Lists self classification categories in private taxonomy
|
57
|
+
#
|
58
|
+
# name:string - Returns all self-classification categories based on the specified
|
59
|
+
# name (whole or partial). The name is case-insensitive.
|
60
|
+
#
|
61
|
+
# offset:integer - Specify the starting index from which to return
|
62
|
+
# the self-classification categories.
|
63
|
+
#
|
64
|
+
# size:integer - Specifies the maximum number of categories to be included in
|
65
|
+
# the response. This filter requires the offset filter to be specified.
|
66
|
+
#
|
67
|
+
# parent_id:integer - Returns all self-classification categories
|
68
|
+
# based on the ID of the specified parent category.
|
69
|
+
#
|
70
|
+
# sort_by:string - Enter 'name' or 'id' to sort the returned self-classification categories in
|
71
|
+
# alphabetical or numerical order (based on categoryId)
|
72
|
+
#
|
73
|
+
# sorting_order:string - Enter 'asc' or 'desc' to list the returned
|
74
|
+
# self-classification categories in ascending
|
75
|
+
# or descending order based on the category
|
76
|
+
# name or categoryId.
|
77
|
+
#
|
78
|
+
# Returns array of category hashes
|
79
|
+
def category_list(query = {})
|
80
|
+
query = { sort_by: 'name',
|
81
|
+
sorting_order: 'asc' }.merge(query)
|
82
|
+
request('GET', '/Services/WS/classificationCategories', query)[:categories]
|
83
|
+
end
|
84
|
+
|
85
|
+
# Public: returns the self-classification category
|
86
|
+
# specified by the category_id
|
87
|
+
#
|
88
|
+
# category_id:integer - MANDATORY The unique ID assigned to the
|
89
|
+
# self-classification category to be retrieved
|
90
|
+
#
|
91
|
+
# stats:string - {'True','False'} Returns the reach (estimated
|
92
|
+
# number of unique users based on 30-day
|
93
|
+
# inventory) for the self-classification category.
|
94
|
+
#
|
95
|
+
# device_type:string - reach for the self-classification category
|
96
|
+
# based on the specified device, which may either
|
97
|
+
# be 'all', 'desktop', or 'mobile'
|
98
|
+
#
|
99
|
+
# intl_code - returns the reach for the self-classification category
|
100
|
+
# based on the specified country. The default country
|
101
|
+
# is ALL. You may enter one of the following country
|
102
|
+
# codes: ALL, US, AU, CA, GB, GER, ESP, NL, MX, IT,
|
103
|
+
# FR, BR, AR, RU, NZ, JP, CL, CN.
|
104
|
+
#
|
105
|
+
# Returns: A hash of Bluekai private category data
|
106
|
+
def category_read(query)
|
107
|
+
fail 'no category_id found in hash' unless query.key?(:category_id)
|
108
|
+
category_id = query.delete(:category_id)
|
109
|
+
request('GET', "/Services/WS/classificationCategories/#{category_id}", query)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Public: Creates a new self-classification category
|
113
|
+
#
|
114
|
+
# name:string - Name of the self-classification category
|
115
|
+
#
|
116
|
+
# parent_id:integer - Unique ID of the parent node for the
|
117
|
+
# self-classification category.
|
118
|
+
#
|
119
|
+
# description:string - Description of uUser attribute
|
120
|
+
# represented by this category.
|
121
|
+
#
|
122
|
+
# analytics_excluded:string - {'True','False'} Specify whether the
|
123
|
+
# self-classification category is to be excluded
|
124
|
+
# from Audience Analytics reports. This property
|
125
|
+
# is false by default.
|
126
|
+
#
|
127
|
+
# navigation_only:string - {'True','False'} Specify whether the
|
128
|
+
# self-classification category functions
|
129
|
+
# exclusively as a parent node that cannot be
|
130
|
+
# selected. This property is false by default.
|
131
|
+
#
|
132
|
+
# mutex_children:string - {'True','False'} Specify whether to limit
|
133
|
+
# the number of the category's child nodes
|
134
|
+
# that can be added to an audience segment to one.
|
135
|
+
# This property is false by default.
|
136
|
+
#
|
137
|
+
# notes:string - (Optional) Enter any notes to be associated with
|
138
|
+
# this self-classification category.
|
139
|
+
#
|
140
|
+
# Example body hash = {name: 'a new category',
|
141
|
+
# parent_id: '2342', description: 'an example category',
|
142
|
+
# analytics_excluded: 'false', navigation_only: 'false',
|
143
|
+
# mutex_children: 'false', notes: 'Just an API test' }
|
144
|
+
#
|
145
|
+
# Returns: hash of created category parameters including its category_id
|
146
|
+
def category_create(body)
|
147
|
+
request('POST', '/Services/WS/classificationCategories', {}, body)
|
148
|
+
end
|
149
|
+
|
150
|
+
# Public: Updates a given self-classification category
|
151
|
+
#
|
152
|
+
# category_id:integer - The unique ID assigned to the self-classification
|
153
|
+
# category to be updated
|
154
|
+
#
|
155
|
+
# name:string - Name of the self-classification category
|
156
|
+
#
|
157
|
+
# parent_id:integer - Unique ID of the parent node for the
|
158
|
+
# self-classification category.
|
159
|
+
#
|
160
|
+
# description:string - Description of uUser attribute
|
161
|
+
# represented by this category.
|
162
|
+
#
|
163
|
+
# analytics_excluded:string - {'True','False'} Specify whether the
|
164
|
+
# self-classification category is to be excluded
|
165
|
+
# from Audience Analytics reports. This property
|
166
|
+
# is false by default.
|
167
|
+
#
|
168
|
+
# navigation_only:string - {'True','False'} Specify whether the
|
169
|
+
# self-classification category functions
|
170
|
+
# exclusively as a parent node that cannot be
|
171
|
+
# selected. This property is false by default.
|
172
|
+
#
|
173
|
+
# mutex_children:string - {'True','False'} Specify whether to limit
|
174
|
+
# the number of the category's child nodes
|
175
|
+
# that can be added to an audience segment to one.
|
176
|
+
# This property is false by default.
|
177
|
+
#
|
178
|
+
# notes:string - (Optional) Enter any notes to be associated with
|
179
|
+
# this self-classification category.
|
180
|
+
#
|
181
|
+
# Example body hash = {category_id: 1234, name: 'a chaged category',
|
182
|
+
# parent_id: '2342', description: 'an example category',
|
183
|
+
# analytics_exclued: 'false', navigation_only: 'false',
|
184
|
+
# mutex_children: 'false', notes: 'Just an API test' }
|
185
|
+
#
|
186
|
+
# Returns: hash of updated category parameters
|
187
|
+
def category_update(category_id, body)
|
188
|
+
request('PUT', "/Services/WS/classificationCategories/#{category_id}", {}, body)
|
189
|
+
end
|
190
|
+
|
191
|
+
####
|
192
|
+
#### Classification Rules
|
193
|
+
#### API definition can be found here
|
194
|
+
#### https://kb.bluekai.com/display/PD/Self-Classification+Rule+API
|
195
|
+
####
|
196
|
+
|
197
|
+
# Public: List the self-classification rules in your private
|
198
|
+
# taxonomy
|
199
|
+
#
|
200
|
+
# sort_by:string - Enter 'status', 'id', 'created_at', 'updated_at',
|
201
|
+
# or 'type' to sort the returned self-classification
|
202
|
+
# rules by the specified option.
|
203
|
+
#
|
204
|
+
# sorting_order:string - Enter 'asc' or 'desc' to list the returned
|
205
|
+
# self-classification rules in ascending or descending
|
206
|
+
# order based on the specified sort option.
|
207
|
+
#
|
208
|
+
# ids:integer - Returns the self-classification rule matching the specified
|
209
|
+
# rule ID, or returns all the self-classification rules matching
|
210
|
+
# the specified list of rule IDs. Syntax for passing multiple rule IDs:
|
211
|
+
# ruleId1&id=ruleId2 Example: 123&id=125
|
212
|
+
#
|
213
|
+
# type:enum - Enter 'phint' or 'url' to return only the phint or
|
214
|
+
# URL-based self-classification rules.
|
215
|
+
#
|
216
|
+
# site_ids:string - Returns all the self-classification rules under the
|
217
|
+
# specified site ID or list of site IDs. Syntax for
|
218
|
+
# passing multiple site IDs: site_id_1&site_ids=site_id_2
|
219
|
+
# Example: 1234&site_ids=1235
|
220
|
+
#
|
221
|
+
# category_ids:string - Returns all the self-classification rules used
|
222
|
+
# to map the specified catgeory ID or list of category IDs.
|
223
|
+
# Syntax for passing multiple category
|
224
|
+
# IDs: category_id_1&category_ids=category_id_2
|
225
|
+
# Example: 1234&category_ids=1235
|
226
|
+
#
|
227
|
+
# offset:integer - Specify the starting index from which to return the
|
228
|
+
# self-classification rules.
|
229
|
+
#
|
230
|
+
# size:integer - Specify the maximum number of rules to be included in
|
231
|
+
# the response. This filter requires the offset filter
|
232
|
+
# to be specified.
|
233
|
+
#
|
234
|
+
# created_date_range:string - Returns all the self-classification rules
|
235
|
+
# created within the specified list of dates.
|
236
|
+
# Syntax: YYYY-MM-DD&created_date_range=YYYY-MM-DD
|
237
|
+
# Example: 2014-01-01&created_date_range=2014-31-01
|
238
|
+
#
|
239
|
+
# updated_date_range:string - Returns all the self-classification rules updated
|
240
|
+
# within the specified list of dates.
|
241
|
+
# Syntax: YYYY-MM-DD&updated_date_range=YYYY-MM-DD
|
242
|
+
# Example: 2014-01-01&updated_date_range=2014-31-01
|
243
|
+
#
|
244
|
+
# status:string - Enter 'Active' or 'Creating' to return the
|
245
|
+
# self-classification rules based on the specified status referrer
|
246
|
+
# boolean Returns all URL-based self-classification rules that
|
247
|
+
# classify the site URL (False) or the referrer URL (True) in
|
248
|
+
# the collected URL.
|
249
|
+
#
|
250
|
+
# exact:boolean - Returns all URL-based self-classification rules that classify
|
251
|
+
# an exact URL (True) or a top-level URL (False) in the collected URL.
|
252
|
+
# Returns: hash of Bluekai rules
|
253
|
+
def rule_list(query)
|
254
|
+
request('GET', '/Services/WS/classificationRules', query)[:rules]
|
255
|
+
end
|
256
|
+
|
257
|
+
# Public: Reads a self-classification rule
|
258
|
+
#
|
259
|
+
# rule_id:integer - The unique ID assigned to the
|
260
|
+
# self-classification rule to be retrieved
|
261
|
+
#
|
262
|
+
# Returns: hash of Blukkai rule parameters
|
263
|
+
def rule_read(rule_id)
|
264
|
+
request('GET', "/Services/WS/classificationRules/#{rule_id}", {})
|
265
|
+
end
|
266
|
+
|
267
|
+
# Public: Creates a new self-classification rule
|
268
|
+
#
|
269
|
+
# name:string - Enter a string specifying the name of the self-classification rule.
|
270
|
+
#
|
271
|
+
# type:string - {'phint', 'url'} Specify the type of classification rule.
|
272
|
+
#
|
273
|
+
# phints:[{phint}] - If you are creating a phint-based rule,
|
274
|
+
# enter a list of your phint definitions.
|
275
|
+
# Each phint requires the following properties:
|
276
|
+
# key - The phint key operator - The criteria
|
277
|
+
# used for determining how the phint value
|
278
|
+
# is applied ('is' or 'contains')
|
279
|
+
# value - The full or partial phint value,
|
280
|
+
# depending on the specified operator.
|
281
|
+
#
|
282
|
+
# urls:[string(s)] - Provide a list of your URL definitions
|
283
|
+
# if you are creating for URL-based rules.
|
284
|
+
#
|
285
|
+
# referrer:string - {'True','False'} If you are creating a
|
286
|
+
# URL-based rule, specify whether the URL to
|
287
|
+
# be classified is the site URL (False) or
|
288
|
+
# the referrer URL (True).
|
289
|
+
#
|
290
|
+
# exact:string - {'True','False'} If you are creating a
|
291
|
+
# URL-based rule, specify whether the URL collected
|
292
|
+
# from your site must match the URL in your
|
293
|
+
# rule (True) or match a top-level URL (False) so
|
294
|
+
# that you can target users visiting the child pages
|
295
|
+
# without specifying them.
|
296
|
+
#
|
297
|
+
# partner_id:integer - Enter the unique ID assigned to your BlueKai DMP seat.
|
298
|
+
#
|
299
|
+
# site_ids (optional):[interger(s)] - Enter a list of containers/site IDs to which
|
300
|
+
# the self-classification rule applies. If
|
301
|
+
# you do not include this parameter, the
|
302
|
+
# rule is applicable to ALL the
|
303
|
+
# container/site IDs in your seat.
|
304
|
+
#
|
305
|
+
# category_ids:[integer(s)] - a list of category IDs to which
|
306
|
+
# the self-classification rule applies.
|
307
|
+
#
|
308
|
+
# JSON example for Phint-based self-classification rule
|
309
|
+
# {
|
310
|
+
# "name": "Phint Example",
|
311
|
+
# "type": "phint",
|
312
|
+
# "phints": [
|
313
|
+
# {
|
314
|
+
# "key": "x",
|
315
|
+
# "value": "123",
|
316
|
+
# "operator": "is"
|
317
|
+
# }
|
318
|
+
# ],
|
319
|
+
# "partner_id": 123,
|
320
|
+
# "site_ids": [1234],
|
321
|
+
# "category_ids": [12345]
|
322
|
+
# }
|
323
|
+
#
|
324
|
+
# JSON example for URL-based self-classiifcation rule
|
325
|
+
# {
|
326
|
+
# "name": "URL Example",
|
327
|
+
# "type": "url",
|
328
|
+
# "urls": ["http://shop.yoursite.com"],
|
329
|
+
# "referrer": false,
|
330
|
+
# "exact": false,
|
331
|
+
# "partner_id": 123,
|
332
|
+
# "site_ids": [1234],
|
333
|
+
# "category_ids": [123456]
|
334
|
+
# }
|
335
|
+
# Returns: hash of created self-classification rule
|
336
|
+
def rule_create(body)
|
337
|
+
body = { partner_id: @partner_id }.merge(body)
|
338
|
+
request('POST', '/Services/WS/classificationRules', {}, body)
|
339
|
+
end
|
340
|
+
|
341
|
+
# Public: Update a self-classification rule
|
342
|
+
#
|
343
|
+
# rule_id:integer (MANDATORY) - id of classification rule to be updated
|
344
|
+
#
|
345
|
+
# for other parameters refer to documentation of rule_create(body)
|
346
|
+
#
|
347
|
+
# Returns: hash of updated self-classification rule
|
348
|
+
def rule_update(rule_id, body)
|
349
|
+
body = { partner_id: @partner_id }.merge(body)
|
350
|
+
request('PUT', "/Services/WS/classificationRules/#{rule_id}", {}, body)
|
351
|
+
end
|
352
|
+
|
353
|
+
private
|
354
|
+
|
355
|
+
def request(method, path, query, body = nil)
|
356
|
+
method.upcase!
|
357
|
+
signature = sign(method, path, query_values(query), body_sorted(body))
|
358
|
+
|
359
|
+
url = "https://#{domain}#{path}?#{query_url_formatted(query)}\
|
360
|
+
bkuid=#{api_user_key}&bksig=#{signature}"
|
361
|
+
|
362
|
+
response = case method
|
363
|
+
when 'GET'
|
364
|
+
HTTParty.get(url)
|
365
|
+
when 'POST'
|
366
|
+
HTTParty.post(url, body: body_sorted(body), headers: json_headers)
|
367
|
+
when 'PUT'
|
368
|
+
HTTParty.put(url, body: body_sorted(body), headers: json_headers)
|
369
|
+
else
|
370
|
+
fail ArgumentError, "request method '#{method}' not supported"
|
371
|
+
end.response
|
372
|
+
fail "HTTP Request Error: #{response.body}" if response.code != '200'
|
373
|
+
return response.code if response.body == '' || response.body.nil?
|
374
|
+
JSON.parse(response.body, symbolize_names: true)
|
375
|
+
end
|
376
|
+
|
377
|
+
def body_sorted(body)
|
378
|
+
# sort hash according to keys for correct signature computation
|
379
|
+
return body.sort_by { |key, _value| key.to_s }.to_h.to_json if body
|
380
|
+
end
|
381
|
+
|
382
|
+
def json_headers
|
383
|
+
{
|
384
|
+
'Accept' => 'application/json',
|
385
|
+
'Content-type' => 'application/json'
|
386
|
+
}
|
387
|
+
end
|
388
|
+
|
389
|
+
def query_values(query)
|
390
|
+
return nil unless query
|
391
|
+
query.values.join
|
392
|
+
end
|
393
|
+
|
394
|
+
def query_url_formatted(query)
|
395
|
+
return nil unless query
|
396
|
+
query.map { |k, v| "#{k}=#{v}" }.join('&') + '&'
|
397
|
+
end
|
398
|
+
|
399
|
+
# HMAC-SHA256(Secret key, HTTP_METHOD + URI_PATH + QUERY_ARG_VALUES + POST_DATA)
|
400
|
+
def sign(method, path, query, body)
|
401
|
+
string_to_sign = method + path + query.to_s + body.to_s
|
402
|
+
digest = OpenSSL::Digest.new('sha256')
|
403
|
+
hmac = OpenSSL::HMAC.digest(digest, @api_private_key, string_to_sign)
|
404
|
+
CGI.escape(Base64.strict_encode64(hmac))
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|