Features
Adjusts bids based on proven historical CPC from the same seasonal period last year.
✓ Seasonal businesses preparing for upcoming high-demand periods (holidays, back-to-school, summer, etc.)
✓ Accounts with at least one year of advertising history to reference previous seasonal performance
✓ Keywords and targets that performed well last season (within 125% of Target ACOS with conversion history)
✓ Manual seasonal optimization sessions where you want to leverage historical success rather than current performance alone
Manual Execution: Change Bid: Set ($) using $suggested_seasonal_bid
This template sets bids based on historical CPC from the corresponding seasonal period one year ago, but only when that historical period showed acceptable ACOS performance. The core logic: if a keyword performed well at a certain CPC last season, it's likely to perform similarly at that CPC this season.
The historical window looks at a 45-day period starting exactly one year ago. For example, if you run this on January 15th, it examines January 15th through February 28th of last year. This forward-looking window captures not just the exact date match, but the seasonal trend that was building during that period.
Unlike simple year-over-year comparisons that only look at the exact same date, this template captures a 45-day forward window starting from one year ago. This approach recognizes that seasonal patterns build over time rather than appearing on a single date. If preparing for Valentine's Day on January 15th, you see not just January 15th last year, but the entire ramp-up period through late February.
Multiple requirements must be met before a bid adjustment is suggested:
This prevents adjusting bids based on insufficient data or poor historical performance.
Two independent caps protect against extreme changes:
Both caps are applied, with the most restrictive limit winning. This prevents the template from, for example, jumping a $0.50 bid to $3.00 even if that was the historical CPC.
The bid safety factor (default 100%) lets you apply a percentage adjustment to the historical CPC. Set to 95% to bid slightly below historical levels for added safety, or 105% to bid slightly above if you want to be more aggressive than last year.
The default 320d..365d setting (45-day window starting 1 year ago) works for most seasonal patterns. Consider adjusting based on your business:
Shorter windows provide more precise seasonal matching but require concentrated historical activity. Longer windows are more forgiving for keywords with sporadic conversion patterns.
The 125% default means historical ACOS ≤ 1.25 × Target ACOS qualifies:
Lower thresholds are safer but may exclude profitable keywords that ran slightly above target. Higher thresholds include more keywords but increase risk of replicating marginally profitable periods.
Percentage cap ($bid_max_change_pct): 50% default prevents doubling or halving bids in one adjustment. Increase to 75% for more aggressive seasonal adjustments, or decrease to 25-30% for more conservative changes.
Absolute maximum ($bid_absolute_max): $2.00 default should be set based on your business economics. Calculate as: Average Order Value × Target ACOS × Typical Conversion Rate × 2-3. This ensures the absolute cap is grounded in your profitability model rather than an arbitrary number.
Four properties show the historical data used for calculations:
Compare $calculated_bid_value to $suggested_seasonal_bid to see when safety caps activated.
Use these to identify keywords with dramatic suggested changes that may warrant manual review before applying.
When $calculated_bid_value is significantly higher than $suggested_seasonal_bid, the safety caps activated. This often indicates:
Review these manually - you may want to increase caps for specific high-value keywords or maintain current lower bids if current performance is acceptable.
Keywords showing "Insufficient historical orders" despite good historical ACOS are edge cases. They converted during that period but not enough times to be statistically reliable. Consider:
When current bid is $0.25 and suggested is $1.00+, review carefully. This pattern suggests:
Check current year-to-date performance before applying large increases to ensure the keyword is still relevant.
If few or no keywords qualify, common causes:
Adjust thresholds incrementally and review diagnostic properties to understand why keywords are being excluded.
/*
=== Seasonal Bid Tuner ===
Purpose: Set bids to historical CPC from the same seasonal period when ACOS performance was within safe limits.
Dataset: Keywords & Targets
Recommended: Change Bid → Set ($) using $suggested_seasonal_bid | Manual Execution
*/
// === Core Settings ===
let $min_orders = 5; // CORE: Minimum historical orders required for reliable data
let $acos_threshold = 200%; // CORE: Only use historical CPC if ACOS ≤ (Target ACOS × 125%) [e.g., 30% target = 37.5% threshold]
// === Strategy Settings ===
let $historical_period = 2024-11-29..2024-12-17; // STRATEGY: Historical evaluation period [1 year ago through 320 days ago - captures same season with forward context]
let $bid_safety_factor = 100%; // STRATEGY: Percentage of historical CPC to use [e.g., 95% = bid at 95% of historical CPC for safety margin]
// === Safeguards ===
let $bid_max_change_pct = 50%; // SAFEGUARD: Maximum bid change percentage [e.g., 50% = can increase/decrease by up to 50%]
let $bid_absolute_max = 2.00; // SAFEGUARD: Never set bids above this amount [$2.00 maximum]
let $protected_terms = ["test", "experiment"]; // SAFEGUARD: Never adjust keywords/targets containing these terms
// === Segment Filters ===
let $include_campaigns = [""]; // FILTER: Apply to all campaigns, or specify terms
let $exclude_campaigns = ["NEVER_MATCH"]; // FILTER: Exclude campaigns containing these terms
// ============================================================================
// === Segment Logic ===
// ============================================================================
// Advanced logic below - modify carefully
// === Historical Data ===
let $hist_orders = orders($historical_period);
let $hist_acos = acos($historical_period);
let $hist_cpc = cpc($historical_period);
// === Protection Check ===
let $protected_term_check = case(
campaign name contains any $protected_terms => 0,
else 1
);
// === Performance Qualification ===
let $performance_ok = case(
target acos <= 0 => 0, // No target set
$hist_orders < $min_orders => 0, // Insufficient orders
$hist_cpc <= 0 => 0, // No CPC data
$hist_acos <= target acos * $acos_threshold => 1, // Performance acceptable
else 0
);
// === Calculate Bid Change Limits ===
let $max_allowed_bid = bid * (1 + $bid_max_change_pct);
let $min_allowed_bid = bid * (1 - $bid_max_change_pct);
// === Suggested Bid Calculation with Safety Caps ===
let $calculated_seasonal_bid = $hist_cpc * $bid_safety_factor;
let $suggested_seasonal_bid = case(
$performance_ok = 0 => bid, // Keep current if not qualified
// Apply maximum change percentage cap
$calculated_seasonal_bid > $max_allowed_bid => $max_allowed_bid,
$calculated_seasonal_bid < $min_allowed_bid => $min_allowed_bid,
// Apply absolute maximum cap
$calculated_seasonal_bid > $bid_absolute_max => $bid_absolute_max,
// Otherwise use calculated seasonal bid
else $calculated_seasonal_bid
);
// === Diagnostic Properties ===
let $historical_cpc_value = $hist_cpc;
let $historical_acos_value = $hist_acos;
let $historical_orders_count = $hist_orders;
let $calculated_bid_value = $calculated_seasonal_bid;
let $bid_change_amount = $suggested_seasonal_bid - bid;
let $bid_change_percent = case(
bid > 0 => (($suggested_seasonal_bid - bid) / bid) * 100,
else 0
);
let $reason = case(
target acos <= 0 => "No target ACOS set - cannot evaluate performance",
$protected_term_check = 0 => "Protected term - excluded from adjustments",
$hist_orders < $min_orders => "Insufficient historical orders for reliable data",
$hist_cpc <= 0 => "No historical CPC data available",
$hist_acos > target acos * $acos_threshold => "Historical ACOS too high for safe adjustment",
$calculated_seasonal_bid > $bid_absolute_max => "Bid capped at absolute maximum",
$calculated_seasonal_bid > $max_allowed_bid => "Bid capped at maximum change percentage",
$calculated_seasonal_bid < $min_allowed_bid => "Bid capped at minimum change percentage",
$performance_ok = 1 => "Historical performance acceptable - bid set to seasonal CPC",
else "Insufficient data for adjustment"
);
let $result = case(
$protected_term_check = 0 => "No Action - Protected Term",
$performance_ok = 0 => "No Action - Historical Performance Insufficient",
$suggested_seasonal_bid = bid => "No Change - Already at Target",
$calculated_seasonal_bid > $bid_absolute_max => "Bid Set - Absolute Maximum Applied",
$calculated_seasonal_bid > $max_allowed_bid => "Bid Increase - Maximum Change Cap Applied",
$calculated_seasonal_bid < $min_allowed_bid => "Bid Decrease - Minimum Change Cap Applied",
$suggested_seasonal_bid > bid => "Bid Increase - Using Historical CPC",
$suggested_seasonal_bid < bid => "Bid Decrease - Using Historical CPC",
else "No Action"
);
// === Final Filter ===
state = "effectively enabled"
and (campaign name contains any $include_campaigns)
and (campaign name does not contain any $exclude_campaigns)
and $protected_term_check = 1
and $performance_ok = 1
and $suggested_seasonal_bid != bid
/*
=== Seasonal Bid Tuner ===
Purpose: Set bids to historical CPC from the same seasonal period when ACOS performance was within safe limits.
Dataset: Keywords & Targets
Recommended: Change Bid → Set ($) using $suggested_seasonal_bid | Manual Execution
*/
// === Core Settings ===
let $min_orders = 5; // CORE: Minimum historical orders required for reliable data
let $acos_threshold = 200%; // CORE: Only use historical CPC if ACOS ≤ (Target ACOS × 125%) [e.g., 30% target = 37.5% threshold]
// === Strategy Settings ===
let $historical_period = 2024-11-29..2024-12-17; // STRATEGY: Historical evaluation period [1 year ago through 320 days ago - captures same season with forward context]
let $bid_safety_factor = 100%; // STRATEGY: Percentage of historical CPC to use [e.g., 95% = bid at 95% of historical CPC for safety margin]
// === Safeguards ===
let $bid_max_change_pct = 50%; // SAFEGUARD: Maximum bid change percentage [e.g., 50% = can increase/decrease by up to 50%]
let $bid_absolute_max = 2.00; // SAFEGUARD: Never set bids above this amount [$2.00 maximum]
let $protected_terms = ["test", "experiment"]; // SAFEGUARD: Never adjust keywords/targets containing these terms
// === Segment Filters ===
let $include_campaigns = [""]; // FILTER: Apply to all campaigns, or specify terms
let $exclude_campaigns = ["NEVER_MATCH"]; // FILTER: Exclude campaigns containing these terms
// ============================================================================
// === Segment Logic ===
// ============================================================================
// Advanced logic below - modify carefully
// === Historical Data ===
let $hist_orders = orders($historical_period);
let $hist_acos = acos($historical_period);
let $hist_cpc = cpc($historical_period);
// === Protection Check ===
let $protected_term_check = case(
campaign name contains any $protected_terms => 0,
else 1
);
// === Performance Qualification ===
let $performance_ok = case(
target acos <= 0 => 0, // No target set
$hist_orders < $min_orders => 0, // Insufficient orders
$hist_cpc <= 0 => 0, // No CPC data
$hist_acos <= target acos * $acos_threshold => 1, // Performance acceptable
else 0
);
// === Calculate Bid Change Limits ===
let $max_allowed_bid = bid * (1 + $bid_max_change_pct);
let $min_allowed_bid = bid * (1 - $bid_max_change_pct);
// === Suggested Bid Calculation with Safety Caps ===
let $calculated_seasonal_bid = $hist_cpc * $bid_safety_factor;
let $suggested_seasonal_bid = case(
$performance_ok = 0 => bid, // Keep current if not qualified
// Apply maximum change percentage cap
$calculated_seasonal_bid > $max_allowed_bid => $max_allowed_bid,
$calculated_seasonal_bid < $min_allowed_bid => $min_allowed_bid,
// Apply absolute maximum cap
$calculated_seasonal_bid > $bid_absolute_max => $bid_absolute_max,
// Otherwise use calculated seasonal bid
else $calculated_seasonal_bid
);
// === Diagnostic Properties ===
let $historical_cpc_value = $hist_cpc;
let $historical_acos_value = $hist_acos;
let $historical_orders_count = $hist_orders;
let $calculated_bid_value = $calculated_seasonal_bid;
let $bid_change_amount = $suggested_seasonal_bid - bid;
let $bid_change_percent = case(
bid > 0 => (($suggested_seasonal_bid - bid) / bid) * 100,
else 0
);
let $reason = case(
target acos <= 0 => "No target ACOS set - cannot evaluate performance",
$protected_term_check = 0 => "Protected term - excluded from adjustments",
$hist_orders < $min_orders => "Insufficient historical orders for reliable data",
$hist_cpc <= 0 => "No historical CPC data available",
$hist_acos > target acos * $acos_threshold => "Historical ACOS too high for safe adjustment",
$calculated_seasonal_bid > $bid_absolute_max => "Bid capped at absolute maximum",
$calculated_seasonal_bid > $max_allowed_bid => "Bid capped at maximum change percentage",
$calculated_seasonal_bid < $min_allowed_bid => "Bid capped at minimum change percentage",
$performance_ok = 1 => "Historical performance acceptable - bid set to seasonal CPC",
else "Insufficient data for adjustment"
);
let $result = case(
$protected_term_check = 0 => "No Action - Protected Term",
$performance_ok = 0 => "No Action - Historical Performance Insufficient",
$suggested_seasonal_bid = bid => "No Change - Already at Target",
$calculated_seasonal_bid > $bid_absolute_max => "Bid Set - Absolute Maximum Applied",
$calculated_seasonal_bid > $max_allowed_bid => "Bid Increase - Maximum Change Cap Applied",
$calculated_seasonal_bid < $min_allowed_bid => "Bid Decrease - Minimum Change Cap Applied",
$suggested_seasonal_bid > bid => "Bid Increase - Using Historical CPC",
$suggested_seasonal_bid < bid => "Bid Decrease - Using Historical CPC",
else "No Action"
);
// === Final Filter ===
state = "effectively enabled"
and (campaign name contains any $include_campaigns)
and (campaign name does not contain any $exclude_campaigns)
and $protected_term_check = 1
and $performance_ok = 1
and $suggested_seasonal_bid != bid
© Merch Jar LLC