Shopify Password Page Countdown
A coming-soon password page with a live countdown and an email signup, no app.
Your details
Your section file (sections/password-countdown.liquid)
{%- comment -%}
Password page countdown, with an optional email signup. Add this as a section on your Password
page: in Customize, use the template picker at the top and choose Password, then Add section.
If your theme instead uses a plain templates/password.liquid file (no sections), paste this
section's contents directly into that file instead.
{%- endcomment -%}
{%- style -%}
#PasswordCountdown-{{ section.id }}{background:#0f1115;color:#ffffff;padding:3rem 1.5rem;text-align:center}
#PasswordCountdown-{{ section.id }} .ea-pwc__inner{max-width:520px;margin:0 auto;display:flex;flex-direction:column;align-items:center;gap:1rem}
#PasswordCountdown-{{ section.id }} .ea-pwc__heading{margin:0;font-size:1.6em;font-weight:600}
#PasswordCountdown-{{ section.id }} .ea-pwc__sub{margin:0;opacity:.85}
#PasswordCountdown-{{ section.id }} .ea-pwc__clock{display:flex;gap:.6rem;flex-wrap:wrap;justify-content:center}
#PasswordCountdown-{{ section.id }} .ea-pwc__unit{min-width:4.5rem;padding:.7rem .5rem;border-radius:8px;background:#1c1f26}
#PasswordCountdown-{{ section.id }} .ea-pwc__num{font-size:1.8em;font-weight:700;font-variant-numeric:tabular-nums}
#PasswordCountdown-{{ section.id }} .ea-pwc__label{font-size:.7em;text-transform:uppercase;letter-spacing:.06em;opacity:.75}
#PasswordCountdown-{{ section.id }} .ea-pwc__form{display:flex;gap:.5rem;flex-wrap:wrap;justify-content:center;margin-top:.5rem}
#PasswordCountdown-{{ section.id }} .ea-pwc__form input[type="email"]{padding:.6em .8em;border-radius:6px;border:1px solid #999;min-width:220px}
#PasswordCountdown-{{ section.id }} .ea-pwc__form button{padding:.6em 1.2em;border-radius:6px;border:0;background:#ffffff;color:#0f1115;font-weight:600;cursor:pointer}
#PasswordCountdown-{{ section.id }} .ea-pwc__success{margin:0;font-weight:600}
@media (prefers-reduced-motion:reduce){#PasswordCountdown-{{ section.id }} .ea-pwc__unit--seconds{display:none}}
{%- endstyle -%}
<div id="PasswordCountdown-{{ section.id }}">
<div class="ea-pwc__inner">
<p class="ea-pwc__heading">We're launching soon</p>
<p class="ea-pwc__sub">Sign up and we'll email you the moment we open.</p>
<ea-password-countdown data-date="{{ section.settings.end_date }}" data-time="{{ section.settings.end_time }}" data-tz="{{ section.settings.timezone }}">
<div class="ea-pwc__clock">
<div class="ea-pwc__unit"><span class="ea-pwc__num" data-days>00</span><span class="ea-pwc__label">Days</span></div>
<div class="ea-pwc__unit"><span class="ea-pwc__num" data-hours>00</span><span class="ea-pwc__label">Hours</span></div>
<div class="ea-pwc__unit"><span class="ea-pwc__num" data-minutes>00</span><span class="ea-pwc__label">Minutes</span></div>
<div class="ea-pwc__unit ea-pwc__unit--seconds"><span class="ea-pwc__num" data-seconds>00</span><span class="ea-pwc__label">Seconds</span></div>
</div>
</ea-password-countdown>
{%- form 'customer', id: 'PasswordCountdownForm' -%}
<input type="hidden" name="contact[tags]" value="prospect,coming-soon">
{%- if form.posted_successfully? -%}
<p class="ea-pwc__success">Thanks! We'll email you when we launch.</p>
{%- else -%}
<div class="ea-pwc__form">
<label class="visually-hidden" for="PasswordCountdownEmail">Email</label>
<input type="email" name="contact[email]" id="PasswordCountdownEmail" placeholder="you@email.com" required>
<button type="submit">Notify me</button>
</div>
{%- if form.errors -%}<p class="ea-pwc__error">{{ form.errors.messages.first }}</p>{%- endif -%}
{%- endif -%}
{%- endform -%}
</div>
</div>
<script>
if (!customElements.get('ea-password-countdown')) {
customElements.define('ea-password-countdown', class extends HTMLElement {
connectedCallback() {
var parts = (this.dataset.date || '').split('-').map(Number);
var time = (this.dataset.time || '09:00').split(':').map(Number);
var y = parts[0], mo = parts[1], d = parts[2], h = time[0], mi = time[1];
var tz = this.dataset.tz || 'UTC';
try { new Intl.DateTimeFormat('en-US', { timeZone: tz }); } catch (e) { tz = 'UTC'; }
var self = this;
function partsIn(date) {
var map = {};
new Intl.DateTimeFormat('en-US', { timeZone: tz, hourCycle: 'h23', year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric' })
.formatToParts(date).forEach(function (p) { map[p.type] = p.value; });
return map;
}
function offset(t) {
var p = partsIn(new Date(t));
return Date.UTC(+p.year, +p.month - 1, +p.day, +p.hour, +p.minute, +p.second) - Math.floor(t / 1000) * 1000;
}
var guess = Date.UTC(y, mo - 1, d, h, mi);
this.end = guess - offset(guess - offset(guess));
var reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
this.tick();
this.timer = setInterval(function () { self.tick(); }, reduce ? 30000 : 1000);
}
disconnectedCallback() { clearInterval(this.timer); }
set(unit, value) {
var el = this.querySelector('[data-' + unit + ']');
if (el) el.textContent = String(value).padStart(2, '0');
}
tick() {
var left = this.end - Date.now();
if (left <= 0) { ['days', 'hours', 'minutes', 'seconds'].forEach(function (u) { this.set(u, 0); }, this); clearInterval(this.timer); return; }
var secs = Math.floor(left / 1000);
this.set('days', Math.floor(secs / 86400));
this.set('hours', Math.floor(secs / 3600) % 24);
this.set('minutes', Math.floor(secs / 60) % 60);
this.set('seconds', secs % 60);
}
});
}
</script>
{% schema %}
{
"name": "Password countdown",
"tag": "section",
"class": "ea-password-countdown-section",
"settings": [
{
"type": "text",
"id": "end_date",
"label": "Launch date",
"info": "Format YYYY-MM-DD.",
"default": "2026-12-01"
},
{
"type": "text",
"id": "end_time",
"label": "Launch time",
"info": "24-hour HH:MM.",
"default": "09:00"
},
{
"type": "select",
"id": "timezone",
"label": "Time zone",
"options": [
{
"value": "UTC",
"label": "UTC"
},
{
"value": "America/New_York",
"label": "America/New York"
},
{
"value": "America/Chicago",
"label": "America/Chicago"
},
{
"value": "America/Denver",
"label": "America/Denver"
},
{
"value": "America/Los_Angeles",
"label": "America/Los Angeles"
},
{
"value": "America/Toronto",
"label": "America/Toronto"
},
{
"value": "Europe/London",
"label": "Europe/London"
},
{
"value": "Europe/Paris",
"label": "Europe/Paris"
},
{
"value": "Europe/Berlin",
"label": "Europe/Berlin"
},
{
"value": "Europe/Madrid",
"label": "Europe/Madrid"
},
{
"value": "Australia/Sydney",
"label": "Australia/Sydney"
},
{
"value": "Pacific/Auckland",
"label": "Pacific/Auckland"
}
],
"default": "America/New_York"
}
],
"presets": [
{
"name": "Password countdown"
}
]
}
{% endschema %}
To install: in Shopify admin go to Online Store → Themes, click … next to your theme → Edit code. Under Sections choose Add a new section, name it as shown above, replace the contents with this code and save. Then open Customize and add the section where you want it. Try it on a duplicate of your theme first. Add it on the Password template specifically: in Customize, use the dropdown at the top to switch to Password, then Add section.
The email form uses Shopify's built-in customer signup form, so entries land in Customers with the tags prospect and coming-soon, no app required.
Live preview
A real signup form, not a fake one
The email field uses Shopify's built-in {% form 'customer' %} tag rather than a hand-rolled form, so submissions land in Customers in your admin like any other signup, tagged prospect and coming-soon so you can find and email them once you launch. No app or third-party service is involved.
The countdown itself runs in the shopper's browser and compares the current time against your launch date and time in the timezone you choose (not the shopper's own timezone), so the promise stays accurate regardless of where a visitor is.
Adding it to the Password page
- 01
Add the section
Online Store → Themes → Edit code → Sections → Add a new section named
password-countdown, paste the code. - 02
Add it to the Password template
Go to Online Store → Themes → Customize, then use the template dropdown at the top and switch to Password. Add the section there, since Customize otherwise opens on your regular home page template.
- 03
Vintage themes
If your theme uses a plain
templates/password.liquidfile instead of sections, paste this section's markup, style and script directly into that file rather than adding it through Customize.
Questions people ask
Where do the emails go?
Into your Shopify Customers list, tagged prospect and coming-soon, exactly like any other newsletter signup. No separate export or app needed.
Does the countdown automatically turn off my password protection?
No. It's purely visual. Remove your store's password separately, under Online Store → Preferences, when you're ready to launch.
Will this work if my theme doesn't support sections on the password page?
Older, vintage (non-Online Store 2.0) themes may only offer a plain password.liquid file. Paste the generated markup into that file directly; you'll lose the theme-editor settings but the countdown and form still work.
Can I reuse the same countdown for a sale instead?
This one is built for the password page specifically (it includes the signup form). For a sale countdown elsewhere on your store, see the general Shopify countdown timer tools in the theme snippets collection instead.
Related tools
Last reviewed 30 September 2026.
