Adding a countdown timer creates scarcity and urgency—two key psychological triggers in e‑commerce marketing. When visitors see that an offer ends soon, they’re more likely to buy. According to conversion rate optimization studies, urgency tools like countdown clocks can increase sales by up to 60%.
Welcome to this ultimate guide on how to add countdown timer in Shopify store without app ⏰, designed for merchants who want to boost urgency, conversions, and sales—without relying on paid apps.
Also if you are looking for a Meta Ads specialist who offers freelance services for lead generation and sales campaigns? You're in the right place. I'm currently offering free strategy sessions and discounted campaign setup for new clients. If you're satisfied with my work, we can explore a long-term partnership to scale your business together. Click Here to Contact.
Add Countdown Timer in Shopify Store Without App
#Step 1 - Duplicate your Current Theme
Step 1: Log in to your Shopify admin dashboard.
Step 2: Navigate to Online Store > Themes.
Step 3: Click the three dots on the current theme.
Step 4: Create a backup of the theme by selecting the Duplicate option.
#Step 2 - Create Countdown Timer Section
{% comment %}
Liquid Variables
{% endcomment %}
{% liquid
assign timer_section_title = section.settings.timer_section_title
assign timer_section_subtitle = section.settings.timer_section_subtitle
assign date_picker_time = section.settings.date_picker
assign cta_bg_color = section.settings.cta_bg_color
assign cta_text_color = section.settings.cta_text_color
assign title_text_color = section.settings.title_text_color
assign subtitle_text_color = section.settings.subtitle_text_color
assign subtitle_font_weight = section.settings.subtitle_font_weight
assign section_bg_color = section.settings.bg_color
assign timer_color = section.settings.timer_color
%}
{% comment %}
Custom CSS Styles
{% endcomment %}
{% style %}
.timer-flex-container{
background: {{ section_bg_color }};
align-items: center;
justify-content: center;
column-gap: 20px;
padding: 10px;
display: flex;
opacity: 1;
transition: 0.5s all linear;
}
.hide-element{
padding: 0 !important;
opacity: 0;
}
.timer-flex-container .timer {
display: flex;
justify-content: space-around;
}
.timer-flex-container .timer-subtitle{
text-align:center; margin: 5px 0;
}
.timer-flex-container .timer-subtitle{
color: {{ subtitle_text_color }};
font-weight: {{ subtitle_font_weight }};
font-family: inherit;
font-size: 18px;
}
.timer-flex-container .timer--expired {
display: none;
}
.timer-flex-container .timer__title {
text-align: center;
font-weight: bold;
}
.timer-flex-container .timer-display {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: center;
margin-top: 5px;
}
.timer-flex-container .timer{
margin-right: 1rem;
}
.timer-flex-container .timer-block {
position: relative;
padding: 0 10px;
}
.timer-flex-container .timer-block__num,
.timer-flex-container .timer-block__unit {
display: block;
text-align: center;
color: {{ timer_color }};
font-family: inherit;
}
.timer-flex-container .timer-block__num{
font-size: 16px;
}
.timer-flex-container .timer-block__unit{
font-size: 13px;
margin-top: -7px;
}
.timer-flex-container .colon {
font-size: 16px;
color: {{ timer_color }};
}
.timer-flex-container .timer-button{
max-height: 45px;
background-color: {{ section.settings.cta_bg_color }} !important;
color: {{ section.settings.cta_text_color }} !important;
border-radius: 4px;
}
.timer-flex-container .timer-button::after{
content: none;
}
.timer-display-flex{
display: flex;
align-items: center;
}
.gradient-bg-animation{background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
background-size: 400% 400%;
animation: gradient 15s ease infinite;}
@keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
@media screen and (max-width: 768px){
.timer-flex-container{
flex-direction: column;
}
}
@media screen and (max-width: 391px){
.timer-display-flex{
width: 100%;
justify-content: space-evenly;
flex-wrap: wrap;
}
}
{% endstyle %}
{% unless date_picker_time == blank %}
<div class="timer-flex-container hide-element gradient-bg-animation">
{% unless timer_section_title == blank %}
<div class="timer-subtitle">{{ timer_section_title }}</div>
{% endunless %}
<div class = "timer-display-flex">
<countdown-timer-bar schema-time="{{ date_picker_time }}">
<div class="timer" style="visibility: hidden;">
<div class="timer-display">
<div class="timer-block">
<span class="timer-block__num js-timer-days">00</span>
<span class="timer-block__unit">Days</span>
</div>
<div class="colon">:</div>
<div class="timer-block">
<span class="timer-block__num js-timer-hours">00</span>
<span class="timer-block__unit">Hrs</span>
</div>
<div class="colon">:</div>
<div class="timer-block">
<span class="timer-block__num js-timer-minutes">00</span>
<span class="timer-block__unit">Mins</span>
</div>
<div class="colon">:</div>
<div class="timer-block">
<span class="timer-block__num js-timer-seconds">00</span>
<span class="timer-block__unit">Secs</span>
</div>
</div>
</div>
</countdown-timer-bar>
{% unless section.settings.timer_section_btn_link == blank and timer_section_btn_text == blank %}
<a class="timer-button button" href="{{ section.settings.timer_section_btn_link }}">
<span>{{
section.settings.timer_section_btn_text }}
</span>
</a>
{% endunless %}
</div>
</div>
{% endunless %}
{% comment %}
Native Web Component Definition
{% endcomment %}
{% javascript %}
class CountdownTimerBar extends HTMLElement {
constructor() {
super();
}
init() {
this.schemaTime = this.getAttribute('schema-time');
this.timer = this.querySelector(".timer")
this.countdown = new Date(this.schemaTime).getTime();
this.second = 1000;
this.minute = this.second * 60;
this.hour = this.minute * 60;
this.day = this.hour * 24;
this.timerInterval = null;
this.startTimer();
setTimeout(() => this.timer.style.visibility = "visible", 1000)
}
padWithLeadingZero = (number) => {
if (number < 10) {
return '0' + number;
} else {
return number;
}
};
isDateInPast(date) {
const now = new Date();
return date < now;
}
startTimer() {
//Have quick check to see if Date input in the countdown class variable is in the past
//Helper function
const timerElem = this.timer
this.timerInterval = setInterval(() => {
const now = new Date().getTime();
const distance = this.countdown - now;
const dayCalc = Math.floor(distance / this.day);
const hourCalc = Math.floor((distance % this.day) / this.hour);
const minuteCalc = Math.floor((distance % this.hour) / this.minute);
const secondCalc = Math.floor((distance % this.minute) / this.second);
timerElem.querySelector('.js-timer-days').textContent = this.padWithLeadingZero(dayCalc);
timerElem.querySelector('.js-timer-hours').textContent = this.padWithLeadingZero(hourCalc);
timerElem.querySelector('.js-timer-minutes').textContent = this.padWithLeadingZero(minuteCalc);
timerElem.querySelector('.js-timer-seconds').textContent = this.padWithLeadingZero(secondCalc);
}, this.second);
}
disconnectedCallback() {
clearInterval(this.timerInterval);
}
connectedCallback(){
this.init();
console.log("countdown timer was added to the page")
const timerFlexContainer = window.document.querySelector(".timer-flex-container")
const timerElem = this.timer
const pastDate = this.isDateInPast(this.countdown)
if(pastDate){
timerFlexContainer.remove()
this.remove()
}
window.setTimeout(() => {
timerFlexContainer.classList.remove("hide-element")
}, 2000);
}
disconnectedCallback(){
console.log("The Timer date has passed so the timer was removed")
}
}
customElements.define('countdown-timer-bar', CountdownTimerBar);
{% endjavascript %}
{% comment %}
Section Customization Options
{% endcomment %}
{% schema %}
{
"name": "Countdown Top Bar",
"tag": "section",
"enabled_on": {
"groups": ["header"]
},
"settings": [
{
"type": "header",
"content": "General Section Settings"
},
{
"type": "color",
"id": "bg_color",
"default": "#fff",
"label": "Section Background Color"
},
{
"type": "header",
"content": "Title Settings"
},
{
"type": "text",
"id": "timer_section_title",
"label": "Section Title",
"default": "Hurry up! Sale ends in:"
},
{
"type": "color",
"id": "subtitle_text_color",
"default": "#fff",
"label": "Section Title Text Color"
},
{
"type": "select",
"id": "subtitle_font_weight",
"default": "500",
"label": "Normal or Bolded Text",
"options": [
{
"label": "Normal",
"value": "500"
},
{
"label": "Bold",
"value": "700"
}
]
},
{
"type": "header",
"content": "Timer Settings"
},
{
"type": "text",
"id": "date_picker",
"label": "Choose a date",
"info": "Input date in this format: 07/21/2023. When date is in past section will disappear"
},
{
"type": "color",
"id": "timer_color",
"default": "#fff",
"label": "Timer Color"
},
{
"type": "header",
"content": "Button Settings"
},
{
"type": "url",
"id": "timer_section_btn_link",
"label": "Call to Action Button Link"
},
{
"type": "text",
"id": "timer_section_btn_text",
"label": "Call to Action Button Text",
"default": "Shop Now!"
},
{
"type": "color",
"id": "cta_bg_color",
"default": "#4770db",
"label": "Call to Action Background Color"
},
{
"type": "color",
"id": "cta_text_color",
"default": "#fff",
"label": "Call to Action Text Color"
}
],
"presets": [
{
"name": "Countdown Top Bar"
}
]
}
{% endschema %}
#Step 3 - Customize Countdown Timer Section
Also if you are looking for a Meta Ads specialist who offers freelance services for lead generation and sales campaigns? You're in the right place. I'm currently offering free strategy sessions and discounted campaign setup for new clients. If you're satisfied with my work, we can explore a long-term partnership to scale your business together. Click Here to Contact.
Looking for something specific? Drop me a message.