How to Add a Countdown Timer to Webflow
One Footer code field, one Code Embed, and a date the browser can actually read.
A countdown is a display embed and nothing else: no sign-in, no moderation queue, no thread id, and not one row written anywhere. That is why this install is genuinely shorter than the Webflow comment widget one on the same platform, where a thread id has to stay stable for the life of the post. Here you paste the BootSignal loader into Site settings, Custom code, Footer code, then drop a Code Embed where the clock belongs and put <div data-bootsignal="countdown" data-target="2026-12-31T23:59:59"></div> in it. One caveat belongs at the top rather than in the FAQ: custom code is a paid Webflow feature, so a site on the free Starter plan cannot do this at all. After that, the part left to get right is the timestamp, not the plumbing.
Custom code is a paid Webflow feature
Webflow opens both relevant help articles with the same requirement. If you have a Core, Growth, Agency or Freelancer Workspace, or if your site has an active Site plan, then Site managers and Designers can add custom code and scripts. The Code Embed element carries that identical sentence. On the pricing comparison table the Custom code row is marked as not included in the free Starter site plan and the free Starter Workspace, and included from the Basic site plan and the Core Workspace upward.
So there are two ways to unlock it: a paid Site plan on the one site you are launching, or a paid Workspace that covers everything you build. Neither is a BootSignal charge, and there is no free path to try this on a Starter site, because the fields are not dimmed, they are absent.
Watch one run before you paste anything
Counts down to your date · then shows your message
A clock that really is counting down as you read. The loader that powers it on your own site is the line you are about to paste into Webflow.
It renders inside a shadow root, which matters more on Webflow than on a hand-built site. Your global styles cannot cascade in and restyle the digits, and the widget cannot leak its CSS into your layout. It reads the background behind it and picks a light or dark palette to match, and data-accent takes any CSS color if you want the numbers in your brand color.
The loader goes in Footer code, the clock goes in a Code Embed
Staging first: an unregistered hostname draws nothing at all
Webflow publishes to two kinds of target and lists them separately in the Publish dialog: the
your-project.webflow.iostaging address every project is given on the day it is created, and any custom domain you have connected. The countdown readslocation.hostnamebefore it draws a digit and stops there if that hostname is not registered, so whichever target you publish to is the one that has to be in the dashboard first. Begin with the staging address, because a timer is the widget you most want to watch run for a minute before a customer does, and add the live hostname when the domain goes up. Saving a domain produces a site id, one short string that serves every widget on the site, and step 2 is where it goes.Paste the loader into Site settings
Go to Site settings, open the Custom code tab, put the loader in the Footer code section, and click Save changes. Webflow recommends script tags there, just before the closing body tag, for load speed. This is the only script the install needs: everything the countdown does is set on the element in the next step, in attributes.
<script src="https://bootsignal.com/bootsignal.js" data-site-id="YOUR_SITE_ID" data-lang="en" defer></script>Drop a Code Embed where the clock should sit
Open the Add panel, drag a Code Embed onto the canvas at the exact spot you want the timer, paste the mount element, then save and close the modal. Double-click the element later to reopen it. This is also the moment to decide what the page will say when the clock runs out.
<div data-bootsignal="countdown" data-target="2026-12-31T23:59:59" data-expired="The sale has ended!"></div>Publish, then check on the published URL
Webflow says the effects of custom code appear in preview mode, but the page you are previewing is served from a Webflow URL rather than the domain you registered, so the timer will not draw there. Publish to staging or to the live domain and open that address instead.
Write a target that ends when you mean it
This is the part that gets shipped wrong. data-target is read by the browser date parser, which has one rule people rarely expect: a timestamp with no zone on the end is the time on the visitor clock, not on yours. Written the plain way, a New Year countdown hits zero at 23:59:59 in Seoul, then again nine hours later in London.
<!-- Local: 23:59:59 on whatever clock the visitor is using -->
<div data-bootsignal="countdown" data-target="2026-12-31T23:59:59"></div>
<!-- Fixed: one instant for everyone, written in UTC -->
<div data-bootsignal="countdown" data-target="2026-12-31T23:59:59Z"></div>
<!-- Fixed: the same instant as the line above, written in Seoul time -->
<div data-bootsignal="countdown" data-target="2027-01-01T08:59:59+09:00"></div>Pick by what the deadline actually means. A shop that closes at midnight wherever the shopper happens to live wants the local form. A product launch, a ticket drop or a webinar that everyone should watch hit zero together wants an explicit zone. Offsets beat zone names here because they survive daylight saving: write the offset that is in force on the target date, not the one in force today.
Two smaller traps. A bare date such as 2026-12-31 is not the local-midnight shortcut it looks like: with no time on it the parser treats it as UTC midnight, which lands mid-afternoon or the previous evening depending where your visitor is. And the number counts down against the device clock, so a visitor whose laptop is set two days fast sees a shorter countdown. No client-side timer can fix that one.
Nothing vanishes at zero
When the target passes, the digits are replaced in place by the text in data-expired. The element keeps its box, so the page does not reflow around a hole where a clock used to be. Leave the attribute off and the widget falls back to its own message in whatever language data-lang is set to.
Since that message stays until someone edits the page, write one that is still true next week. "Registration for the spring cohort is closed. The next one opens in March." reads better a month later than "Hurry, ends tonight!" frozen in place. There is one more behavior worth knowing before you debug the wrong thing: if the browser cannot parse data-target at all, the widget shows the expired message immediately, on load. A brand new timer that displays your ending line the moment you publish has a malformed timestamp, not a date in the past.
Every attribute the countdown reads
| Attribute | Required | What it does |
|---|---|---|
| data-bootsignal="countdown" | Yes | Marks the element as the mount point the loader fills. |
| data-target | Yes | The ISO timestamp being counted to. No zone suffix means visitor local time. |
| data-expired | No | Text shown in place of the digits after the target passes. Falls back to a built-in message. |
| data-lang | No | Unit labels. Widget text across the catalog is Korean, English and Japanese; the countdown is one of the few that also carries Chinese, so zh-cn and zh-tw work here. Inherits the loader language if omitted. |
| data-theme | No | light or dark. Left off, the widget reads the background behind it and follows the page. |
| data-accent | No | Any CSS color for the digits, so the clock matches your Webflow palette. |
| data-thread-id | Not used | The countdown stores nothing, so it has no per-page data to keep separate. |
That last row is the difference between this install and the Webflow comment widget one. Comments, ratings and polls need data-thread-id so one page worth of data stays apart from the next. A countdown has no data, so putting several on one page is just several mount elements with different targets, and the single loader finds all of them.
Register the domain, paste one script, drop one Code Embed.
Let the CMS carry the date so a launch never waits on the Designer
On a Collection page template the target does not have to be a literal. A Code Embed can take CMS field values inside an attribute, which turns one template into every launch page, event page and enrollment deadline you will ever publish.
Add a plain text field to the collection, call it something like Countdown Target, and store a full ISO timestamp in it, zone suffix included. Then open the Code Embed on the template, put the cursor inside the quotes of data-target, and insert the field from the field picker.
<div data-bootsignal="countdown"
data-target="[Countdown Target]"
data-expired="Enrollment for this session has closed."></div>The Designer shows the inserted field as a colored token rather than the bracket text above, which is only there to mark the spot. Use a plain text field rather than a date field: a date field renders in whichever display format you picked, and the parser is fussier than a human reader. Whichever you choose, open one published item and confirm the digits are counting instead of showing your ending line.
The payoff is who gets to move a date. Once the field drives the clock, pushing a launch back a week is an edit on one CMS item, not a Designer session and a full republish by whoever holds the Workspace seat.
Two bills, and only one of them is ours
Webflow charges for the plan that unlocks custom code. BootSignal charges $20 per month or $200 per year per registered domain, and that one subscription covers the countdown, the announcement bar and the rest of the catalog: 31 paid widgets today, plus anything added later, plus 31 free browser tools. Nothing in it is metered by pageviews, so a landing page that gets picked up by a newsletter costs exactly what it cost the day before. The number that moves the bill is how many hostnames you keep registered, so a project that leaves its staging address on after launch is paying for two.
If you are weighing that against timer tools whose price climbs with traffic or with the number of campaigns, the alternatives section carries the priced comparisons.
The clock says how long, not what is ending
A countdown on its own is a number with no sentence attached. On most launch pages it pairs with a bar that names the thing, and since the loader is already in your Footer code, that is one more Code Embed.
Dismissible top banner · remembers per visitor
The announcement bar. Site-wide from Footer code, or on one page from a Code Embed.
<div data-bootsignal="announce"
data-message="Early-bird pricing ends Friday"
data-link="/pricing" data-link-text="See plans"
data-id="launch-1"></div>It takes no thread id either. data-id is only a dismissal key: a reader who closes the bar has that choice remembered in their own browser, and bumping the id brings the bar back for your next announcement.
It is nearly always the hostname or the timestamp
- Nothing renders at all: the page is not on a registered domain. Designer preview and Webflow preview URLs are not your domain, so publish to staging or live first.
- Your expired message shows the moment you publish: the target could not be parsed. Check the timestamp against the ISO shape, including the T between date and time.
- The ending lands an hour off: daylight saving. Write the offset that applies on the target date rather than the one in force when you typed it.
- A placeholder box sits on the Designer canvas: normal. Only iframe and style content previews there.
- It worked on staging and stopped after you connected the custom domain: register the new hostname too. The check is on hostname, not on the Webflow site.
- The Code Embed silently refuses your paste: Webflow rejects html, body and head tags inside custom code, and caps each field at 50,000 characters.
Whatever the page is built around, write the deadline into the copy as well as into the attribute, in words, with the zone spelled out. "Doors close Friday at 11:59pm KST" is the part a visitor can put in a calendar, and it is the only part that still makes sense after the clock hits zero.
Questions people ask
- My deadline hit zero for me, then again nine hours later for a colleague. Why?
- Because
data-targetwas written without a zone suffix, and a bare timestamp is read against whichever clock the visitor happens to be on. That is correct for a shop that closes at midnight wherever the shopper lives, and wrong for a launch everyone should watch land together. For a single fixed instant, appendZfor UTC or a numeric offset such as+09:00, and use the offset that is in force on the target date rather than the one in force today, so a deadline sitting on the far side of a daylight saving change does not slip by an hour. - Will the timer show up in the Designer or in preview?
- Webflow says custom code effects appear in preview mode, and a Code Embed holding a script shows only a placeholder on the Designer canvas. Either way you should judge it on a published URL: BootSignal matches
location.hostnameagainst your registered domains, and a Webflow preview address is not one of them. Publish to your.webflow.iostaging domain and open that. - Can I put more than one countdown on the same page?
- Yes. Add a mount element for each, give each its own
data-target, and leave the loader alone: one loader tag per page finds and fills all of them. A page with a shipping cutoff timer near the top and an event timer further down needs two Code Embeds and no extra script. - What does the page show after the countdown reaches zero?
- The digits are replaced in place by your
data-expiredtext, and the element keeps its space in the layout so nothing shifts. If you did not setdata-expired, the widget shows a built-in message in the language you selected withdata-lang. - Can the date come from a CMS field instead of being hard-coded?
- Yes, and that is the right setup for anything recurring. Put a full ISO timestamp in a plain text field on the collection, then insert that field inside the
data-targetvalue in a Code Embed on the Collection page template. Every item gets its own deadline, and changing one is a field edit rather than a Designer change. - Does it slow the site down?
- It is one deferred script that fetches after the HTML is parsed, plus a timer that updates once a second. There are no images and no library to load. Newly published Webflow sites already include jQuery 3.5.1, and the widget neither uses it nor loads another copy, so there is nothing to conflict. Its styles live in a shadow root, so they never cascade into your page.
One loader in Footer code, one Code Embed, and a date the browser can read.
Services in this guide
Read next
Where these numbers come from
- Webflow Help Center: Custom code in head and body tags (checked 2026-08-25)
- Webflow Help Center: Custom code embed (checked 2026-08-25)
- Webflow pricing (Custom code row in the plan comparison) (checked 2026-08-25)