In order to set up a custom bidding algorithm in the DSP, it must be written in the form of a decision tree using the Sequoia language. Sequoia is a high-level, domain specific language that can be used to write custom predictive bidding models for optimizing bidding based on multiple targeting attributes.
Limitations
Use only allowed keywords, operators and statements. Otherwise, the rules file will not be processed.
Terms
Before writing the algorithm in Sequoia, there are a few key terms to be aware of.
Rule - A rule is a combination of conditions involving targeting attributes (features) that are evaluated against a bid opportunity and if satisfied, corresponding bid_price/bid_multiplier is used in the final bid price calculation.
Feature - A feature is a set of attributes like (domain, viewability etc ) that are supported.
Node - A node defines the point in the decision tree where a rule is evaluated and a bid price or bid multiplier is assigned. A node consists of a rule_name(which uniquely identifies the rule & bid_price/bid_multipler) and specifies a bid_price or bid_multiplier value. Specifying the rule name might help to easily identify which rule got applied during serving time. Like any other language, Sequoia has syntax and comes with supported constructs including: expressions, operators (both relational & logical), and constraints.
Expressions - Sequoia supports if/else and switch expressions.
Operator - Sequoia supports relational, logical, and In operators.
Evaluation Order
The DSP processes BYOA rules sequentially by evaluating the rules in order of what conditions apply. When a condition is met, that rule will be used by the algorithm and all following rules will be ignored. For example, if the conditions for the first rule apply, the DSP will use that multiplier and skip the others.
Example
When there is an impression coming from “sports.yahoo.com” with the following BYOA rules in place, an impression from “sports.yahoo.com” would trigger rule A123 and the bid will be set to 1.5.
if(domain ==“yahoo.com”) {
rule_name = “A123”;
bid_price = 1.5;
} else if (domain ==“sports.yahoo.com”) {
rule_name = “A124”;
bid_price = 2;
}In this scenario, the rule A123 will be triggered because the domain is yahoo.com and the first written condition is met. As a result, the bid will be set to 1.5. The proper way to write this would be:
if(domain ==“sports.yahoo.com”) {
rule_name = “A124”;
bid_price = 2;
} else if (domain ==“yahoo.com”) {
rule_name = “A124”;
bid_price = 1.5;
}This way:
Impressions from “sports.yahoo.com” will get 2 as a bid_price.
Other impressions from “yahoo.com” will get 1.5 as a bid price.
Rules
Rule: <Set of Conditions separated by logical operators>
<Assignment Statements>
Conditions: Feature keywords, operators (logical and relational)
Assignment Statements: set ``bid_price``/``bid_multiplier``, rule_nameMultiple rules can be combined for optimization by combining conditions that are evaluated repeatedly into a single condition by using if or if /else or switch expression statements. This makes reading the decision tree with multiple rules easy for humans as well as machines.
Features
Every decision tree is composed of algorithms for evaluating sets of conditions called features and assigning values based on those evaluations.
A feature consists of three elements: a keyword, a logical operator and a value that is evaluated.
The keyword identifies a targetable attribute. The following keywords are listed in the Supported Features table.
The relational operator specifies how the platform should evaluate the feature. Sequoia supports the following logical operators: ==, IN, !, >, >=, < and <=.
The value specifies the value of the targetable attribute.
In the following example, the feature is composed of the user_day keyword, the equals (==) operator, and a value of 28.
if(user_day == 28) {
rule_name = “X1234”;
bid_price = 0.21;
}Supported Features
DSP Field | Keyword | Supported Relational Operators | Valid Values |
|---|---|---|---|
Day of the Week | user_day |
| An integer value between 0 to 6 that represents the day of the week. 0 is Sunday and 6 is Saturday. |
Time of day | user_hour |
| An integer between 0 to 23 that represents the hour of the day. |
Country | pulse_country_id |
| The id is an integer value that is returned in the code field in the DSP API that identifies a country. |
State | pulse_region_id |
| The id is an integer value that is returned in the code field in the DSP API that identifies a state. |
Region | pulse_locality_woeid |
| The id is an integer value that is returned in the woeid field in the DSP API that identifies a region. |
Sub Region | pulse_sub_locality_woeid |
| The id is an integer value that is returned in the woeid field in the DSP API that identifies a sub region. |
Metro Area | pulse_major_metro_area_woeid |
| The id is an integer value that is returned in the woeid field in the DSP API that identifies a metro area. |
DMA | pulse_metro_id |
| The id is an integer value that is returned in the code field in the DSP API that identifies a DMA. |
City | pulse_city_id |
| The id is an integer value that is returned in the code field in the DSP API that identifies a city. |
Zip | postal_code |
| The id is an integer value that is returned in the woeid field in the DSP API that identifies a postal code. |
Domain / App | domain/appname |
| A string that represents the address of the publisher site. For example, sports.yahoo.com. A comma separated list of addresses when used with IN clause like domain IN “address1,address2,address3”. |
Ad size | layout |
| An integer that represents the layout. |
Ad Position | ad_position |
| An Integer representing the position of the ad. |
Device Type | device_type |
| An integer representing the device type. |
Predicted Viewability | viewability |
| A Double value representing the viewability percentage. |
Audience | Segment |
| A comma separated list of segment ids enclosed in double quotes. For example, “1234,89653,76542”. |
User Day
The user_day feature enables you to evaluate ad placement opportunities based on the day of the week.
The day of the week is specified as an integer value between 0 to 6.
0 - Sunday
1 - Monday
2 - Tuesday
3 - Wednesday
4 - Thursday
5 - Friday
6 - Saturday
The user_day feature accepts five operators.
==
>
>=
<
<=
Using the == operator, consumers can be targeted on a specific day of the week. For example, to specify a bid price for ads served on Saturday, write the following set of rules.
if(user_day == 6) {
rule_name = “A123”;
bid_price = 1.2;
} else {
rule_name = “A124”;
bid_price = 1.1;
}User Hour
The user_hour feature enables you to target ad placement opportunities based on the hour of the day that the ad is served to the consumer.
A user_hour value is an integer between 0 to 23 that represents the hour of the day. The hour specified is always local to the time of the day of the consumer.
The user_hour feature accepts two operators.
==
>
>=
<
<=
Geo Related Features
Use the Geography Targeting Trafficking API endpoint to obtain the correct ID (code or woeid field integer value) in order to target specific geographical locations with BYOA.
Supported Features
Level Field from Geography Targeting API | BYOA Rule Parameter | Field to use from Geography Targeting API |
|---|---|---|
Zip | postal_code | woeid |
Country | pulse_country_id | code |
State | pulse_region_id | code |
Region | pulse_locality_woeid | woeid |
Sub Region | pulse_sub_locality_woeid | woeid |
Metro Area | pulse_major_metro_area_woeid | woeid |
DMA | pulse_metro_id | code |
City | pulse_city_id | code |
For example, New York can refer to a city or a state, each having its own ID.
if(postal_code == 12784282) {
rule_name = “A123”;
bid_price = 1.4;
}
else if(pulse_metro_id == 501) {
rule_name = "M60629";
bid_multiplier = 1.05;
}
else if(pulse_city_id == 57) {
rule_name = "M60630";
bid_multiplier = 1.05;
}
else if(pulse_country_id == 840) {
rule_name = "M60629";
bid_multiplier = 1.05;
}Domain/Appname
The domain feature allows for the targeting of ad placement opportunities based on the web page address serving the ad.
A domain value is a string that represents the address of the publisher site. For example, sports.yahoo.com.
The domain feature accepts two operators.
==
IN (to support single or multiple domain values)
Using the == operator, you can set bid prices for ads served to consumers in a specific domain. For example, if you want to specify a bid price for ads served to a domain, you could write the following set of rules.
if(domain ==“sports.yahoo.com”) {
rule_name = “A123”;
bid_price = 1.4;
} else {
rule_name = “A124”;
bid_price = 1.2;
}It’s important to have an exact match of the domain or subdomain that the rule is targeting. For example, if a rule is set up for “yahoo.com”, impressions coming from “sports.yahoo.com” will not match it. Instead, a second rule for “sports.yahoo.com” should be set up.
Layout
The layout/ad_size feature enables you to target ad placement opportunities based on the size of the ad.
A layout/ad_size value is an integer that specifies the size of the ad.
Use the Layout API endpoint to obtain the correct ID in order to utilize different layout/ad size with BYOA.
The layout/ad_size feature accepts two operators.
==
>
>=
<
<=
Bid prices for ads served to consumers can be set based on the size of the ad. For example, to bid more to deliver large ads, write the following set of rules:
if(layout >=4 and layout <=6) {
rule_name = “A123”;
bid_price = 1.4;
} else {
rule_name = “A124”;
bid_price = 1.2;
}Ad Position
The ad_position feature allows for the targeting of ad placement opportunities based on the position of the ad on the web page.
The ad_position value is defined as an integer that identifies the ad position.
0-Unknown
1- Above the fold
2- Partial view
3- Below fold
4- Header
5-Footer
The ad_position feature accepts a single operator.
==
>
>=
<
<=
Using the == operator, bid prices can be set based on the position of the ad on the page. For example, to bid more for ads that are above the fold, write the following set of rules.
if(ad_position == 1000) { // like Above the fold
rule_name = “A123”;
bid_price = 1.4;
} else {
rule_name = “A124”;
bid_price = 1.2;
}Device Type
The device_type feature enables you to target ad placement opportunities based on the types of physical devices serving the impression.
The device_type value is defined as an integer that represents the device type.
1 - Desktop
2 - Laptop
3 - Phone/Mobile
4 - Tablet
5- Connected TV
The device_type feature accepts a single operator.
==
>
>=
<
<=
Using the == operator, bid prices can be set for ads served to consumers using specific types of devices. For example, to bid more for ads served to consumers using a mobile phone, write the following set of rules.
if(device_type == 3) {
rule_name = “A123”;
bid_price = 1.4;
} else {
rule_name = “A124”;
bid_price = 1.2;
}Viewability
The viewability feature allows for the targeting of ad placement opportunities based on the viewability rate of the impressions measured by Yahoo.
The viewability value is specified as a number between 0 and 1 that represents a viewability rate percentage. For example, 0.65 means 65%.
The viewability feature accepts five operators.
==
>
>=
<
<=
Using the > operator, bid prices can be set for ads with a viewability rate that is greater than the value specified. For example, to bid more for ads that are more than 54% visible, write the following set of rules.
if(viewability_rate > 0.54) {
rule_name = “A123”;
bid_price = 1.4;
} else {
rule_name = “A124”;
bid_price = 1.2;
}Segment
The segment feature enables you to target ad placement opportunities based on the audience. Audience groups are identified as segments of users and advertisers can target various segments of people.
The segment feature accepts only one operator.
IN
Using the IN operator, you can specify a list of segment ids to target multiple groups of audiences. For example, if you are willing to bid more for ads that are for segment Ids 2345 or 7895 or 3459.
if(segment IN “2345,7895,3459”) {
rule_name = “A999”;
bid_price = 1.23;
} else {
rule_name = “A1000”;
bid_price = 1.145;
}Expressions
In Sequoia, decision trees can be written using following expressions.
if/else
switch
If Else Statement
As with any modern language, Sequoia supports if and else to enable users to write conditions that execute a set of statements when evaluated as true and optionally execute a different set of statements if evaluated as false. For example, the following Sequoia language represents the following if else statement: if a user’s pulse_country_id is 1001, then set the bid price to 0.5, else the bid price is set to 0.4.
if (pulse_country_id == 1001) {
bid_price = 0.5;
rule_name = “A1234”;
} else {
bid_price = 0.4;
rule_name = “A1235”;
}Is the user from pulse_country_id 1001?
If yes, then set the bid price as 0.5.
Else set the bid price as 0.4.
Nested if or if/else statements are also allowed and any combination of them.
Note
To evaluate a condition using an if statement, we use the == operator, while for assigning a value we use =.
Switch Statement
The switch statement is an alternative to writing multiple nested if /else statements. It will be handy to test against a lot of values for a single feature and have different bid prices.
switch(expression) {
case 1: {
statement1;
Break;
}
case 2: {
statement2;
Break;
}
case 3: {
statement3;
Break;
}
Default: {
statement;
Break;
}
}The switch statement will have an expression that will be evaluated, and based on the value of the expression, the statements of case that match with the expression value get executed. If no cases match then statements in the default section will get executed.
Each case block should end with a break statement, and every switch must have a default clause.
Example
if(domain == “sports.yahoo.com”) {
switch(pulse_country_id) {
case 3261: {
rule_name = “S1111”;
bid_multiplier = 2.5;
break;
}
case 4425: {
if(user_hour == 5 && segment IN “2222,3333,4444”) {
rule_name = “S1114”;
Bid_price = 3.5;
}
break;
}
case 4578:
rule_name = “S1118”;
bid_multiplier = 2.38;
break;
default : {
rule_name = “S1120”;
bid_price = 1.42;
break;
}
}
}
}The example uses the following logic.
Is the domain “sports.yahoo.com”?
If yes, go to step 2.
If no, then NO bid.
Is the pulse_country_id equal to 3261?
If yes, use bid 0.34.
If no, go to step 3.
Is the user pulse_country_id equal to 4425?
If yes, use go to step 4.
If no, go to step 5.
Is the user time equal to the 5th hour and does the user belong to any of the following targeted segments: 2222,3333,4444?
If yes, use bid 0.36.
If no, NO bid.
Is the user pulse_country_id equal to 4578?
If yes, bid 0.38.
If no, NO bid.
If the user does not belong to any of the following pulse_country_ids: 3261, 4425, 4578.
Bid 0.42.
Operators
Relational Operators
Sequoia supports six relational operators. Use these operators to make comparisons against primitive data types like integer, long, and float.
Operator | Meaning |
|---|---|
== | Equal to used for comparison. |
< | Less than. |
<= | Less than or equal to. |
> | Greater than. |
>= | Greater than or equal to. |
In the example, a user_day feature is evaluated using the >=, <=, and == operators.
if(user_day >= 5 && user_day <= 8 && (user_hour == 9 || user_hour == 22)) {
rule_name = “C1111”;
bid_multiplier = 1.54;
}Logical Operators
Sequoia supports three logical operators.
Operator | Meaning |
|---|---|
&& | AND |
|| | OR |
! | NOT |
Example
if(!(domain == “finance.yahoo.com”) && user_hour <= 15 && (user_day == 2 || user_day == 06)) {
rule_name = “L1111”;
bid_multiplier = 1.71;
}IN Operator (for ‘segment’ and ‘domain’/’appname’ features)
The IN operator can be used to test whether the value of the feature is among a list of the values. The list of values must be enclosed using double quotes (“ ‘).
if(segment in “23456,4789654,67544332”) {
rule_name = “X1234”;
bid_multiplier = 1.33;
}
if(domain in “finance.yahoo.com,cnn.com,abcnews.com”) {
rule_name = “X333”;
bid_price = 0.85;
}Special Flags
When writing your algorithm, you can use some special flags that will overwrite some functions of the bidder.
Default Bid
default_bid_flag = 0;
In a situation that doesn’t match a rule defined in the custom algorithm, the DSP will not bid.
default_bid_flag = 1;
In a situation that doesn’t match a rule defined in the custom algorithm, the DSP will bid as per the optimisation.