Want to add a sleek countdown timer to your WooCommerce product sales? You’re in the right place! Today, I’ll show you how to add a professional-looking countdown timer that shows your customers exactly how long they have until a sale ends. The best part? It works for simple and tricky variable products with different variations.
What Does This Code Do?
Let me break it down in simple terms:
- Creates a countdown timer that shows days, hours, minutes, and seconds
- Automatically appears when a product is on sale
- Disappears when the sale ends
- Works with both regular products and products with variations
- Looks clean and professional with minimal styling
What You’ll See?
Once activated, you’ll see a nice countdown timer appear automatically on any product that’s on sale with an end date set. The timer shows:
- Days remaining
- Hours
- Minutes
- Seconds
The timer updates in real-time, and when the sale ends, the timer is hidden automatically.
See the screenshot here below.
How to Add the Code to Your Site?
There are two ways to add this code to your WordPress site:
- Adding it to your child theme’s functions.php file
- Using the Code Snippets plugin (my recommended method!)
Why I Recommend Code Snippets Plugin
Here’s why Code Snippets is the way to go:
- Safer: If you make a mistake, it won’t break your entire site
- Theme Independent: Your code stays active even if you change themes
- Organized: Each piece of code is separate and easy to manage
- Easy to Disable: Just click a button to turn features on/off
- No FTP Required: Everything happens right in your WordPress dashboard
When you add code directly to functions.php, it’s tied to your theme. Switch themes? Poof! Your code is gone. Plus, one tiny typo could make your whole site go blank – yikes!
Video: How to Add a Sale Countdown Timer to Your WooCommerce Products Page?
Installation Steps
1. First, install the “Code Snippets” plugin:
- Go to Plugins → Add New in your WordPress dashboard
- Search for “Code Snippets”
- Click “Install Now” then “Activate”
2. Add the PHP code:
- Go to Snippets → Add New
- Give it a title like “WooCommerce Sale Countdown”
- Copy and paste the PHP code (see here below) into the editor
- Check “Only run in frontend area” is CHECKED
- Click “Save Changes and Activate”
// Add sale end date to variation data and pass it via wp_localize_script
add_action('woocommerce_single_product_summary', 'custom_sale_end_timer', 25);
function custom_sale_end_timer() {
global $product;
// Pre-fetch sale dates for variations if it's a variable product
if( $product->is_type('variable') ) {
$sale_dates = array();
$variation_ids = $product->get_visible_children(); // Get visible variation IDs
foreach( $variation_ids as $variation_id ) {
$variation = wc_get_product( $variation_id );
if( $variation->is_on_sale() ) {
$date_on_sale_from = $variation->get_date_on_sale_from();
$date_on_sale_to = $variation->get_date_on_sale_to();
if( ! empty($date_on_sale_from) || ! empty($date_on_sale_to) ) {
$sale_dates[$variation_id] = array(
'from' => $date_on_sale_from ? $date_on_sale_from->getTimestamp() : '',
'to' => $date_on_sale_to ? $date_on_sale_to->getTimestamp() : '',
);
}
}
}
// Pass the sale dates to the frontend JavaScript
wc_enqueue_js( "
var variationSaleDates = " . json_encode($sale_dates) . ";
var countdownInterval = null;
jQuery(document).ready(function($) {
// Function to update the countdown timer
function updateCountdown(saleEndDate) {
var now = new Date().getTime();
var timeLeft = (saleEndDate - now) / 1000;
var days = Math.floor(timeLeft / 86400);
var hours = Math.floor((timeLeft % 86400) / 3600);
var minutes = Math.floor((timeLeft % 3600) / 60);
var seconds = Math.floor(timeLeft % 60);
if (timeLeft > 0) {
$('.custom-sale-countdown .days .value').text(days.toString().padStart(2, '0'));
$('.custom-sale-countdown .hours .value').text(hours.toString().padStart(2, '0'));
$('.custom-sale-countdown .mins .value').text(minutes.toString().padStart(2, '0'));
$('.custom-sale-countdown .secs .value').text(seconds.toString().padStart(2, '0'));
} else {
$('.custom-sale-countdown .countdown').text('Sale Ended');
clearInterval(countdownInterval); // Clear interval when sale ends
}
}
// Clear any previous countdown interval
function clearPreviousCountdown() {
if (countdownInterval) {
clearInterval(countdownInterval);
countdownInterval = null;
}
}
// Handle variable product variation selection
$('form.variations_form').on('found_variation', function(event, variation) {
var variationId = variation.variation_id;
// Check if the selected variation has a sale date
if (variationSaleDates[variationId] && variationSaleDates[variationId].to) {
var saleEndDate = new Date(variationSaleDates[variationId].to * 1000);
// Clear any existing interval to prevent multiple countdowns
clearPreviousCountdown();
// Immediately update countdown once
updateCountdown(saleEndDate);
// Update countdown every second
countdownInterval = setInterval(function() {
updateCountdown(saleEndDate);
}, 1000);
// Show countdown if hidden
$('.custom-sale-countdown').show();
} else {
// Hide countdown if no sale
clearPreviousCountdown();
$('.custom-sale-countdown').hide();
}
});
});
");
// Display countdown HTML structure, hidden initially
echo '<div class="custom-sale-countdown" style="display: none;">
<h3>Sale ends in</h3>
<div class="countdown">
<span class="days">
<span class="value">00</span>
<span class="countdown-label">Days</span>
</span>
:
<span class="hours">
<span class="value">00</span>
<span class="countdown-label">Hours</span>
</span>
:
<span class="mins">
<span class="value">00</span>
<span class="countdown-label">Min</span>
</span>
:
<span class="secs">
<span class="value">00</span>
<span class="countdown-label">Sec</span>
</span>
</div>
</div>';
}
// Handle simple products
if ($product->is_on_sale() && $product->get_date_on_sale_to()) {
$sale_end_date = $product->get_date_on_sale_to()->getTimestamp();
wc_enqueue_js( "
jQuery(document).ready(function($) {
var saleEndDate = new Date($sale_end_date * 1000);
function updateCountdown() {
var now = new Date().getTime();
var timeLeft = (saleEndDate - now) / 1000;
var days = Math.floor(timeLeft / 86400);
var hours = Math.floor((timeLeft % 86400) / 3600);
var minutes = Math.floor((timeLeft % 3600) / 60);
var seconds = Math.floor(timeLeft % 60);
if (timeLeft > 0) {
$('.custom-sale-countdown .days .value').text(days.toString().padStart(2, '0'));
$('.custom-sale-countdown .hours .value').text(hours.toString().padStart(2, '0'));
$('.custom-sale-countdown .mins .value').text(minutes.toString().padStart(2, '0'));
$('.custom-sale-countdown .secs .value').text(seconds.toString().padStart(2, '0'));
} else {
$('.custom-sale-countdown .countdown').text('Sale Ended');
clearInterval(countdownInterval); // Clear interval when sale ends
}
}
// Immediately update countdown once
updateCountdown();
// Update countdown every second
var countdownInterval = setInterval(updateCountdown, 1000);
});
");
// Display countdown HTML structure for simple products
echo '<div class="custom-sale-countdown">
<h3>Sale ends in</h3>
<div class="countdown">
<span class="days">
<span class="value">00</span>
<span class="countdown-label">Days</span>
</span>
:
<span class="hours">
<span class="value">00</span>
<span class="countdown-label">Hours</span>
</span>
:
<span class="mins">
<span class="value">00</span>
<span class="countdown-label">Min</span>
</span>
:
<span class="secs">
<span class="value">00</span>
<span class="countdown-label">Sec</span>
</span>
</div>
</div>';
}
}
3. Add the CSS:
- Go to Snippets → Add New again
- Create a new snippet called “WooCommerce Sale Countdown CSS”
- Paste the CSS code (the styling part)
- Change the snippet type to “CSS”
- Save and activate
.custom-sale-countdown {
text-align: left;
margin-bottom: 20px;
font-weight: bold;
color: #333;
}
.custom-sale-countdown h3 {
font-size: 18px;
margin-bottom: 10px;
}
.custom-sale-countdown .countdown {
display: flex;
justify-content: flex-start;
gap: 10px;
font-size: 32px;
letter-spacing: 2px;
}
.custom-sale-countdown .countdown span {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 5px 10px;
background-color: #f8f9fa;
border-radius: 5px;
color: #000;
font-size: 24px;
border: none; /* Remove the border */
}
.custom-sale-countdown .countdown span .countdown-label {
font-size: 12px; /* Smaller label size */
font-weight: normal;
text-transform: uppercase;
color: #666;
margin-top: -15px;
}
Setting Up Sale End Dates
Don’t forget to set your sale end dates in WooCommerce:
- Edit your product
- Set the sale price
- Click the calendar icon next to the sale price
- Choose when you want the sale to end
For variable products, you’ll need to set the sale end date for each variation separately.
The Alternative Method: Using functions.php (Not Recommended)
While I strongly recommend using Code Snippets, I know some of you might want to know how to add this code to your functions.php file. So, let’s talk about it – but first, some important warnings!
What’s a Child Theme and Why It’s Important
Before thinking about editing functions.php, let’s talk about child themes. A child theme is like a safe playground for your customizations. Here’s why you need one:
- Never edit your main theme directly: It’s like writing in permanent marker – when the theme updates, all your changes will be erased!
- Your main theme needs updates: Theme updates often include security fixes and new features. If you modify the main theme, you can’t update without losing your changes.
- Protection for your customizations: A child theme keeps your custom code separate and safe.
Think of it this way: Your main theme is like a rental apartment, and a child theme is like putting up removable wallpaper instead of painting the walls. When you move out (change themes), you can take your wallpaper (customizations) with you!
How to Add Code to functions.php
If you still want to go this route (remember, Code Snippets is safer!), here’s how:
1. Create a Child Theme (if you haven’t already):
- Create a new folder in wp-content/themes/
- Name it yourtheme-child (replace “yourtheme” with your actual theme name)
- Create a style.css file with the proper theme headers
- Create a functions.php file
2. Add the Code:
- Open your child theme’s functions.php file
- Paste the PHP code at the bottom of the file
- Save the file
3. Add the CSS:
- Add the CSS code to your child theme’s style.css file
- Or use your theme’s custom CSS section in the customizer
The Big Warning: Theme Changes
Here’s what happens when you change themes while using functions.php:
- All Your Code Disappears: When you switch themes, your countdown timer will stop working immediately.
- Manual Transfer Required: You’ll need to copy all your code to your new theme’s child theme.
- Potential Conflicts: Your code might not work the same way with the new theme.
- Risk of Errors: If you forget to transfer any part of the code, features might break.
It’s like moving houses and having to reinstall all your light fixtures every time – not fun!
Why Code Snippets is Better (One More Time!)
Let me give you one final comparison:
functions.php Method:
- ❌ Code disappears when changing themes
- ❌ Need to create and manage child theme
- ❌ Risk of breaking your site
- ❌ Harder to disable if something goes wrong
- ❌ Need FTP or file manager access
- ❌ Must copy/paste code when changing themes
Code Snippets Plugin:
- ✅ Code stays active with any theme
- ✅ No child theme needed
- ✅ Safe and easy to manage
- ✅ One-click disable if needed
- ✅ No file editing required
- ✅ Works right from your dashboard
Conclusion
While both methods will get the job done, using Code Snippets is like having a safety net while walking a tightrope. Sure, you could do it without one, but why take the risk?
Plus, if you ever need to hand over the site to someone else or make quick changes, Code Snippets makes everything so much easier to manage. Trust me, your future self will thank you for choosing the safer, more flexible option!
Need help setting up a child theme or have questions about Code Snippets? Drop a comment below, and I’ll be happy to help! 🤗
Need Help?
If something’s not working quite right:
- Double-check that both snippets are activated
- Make sure you’ve set sale end dates for your products
- Clear your website’s cache if you don’t see the changes immediately
Happy selling!