How to Add a Flash Sale Timer to WooCommerce Without Changing Prices?
Want to create limited-time offers in your WooCommerce store without actually changing product prices in the database? In this tutorial, we’ll show you how to set up dynamic flash sale pricing with a countdown timer—using a custom plugin that temporarily modifies product prices at runtime. No manual price updates needed!
What We’re Building
- A custom WooCommerce plugin that:
- Adds a price drop metabox to the product editor.
- Lets you enable a timed discount (e.g., 20% off for 60 minutes).
- Dynamically applies the discount without saving the new price to the database.
- Displays a live countdown timer on the product page.
- Automatically disables the price drop when the timer expires.
Why Use Dynamic Pricing?
- ✅ No need to edit actual prices.
- ✅ Perfect for flash sales or countdown offers.
- ✅ Doesn’t interfere with existing sale prices or scheduling.
Step 1: The Plugin Code
Create a new plugin file in your WordPress installation:
/wp-content/plugins/woocommerce-price-drop-timer/woocommerce-price-drop-timer.php
Paste the following code:
<?php
/**
* Plugin Name: WooCommerce Price Drop Timer
* Description: Adds a temporary price drop (like flash sale) with timer, no database price update needed.
* Version: 1.0.0
* Author: Kishore
*/
if (!defined('ABSPATH')) exit;
// 1. Metabox: Add price drop controls to product editor
add_action('add_meta_boxes', function () {
add_meta_box('wc_price_drop_timer', 'Price Drop Timer', function ($post) {
$enabled = get_post_meta($post->ID, '_pd_enabled', true);
$discount = get_post_meta($post->ID, '_pd_discount', true);
$duration = get_post_meta($post->ID, '_pd_duration', true);
echo '<label><input type="checkbox" name="pd_enabled" value="1" ' . checked($enabled, '1', false) . '> Enable Price Drop</label><br><br>';
echo '<label>Discount (%):<br><input type="number" name="pd_discount" value="' . esc_attr($discount) . '" min="1" max="100" style="width:100%"></label><br><br>';
echo '<label>Duration (minutes):<br><input type="number" name="pd_duration" value="' . esc_attr($duration) . '" min="1" style="width:100%"></label>';
wp_nonce_field('pd_save_meta', 'pd_nonce');
}, 'product', 'side');
});
// 2. Save fields
add_action('save_post_product', function ($post_id) {
if (!isset($_POST['pd_nonce']) || !wp_verify_nonce($_POST['pd_nonce'], 'pd_save_meta')) return;
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
$enabled = isset($_POST['pd_enabled']) ? '1' : '0';
$discount = isset($_POST['pd_discount']) ? intval($_POST['pd_discount']) : 0;
$duration = isset($_POST['pd_duration']) ? intval($_POST['pd_duration']) : 0;
update_post_meta($post_id, '_pd_enabled', $enabled);
update_post_meta($post_id, '_pd_discount', $discount);
update_post_meta($post_id, '_pd_duration', $duration);
if ($enabled === '1' && $discount > 0 && $duration > 0) {
update_post_meta($post_id, '_pd_start_time', time());
} else {
delete_post_meta($post_id, '_pd_start_time');
}
});
Step 2: Dynamically Discount the Price
This next section ensures the discounted price is applied in the frontend only—and only during the active time window:
// 3. Apply dynamic discount (runtime only)
add_filter('woocommerce_product_get_price', 'pd_apply_dynamic_discount', 20, 2);
add_filter('woocommerce_product_get_sale_price', 'pd_apply_dynamic_discount', 20, 2);
function pd_apply_dynamic_discount($price, $product) {
if (is_admin() || !$product instanceof WC_Product_Simple) return $price;
pd_maybe_cleanup_expired_price_drop($product);
$id = $product->get_id();
$enabled = get_post_meta($id, '_pd_enabled', true);
$discount = floatval(get_post_meta($id, '_pd_discount', true));
$duration = intval(get_post_meta($id, '_pd_duration', true));
$start = intval(get_post_meta($id, '_pd_start_time', true));
if ($enabled !== '1' || $discount <= 0 || $duration <= 0 || $start <= 0) return $price;
$now = time();
$end = $start + ($duration * 60);
if ($now >= $start && $now <= $end) {
$regular = floatval($product->get_regular_price());
if ($regular <= 0) return $price;
return round($regular * (1 - ($discount / 100)), 2);
}
return $price;
}
Step 3: Add Countdown Timer to Product Page
Add a visual countdown to build urgency:
// 4. Frontend timer
add_action('woocommerce_single_product_summary', 'pd_show_timer_on_product_page', 25);
function pd_show_timer_on_product_page() {
global $product;
if (!$product || !$product instanceof WC_Product_Simple) return;
$id = $product->get_id();
$enabled = get_post_meta($id, '_pd_enabled', true);
$discount = floatval(get_post_meta($id, '_pd_discount', true));
$duration = intval(get_post_meta($id, '_pd_duration', true));
$start = intval(get_post_meta($id, '_pd_start_time', true));
if ($enabled === '1' && $discount > 0 && $duration > 0 && $start > 0) {
$end = $start + ($duration * 60);
if (time() < $end) {
echo '<div id="pd-timer" data-end="' . esc_attr($end) . '" style="margin-top:20px;padding:10px;background:#f1f8e9;border-left:4px solid #689f38;font-weight:bold;"></div>';
echo '<script>
document.addEventListener("DOMContentLoaded",function(){
const el = document.getElementById("pd-timer");
const end = parseInt(el.dataset.end)*1000;
function tick(){
const now = Date.now();
const left = end - now;
if(left <= 0){
el.textContent = "Price drop ended.";
return;
}
const m = Math.floor(left/60000),
s = Math.floor((left%60000)/1000);
el.textContent = "🔥 Limited time offer! Ends in " + m + "m " + s + "s";
setTimeout(tick, 1000);
}
tick();
});
</script>';
}
}
}
Step 4: Auto Cleanup After Expiry
Automatically disable the price drop after the timer runs out:
// 5. Cleanup after expiry
function pd_maybe_cleanup_expired_price_drop($product) {
$id = $product->get_id();
$enabled = get_post_meta($id, '_pd_enabled', true);
$duration = intval(get_post_meta($id, '_pd_duration', true));
$start = intval(get_post_meta($id, '_pd_start_time', true));
if ($enabled === '1' && $duration > 0 && $start > 0) {
$now = time();
$end = $start + ($duration * 60);
if ($now > $end) {
update_post_meta($id, '_pd_enabled', '0');
delete_post_meta($id, '_pd_start_time');
}
}
}
Final Result
- ✅ Price drops only when enabled and during the specified time.
- ✅ No price stored in the database is modified.
- ✅ Visual timer creates urgency for customers.
Want More?
This is just the beginning. You could extend this plugin with:
- Product archive badge (e.g., “Flash Deal!”)
- Support for variable products
- Discount per user role or cart condition
- Admin dashboard countdown views
Wrap-up
With this simple plugin, you now have the power to run real-time flash sales in WooCommerce—without ever touching the actual product prices. It’s fast, non-intrusive, and great for conversions. You can download from here.
Need help turning this into a professional plugin? Let me know—I’d be happy to assist!
Leave a Reply