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

The Code

Here's the complete snippet. Copy it, paste it into a new file in your Shopify theme, and you're done.

snippets/plynthr-announcement-countdown.liquid
{% 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

  1. In your Shopify admin, go to Online Store → Themes → Edit Code
  2. Under Snippets, click "Add a new snippet" and name it plynthr-announcement-countdown
  3. Paste the code above and hit Save
  4. Open layout/theme.liquid
  5. Find the <body> tag and add {%- render 'plynthr-announcement-countdown' -%} directly after it
  6. Update the targetDate in the script to your sale end date
  7. Update the announcement_text, announcement_link, and announcement_link_text variables to match your promotion
  8. 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:

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.