Countdown Timer ✅
A simple countdown timer for marketers, to manufacture urgency.
This is a personalized countdown timer that begins counting on each visitor's first visit. The timer persists across page loads and browser sessions using LocalStorage.
Features
Custom countdown timer, any duration. timer representation
100% designer-controlled styling, any element arrangement you want
Timer-expired state, e.g. hide the timer, show a different element set
Animation support- the ability to trigger custom code to handle custom animations as the timer updates
Debug support, so you can see what it's tracking and calculating

Demo
Use Cases
Currently this timer is designed for marketing purposes, so the start and end time are user-specific. The primary use case is;
Create urgency from first visit to purchase or other conversion action
If it's desired, I'll expand this to other variants, like "count to deadline", which could be used for;
Submission deadlines
Time-until-launch
Quick Start
Install the Sygnal Components lib from Sygnal Marketplace
Add the Countdown Timer component to your page
Set the
durationprop (e.g.,24hfor 24 hours, or3d 10mfor 3 days, 10 minutes)Slot in HTML elements with
countdown-remainingattributes for your countdown presentation. Build and customize this slotted component any way you like in the Webflow designer.The component automatically updates the text content, based on specific attributes;
Example slot content
Can be any HTML structure; the attributes determine where the component will update text during the countdown.
Properties
duration
Type: Text
Default: "24h"
Group: Settings
The countdown duration as a human-readable string. Supports years, months, days, hours, minutes, and seconds.
Format: Whitespace-separated parts, each with a number and unit character.
Years
y
Calculated as 365 days
Months
M
Uppercase, calculated as 30 days
Days
d
Hours
h
Minutes
m
Lowercase
Seconds
s
Examples:
24h— 24 hours2d 12h— 2 days and 12 hours1y 6M— 1 year and 6 months30m 30s— 30 minutes and 30 seconds1d 2h 30m 15s— 1 day, 2 hours, 30 minutes, 15 seconds
Notes:
Invalid parts are ignored
Duplicate units use the first occurrence only (e.g.,
1h 2h= 1 hour)Anomalous values are calculated correctly (e.g.,
36h= 1.5 days)
content
Type: Slot
Group: Content
The slot for your countdown display HTML. Place elements with countdown-remaining attributes inside this slot.
storageKey
Type: Text
Default: "countdown"
Group: Settings
The LocalStorage key prefix for this timer instance. Use different keys to create multiple independent countdown timers on the same site.
Example: If you have two offers with different countdowns:
Offer A:
storageKey="offer-a-countdown"Offer B:
storageKey="offer-b-countdown"
leadingZeros
Type: Boolean
Default: true
Group: Settings
When enabled, single-digit numbers are padded with a leading zero.
5
"05"
"5"
12
"12"
"12"
0
"00"
"0"
debugMode
Type: Boolean
Default: false
Group: Advanced
When enabled, displays a debug panel showing:
Storage key in use
Parsed duration in milliseconds
First visit timestamp
End time timestamp
Current remaining time
Expired status
Useful for testing and troubleshooting. Disable in production.
Slot Attributes
Add these attributes to elements in your slotted content. The component will find and update them automatically.
Time Values
countdown-remaining="days"
Days remaining (e.g., "05")
countdown-remaining="hours"
Hours remaining (e.g., "23")
countdown-remaining="minutes"
Minutes remaining (e.g., "59")
countdown-remaining="seconds"
Seconds remaining (e.g., "45")
Visibility Controls
countdown-remaining="active"
Visible while timer is running; hidden when expired
countdown-remaining="expired"
Hidden while timer is running; visible when expired
Example:
JavaScript Events
The component dispatches CustomEvents on the window object for animation integration and custom behaviors.
countdown:update
Fired every second with the complete timer state.
countdown:days
Fired when the days value changes.
countdown:hours
Fired when the hours value changes.
countdown:minutes
Fired when the minutes value changes.
countdown:seconds
Fired when the seconds value changes.
countdown:expired
Fired once when the timer expires.
Animation Example
Here's a complete example showing how to animate SVG progress rings using the countdown events:
How It Works
First Visit Detection
When a visitor first loads a page with the Countdown Timer:
The component checks LocalStorage for existing timer state
If none exists, it records the current timestamp as
firstVisitIt calculates
endTimeasfirstVisit + durationBoth values are saved to LocalStorage
Subsequent Visits
On return visits:
The component loads the saved
firstVisitandendTimeIt compares the current time to
endTimeThe countdown displays the remaining time (or expired state)
Duration Changes
If you change the duration prop after a timer has started:
The component detects the duration change
It recalculates
endTimefrom the originalfirstVisit+ new durationThe new end time is saved to LocalStorage
This means changing from 24h to 48h extends the timer from the original first visit, not from now.
Expiration
When the countdown reaches zero:
All time values display as
00Elements with
countdown-remaining="active"are hiddenElements with
countdown-remaining="expired"are shownThe
countdown:expiredevent fires onceThe timer stops (no more updates)
The expired state persists until LocalStorage is cleared
LocalStorage
The component stores timer state in LocalStorage using the storageKey prop as a prefix.
Key: {storageKey}_state
Value:
Clearing the Timer
To reset a timer (e.g., for testing), clear the LocalStorage entry:
Or for a custom storage key:
Browser Support
Works in all modern browsers that support:
LocalStorage
CustomEvent
Shadow DOM (handled by Webflow)
LocalStorage unavailable: Timer still works but resets on page refresh
Troubleshooting
Timer shows 00:00:00 immediately
Check if the timer has already expired (enable
debugMode)Clear LocalStorage and refresh to reset
Slotted elements not updating
Verify elements have the correct
countdown-remainingattributeCheck browser console for errors
Ensure the content is slotted into the
contentslot
Timer resets on every page load
LocalStorage may be blocked or unavailable
Check browser privacy settings
Verify the
storageKeyis consistent across pages
Animation not triggering
Verify event listener is attached to
windowCheck that event name matches exactly (e.g.,
countdown:update)Use
console.login the event handler to confirm events are firing
Best Practices
Use unique storage keys for different countdown timers to avoid conflicts
Test with debugMode enabled during development, then disable for production
Provide expired content using
countdown-remaining="expired"for good UXKeep duration realistic — extremely long durations (years) may cause precision issues
Consider time zones — the timer uses the visitor's local time via
Date.now()
Last updated
