Building a Store Locator in React using Algolia, Mapbox, and Twilio – Part 3
source link: https://www.algolia.com/blog/engineering/building-a-store-locator-in-react-using-algolia-mapbox-and-twilio-part-3/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
This article completes our 3-part series on building a Store Locator. Make sure to check out Building a Store Locator – Part 1 and Building a Store Locator – Part 2.
These days, ecommerce shoppers expect convenience and want the physical and online worlds to mesh, allowing them to conduct their business on whatever channel they want. This is what a Store Locator is built for, so that users can:
- Search products online, then purchase in-store
- Browse and compare products in person, then buy online
- Shop and buy products online, then pick up the purchase in person
- Return previously purchased items in person, rather than shipping them back
Despite that, we observe that too many websites don’t offer an elegant way for their users to find their “nearest store,” whether for testing, purchasing offline, or picking up a purchase made online.
Building a store locator may seem complex as it requires implementing a geo-search, address/POI (Point of Interest) search, and displaying results on a map. To make it as easy as possible for everyone to follow along, we’re going to create a Store Locator in React in three Live Coding Sessions accompanied by three blog posts, using:
- Algolia, for its geo-search capabilities
- Mapbox, for displaying a map and searching for locations and points of interest
- Twilio, for sending texts once the order is ready
- Clever Cloud, for hosting
What we’ve seen until now
In Part 1, we created all required accounts, scaffolded the React project, and indexed the dataset with our stores in an Algolia index before wrapping up by configuring its textual and business relevance.
In Part 2, we added Geo search capabilities into the app, using Algolia, React InstantSearch, and Mapbox, to display the results on a map connected to Algolia’s InstantSearch, thanks to the connectGeoSearch Higher-Order Component. We also added a “Search as I move the map” option, similar to what you can find on Airbnb or GetAround.
Today’s focus
To complete the series, we’ll do the following:
- Add an Autocomplete dropdown menu using Algolia Autocomplete and the Mapbox Geocoding API, allowing users to find the nearest stores around a city, along with finding the stores themselves
- Add SMS alerting to inform users if products are ready to collect, similar to what you can find on IKEA in their Buy online, pick up in-store (BOPIS) feature
The code is available in the project’s Github repository:
Adding Autocomplete
The Autocomplete experience
Autocomplete is a crucial part of the user journey on any website or app because of its effectiveness at guiding users. Your users don’t have to know the exact term they’re looking for—they can type a few letters, and the autocomplete menu shows available search options, ready to be selected.
It could be on an ecommerce platform, a search engine, or a map, where you don’t need to know the full address anymore.
What is Algolia Autocomplete?
Algolia Autocomplete is a free and open source JavaScript library. We recently refactored it completely to deliver the best developer experience, focusing on creating smooth search experiences with the autocomplete UX pattern.
By design, it provides an easy way to search in multiple sources, which can be Algolia indices or external APIs. Building federated search experiences has never been easier.
Today, we’ll create and add two sources to the Autocomplete plugin, so you can reuse them in your own code base:
- The first source targets the Algolia index with the stores, so users can search for a store by its name or city
- The second source targets the Mapbox Geocoding API, so users can search for any available city or point of interest all around the world
In our project, we use Autocomplete to search for locations and stores. As mentioned, it can be used in many other ways, for example, to power search experiences on documentation websites, via the Algolia DocSearch project, which you can find on websites such as TailwindCSS, React, or Twilio.
Installing AutocompleteJS
Let’s first install the required packages :
Let’s also install @algolia/autocomplete-plugin-query-suggestions
as we will use it in a moment.
Now, let’s create an <Autocomplete/>
component.
Here, we won’t go into detail, but you can find all about this component in the docs.
The only thing you should notice here is the spread operator … props
which will allow us to spread more props on component initialization.
Components/Autocomplete/Autocomplete.tsx
Now, let’s add it to our Header
component as a child.
First, let’s update our header
component to let it handle child components.
Components/Header/Header.tsx
Then, let’s add the <Autocomplete/>
component we’ve just created to this header in our App.tsx file
Components/App/App.tsx
The Autocomplete component takes these props:
- The
placeholder
text for the search input - The
openOnFocus={true}
will open the content panel if the search field is focused. - The
onStateChange={onSubmit}
is triggered whenever content in the autocomplete changes - The
onSubmit={onSubmit}
is triggered when you hit the “enter” key, or a result is selected - The
onReset={onReset}
is triggered when you click on the x button in the input
These methods are responsible for updating the state:
The useCallback hook returns a memoized version of the callback that only changes if one of the dependencies has changed. This can be useful to prevent unnecessary renders.
Adding the createQuerySuggestionsPlugin
Now that we’ve set the scene, it’s time to populate the Autocomplete component with data. You can use plugins to get data from many sources: such as your own database, third-party APIs, and Algolia. Algolia provides official plugins for some data sources, for example, an Algolia Index.
For our app, we’ll create two plugins :
createSuggestionsPlugin
mapboxGeocodingPlugin
Let’s create a new folder under src/
and call it AutocompletePlugins
.
We’ll create a function called createSuggestionsPlugin
which will be a wrapper around the createQuerySuggestionsPlugin
provided by Algolia in the @algolia/autocomplete-plugin-query-suggestions
package. This way, we can extend and enrich the behavior of the default plugin in order to search in our Algolia Store index.
Our function takes :
- An AlgoliaSearch client (we created this in blog post 2)
- An index name (same)
- A
HitComponent
which is the same component as the one we used in part 2 to render each hit in the sidebar - An
onClick
handler, to map which function is called when users click on theHitComponent
- An
onSelectHandler
, responsible for updating the state of the search input.
The search client and index name are called in the method initialization, and the others are used in the transformSource
function of the plugin, which is responsible for transforming the data after it has been retrieved from our remote source—here, the Algolia API.
Now, let’s add this plugin to our Autocomplete
instance, and check if everything is working as expected.
If we refresh our browser, we should see store names when we type in the search input, meaning that our plugin is fully functional!
Creating our own plugin to add POI Search with Mapbox
In addition to finding a specific store by searching by its name or city name, users should also be able to search for a given location and then find all stores around that location.
The best way to do that is a Geocoding service. Here, we’re going to use the Mapbox places API. Each new search from the end-user triggers a new request to this API, returning the name of the location and its latitude and longitude information. Once the user selects a result, we can use the lat/long attributes to trigger a GeoSearch against the Algolia API and retrieve stores around that location.
To create your custom plugin, you need to implement a given interface..
In our case, to reduce the number of API calls to the Mapbox API, we use a debouncing strategy which:
- Avoids sending API calls at every single keystroke, but only when a time interval has passed, 300 ms in our case.
- Is based on a setTimeout. At first, it sets the timeout at the value passed as parameter. If the function is called again before the timeout ends, then it clears it and sets it again with the same duration.
Let’s build the Mapbox API request
Before creating the plugin, we want to create the piece of code responsible for calling the Mapbox API.
Note: You can find all available parameters for the request in the Mapbox docs.
Passing the results to Autocomplete as a Source Plugin
Now, we need to connect this function to our Autocomplete. The idea is to pass the results to the response awaited by Autocomplete
, and wrap it in a function for easy reuse.
This code adds the new plugin to our Autocomplete
instance.
Same as before, we now want to add the plugin to our Autocomplete instance.
Note: In our implementation, we limit the results to a few countries and types of places, so the MapBox API returns the most relevant results. You can adjust these variables according to your needs.
Once that’s done, we can now check our app to see if Mapbox results have been added to our autocomplete. Let’s type “Marsel” in the search bar and see if we get shops located outside of the Marseille-Provence Airport…
And it seems to be working! Hooray!
Passing clicked information to our InstantSearch instance
Now that users can select a result in the Autocomplete dropdown, we want to pass the information to the InstantSearch instance, so that we can:
- Display the selected store location with its details
- Run an Algolia Geo Search using the latitude and longitude of the selected location, to retrieve and display the closest stores from that location
As we’ll be using Geolocation coordinates, this method will work for both plugins.
Creating a place to store current coordinates
To store the selected place/shop in the Autocomplete, let’s create a state variable to store this data, we’ll call it currentStoreCoordinates
Creating the handlers
Next, let’s create a method which updates this store according to the element we click. Items returned from createSuggestionsPlugin
will have a _geoloc
object with lat
and lng
keys, which themselves come from the record stored in the Algolia index.
Items returned by createMapboxGeocodingPlugin
will have a geometry object with a coordinates array.
First, let’s create a method to handle clicks on the suggestions:
Add this to the querySuggestionPlugin
instance as the onClick
handler.
Now, let’s update the onClick
handler for the Mapbox plugin:
Passing latitude and longitude to InstantSearch and to our components
In Part 2, we configured our <InstantSearch/>
wrapper:
Now, we’ll leverage the aroundLatLng
property to trigger a Geo Search based on the latitude and longitude parameters.
This time, we’re setting aroundLatLngViaIP
to either true or false, depending on the state of
. If currentStoreCoordinates
currentStoreCoordinates
is empty, we set aroundLatLngViaIP
to true and perform a Geo Search based on the user’s IP address, otherwise we pass the coordinates as strings to aroundLatLng
to perform a GeoSearch with these coordinates! That’s all!
Now, let’s add currentStore={currentStoreCoordinates}
to our StoreComponent
and to the Map to highlight the selected store.
With this we’ve completed the Autocomplete part! We now have a fully functional Store Locator, which allow users to find stores:
- Near their current location, thanks to their IP address and from the page load
- Based on the current
viewport
, with updates every time the map is moved or zoomed in or out - Using keyword search via the autocomplete, searching either for a store by its name or the city’s name
- Using keyword search via the autocomplete, searching for a location name and find all stores nearby
Adding the Twilio SMS experience
What is Twilio?
Twilio is the leading CPaaS (Communication Platform as a Service) company created in 2008 by Jeff Lawson in San Francisco. Companies like Deliveroo, Uber, Amazon GetAround are customers, so it’s likely that you use Twilio’s services without knowing.
They serve many communications channels, from SMS, voice calls, and push notifications, all the way up to fully configurable call centers for enterprises. They also expanded into emails and customer analytics via the acquisition of SendGrid and Segment.
In this project, we’ll use SMS for three reasons:
- BOPIS feature (buy online, pick-up in-store) to receive the store location by text
- Out-of-Stock notification, so you get a text whenever the product is back in-stock
- Marketing notifications
Creating your account
Let’s create our account and get the Account SID and Authentication token.
Go to Twilio.com and click “Sign up”. Enter the necessary information to create your free Twilio account.
Once you’re logged in, you’ll land on the “console”, where you find two critical pieces of information: your Twilio Account SID and Auth Token.
We’ll use their serverless feature (Functions) and not our own back end. If one day you need to send API requests from your servers to Twilio, you know where to find it!
Getting your first phone number and creating your first SMS request
To send SMS (especially in the US and Canada) you’ll need to buy a dedicated phone number, for other countries, you can have a look at Twilio’s regulatory guidelines available on Twilio Website ]
If you want to send an SMS in France, you can skip this step, as buying a French phone number is tricky. This isn’t Twilio’s fault, but a consequence of the rules of the ARCEP (Autorité de Régulation des Communications Électroniques et des Postes). You can go to “Creating your first messaging service”. For France, we’ll use Alpha Senders., which identifies your brand as the sender—it’s required by law in France.
If you need to buy a phone number, go to the left side bar and go to Phone Number > Manage > Buy a Phone Number
Next, select the country where you want to buy a phone number, and click buy.
After confirming, you’re now the proud owner of a new phone number!
Creating your first messaging service
After setting up a new phone number (or an Alpha Sender if you’re in France), type “Messaging Service” in the search bar type “Messaging Service” (You can appreciate another autocomplete experience).
- From the list of suggestions, select Create Messaging Service
- Name your new messaging service, for example, Store Locator and select Notify my users.
- Next, click Add Senders and then Alpha Sender and enter your business name.
- If you bought a phone number, you can select your phone number from a list.
At the end, your messaging service should look similar to what’s shown in the following screenshot
Now, go to Properties and copy your messaging service SID.
Creating a function to send SMS
With the messaging SID, navigate to Functions (you can search for it or find it under Explore Products > Developer Tools > Functions).
Once again, create a service, give it a name, and click Next. An IDE opens in the browser.
Create a new function by clicking on + Add > new function and name it “place-order”. Set its visibility to “public” as we’ll need to call it from outside of Twilio.
Now, go to Dependencies and add the date-fns
package to handle dates.
In the module field, type date-fns
and click add.
Now, let’s add the code responsible for sending the messages:
And that’s all! Click Save and Deploy all, it will take ~2 minutes, and a green check mark will appear next to your function name. The function is now available from the outside by calling the Twilio API with our Twilio credentials.
Note: you can test it using an API explorer such as Postman or Paw.cloud (on macOS)
Calling the place-order function from your code
You’ll find the form component in the Components/ directory. It appears on-screen when you select a store from the list or on the map.
It has three fields: for customer name, pick-up date, and phone number. Now we need to perform the request when we click the “Place Order” button.
We’ll use axios to perform the request, but you can use your preferred library.
Let’s populate the sendRequest()
method:
And that’s all, your app will now send text messages to your customer. These were our last lines of code for this app, it’s now time to deploy it to Clever Cloud!
Deploying your app on Clever Cloud
As a final step, we’re going to deploy the Store Locator to Clever Cloud hosting platform, so you can show your freshly built app to your friends and colleagues.
Go to your Clever Cloud dashboard and click on + Create / An application
Select Create a new application:
Select the type of application: Node. Proceed by clicking Next
Give your app a name, and select your data center.
Finally, select Configuration Provider. This will replace our .local.env file and inject variables in our app at build time. Then click Next and give your configuration provider a name.
On the next screen, click on Expert and copy / paste your .local.env
file.
Add these two lines to the environment variables to use yarn and to build the project after the dependencies are installed:
Click on the green button twice and click on your node machine in the left menu. Follow the steps on top of your screen to add Clever’s git URL to your project and push it! It’ll be available in 3 to 4 minutes using the URL under “domain names”.
Wrapping up
To summarize what we’ve accomplished this week:
- We’ve added an Autocomplete dropdown that complements the existing app experience, allowing users to search for stores by their name, or by location name, so they can then find the nearest store nearby that location.
- We’ve added Twilio support to send texts to our customers.
- We’ve deployed our app on Clever cloud. 🎊
And that’s a wrap for our series about building a Store Locator in React with Algolia, Mapbox, and Twilio. But there are (as always) many more features you can add:
- Leverage the store locator to offer a BOPIS feature
- Send emails rather than SMS, with Twilio SendGrid
- Track and update most clicked store with Twilio Segment
- Add payment options with Stripe APIs
I hope you liked this series! And to paraphrase a CEO and developer I really admire: I can’t wait to see what you’ll build.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK