Urgency sells. A countdown timer in your announcement bar creates genuine FOMO — and when it's dismissible and well-designed, it doesn't annoy customers the way pop-ups do.
This tutorial adds a sleek announcement bar with a live countdown timer, a dismiss button that remembers the customer's preference, and fully customisable text and colours. No app, no monthly fee, no theme conflicts.
What You'll Build
- A fixed announcement bar at the top of every page
- A live countdown timer that ticks down to your target date
- A dismiss button that remembers the customer's choice via localStorage
- Customisable text, link, colours, and target date
- Clean design with pill-style countdown digits
The Code
Here's the complete snippet. Copy it, paste it into a new file in your Shopify theme, and you're done.
{% comment %}
Plynthr — Announcement Bar + Countdown
https://plynthr.com/snippets/announcement-bar-countdown/
INSTALL:
1. Create snippets/plynthr-announcement-countdown.liquid
2. Paste this code
3. Add {%- render 'plynthr-announcement-countdown' -%} at the top of
your theme.liquid, just after <body>
CUSTOMIZE:
- --pac-bg for background color
- --pac-color for text color
- Set your target date in the script below
{% endcomment %}
<style>
:root {
--pac-bg: #1a1a1a;
--pac-color: #ffffff;
--pac-font-size: 14px;
--pac-height: 44px;
--pac-link-color: #fbbf24;
}
.plynthr-announcement {
background: var(--pac-bg);
color: var(--pac-color);
font-size: var(--pac-font-size);
height: var(--pac-height);
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
position: relative;
z-index: 100;
text-align: center;
padding: 0 40px;
}
.plynthr-announcement.is-hidden { display: none; }
.plynthr-announcement a {
color: var(--pac-link-color);
text-decoration: underline;
text-underline-offset: 2px;
font-weight: 600;
}
.plynthr-announcement__countdown {
display: inline-flex;
gap: 6px;
font-weight: 700;
font-variant-numeric: tabular-nums;
}
.plynthr-announcement__countdown span {
background: rgba(255,255,255,0.15);
padding: 2px 6px;
border-radius: 4px;
font-size: 12px;
}
.plynthr-announcement__close {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
color: var(--pac-color);
cursor: pointer;
opacity: 0.6;
transition: opacity 0.2s;
padding: 4px;
line-height: 1;
}
.plynthr-announcement__close:hover { opacity: 1; }
</style>
{%- assign announcement_text = "Sale ends soon!" -%}
{%- assign announcement_link = "/collections/sale" -%}
{%- assign announcement_link_text = "Shop now" -%}
<div class="plynthr-announcement" id="plynthr-announcement">
<span>{{ announcement_text }}</span>
<span class="plynthr-announcement__countdown" id="plynthr-countdown"></span>
<a href="{{ announcement_link }}">{{ announcement_link_text }}</a>
<button class="plynthr-announcement__close" aria-label="Dismiss">✕</button>
</div>
<script>
(() => {
const bar = document.getElementById('plynthr-announcement');
const countdown = document.getElementById('plynthr-countdown');
const closeBtn = bar?.querySelector('.plynthr-announcement__close');
const STORAGE_KEY = 'plynthr_announcement_dismissed';
/* SET YOUR TARGET DATE HERE */
const targetDate = new Date('2026-03-31T23:59:59');
if (!bar) return;
if (localStorage.getItem(STORAGE_KEY) === 'true') {
bar.classList.add('is-hidden');
return;
}
closeBtn?.addEventListener('click', () => {
bar.classList.add('is-hidden');
localStorage.setItem(STORAGE_KEY, 'true');
});
function updateCountdown() {
const now = new Date();
const diff = targetDate - now;
if (diff <= 0) { countdown.textContent = 'Ended'; return; }
const d = Math.floor(diff / 86400000);
const h = Math.floor((diff % 86400000) / 3600000);
const m = Math.floor((diff % 3600000) / 60000);
const s = Math.floor((diff % 60000) / 1000);
countdown.innerHTML =
(d > 0 ? '<span>' + d + 'd</span>' : '') +
'<span>' + h + 'h</span>' +
'<span>' + m + 'm</span>' +
'<span>' + s + 's</span>';
}
updateCountdown();
setInterval(updateCountdown, 1000);
})();
</script>
You can also grab this from the snippet page on Plynthr.
Installation
- In your Shopify admin, go to Online Store → Themes → Edit Code
- Under Snippets, click "Add a new snippet" and name it
plynthr-announcement-countdown - Paste the code above and hit Save
- Open
layout/theme.liquid - Find the
<body>tag and add{%- render 'plynthr-announcement-countdown' -%}directly after it - Update the
targetDatein the script to your sale end date - Update the
announcement_text,announcement_link, andannouncement_link_textvariables to match your promotion - Save and preview your store
Customisation
All the visual properties are controlled by CSS custom properties (variables) in the :root block. Here's what you can change:
--pac-bg— Bar background colour (default: #1a1a1a, a dark grey)--pac-color— Text colour (default: white)--pac-link-color— CTA link colour (default: #fbbf24, amber)--pac-height— Bar height (default: 44px)--pac-font-size— Text size (default: 14px)targetDate— Your countdown end date in the JavaScript (ISO 8601 format)STORAGE_KEY— Change this if you want to reset dismissals for a new campaign
Troubleshooting
Bar appears behind the nav: Increase the z-index value in the .plynthr-announcement CSS, or add position: relative if it's being overlapped.
Countdown shows "Ended" immediately: Check your targetDate — make sure it's set to a future date and the format is correct: new Date('2026-03-31T23:59:59').
Dismiss button doesn't persist: The snippet uses localStorage to remember dismissals. If you're testing in incognito mode, localStorage is cleared when the window closes. In normal browsing, it persists until the customer clears their browser data.
Want to reset dismissals for a new sale: Change the STORAGE_KEY value to something unique for each campaign, like 'plynthr_summer_sale_2026'. This forces the bar to reappear for everyone.
Want this done for you?
I'll install this on your Shopify store, test it across devices, and make sure it's working perfectly. Done within 24 hours.