How to Create a Flash Sale Countdown Timer Plugin for Your Online Store
A countdown timer can give an online promotion a clear end point and help shoppers understand how long a special price will remain available. For an Australian online store, it can be useful during end-of-financial-year promotions, Boxing Day campaigns, product launches, and short weekend offers.
This guide explains how to create a lightweight WordPress plugin for a WooCommerce store. The plugin will display a live countdown, show the sale price, and add a link to the product page. The timer will improve the shopping experience, but the actual sale expiry must always be controlled by WooCommerce on the server.
Plan the sale before writing code
Start by deciding what the timer represents. It may count down to the end of a product discount, the closing time for a collection-wide promotion, or the end of a limited launch offer. Keeping this rule clear prevents customers from seeing a timer that expires while the advertised price remains active.
For a WooCommerce product, set the regular price, sale price, and sale end date in the product editor. The plugin should display information already configured in WooCommerce rather than changing the price through JavaScript. Browser code can be manipulated, and a customer may have an inaccurate computer clock.
Time zones need careful handling in Australia. Sydney and Melbourne switch between AEST and AEDT during the year, while Brisbane stays on AEST. Use the WordPress website time zone and send the countdown an ISO 8601 date with its correct offset, such as +10:00 or +11:00. This avoids an offer ending at the wrong local time.
A mobile-first design is important because many shoppers browse during a commute, lunch break, or evening session on a phone. Keep the message short, make the remaining time easy to scan, and avoid placing the timer over the product image or checkout button.
Create the WordPress plugin foundation
Create a folder named flash-sale-countdown inside wp-content/plugins/. Add a file named flash-sale-countdown.php, then place the following code inside it. This example creates a shortcode called [flash_sale] and loads the front-end assets only when the shortcode is used.
<?php
/**
* Plugin Name: Flash Sale Countdown
* Description: Displays a WooCommerce flash sale countdown.
* Version: 1.0.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
function fsc_register_assets() {
wp_register_style(
'fsc-style',
plugins_url( 'assets/flash-sale.css', __FILE__ ),
array(),
'1.0.0'
);
wp_register_script(
'fsc-script',
plugins_url( 'assets/flash-sale.js', __FILE__ ),
array(),
'1.0.0',
true
);
}
add_action( 'wp_enqueue_scripts', 'fsc_register_assets' );
function fsc_countdown_shortcode( $atts ) {
if ( ! function_exists( 'wc_get_product' ) ) {
return '';
}
$atts = shortcode_atts(
array(
'product_id' => 0,
'end' => '',
'label' => 'Sale ends in',
),
$atts,
'flash_sale'
);
$product_id = absint( $atts['product_id'] );
$end_time = sanitize_text_field( $atts['end'] );
$timestamp = strtotime( $end_time );
$product = wc_get_product( $product_id );
if ( ! $product || ! $timestamp ) {
return '';
}
wp_enqueue_style( 'fsc-style' );
wp_enqueue_script( 'fsc-script' );
$data_end = gmdate( 'c', $timestamp );
ob_start();
?>
<section class="fsc-box" data-end="<?php echo esc_attr( $data_end ); ?>">
<p class="fsc-label"><?php echo esc_html( $atts['label'] ); ?></p>
<div class="fsc-timer" aria-live="polite">
<span><strong data-unit="days">00</strong><small>Days</small></span>
<span><strong data-unit="hours">00</strong><small>Hours</small></span>
<span><strong data-unit="minutes">00</strong><small>Minutes</small></span>
<span><strong data-unit="seconds">00</strong><small>Seconds</small></span>
</div>
<p class="fsc-price">
<?php echo wp_kses_post( $product->get_price_html() ); ?>
</p>
<a class="fsc-button" href="<?php echo esc_url( get_permalink( $product_id ) ); ?>">
Shop the offer
</a>
<p class="fsc-expired" hidden>This offer has ended.</p>
</section>
<?php
return ob_get_clean();
}
add_shortcode( 'flash_sale', 'fsc_countdown_shortcode' );
The plugin checks that WooCommerce is active and that the product exists before printing anything. It also escapes the product link, sale label, and date value. These small precautions matter when shortcode attributes are entered by administrators or reused across several pages.
Create an assets folder inside the plugin directory. Add flash-sale.css and flash-sale.js to that folder. You can later add an administration page, but a shortcode is a practical first version because it gives store owners control over where the promotion appears.
Add the live countdown display
Place this JavaScript in assets/flash-sale.js. It reads the expiry date from the section’s data-end attribute and updates the four time units every second.
document.addEventListener('DOMContentLoaded', function () {
document.querySelectorAll('.fsc-box').forEach(function (box) {
const end = Date.parse(box.dataset.end);
const expiredMessage = box.querySelector('.fsc-expired');
const timer = box.querySelector('.fsc-timer');
const button = box.querySelector('.fsc-button');
function updateTimer() {
const remaining = end - Date.now();
if (remaining <= 0) {
timer.hidden = true;
button.hidden = true;
expiredMessage.hidden = false;
return;
}
const seconds = Math.floor(remaining / 1000);
const days = Math.floor(seconds / 86400);
const hours = Math.floor((seconds % 86400) / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const secs = seconds % 60;
box.querySelector('[data-unit="days"]').textContent =
String(days).padStart(2, '0');
box.querySelector('[data-unit="hours"]').textContent =
String(hours).padStart(2, '0');
box.querySelector('[data-unit="minutes"]').textContent =
String(minutes).padStart(2, '0');
box.querySelector('[data-unit="seconds"]').textContent =
String(secs).padStart(2, '0');
}
updateTimer();
setInterval(updateTimer, 1000);
});
});
Add basic styling to assets/flash-sale.css. The layout uses flexible columns so it remains readable on smaller screens.
.fsc-box {
max-width: 520px;
margin: 24px auto;
padding: 20px;
text-align: center;
border: 1px solid #e5e5e5;
border-radius: 8px;
background: #fff8f0;
}
.fsc-label {
margin: 0 0 12px;
font-weight: 600;
}
.fsc-timer {
display: flex;
justify-content: center;
gap: 10px;
}
.fsc-timer span {
min-width: 58px;
padding: 8px 4px;
border-radius: 5px;
background: #202020;
color: #fff;
}
.fsc-timer strong,
.fsc-timer small {
display: block;
}
.fsc-timer strong {
font-size: 1.25rem;
}
.fsc-timer small {
font-size: .7rem;
}
.fsc-price {
margin: 16px 0;
font-size: 1.2rem;
}
.fsc-button {
display: inline-block;
padding: 10px 18px;
border-radius: 4px;
background: #c62828;
color: #fff;
text-decoration: none;
}
The aria-live="polite" attribute allows assistive technology to receive updates without interrupting the shopper. Avoid aggressive flashing effects, loud alerts, or rapidly changing visual elements. A countdown should provide useful information rather than create an accessibility problem.
Add the shortcode to a WooCommerce offer
Activate the plugin from Plugins in the WordPress dashboard. Open the product you want to promote and confirm that its sale price and scheduled end date are correct. Then add the shortcode to a product description, landing page, promotional page, or block area.
For example:
[flash_sale product_id="123" end="2026-06-30T23:59:59+10:00" label="EOFY offer ends in"]
Replace 123 with the WooCommerce product ID. The date should match the intended local time. For a Sydney promotion during daylight saving, use the correct AEDT offset instead of assuming that every date uses AEST. WordPress’s configured time zone should also be checked under Settings > General.
The product price shown by the shortcode comes from WooCommerce’s price HTML. This means the sale price, currency formatting, tax display settings, and strike-through regular price can follow the store’s existing configuration. Australian customers generally expect the total payable price to be clear, including required charges such as GST where applicable.
A timer should support an honest offer rather than manufacture pressure. Under Australian Consumer Law, businesses must not make false or misleading claims about discounts, stock levels, or the length of a promotion. If the same product will remain at the same price after the countdown, the message should not imply that the deal is permanently disappearing.
Secure, test, and improve the plugin
Test the timer while logged out and on several devices. Check Chrome, Safari, Firefox, Android, and iPhone browsers, then test narrow screens around 320 to 390 pixels wide. Confirm that long product names, different currency formats, and translated labels do not break the layout.
Test the expired state by setting an end date a few minutes in the past. The timer should disappear, the expired message should appear, and the product should no longer be presented as part of an active flash sale. Most importantly, confirm that WooCommerce has also stopped applying the sale price. The JavaScript display is only a visual layer.
Run a page-speed test after installation. Loading the CSS and JavaScript only when the shortcode appears keeps unrelated pages lighter. Avoid adding a large animation library for a simple timer. If the store uses caching, clear the page cache after changing the end date, or shoppers may receive an old HTML timestamp.
For stores operating across Australian cities, use one clearly stated campaign time rather than relying on each visitor’s device clock. A customer in Perth should be able to see when a promotion ends in the store’s advertised time zone. Add the time zone to campaign emails and banners, and remember that promotional emails must also comply with Australia’s Spam Act, including consent and unsubscribe requirements.
Once the basic plugin works, useful additions can include an admin settings page, reusable campaign IDs, an optional stock message, translation support, and analytics events for timer views and product clicks. If analytics or marketing cookies are added, review the store’s privacy notice and ensure the tracking setup matches the Privacy Act obligations that apply to the business.
Upload the plugin files through WordPress, activate the extension, configure a real WooCommerce sale, and publish the shortcode on a campaign page. A simple, accurate countdown can make EOFY, Boxing Day, and short product promotions easier to understand while keeping the purchasing experience fast and transparent.