One of the best parts of running your own ecommerce store is being able to add custom features that work well for you and your customers. For a store that sells a lot of party supplies, the ability to display an estimated delivery date right on the product page was important to improve customer trust and cut down on the dozens of emails we were getting about delivery times. It's been a huge help for my store, and I hope you find it helpful too!
Just as a disclaimer before we begin: I do not work for Shopify, and am by no means an expert in Shopify code. I am providing this code as-is for you to use or alter to fit your store's needs. You should always create a backup of your code before making any edits just in case something goes wrong.
Step 1: Production and shipping times
Most of the items in my store are hand made to order, so I have a "production" time that estimates the number of days it will take to make an item before it is ready to ship. In this example, we'll say it takes about 1-3 business days to make the item.
Shipping time is self explanatory—the number of days it will take for the shipping carrier to deliver the item to your customer. In this example, we'll say it takes about 3-5 business days.
Most of this tutorial will use JavaScript. I'm keeping track of these date ranges by creating arrays:
var productionTimeArray = [1, 3];
var shippingTimeArray = [3, 5];
Step 2: Setting up dates
The next step is to figure out what today's date is and use that as a starting point. Lucky for us, JavaScript makes this easy with their date methods. For this setup, we'll be using the following:
var date = new Date();
var currentDay = date.getDay();
var currentDate = date.getDate();
var currentMonth = date.getMonth();
var currentYear = date.getYear();
Then we create a couple more arrays to define the days of the week, the months in a year, and the number of days in each month. And of course, we have to check if it's a leap year.
var dayArray = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
var monthNamesArray = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var daysInMonthsArray = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];//check if it's a leap year
if (currentYear % 4 == 0){
daysInMonthsArray[1] = 29;
} else {
daysInMonthsArray[1] = 28;
}
Step 3: A little more setup
Now we'll just create a couple more sets of variables and put them into arrays of two (because we'll have to do the date calculations twice—one for each end of the estimated date range) to finish our setup:
var dayCounter1 = currentDate;
var dayCounter2 = currentDate;
var dayCounterArray = [dayCounter1, dayCounter2];var dayOfWeek1 = currentDay;
var dayOfWeek2 = currentDay;
var dayOfWeekArray = [dayOfWeek1, dayOfWeek2];var month1 = currentMonth;
var month2 = currentMonth;
var monthArray = [month1, month2];var oldDay = 0;
var newDay = 0;var tempDayCounter = 0;
var tempDayOfWeek = 0;
Since all of the calculations will be based on the current date, I'm setting all the initial values to our current day, date, and month.
Step 4: Calculations
Finally! We're getting to the good stuff. Since we set up all our date variables in handy arrays, I'll be using a for loop to run through the calculations twice, one for each end of the delivery range:
for (var i = 0; i < currentEstimateArray.length; i++){
...
}
All of the following will go inside this loop. Since we don't work on weekends, the first thing we're doing is checking if the current day is a Saturday or Sunday:
//check if current date is a weekend
if (dayOfWeekArray[i] == 0){
dayCounterArray[i] += 1;
dayOfWeekArray[i] = 1;
} else if (dayOfWeekArray[i] == 6){
dayCounterArray[i] +=2;
dayOfWeekArray[i] = 1;
}
If it is, we're bumping the estimate forward 1-2 days to start the clock on the following Monday.
Next, we're going to add the production time to our current date. I'm using some of the temporary variables we created in step 3 so that we can put all the calculations in their own function:
oldDay = dayCounterArray[i];
newDay = dayCounterArray[i] + productionTimeArray[i];tempDayCounter = dayCounterArray[i];
tempDayOfWeek = dayOfWeekArray[i];
We'll call the function "addDays" and create it outside the loop:
function addDays(){
for (var i = oldDay + 1; i < (newDay + 1); i++){
while (tempDayOfWeek > 6){
tempDayOfWeek -=6;
}
if (tempDayOfWeek == 0){
i--;
tempDayCounter += 1;
tempDayOfWeek = 1;
} else if (tempDayOfWeek == 6){
i--;
tempDayCounter += 2;
tempDayOfWeek = 1;
} else {
tempDayOfWeek++;
tempDayCounter++;
}
}
}
Since the week array only goes up to 6, we're resetting the "day of the week" counter every time it hits the max. Again, this is calculating business days only. We're checking each day between today and the first projected estimate to make sure there's no weekends in between. If there are, we bump the date forward to the following Monday. A caveat is that we do ship items on Saturdays, so we're allowing the last day of the production period to fall on a Saturday.
Back inside our for loop, we'll call the function we just made, and then we'll go through the steps again to add the shipping time to our delivery estimate.
addDays();
dayCounterArray[i] = tempDayCounter;
dayOfWeekArray[i] = tempDayOfWeek;
oldDay = dayCounterArray[i];
newDay = dayCounterArray[i] + shippingTimeArray[i];
tempDayCounter = dayCounterArray[i];
tempDayOfWeek = dayOfWeekArray[i];
addDays();
dayCounterArray[i] = tempDayCounter;
dayOfWeekArray[i] = tempDayOfWeek;
The last step of the calculations is to check if the production and shipping time have bumped us into the next month:
if (dayCounterArray[i] > (daysInMonthsArray[monthArray[i]])){
dayCounterArray[i] -= (daysInMonthsArray[monthArray[i]]);
if (monthArray[i] < 11){
monthArray[i]++;
} else {
monthArray[i] = 0;
}
Since we set up the values for the number of days in each month back in step 1, all we have to do now is check if the estimated day is larger than the number of the days in that month, and then move forward accordingly. We're also going to make sure that December rolls back into January. Our production times are pretty short, but if yours are longer you may want to adjust this to work over several months.
Step 5: Displaying the estimates
Now that you have all your calculations done (woohoo!) we just need to display the dates to our customers. I created an empty paragraph tag:
<p id="estimatedDates"></p>
Then, after the for loop, I'm changing the contents of the paragraph to display the estimated delivery dates:
document.getElementById("estimatedDates").innerHTML = "Order today for an estimated delivery date between <strong>" + dayArray[dayOfWeekArray[0]] + ", " + monthNamesArray[monthArray[0]] + " " + dayCounterArray[0] + "</strong> and <strong>" + dayArray[dayOfWeekArray[1]] + ", " + monthNamesArray[monthArray[1]] + " " + dayCounterArray[1] + "</strong>";
We're converting the 0 - 6 and 0 - 11 array values into the names for the days of the week and the months, and formatting it all into an easy to read sentence.
Step 6: Add to Shopify
And there you have it! Now all you'll need to do is tell Shopify where you'd like the estimated dates displayed. We created a new snippet called estimated-delivery-date.liquid for all of the code, then simply dropped an include line in the product-template.liquid file where we wanted the dates to show up:
{% include 'estimated-delivery-date' %}
We chose to display the dates right under the "add to cart" button on each product page.
Bonus: Add different estimates to different products
Some of our products take different amounts of time to make, or ship with different carriers. We ended up making a small adjustment to our code so we could display different estimates for each product type. To do this, we simply initialized the production and shipping time arrays with values of 0:
var productionTimeArray = [0, 0];
var shippingTimeArray = [0, 0];
Then we created a switch statement to have Shopify check the product type and fill in the appropriate production and shipping values.
{% case product.type %}
{% when 'Cake Toppers' or 'Stickers' %}
<script>
productionTimeArray = [1, 2];
shippingTimeArray = [3, 5];
</script>
{% when 'Mug' %}
<script>
productionTimeArray = [2, 5];
shippingTimeArray = [4, 8];
</script>
{% endcase %}
If sorting by product type doesn't work for your store, you can easily change it to check the product's collection, vendor, and many other attributes.
And that's it! Expect an instant increase in conversions and a decrease in the time you spend answering emails. Happy selling!