Skip to content

Commit 3bdbe21

Browse files
authored
New module: optable-targeting (#3815)
1 parent ff51661 commit 3bdbe21

File tree

60 files changed

+4567
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+4567
-0
lines changed

extra/bundle/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@
5555
<artifactId>pb-request-correction</artifactId>
5656
<version>${project.version}</version>
5757
</dependency>
58+
<dependency>
59+
<groupId>org.prebid.server.hooks.modules</groupId>
60+
<artifactId>optable-targeting</artifactId>
61+
<version>${project.version}</version>
62+
</dependency>
5863
</dependencies>
5964

6065
<build>
Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
## Overview
2+
Optable module operates using a DCN backend API. Please contact your account manager to get started.
3+
4+
The optable-targeting module enriches an incoming OpenRTB request by adding to the `user.eids` and `user.data`
5+
objects. Under the hood the module extracts PPIDs (publisher provided IDs) from the incoming request's `user.ext.eids`,
6+
and also if present sha256-hashed email, sha256-hashed phone, zip or Optable Visitor ID provided correspondingly in the
7+
`user.ext.optable.email`, `.phone`, `.zip`, `.vid` fields (a full list of IDs is given in a table below). These IDs are
8+
sent as input to the Targeting API. The received response data is used to enrich the OpenRTB request and response.
9+
Targeting API endpoint is configurable per publisher.
10+
11+
## Setup
12+
13+
### Execution Plan
14+
15+
This module runs at two stages:
16+
17+
* Processed Auction Request: to enrich `user.eids` and `user.data`.
18+
* Auction Response: to inject ad server targeting.
19+
20+
We recommend defining the execution plan in the account config so the module is only invoked for specific accounts. See
21+
below for an example.
22+
23+
### Global Config
24+
25+
There is no host-company level config for this module.
26+
27+
### Account-Level Config
28+
29+
To start using current module in PBS-Java you have to enable module and add
30+
`optable-targeting-processed-auction-request-hook` and `optable-targeting-auction-response-hook` into hooks execution
31+
plan inside your config file:
32+
Here's a general template for the account config used in PBS-Java:
33+
34+
```yaml
35+
hooks:
36+
optable-targeting:
37+
enabled: true
38+
host-execution-plan: >
39+
{
40+
"endpoints": {
41+
"/openrtb2/auction": {
42+
"stages": {
43+
"processed-auction-request": {
44+
"groups": [
45+
{
46+
"timeout": 100,
47+
"hook-sequence": [
48+
{
49+
"module-code": "optable-targeting",
50+
"hook-impl-code": "optable-targeting-processed-auction-request-hook"
51+
}
52+
]
53+
}
54+
]
55+
},
56+
"auction-response": {
57+
"groups": [
58+
{
59+
"timeout": 10,
60+
"hook-sequence": [
61+
{
62+
"module-code": "optable-targeting",
63+
"hook-impl-code": "optable-targeting-auction-response-hook"
64+
}
65+
]
66+
}
67+
]
68+
}
69+
}
70+
}
71+
}
72+
}
73+
```
74+
75+
Sample module enablement configuration in JSON and YAML formats:
76+
77+
```json
78+
{
79+
"modules":
80+
{
81+
"optable-targeting":
82+
{
83+
"api-endpoint": "endpoint",
84+
"api-key": "key",
85+
"timeout": 50,
86+
"ppid-mapping": {
87+
"pubcid.org": "c"
88+
},
89+
"adserver-targeting": false
90+
}
91+
}
92+
}
93+
```
94+
95+
```yaml
96+
modules:
97+
optable-targeting:
98+
api-endpoint: endpoint
99+
api-key: key
100+
timeout: 50
101+
ppid-mapping: {
102+
"pubcid.org": "c"
103+
}
104+
adserver-targeting: false
105+
```
106+
107+
### Timeout considerations
108+
109+
The timeout value specified in the execution plan for the `processed-auction-request` hook is very important to be
110+
picked such that the hook has enough time to make a roundtrip to Optable Targeting Edge API over HTTP.
111+
112+
**Note:** Do not confuse hook timeout value with the module timeout parameter which is optional. The hook timeout value
113+
would depend on the cloud/region where the PBS instance is hosted and the latency to reach the Optable's servers. This
114+
will need to be verified experimentally upon deployment.
115+
116+
The timeout value for the `auction-response` can be set to 10 ms - usually it will be sub-millisecond time as there are
117+
no HTTP calls made in this hook - Optable-specific keywords are cached on the `processed-auction-request` stage and
118+
retrieved from the module invocation context later.
119+
120+
## Module Configuration Parameters for PBS-Java
121+
122+
The parameter names are specified with full path using dot-notation. F.e. `section-name` .`sub-section` .`param-name`
123+
would result in this nesting in the JSON configuration:
124+
125+
```json
126+
{
127+
"section-name": {
128+
"sub-section": {
129+
"param-name": "param-value"
130+
}
131+
}
132+
}
133+
```
134+
135+
136+
| Param Name | Required | Type | Default value | Description |
137+
|:-------------------|:---------|:--------|:---------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
138+
| api-endpoint | yes | string | none | Optable Targeting Edge API endpoint URL, required |
139+
| api-key | no | string | none | If the API is protected with a key - this param needs to be specified to be sent in the auth header |
140+
| ppid-mapping | no | map | none | This specifies PPID source (`user.ext.eids[].source`) to a custom identifier prefix mapping, f.e. `{"example.com" : "c"}`. See the section on ID Mapping below for more detail. |
141+
| adserver-targeting | no | boolean | false | If set to true - will add the Optable-specific adserver targeting keywords into the PBS response for every `seatbid[].bid[].ext.prebid.targeting` |
142+
| timeout | no | integer | false | A soft timeout (in ms) sent as a hint to the Targeting API endpoint to limit the request times to Optable's external tokenizer services |
143+
| id-prefix-order | no | string | none | An optional string of comma separated id prefixes that prioritizes and specifies the order in which ids are provided to Targeting API in a query string. F.e. "c,c1,id5" will guarantee that Targeting API will see id=c:...,c1:...,id5:... if these ids are provided. id-prefixes not mentioned in this list will be added in arbitrary order after the priority prefix ids. This affects Targeting API processing logic |
144+
145+
## ID Mapping
146+
147+
Internally the module sends requests to Optable Targeting API. The output of Targeting API is used to enrich the request
148+
and response. The below table describes the parameters that the module automatically fetches from OpenRTB request and
149+
then sends to the Targeting API. The module will use a prefix as specified in the table to prepend the corresponding ID
150+
value when sending it to the Targeting API in the form `id=prefix:value`.
151+
152+
See [Optable documentation](https://docs.optable.co/optable-documentation/dmp/reference/identifier-types#type-prefixes)
153+
on identifier types. Targeting API accepts multiple id parameters - and their order may affect the results, thus
154+
`id-prefix-order` specifies the order of the ids.
155+
156+
157+
| Identifier Type | OpenRTB field | ID Type Prefix |
158+
|--------------------------------------------------------------------------------|-----------------------------------------------------------------------|------------------------------------------|
159+
| Email Address | `user.ext.optable.email` | `e:` |
160+
| Phone Number | `user.ext.optable.phone` | `p:` |
161+
| Postal Code | `user.ext.optable.zip` | `z:` |
162+
| IPv4 Address | `device.ip` | ~~i4:~~ Sent as `X-Forwarded-For` header |
163+
| IPv6 Address | `device.ipv6` | ~~i6:~~ Sent as `X-Forwarded-For` header |
164+
| Apple IDFA | `device.ifa if lcase(device.os) contains 'ios' and device.lmt!=1` | `a:` |
165+
| Google GAID | `device.ifa if lcase(device.os) contains 'android' and device.lmt!=1` | `g:` |
166+
| Roku RIDA | `device.ifa if lcase(device.os) contains 'roku' and device.lmt!=1` | `r:` |
167+
| Samsung TV TIFA | `device.ifa if lcase(device.os) contains 'tizen' and device.lmt!=1` | `s:` |
168+
| Amazon Fire AFAI | `device.ifa if lcase(device.os) contains 'fire' and device.lmt!=1` | `f:` |
169+
| [NetID](https://docs.prebid.org/dev-docs/modules/userid-submodules/netid.html) | `user.ext.eids[].uids[0] when user.ext.eids[].source="netid.de"` | `n:` |
170+
| [ID5](https://docs.prebid.org/dev-docs/modules/userid-submodules/id5.html) | `user.ext.eids[].uids[0] when user.ext.eids[].source="id5-sync.com"` | `id5:` |
171+
| [Utiq](https://docs.prebid.org/dev-docs/modules/userid-submodules/utiq.html) | `user.ext.eids[].uids[0] when user.ext.eids[].source="utiq.com"` | `utiq:` |
172+
| Optable VID | `user.ext.optable.vid` | `v:` |
173+
174+
### Optable input erasure
175+
176+
**Note**: `user.ext.optable.email`, `.phone`, `.zip`, `.vid` fields will be removed by the module from the original
177+
OpenRTB request before being sent to bidders.
178+
179+
### Publisher Provided IDs (PPID) Mapping
180+
181+
Custom user IDs are sent in the OpenRTB request in the
182+
[`user.ext.eids[]`](https://github.com/InteractiveAdvertisingBureau/openrtb2.x/blob/main/2.6.md#3227---object-eid-).
183+
The `ppid-mapping` allows to specify the mapping of a source to one of the custom identifier type prefixes `c`-`c19` -
184+
see [documentation](https://docs.optable.co/optable-documentation/dmp/reference/identifier-types#type-prefixes), f.e.:
185+
186+
```yaml
187+
ppid-mapping: {"example.com": "c2", "test.com": "c3"}
188+
```
189+
190+
It is also possible to override any of the automatically retrieved `user.ext.eids[]` mentioned in the table above (s.a.
191+
id5, utiq) so they are mapped to a different prefix. f.e. `id5-sync.com` can be mapped to a prefix other than `id5:`,
192+
like:
193+
194+
```yaml
195+
ppid-mapping: {"id5-sync.com": "c1"}
196+
```
197+
198+
This will lead to id5 ID supplied as `id=c1:...` to the Targeting API.
199+
200+
## Analytics Tags
201+
202+
The following 2 analytics tags are written by the module:
203+
204+
* `optable-enrich-request`
205+
* `optable-enrich-response`
206+
207+
The `status` is either `success` or `failure`. Where it is `failure` a `results[0].value.reason` is provided.
208+
For the `optable-enrich-request` activity the `execution-time` value is logged.
209+
Example:
210+
211+
```json
212+
{
213+
"analytics": {
214+
"tags": [
215+
{
216+
"stage": "auction-response",
217+
"module": "optable-targeting",
218+
"analyticstags": {
219+
"activities": [
220+
{
221+
"name": "optable-enrich-request",
222+
"status": "success",
223+
"results": [
224+
{
225+
"values": {
226+
"execution-time": 33
227+
}
228+
}
229+
]
230+
},
231+
{
232+
"name": "optable-enrich-response",
233+
"status": "success",
234+
"results": [
235+
{
236+
"values": {
237+
"reason": "none"
238+
}
239+
}
240+
]
241+
}
242+
]
243+
}
244+
}
245+
]
246+
}
247+
}
248+
```
249+
250+
If `adserver-targeting` was set to `false` in the config `optable-enrich-response` analytics tag is not written.
251+
252+
## Running the demo (PBS-Java)
253+
254+
1. Build the server bundle JAR as described in [Build Project](https://github.com/prebid/prebid-server-java/blob/master/docs/build.md#build-project), e.g.
255+
256+
```bash
257+
mvn clean package --file extra/pom.xml
258+
```
259+
260+
2. In the `sample/configs/prebid-config-optable.yaml` file specify the `api-endpoint` URL of your DCN, f.e.:
261+
262+
```yaml
263+
api-endpoint: https://example.com/v2/targeting
264+
```
265+
266+
3. Start server bundle JAR as described in [Running project](https://github.com/prebid/prebid-server-java/blob/master/docs/run.md#running-project), e.g.
267+
268+
```bash
269+
java -jar target/prebid-server-bundle.jar --spring.config.additional-location=sample/configs/prebid-config-with-optable.yaml
270+
```
271+
272+
4. Run sample request against the server as described in [the sample directory](https://github.com/prebid/prebid-server-java/tree/master/sample), e.g.
273+
274+
```bash
275+
curl http://localhost:8080/openrtb2/auction --data @extra/modules/optable-targeting/sample-requests/data.json
276+
```
277+
278+
5. Observe the `user.eids` and `user.data` objects enriched.
279+
280+
## Maintainer contacts
281+
282+
Any suggestions or questions can be directed to [prebid@optable.co](mailto:prebid@optable.co).
283+
284+
Alternatively please open a new [issue](https://github.com/prebid/prebid-server-java/issues/new) or [pull request](https://github.com/prebid/prebid-server-java/pulls) in this repository.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
lombok.anyConstructor.addConstructorProperties = true
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<parent>
6+
<groupId>org.prebid.server.hooks.modules</groupId>
7+
<artifactId>all-modules</artifactId>
8+
<version>3.29.0-SNAPSHOT</version>
9+
</parent>
10+
11+
<artifactId>optable-targeting</artifactId>
12+
13+
<name>optable-targeting</name>
14+
<description>Optable targeting module</description>
15+
</project>

0 commit comments

Comments
 (0)