Medusa.js is an open-source Shopify alternative built with JavaScript. It’s a great solution if you’re looking for a customizable ecommerce solution.
In this tutorial, we’ll see how to add Lob’s Address Autocomplete API feature to a Medusa project to give customers a faster checkout process.
You can find the complete code in this GitHub repo.
Why use address autocomplete?
Every bit of extra information that customers must enter in the checkout process adds to the likelihood of cart abandonment.
The information that takes the longest is undoubtedly the shipping address.
By using Lob’s Address Autocomplete API we can not only save time for customers but also validate addresses to reduce the possibility of errors.
Installing Medusa
In this tutorial, we’ll add the Lob Autocomplete React component to the checkout form found in the Medusa Next.js starter template.
To begin, you’ll need to install these two repos:
- medusa-starter-default which is the Medusa server. (Do NOT seed your database yet)
- medusa-nextjs-starter which is the Next.js frontend template.
You’ll find the installation instructions in the respective repos so we won’t repeat them here for the sake of brevity.
After installing, make sure you run the dev server on both projects (which run on ports 8000 and 9000 by default).
Set up Medusa for the US market
This walkthrough is designed for a US Storefront—though Lob has International Autocomplete support and could be used for non-US storefronts. We will need to make three adjustments so you get US dollars (USD) instead of Euros displayed in our starter store.
Seeding our store database
In your Medusa store project, open my-medusa-store/data/seed.json
.
Swap the order of the regions, so NA (North America) is first, and therefore the default.
To seed your Medusa store run the following command:
Setting currency to USD
The default currency of the Next template is set to EUR. Let’s change that to USD as Lob’s autocomplete API generates US addresses while in test mode.
To do this, go to the frontend project (all our customizations will apply to the frontend) and change the currencyCode
property to "usd" in the file context/store-context.js.
context/store-context.js
We’ll also need to change the default display from EUR to USD which we can do in the file components/checkout/shipping-method.jsx.
components/checkout/shipping-method.jsx
Adding autocomplete
The default checkout page of the Medusa store currently looks like this:
Our approach to adding address autocomplete will be:
Replace the “Address 1” field with the Lob autocomplete React component.
Add a “State” field (Medusa doesn’t provide this by default and it’s needed for US addresses).
When an address is selected through the autocomplete, programmatically fill the country, city, state, and postal code fields.
With this done, filling out the address form will be significantly faster—users only need to type a few characters to get a full address.
Creating address field component
The main component for the checkout form is in the file components/checkout/information-step.jsx
. This is where you’ll find the address input that we’re going to replace with the address autocomplete component.
Let’s first make a copy of the input-field
component and customize it to include the autocomplete. By doing it this way, we can keep the wrapper for error handling that is already present in the input-field
.
To do this, go to the terminal and copy the input-field
component to a new component address-field
:
In the new component file, rename the exported function from InputField
to AddressField
.
components/checkout/address-field.jsx
Adding autocomplete component
We’re now going to install Lob’s React address autocomplete component which provides a ready-to-use autocomplete, saving us from having to implement one from scratch.
Let’s first go to the terminal and install it with NPM. We add @previous so the component supports React 17 which is compatible with the Medusa starter project.
To use the autocomplete API, we’ll need a Lob API key. The instructions for generating one are outlined here.
Grab the publishable test key and add it to your .env.local file. We’ll use a variable name _NEXT_PUBLIC_LOB_PUBLISHABLE_KEY
_. By prefixing it with _NEXT_PUBLIC__ we can make it accessible from the frontend source code.
.env.local
Now, open the component file components/checkout/address-field.jsx
and import the Autocomplete component at the top of the file under the existing imports. Then, create a variable apiKey and assign to it your publishable Lob API key.
components/checkout/address-field.jsx
We’ll then replace the Field component declaration here with the autocomplete component. To do that, locate where Field is declared in the JSX template.
components/checkout/address-field.jsx
Replace that with the following:
components/checkout/address-field.jsx
Adding address field to form
Let’s now add our newly created address field to the checkout form. The first thing we’ll do is import the component at the top of the file components/checkout/information-step.jsx.
components/checkout/information-step.jsx
Next, in the same file, we’ll replace the address line 1 InputField component. You can identify it by the id address_1.
components/checkout/information-step.jsx
Replace that with the following:
components/checkout/information-step.jsx
Note that we keep the id, error, and errorMsg props but not the others as they aren’t relevant in our new address field.
Adding styling
To make the Lob autocomplete component fit with the Medusa checkout’s appearance we’ll need to add a few CSS rules.
Let’s create a CSS module in the styles directory called address.module.css.
Put the following rules into that new file:
styles/address.module.css
Let’s now import the CSS module file into our address field component and apply the class addressStyle.address
to the autocomplete component.
components/checkout/address-field.jsx
With that done, the autocomplete component has now been integrated into the checkout. Go ahead and start typing into the form and you should see the address autocomplete working:
Setting up state field
As mentioned, the checkout form doesn’t include a field for the customer’s state by default. We’ll need this field as it’s required for US shipping addresses.
Although not in the form, the Medusa checkout API does include a field “province” which we should use for the state.
We’ll first create the field in the form’s validation schema which is handled by the library Yup. You’ll see the config object already has a value province that is set to be nullable. Let’s change this so it’s now required by removing nullable() and replacing it with required("Required")
.
components/checkout/information-step.jsx
The checkout also uses the form library Formik. This has a prop initialValues which allows the form to be pre-filled with saved values for returning customers.
Let’s add the province field to the initialValues by adding a property province and assigning to it savedValues.province || ""
.
components/checkout/information-step.jsx
Adding state field to template
We’ll now add the state (i.e., province) field to the form. We’ll make it share a row with the country field so the form is not too long.
To do this, find the field with id _country_code
_.
Wrap this in a div with className
styles.sharedrow
.
Add an InputField
child with id province
. You can make the placeholder “State” so it’s consistent with US addresses.
With that done, the form will now have a state field next to the country field.
Creating select handler
Looking again at the address autocomplete field, you’ll see that as we begin typing an address we get suggestions in a drop-down below.
When the user selects one of these suggestions, the autocomplete component calls an onSelection
callback and passes the selected address to it.
Let’s create a handler function handleSelect
and pass it to the onSelection
prop. In this function, we’ll take the selected autocomplete address and populate the other address fields in the form.
The first thing we need to do is import the useFormikContext
hook from the formik
module. This gives us access to the form API in a functional component.
Let’s then destructure the object to get the setFieldValue
method.
components/checkout/address-field.jsx
Now we can define the callback function. This function will receive an object argument that has a property. This is itself an object with the full address components as sub properties.
Let’s now use the setFieldValue
method in the callback to provide values for postal_code, city, province, address_1 and country_code.
Finally, we’ll assign handleSelect to the onSelection prop. We’ll also add the primaryLineOnly prop. What this does is ensure that when the user makes a selection that the entire address (with state, country, zip code, etc.) is not populated in the address field—just the primary line is e.g., “12 Test St”.
components/checkout/address-field.jsx
Wrap up
With that done, we now have implemented a quick and stylish address autocomplete in Medusa! By typing a few characters into the autocomplete, customers get their validated address pre-filled, saving them a significant amount of time.