← Template Library Download Template ↗

Automation template

KDP Core: Dynamic Bid Management

Scales bid adjustments proportionally based on distance from target ACOS using adaptive timing controls.

Ready to use Merch Jar workflow
Version
1.0
Type
Last updated
2026-01-08T00:00:00.000Z
Active
Yes

Download this template

Description

Purpose

Scales bid adjustments proportionally based on distance from target Blended ACOS using adaptive timing controls.

This Blueprint is for:

✓ KDP advertisers wanting performance-based bid optimization that accounts for KENP royalties

✓ Accounts with keywords/targets generating page reads where standard ACOS understates true performance

✓ Sellers who want proportional adjustments - bigger changes when further from target, smaller when close

✓ Accounts with Target ACOS configured at campaign, ad group, or target level

Key Features

  • Proportional bid scaling - adjustments range from 3-10% based on how far Blended ACOS is from target
  • Multi-period data selection - automatically uses 7d, 14d, 30d, or 60d based on blended profit volume
  • Adaptive cooldowns - longer lookback periods get longer cooldowns to prevent over-adjustment
  • CPC-based bid limits - caps maximum bid at 2× average CPC to prevent runaway increases

Configuration Guidance

  • Blended Profit Minimum ($6): Threshold for reliable Blended ACOS. Lower for low-royalty books, raise if you want more conservative data requirements.
  • Buffer Zone (±10%): No changes when Blended ACOS is within 10% of target. Widen to 15% for less frequent adjustments, narrow to 5% for tighter optimization.
  • Max Change (10%): Largest bid adjustment per cycle. Conservative default prevents dramatic swings - raise only if you want faster convergence.
  • CPC Multiplier (2.0×): Bid ceiling based on historical CPC. Lower to 1.5× for tighter control, raise to 2.5× if you're comfortable with higher bids.

Daily Automation: Change Bid using Set ($) with $target_bid

How it works

How the Logic Works

The blueprint calculates a performance ratio by comparing actual Blended ACOS to target, then scales bid adjustments proportionally. Keywords far from target get larger adjustments (up to 10%), while those closer get smaller tweaks (down to 3%). A buffer zone around target prevents unnecessary churn on keywords already performing well.

Key Technical Concepts

Proportional Adjustment Scaling

Rather than fixed percentage changes, adjustments scale based on distance from target:

  • Blended ACOS at 50% of target or better: Maximum increase (10%)
  • Blended ACOS between 50% and 90% of target: Scaled increase (3-10%)
  • Blended ACOS between 90% and 110% of target: No change (buffer zone)
  • Blended ACOS between 110% and 200% of target: Scaled decrease (3-10%)
  • Blended ACOS at 200% of target or worse: Maximum decrease (10%)

This creates smooth, predictable bid curves that converge toward target without dramatic swings.

Multi-Period Data Selection

The blueprint automatically selects the shortest period with sufficient blended profit:

  • 7-day data if blended profit ≥ $6
  • 14-day data if 7-day insufficient
  • 30-day data if 14-day insufficient
  • 60-day data if 30-day insufficient
  • No action if all periods lack sufficient data

This ensures high-volume keywords respond quickly to performance changes while low-volume keywords use more stable long-term data.

Adaptive Cooldown Periods

Cooldowns match data period length to prevent over-adjustment:

  • 7-day data → 2-day cooldown
  • 14-day data → 3-day cooldown
  • 30-day data → 5-day cooldown
  • 60-day data → 7-day cooldown

Keywords using longer lookback periods get longer cooldowns because their performance signals change more slowly.

CPC-Based Bid Limits

Maximum bid is capped at 2× the 90-day average CPC. This prevents runaway bid increases on keywords that historically convert at lower click costs, protecting against overpaying for traffic.

Configuration Deep Dive

Blended Profit Minimum ($6 default)

The threshold for considering a time period's Blended ACOS reliable. Lower values allow faster response but risk acting on noisy data. Higher values are more conservative but may leave low-volume keywords unoptimized.

  • Aggressive optimization: $3-4
  • Balanced (default): $6
  • Conservative: $10-12

Buffer Zone (±10% default)

Keywords within this range of target get no bid changes. This prevents constant small adjustments on keywords that are essentially at target. The buffer is symmetric - both slightly above and slightly below target are left alone.

  • Tight optimization: ±5%
  • Balanced (default): ±10%
  • Minimal churn: ±15-20%

Min/Max Change (3%/10% defaults)

The range of possible bid adjustments. Minimum ensures changes are meaningful when made. Maximum prevents dramatic swings that could destabilize performance.

  • Conservative: 2%/7%
  • Balanced (default): 3%/10%
  • Aggressive: 5%/15%

Threshold Settings (50%/200% defaults)

Define where maximum adjustments kick in:

  • Max Increase Threshold (50%): Blended ACOS at half of target or better triggers maximum bid increase
  • Max Decrease Threshold (200%): Blended ACOS at double target or worse triggers maximum bid decrease

The asymmetry (50% vs 200%) reflects that it's easier to overspend than underspend - the blueprint is more patient with high ACOS before applying maximum decreases.

Diagnostic Property Interpretation

$reason values

  • "No target blended ACOS set" → Configure Target ACOS in Ad Manager
  • "Insufficient blended profit data across all lookback periods" → Not enough conversions for reliable optimization
  • "[Volume Level] Within target buffer zone" → Performing close to target, no adjustment needed
  • "[Volume Level] Recently changed - cooldown active" → Waiting for recent change to take effect
  • "Limited by CPC-based maximum" → Increase was capped by CPC limit
  • "[Volume Level] Blended ACOS below target threshold" → Outperforming, bid increasing
  • "[Volume Level] Blended ACOS above target threshold" → Underperforming, bid decreasing

$result categories

  • "Bid Increase: Max" → Excellent performance, 10% increase
  • "Bid Increase: Upper Range" → Strong performance, 6.5-10% increase
  • "Bid Increase: Lower Range" → Good performance, 3-6.5% increase
  • "Bid Decrease: Lower Range" → Slightly over target, 3-6.5% decrease
  • "Bid Decrease: Upper Range" → Significantly over target, 6.5-10% decrease
  • "Bid Decrease: Max" → Poor performance, 10% decrease
  • "No action needed" → Within buffer, cooldown active, or no change calculated

Common Performance Patterns

Gradual convergence: Keywords typically take 3-5 adjustment cycles to reach target range. This is intentional - gradual changes are more stable than dramatic swings.

Buffer zone clustering: Over time, most active keywords should cluster within the buffer zone. If you see many keywords consistently outside the buffer, consider adjusting your Target ACOS or buffer width.

Volume-based response times: High-volume keywords (using 7-day data) respond within days. Low-volume keywords (using 60-day data) may take weeks. This is by design - low-volume keywords need more data before confident adjustments.

CPC limit hits: If many keywords show "Limited by CPC-based maximum," either your bids are approaching reasonable limits (good) or you may want to raise the CPC multiplier for more headroom.

Cooldown blocking: Seeing many keywords in cooldown is normal, especially early on. The blueprint is pacing changes to let previous adjustments take effect before making more.

Syntax

/*
=== KDP Core: Dynamic Bid Management ===
Purpose: Scales bid adjustments proportionally based on distance from target ACOS using adaptive timing controls.
Recommended: Change Bid: Set ($) using $target_bid | Daily
*/
 
// === Core Settings ===
let $blend_profit_min = 6.00;                           // CORE: Minimum blended profit required for reliable ACOS evaluation ($6.00 threshold)
let $bid_min_change = 3%;                               // CORE: Minimum bid adjustment when change is warranted
let $bid_max_change = 10%;                              // CORE: Maximum bid adjustment when ACOS is at or beyond target ACOS thresholds
 
// === Target ACOS Thresholds ===
// Between buffer and thresholds: bid adjustments scale linearly from min to max change percent
let $t_blend_acos_buffer_min_change = 10%;              // STRATEGY: No-change buffer around target blended ACOS - min changes start outside this zone (Target Blended ACOS ± 10%) [e.g., 100% target = 90-110% no-change zone]
let $t_blend_acos_threshold_max_increase = 50%;         // STRATEGY: Max increase when blended ACOS ≤ (Target Blended ACOS × 50%) [e.g., 100% target = 50% max increase threshold]
let $t_blend_acos_threshold_max_decrease = 200%;        // STRATEGY: Max decrease when blended ACOS ≥ (Target Blended ACOS × 200%) [e.g., 100% target = 200% max decrease threshold]
 
// === Time Periods ===
let $period_short = 0d..7d;                    // TIME: Primary evaluation period (7 days including today)
let $cooldown_short = 2d;                      // TIME: Wait period after bid change for short data periods
 
let $period_medium = 0d..14d;                  // TIME: Secondary evaluation period (14 days including today)
let $cooldown_medium = 3d;                     // TIME: Wait period after bid change for medium data periods
 
let $period_long = 0d..30d;                    // TIME: Tertiary evaluation period (30 days including today)
let $cooldown_long = 5d;                       // TIME: Wait period after bid change for long data periods
 
let $period_extended = 0d..60d;                // TIME: Final fallback evaluation period (60 days including today)
let $cooldown_extended = 7d;                   // TIME: Wait period after bid change for extended data periods
 
// === Advanced Settings ===
let $bid_limit_cpc_multiplier = 2.0;          // SAFEGUARD: Max bid = Avg CPC × 2.0 [e.g., $0.50 CPC = $1.00 max]
let $bid_limit_cpc_period = 90d;              // SAFEGUARD: Period for calculating CPC-based bid limits
 
// === Segment Filters ===
let $include_campaigns = [""];                // FILTER: Apply to all campaigns, or specify terms like ["SP-", "Auto", "Research"]
let $exclude_campaigns = ["NEVER_MATCH"];     // FILTER: Exclude campaigns containing these terms, e.g., ["Brand", "Test", "Archive"]
 
// ============================================================================
// === Blueprint Logic ===
// ============================================================================
// Advanced logic below - modify carefully
 
// Multi-period data selection with extended coverage
let $blend_profit_short = blended profit($period_short);
let $blend_profit_medium = blended profit($period_medium);  
let $blend_profit_long = blended profit($period_long);
let $blend_profit_extended = blended profit($period_extended);
 
let $evaluation_blend_acos = case(
    $blend_profit_short >= $blend_profit_min => blended acos($period_short),
    $blend_profit_medium >= $blend_profit_min => blended acos($period_medium),
    $blend_profit_long >= $blend_profit_min => blended acos($period_long),
    $blend_profit_extended >= $blend_profit_min => blended acos($period_extended),
    else 99999  // No reliable data
);
 
// Track which period was used for diagnostics
let $data_quality = case(
    $blend_profit_short >= $blend_profit_min => "High Volume: Short Lookback",
    $blend_profit_medium >= $blend_profit_min => "Med Volume: Medium Lookback",
    $blend_profit_long >= $blend_profit_min => "Low Volume: Long Lookback",
    $blend_profit_extended >= $blend_profit_min => "Very Low Volume: Extended Lookback",
    else "insufficient"
);
 
// Adaptive cooldown periods based on data source
let $cooldown_cutoff = case(
    $blend_profit_short >= $blend_profit_min => now() - interval($cooldown_short),
    $blend_profit_medium >= $blend_profit_min => now() - interval($cooldown_medium),
    $blend_profit_long >= $blend_profit_min => now() - interval($cooldown_long),
    else now() - interval($cooldown_extended)
);
 
// Calculate performance ratio with Target Blended ACOS validation
let $blend_acos_ratio = case(
    $evaluation_blend_acos = 99999 => -1,       // No reliable data
    target acos <= 0 => -1,                     // Invalid target blended ACOS
    else $evaluation_blend_acos / target acos   // Performance ratio
);
 
// Check if within no-change buffer zone
let $within_buffer = case(
    $blend_acos_ratio < 0 => 1,                 // No change if no data or invalid target
    $blend_acos_ratio >= (1 - $t_blend_acos_buffer_min_change) and $blend_acos_ratio <= (1 + $t_blend_acos_buffer_min_change) => 1,
    else 0
);
 
// Proportional scaling for bid adjustments
let $performance_gap = case(
    $blend_acos_ratio < 0 => 0,                 // No gap if no data
    // Max increase region: ACOS at 50% of target or better
    $blend_acos_ratio <= $t_blend_acos_threshold_max_increase => 1,
    // Scaled increase region: ACOS between 50% and buffer zone (90% of target)
    $blend_acos_ratio < (1 - $t_blend_acos_buffer_min_change) => 
        ((1 - $t_blend_acos_buffer_min_change) - $blend_acos_ratio) / 
        ((1 - $t_blend_acos_buffer_min_change) - $t_blend_acos_threshold_max_increase),
    // Max decrease region: ACOS at 200% of target or worse
    $blend_acos_ratio >= $t_blend_acos_threshold_max_decrease => 1,
    // Scaled decrease region: ACOS between buffer zone (110%) and 200% of target
    $blend_acos_ratio > (1 + $t_blend_acos_buffer_min_change) => 
        ($blend_acos_ratio - (1 + $t_blend_acos_buffer_min_change)) / 
        ($t_blend_acos_threshold_max_decrease - (1 + $t_blend_acos_buffer_min_change)),
    else 0                                      // Within buffer zone - no adjustment
);
 
let $adjustment_percent = case(
    $within_buffer = 1 => 0%,                   // No change within buffer zone
    // Increase adjustments for ACOS below target
    $blend_acos_ratio <= $t_blend_acos_threshold_max_increase => 
        $bid_min_change + ($performance_gap * ($bid_max_change - $bid_min_change)),
    $blend_acos_ratio < (1 - $t_blend_acos_buffer_min_change) => 
        $bid_min_change + ($performance_gap * ($bid_max_change - $bid_min_change)),
    // Decrease adjustments for ACOS above target
    $blend_acos_ratio > (1 + $t_blend_acos_buffer_min_change) => 
        -1 * ($bid_min_change + ($performance_gap * ($bid_max_change - $bid_min_change))),
    else 0%
);
 
// Calculate target bid with CPC-based limits
let $initial_target_bid = bid * (1 + $adjustment_percent);
 
let $avg_cpc = cpc($bid_limit_cpc_period);
let $dynamic_max = case(
    $avg_cpc > 0 => $avg_cpc * $bid_limit_cpc_multiplier,
    else 999  // No CPC data = no dynamic limit
);
 
let $target_bid = case(
    $avg_cpc > 0 and $initial_target_bid > $dynamic_max => $dynamic_max,
    else $initial_target_bid
);
 
// Cooldown validation
let $cooldown_ready = case(
    is_null(last bid change) => 1,
    last bid change < $cooldown_cutoff => 1,
    else 0
);
 
// Diagnostic properties
let $reason = case(
    target acos <= 0 => "No target blended ACOS set",
    $evaluation_blend_acos = 99999 => "Insufficient blended profit data across all lookback periods",
    $within_buffer = 1 => case(
        $data_quality = "High Volume: Short Lookback" => "[High Volume: Short Lookback] Within target buffer zone",
        $data_quality = "Med Volume: Medium Lookback" => "[Med Volume: Medium Lookback] Within target buffer zone",
        $data_quality = "Low Volume: Long Lookback" => "[Low Volume: Long Lookback] Within target buffer zone",
        $data_quality = "Very Low Volume: Extended Lookback" => "[Very Low Volume: Extended Lookback] Within target buffer zone",
        else "Performance within target buffer zone"
    ),
    $cooldown_ready = 0 => case(
        $data_quality = "High Volume: Short Lookback" => "[High Volume: Short Lookback] Recently changed - cooldown active",
        $data_quality = "Med Volume: Medium Lookback" => "[Med Volume: Medium Lookback] Recently changed - cooldown active",
        $data_quality = "Low Volume: Long Lookback" => "[Low Volume: Long Lookback] Recently changed - cooldown active",
        $data_quality = "Very Low Volume: Extended Lookback" => "[Very Low Volume: Extended Lookback] Recently changed - cooldown active",
        else "Recently changed - cooldown active"
    ),
    $target_bid = bid => "No bid change calculated",
    $avg_cpc > 0 and $initial_target_bid > $dynamic_max => "Limited by CPC-based maximum",
    $adjustment_percent > 0 => case(
        $data_quality = "High Volume: Short Lookback" => "[High Volume: Short Lookback] Blended ACOS below target threshold",
        $data_quality = "Med Volume: Medium Lookback" => "[Med Volume: Medium Lookback] Blended ACOS below target threshold",
        $data_quality = "Low Volume: Long Lookback" => "[Low Volume: Long Lookback] Blended ACOS below target threshold",
        $data_quality = "Very Low Volume: Extended Lookback" => "[Very Low Volume: Extended Lookback] Blended ACOS below target threshold",
        else "Blended ACOS below target threshold"
    ),
    $adjustment_percent < 0 => case(
        $data_quality = "High Volume: Short Lookback" => "[High Volume: Short Lookback] Blended ACOS above target threshold",
        $data_quality = "Med Volume: Medium Lookback" => "[Med Volume: Medium Lookback] Blended ACOS above target threshold",
        $data_quality = "Low Volume: Long Lookback" => "[Low Volume: Long Lookback] Blended ACOS above target threshold",
        $data_quality = "Very Low Volume: Extended Lookback" => "[Very Low Volume: Extended Lookback] Blended ACOS above target threshold",
        else "Blended ACOS above target threshold"
    ),
    else "Performance at target"
);
 
let $result = case(
    $within_buffer = 0 and $cooldown_ready = 1 and $target_bid != bid => case(
        $adjustment_percent >= $bid_max_change => "Bid Increase: Max",
        $adjustment_percent >= $bid_max_change * 0.5 => "Bid Increase: Upper Range", 
        $adjustment_percent > 0 => "Bid Increase: Lower Range",
        $adjustment_percent <= -1 * $bid_max_change => "Bid Decrease: Max",
        $adjustment_percent <= -1 * $bid_max_change * 0.5 => "Bid Decrease: Upper Range",
        $adjustment_percent < 0 => "Bid Decrease: Lower Range",
        else "No action needed"
    ),
    else "No action needed"
);
 
// === Final Filter ===
state = "effectively enabled"
and (campaign name contains any $include_campaigns)
and (campaign name does not contain any $exclude_campaigns)
and $within_buffer = 0
and $target_bid != bid
and $cooldown_ready = 1