How to Build a Custom Shopify Estimated Delivery Date Feature Without an App

Shopify August 19, 2024

 

Last week, I took on one of those infamous projects where a client asked if I could "build a website that looks like this." The link they shared was to Fashion Nova, a popular clothing e-commerce brand. Specifically, the client wanted me to replicate the header navigation and product page design.

Side note: Fashion Nova is built with Shopify. As a Shopify developer, I love seeing big brands using the platform.

 

While most of the design elements could be easily replicated by editing the template, the product page had a delivery estimate feature that typically requires an app.

The one-day delivery countdown and estimated product delivery are conversion tactics used by many popular e-commerce brands, with the most notable being Amazon. There’s good reason for this: according to Project 44, three-fourths (75.1%) of shoppers state that showing the estimated delivery date on the product page or in the cart positively influences their decision to buy.

Additionally, Baymard Institute’s checkout usability study showed that what users care about isn’t “shipping speed” but rather the specific delivery date, like “when will I receive my order?”

But even with all the potential CRO benefits, the client didn’t want to deal with recurring app charges and asked if there was a way to build this component without an app.

With some brainstorming and the help of ChatGPT, I was able to create a custom block that can be easily customized and added to product pages directly from within the CMS.

 

Product Page Schema

To set up a dynamic delivery estimate feature, the first step is to add a custom block to your product page. The goal is to place this block under the product information tab, where customers can easily see it.

  1. Navigate to Your Product Page: Start by going to the product template in your theme editor.

  2. Create a Custom Block: In your product page template, create a new block for displaying the estimated delivery time. This will allow you to customize the component directly from the Shopify admin.

 

Focus on US Delivery Times

For this example, I focused on U.S. delivery times and broke down estimated ETAs based on time zones (EST, CST, MST, and PST). The idea is to add your processing and handling time to the average delivery time for each time zone, providing an accurate day estimate for customers.

By considering different time zones, you can give customers a tailored delivery estimate based on their location, improving transparency and increasing trust.

 

Product Page HTML/Liquid

Adding the HTML for this is fairly simple since the JavaScript does most of the heavy lifting. The EDD feature is just a div and a p tag, so there isn’t much required on the HTML side.

However, there are important considerations when combining Liquid and JavaScript.

Server Side vs Client Side

  1. Liquid runs at compile-time: Liquid is a templating language that runs on the server side, generating the final HTML before sending it to the browser. This means all variables and settings need to be defined in Liquid before they are accessible in the rendered HTML and thus in your JavaScript.

  2. Passing Variables from Liquid to JavaScript: Since JavaScript runs in the browser after the page is fully loaded, any values from Liquid that you need in your JavaScript must first be outputted in the HTML. This can be done by assigning Liquid variables to JavaScript variables within <script> tags.

 

Product Page JavaScript

As mentioned before, JavaScript handles most of the heavy lifting for this project. This is because we need to access the customer’s location, determine their time zone and ZIP code, and then match that information to one of the shipping settings defined in the schema.

Mapping Customer's Location to Delivery Times 

The first function is designed to take the user’s time zone offset and map it to the appropriate delivery time setting.

Accessing Assigned Variables from Liquid: The variables (est_days, cst_days, mst_days, pst_days) from earlier are passed from the Liquid code into JavaScript. These represent the estimated delivery days for each time zone.

Creating a Hash Map: We store these values in a hash map (deliveryDaysSettings) to pair each time zone with its corresponding delivery time. This allows us to easily look up the correct delivery days based on the user’s location.

Understanding Time Zone Offsets: By default, computers use Coordinated Universal Time (UTC). The time zone offset is the difference (in hours) between the user’s local time and UTC. For example:

  • EST is UTC-5 (offset is -5 hours).
  • CST is UTC-6 (offset is -6 hours).
Using a Switch Statement: We use a switch statement to adjust the delivery days based on the time zone offset. Depending on the offset value (e.g., -5 for EST, -6 for CST), the code selects the corresponding delivery days from the hash map.

 

 

Obtaining Customers' Zip Code 

The getUserZipCode function aims to fetch the customer's ZIP code based on their current geographic location. It uses the browser's geolocation API to get the customer's latitude and longitude, then uses a reverse geocoding API to convert these coordinates into a ZIP code.

Return a Promise: The function returns a Promise, which is a common JavaScript pattern for handling asynchronous operations. A promise has two possible outcomes: resolved (successful completion) or rejected (an error or failure).

Check Geolocation Support: This checks if the user's browser supports the Geolocation API. If supported, it proceeds to get the current position. If not supported, it rejects the promise.

Get Current Position: navigator.geolocation.getCurrentPosition is an asynchronous method that retrieves the user's current geographic position. It takes a callback function that receives a position object with latitude and longitude properties.

Extract Coordinates: Destructures the latitude and longitude from the position.coords object.

Fetch ZIP Code Using Reverse Geocoding API: fetch sends a request to the reverse geocoding API with the latitude and longitude. The await keyword is used to wait for the response. The response is then converted to JSON format. The ZIP code (data.postcode) is extracted and resolved. If the ZIP code is not available, it resolves with "Unknown ZIP Code".

  • If there's an error in fetching or processing the API response, the promise is rejected with an error message.
  • If the browser does not support geolocation, the promise is rejected with a specific error message.

Creating Date String

The getDeliveryDate function calculates a future delivery date based on a number of days from the current date. It formats the resulting date into a readable string.

Initialize Current Date: Creates a new Date object representing the current date and time. This object is stored in the deliveryDate variable.

Add Days to Current Date: 

Defines a configuration object options for date formatting:

  • deliveryDate.getDate() retrieves the day of the month from the deliveryDate object.
  • deliveryDate.setDate() sets the day of the month to the current day plus the number of days specified by the days parameter. This effectively advances the date by the specified number of days.

toLocaleDateString('en-US', options) converts the deliveryDate object into a string based on the specified options and locale (en-US). This produces a date formatted as "Mon, Aug 26".



Displaying The EDD

The showEstimatedDelivery function calculates and displays an estimated delivery date based on the user's location and time zone. It asynchronously fetches the user's ZIP code, determines delivery days based on the time zone, calculates the delivery date, and updates the page with the estimated delivery information.

We start by declaring an asynchronous function named showEstimatedDelivery. This allows the function to use await to handle promises.

Fetch User ZIP Code: Calls the getUserZipCode function from earlier, which returns a promise. await pauses execution until the promise is resolved, returning the user's ZIP code.

Determine Time Zone Offset: Uses new Date().getTimezoneOffset() to get the time zone offset in minutes from UTC. Divides by 60 to convert this to hours.

Determine Delivery Days: Calls determineDeliveryDays with the time zone offset to get the number of delivery days for the user's time zone.

Calculate Delivery Date: Calls getDeliveryDate with the number of delivery days to compute the estimated delivery date. 

Update Display with Estimated Delivery Information:
  • Constructs a string etaText containing the estimated delivery date and ZIP code.
  • Updates the content of the HTML element with ID estimated-delivery to display the estimated delivery information.

Catch Block for Error Handling:

  • Catches any errors that occur during the asynchronous operations.
  • Updates the content of the HTML element with ID estimated-delivery to display an error message.

 Running The Function

The code we’ve broken down here showcases the importance of blending Liquid and JavaScript when building dynamic features in Shopify. By leveraging Liquid to pull in product settings and using JavaScript to handle geolocation and timezone detection, we can create a fully customizable estimated delivery date feature. This approach not only enhances the user experience but also allows merchants to implement a powerful conversion tactic without relying on third-party apps. 

The Final Result

 

Building custom Shopify components like this estimated delivery date feature is a great way to enhance user experience and boost conversions without relying on recurring app charges. Through a mix of Liquid for server-side settings and JavaScript for client-side processing, you can provide customers with real-time, location-specific information that builds trust and nudges them toward completing their purchase. Whether you’re a developer looking to offer more value to your clients or a merchant seeking to improve your store, custom solutions like these give you the flexibility and control to stand out in the crowded e-commerce space.

You can download the product page on GitHub.

img not found

Chris Snowden

Author

Hi, I'm Christopher Snowden, a Shopify developer. I enjoy building and learning about e-commerce solutions that help businesses grow. With the rise of AI, I believe it is important for developers to understand more aspects of business and have a deeper understanding of how their skills translate to profit. Let's connect and collaborate! Follow me on social media to stay updated with my latest projects and insights.