Skip to main content

Countdown timer

A live countdown to a fixed deadline — days, hours, minutes, seconds, ticking once a second. It's the smallest complete thing you can build with the SDK, and it covers the moves every script uses: connect, find, and drive.

You'll use: connect, findByLocator, and the text capability.

Set it up in Flex

Add four text elements — one each for days, hours, minutes, and seconds — and give each one a locator in the SDK Locators inspector:

ElementLocator
Dayscountdown-days
Hourscountdown-hours
Minutescountdown-minutes
Secondscountdown-seconds

Style them however you like, and add any labels you want around them. The script only writes the four numbers.

The script

Paste this into the experience's custom body HTML, setting DEADLINE to your target date.

<script type="module">
import { connect } from '@ceros/flex-experience-sdk'

const DEADLINE = new Date('2026-09-17T00:00:00Z').getTime()

const experience = await connect()

// Find each element once — they don't move.
const days = experience.findByLocator('countdown-days')
const hours = experience.findByLocator('countdown-hours')
const minutes = experience.findByLocator('countdown-minutes')
const seconds = experience.findByLocator('countdown-seconds')

const pad = (n) => String(n).padStart(2, '0')

function tick() {
const remaining = Math.max(0, DEADLINE - Date.now())
const totalSeconds = Math.floor(remaining / 1000)

days.text.setText(String(Math.floor(totalSeconds / 86400)))
hours.text.setText(pad(Math.floor((totalSeconds % 86400) / 3600)))
minutes.text.setText(pad(Math.floor((totalSeconds % 3600) / 60)))
seconds.text.setText(pad(totalSeconds % 60))

if (remaining === 0) clearInterval(timer)
}

tick() // draw immediately, so there's no blank first second
const timer = setInterval(tick, 1000)

</script>

Publish, and the countdown runs.

Or have Flex AI build it

Rather than laying this out by hand, you can paste the prompt below into Flex AI in the Flex editor. It builds the elements, names them, and writes the script — giving you a working experience to try the SDK against in one step.

In this experience, build a countdown section:

- Four text elements labelled Days, Hours, Minutes, and Seconds.
- Give them the SDK locators countdown-days, countdown-hours,
countdown-minutes, and countdown-seconds.
- Add SDK code that connects to the experience and updates all four
every second, counting down to this deadline:

Deadline: <paste your date here, e.g. 2027-01-01T00:00:00Z>

Pad the hours, minutes, and seconds to two digits, stop at zero, and
draw once immediately so there's no blank first second.

Flex AI writes the script into the experience's custom body HTML, which is the same place you'd paste it yourself. Two things to expect:

  • You still have to publish (or open the standalone preview) to see it run. Custom body HTML doesn't execute in the editor's Preview tab.
  • Read the code before you ship it. It's generated, so treat it as a first draft — the sections below explain what a good version looks like.

Why it's written this way

  • The lookups happen once, outside tick(). A lookup reads the page when you call it, and these four elements never move — so there's no reason to search again every second.
  • tick() runs before the interval starts. Otherwise the page would show whatever was published for a full second before the first update.
  • text.setText(), not textContent. setText is the supported way to change text; writing to the element directly can corrupt what Ceros renders.
  • Duplicates are free. Each lookup returns a set, and a call reaches every member. If someone duplicates the seconds element for a mobile layout and gives it the same locator, both update — no code change.

Variations

Count down to a date the design carries. Instead of hard-coding the deadline, put it in the SDK Data inspector on the countdown section (deadline), and read it with getData:

const section = experience.findByLocator('countdown').only()
const DEADLINE = new Date(section.getData('deadline')).getTime()

Reveal something when it hits zero. Design the "we're live" panel, hide it in Flex, then show it from tick():

if (remaining === 0) {
clearInterval(timer)
experience.findByLocator('were-live').visibility.show()
}

Show a per-visitor deadline. Store the first-visit timestamp with the store and a localStorage adapter, so a 24-hour window starts when each visitor arrives:

import { createStore, localStorageAdapter } from '@ceros/flex-experience-sdk'

const store = createStore(
{ startedAt: Date.now() },
{ persist: localStorageAdapter('promo.countdown') },
)

const DEADLINE = store.get('startedAt') + 24 * 60 * 60 * 1000