User story
Currently, mocktioneer uses fixed CPM pricing based on ad size ($1.70-$4.20) with a simple per impression override via ext.mocktioneer.bid. To better simulate realnworld DSP bidding behavior in testing scenarios, we need a comprehensive bid price configuration system that supports common targeting and pricing strategies.
Prod DSPs evaluate multiple factors when determining bid prices: deal agreements, audience data, geographic targeting, contextual relevance, and inventory quality. A testing tool should replicate these pricing mechanics to ensure integrations handle various bid scenarios correctly.
Acceptance criteria
- Rule Evaluation Order: Define clear precedence (e.g., deal IDs override all other rules, then segments, then geo, etc.)
- Composition Strategy: Support both additive and multiplicative modifiers
- Determinism: Maintain mocktioneer's core principle—identical requests produce identical bids
- Validation: Reject invalid configurations at startup with clear error messages
- Observability: Log which rules were applied to calculate each bid (useful for debugging)
- Backward Compatibility: Preserve existing size-based pricing as default when no advanced rules are configured
Testing Requirements
- Unit tests for each pricing rule type
- Integration tests with realistic OpenRTB requests
- Validation that complex rule combinations work correctly
- Performance benchmarks to ensure rule evaluation doesn't significantly impact latency
Documentation Needs
- Update API reference with pricing rule details
- Add configuration examples to guide
- Create troubleshooting section for common pricing configuration errors
Affected area
Core (auction, OpenRTB, APS, mediation, rendering)
Proposed approach
Core Pricing Rules
Deal ID Pricing
Support imp[].pmp.deals[] from OpenRTB spec
Configure fixed or floor prices per deal ID
Example: Deal "PMP-12345" always bids $8.50 CPM
[[pricing.deals]]
id = "PMP-12345"
price = 8.50
Price Floor & Ceiling Controls
Global and per-size min/max bid constraints
Honor imp[].bidfloor from bid requests
Configurable hard limits to prevent unrealistic bids
[pricing.limits]
global_floor = 0.50
global_ceiling = 25.00
Geographic Pricing
Country, region/state, DMA, and postal code-based multipliers
Extract from device.geo in OpenRTB requests
Example: US traffic at 1.5x base price, UK at 1.2x
[pricing.geo]
"US" = 1.5
"GB" = 1.2
"CA" = 1.3
Audience Segment Pricing
Match against user.data[] segments from bid request
Configurable premiums for high-value audiences
Example: "auto-intender" segment adds $2.00 CPM
[[pricing.segments]]
id = "auto-intender"
modifier = 2.00 # additive
[[pricing.segments]]
id = "high-income"
multiplier = 1.3 # multiplicative
Contextual Match Pricing
Keyword/category matching from site.keywords or app.cat[]
IAB taxonomy category-based pricing tiers
Example: "finance" content at $6 base CPM
[[pricing.contextual]]
keywords = ["finance", "investment", "banking"]
base_price = 6.00
[[pricing.contextual]]
iab_categories = ["IAB13"] # Personal Finance
multiplier = 1.4
Additional DSP-Realistic Features
Device Type Modifiers
Differential pricing for mobile, tablet, desktop, CTV
Extract from device.devicetype (OpenRTB 2.x)
[pricing.device]
mobile = 0.8 # devicetype = 4
tablet = 1.0 # devicetype = 5
desktop = 1.2 # devicetype = 2
ctv = 2.0 # devicetype = 3
Publisher/Domain Pricing
Allowlist premium publishers with higher bids
Blocklist or reduce bids for low-quality inventory
[[pricing.publishers]]
domain = "nytimes.com"
multiplier = 1.8
[[pricing.publishers]]
domain = "example-low-quality.com"
multiplier = 0.3
Dayparting (Time-Based Pricing)
Hour-of-day and day-of-week bid adjustments
Timezone-aware or UTC-based schedules
[[pricing.daypart]]
days = ["mon", "tue", "wed", "thu", "fri"]
hours = [9, 10, 11, 12, 13, 14, 15, 16, 17]
multiplier = 1.3 # Business hours premium
Ad Position Multipliers
Above-the-fold vs. below-the-fold pricing
Based on imp[].banner.pos (OpenRTB field)
[pricing.position]
above_fold = 1.5 # pos = 1
below_fold = 0.7 # pos = 3
Supply Source Pricing
Different pricing for web, in-app, CTV
Derived from presence of site vs. app object
[pricing.supply]
web = 1.0
app = 1.2
ctv = 2.5
Private Marketplace (PMP) vs. Open Exchange
Automatically bid higher for imp[].pmp requests
Simulate preferential treatment of private deals
[pricing.marketplace]
pmp_multiplier = 1.5
open_exchange_multiplier = 1.0
Brand Safety & Viewability Scores
Optional risk-based bid reduction
Custom fields via ext.brand_safety or ext.viewability
[[pricing.brand_safety]]
score_min = 0.8
multiplier = 1.0
[[pricing.brand_safety]]
score_min = 0.0
score_max = 0.5
multiplier = 0.3 # Risky inventory
Bid Shading/Reduction Strategies
Simulate second-price auction mechanics
Configurable shading percentage
[pricing.bid_shading]
enabled = true
reduction_percent = 5 # Bid 5% below calculated price
Currency Support with Custom Rates
Multi-currency bid responses
Configurable exchange rates for testing
[pricing.currency]
default = "USD"
[pricing.currency.rates]
EUR = 0.92
GBP = 0.79
JPY = 148.50
Configuration Schema Proposal
Extend edgezero.toml with a new [pricing] section:
[pricing]
Base pricing (existing behavior)
base_price_by_size = true
area_fallback = true
Global constraints
[pricing.limits]
global_floor = 0.50
global_ceiling = 25.00
Deal-specific pricing
[[pricing.deals]]
id = "PMP-12345"
price = 8.50
[[pricing.deals]]
id = "PMP-67890"
floor = 5.00
ceiling = 12.00
Geographic multipliers
[pricing.geo]
"US" = 1.5
"GB" = 1.2
default = 1.0
Segment-based modifiers
[[pricing.segments]]
id = "auto-intender"
modifier = 2.00
[[pricing.segments]]
id = "high-income"
multiplier = 1.3
Contextual pricing
[[pricing.contextual]]
keywords = ["finance", "investment"]
base_price = 6.00
Device type modifiers
[pricing.device]
mobile = 0.8
desktop = 1.2
ctv = 2.0
Publisher allowlist/blocklist
[[pricing.publishers]]
domain = "nytimes.com"
multiplier = 1.8
Dayparting
[[pricing.daypart]]
days = ["mon", "tue", "wed", "thu", "fri"]
hours = [9, 10, 11, 12, 13, 14, 15, 16, 17]
multiplier = 1.3
Position-based pricing
[pricing.position]
above_fold = 1.5
below_fold = 0.7
Marketplace type
[pricing.marketplace]
pmp_multiplier = 1.5
open_exchange_multiplier = 1.0
Additional context
No response
User story
Currently, mocktioneer uses fixed CPM pricing based on ad size ($1.70-$4.20) with a simple per impression override via ext.mocktioneer.bid. To better simulate realnworld DSP bidding behavior in testing scenarios, we need a comprehensive bid price configuration system that supports common targeting and pricing strategies.
Prod DSPs evaluate multiple factors when determining bid prices: deal agreements, audience data, geographic targeting, contextual relevance, and inventory quality. A testing tool should replicate these pricing mechanics to ensure integrations handle various bid scenarios correctly.
Acceptance criteria
Testing Requirements
Documentation Needs
Affected area
Core (auction, OpenRTB, APS, mediation, rendering)
Proposed approach
Core Pricing Rules
Deal ID Pricing
Support imp[].pmp.deals[] from OpenRTB spec
Configure fixed or floor prices per deal ID
Example: Deal "PMP-12345" always bids $8.50 CPM
[[pricing.deals]]
id = "PMP-12345"
price = 8.50
Price Floor & Ceiling Controls
Global and per-size min/max bid constraints
Honor imp[].bidfloor from bid requests
Configurable hard limits to prevent unrealistic bids
[pricing.limits]
global_floor = 0.50
global_ceiling = 25.00
Geographic Pricing
Country, region/state, DMA, and postal code-based multipliers
Extract from device.geo in OpenRTB requests
Example: US traffic at 1.5x base price, UK at 1.2x
[pricing.geo]
"US" = 1.5
"GB" = 1.2
"CA" = 1.3
Audience Segment Pricing
Match against user.data[] segments from bid request
Configurable premiums for high-value audiences
Example: "auto-intender" segment adds $2.00 CPM
[[pricing.segments]]
id = "auto-intender"
modifier = 2.00 # additive
[[pricing.segments]]
id = "high-income"
multiplier = 1.3 # multiplicative
Contextual Match Pricing
Keyword/category matching from site.keywords or app.cat[]
IAB taxonomy category-based pricing tiers
Example: "finance" content at $6 base CPM
[[pricing.contextual]]
keywords = ["finance", "investment", "banking"]
base_price = 6.00
[[pricing.contextual]]
iab_categories = ["IAB13"] # Personal Finance
multiplier = 1.4
Additional DSP-Realistic Features
Device Type Modifiers
Differential pricing for mobile, tablet, desktop, CTV
Extract from device.devicetype (OpenRTB 2.x)
[pricing.device]
mobile = 0.8 # devicetype = 4
tablet = 1.0 # devicetype = 5
desktop = 1.2 # devicetype = 2
ctv = 2.0 # devicetype = 3
Publisher/Domain Pricing
Allowlist premium publishers with higher bids
Blocklist or reduce bids for low-quality inventory
[[pricing.publishers]]
domain = "nytimes.com"
multiplier = 1.8
[[pricing.publishers]]
domain = "example-low-quality.com"
multiplier = 0.3
Dayparting (Time-Based Pricing)
Hour-of-day and day-of-week bid adjustments
Timezone-aware or UTC-based schedules
[[pricing.daypart]]
days = ["mon", "tue", "wed", "thu", "fri"]
hours = [9, 10, 11, 12, 13, 14, 15, 16, 17]
multiplier = 1.3 # Business hours premium
Ad Position Multipliers
Above-the-fold vs. below-the-fold pricing
Based on imp[].banner.pos (OpenRTB field)
[pricing.position]
above_fold = 1.5 # pos = 1
below_fold = 0.7 # pos = 3
Supply Source Pricing
Different pricing for web, in-app, CTV
Derived from presence of site vs. app object
[pricing.supply]
web = 1.0
app = 1.2
ctv = 2.5
Private Marketplace (PMP) vs. Open Exchange
Automatically bid higher for imp[].pmp requests
Simulate preferential treatment of private deals
[pricing.marketplace]
pmp_multiplier = 1.5
open_exchange_multiplier = 1.0
Brand Safety & Viewability Scores
Optional risk-based bid reduction
Custom fields via ext.brand_safety or ext.viewability
[[pricing.brand_safety]]
score_min = 0.8
multiplier = 1.0
[[pricing.brand_safety]]
score_min = 0.0
score_max = 0.5
multiplier = 0.3 # Risky inventory
Bid Shading/Reduction Strategies
Simulate second-price auction mechanics
Configurable shading percentage
[pricing.bid_shading]
enabled = true
reduction_percent = 5 # Bid 5% below calculated price
Currency Support with Custom Rates
Multi-currency bid responses
Configurable exchange rates for testing
[pricing.currency]
default = "USD"
[pricing.currency.rates]
EUR = 0.92
GBP = 0.79
JPY = 148.50
Configuration Schema Proposal
Extend edgezero.toml with a new [pricing] section:
[pricing]
Base pricing (existing behavior)
base_price_by_size = true
area_fallback = true
Global constraints
[pricing.limits]
global_floor = 0.50
global_ceiling = 25.00
Deal-specific pricing
[[pricing.deals]]
id = "PMP-12345"
price = 8.50
[[pricing.deals]]
id = "PMP-67890"
floor = 5.00
ceiling = 12.00
Geographic multipliers
[pricing.geo]
"US" = 1.5
"GB" = 1.2
default = 1.0
Segment-based modifiers
[[pricing.segments]]
id = "auto-intender"
modifier = 2.00
[[pricing.segments]]
id = "high-income"
multiplier = 1.3
Contextual pricing
[[pricing.contextual]]
keywords = ["finance", "investment"]
base_price = 6.00
Device type modifiers
[pricing.device]
mobile = 0.8
desktop = 1.2
ctv = 2.0
Publisher allowlist/blocklist
[[pricing.publishers]]
domain = "nytimes.com"
multiplier = 1.8
Dayparting
[[pricing.daypart]]
days = ["mon", "tue", "wed", "thu", "fri"]
hours = [9, 10, 11, 12, 13, 14, 15, 16, 17]
multiplier = 1.3
Position-based pricing
[pricing.position]
above_fold = 1.5
below_fold = 0.7
Marketplace type
[pricing.marketplace]
pmp_multiplier = 1.5
open_exchange_multiplier = 1.0
Additional context
No response