bluekai 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](http://img.shields.io/gem/v/bluekai.svg)](http://rubygems.org/gems/bluekai)
|
3
|
+
[![Circle CI](https://circleci.com/gh/ad2games/bluekai.png?style=shield&circle-token=323d6ce1376f1473cab4474d89f8fc7287446595)](https://circleci.com/gh/ad2games/bluekai)
|
4
|
+
[![Code Climate](https://codeclimate.com/repos/5523e6d8695680516e00144d/badges/40648ea53c768dd15de5/gpa.svg)](https://codeclimate.com/repos/5523e6d8695680516e00144d/feed)
|
5
|
+
[![Test Coverage](https://codeclimate.com/repos/5523e6d8695680516e00144d/badges/40648ea53c768dd15de5/coverage.svg)](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
|