Magento 2 is a powerful ecommerce platform that offers extensive customization capabilities. Integrating it with the Google Maps API allows you to leverage the vast location data provided by Google to offer enhanced features to your customers. Providing a seamless and convenient shopping experience is crucial. One way to enhance customer satisfaction is by helping them locate the nearest store locations quickly and efficiently.
In this blog post, In this tutorial, we’ll show you how to create an Ajax-based functionality that returns the nearest store locations based on the user’s zip code. We’ll also learn more about Magento 2 implementation that uses the Google Maps API to find the nearest stores based on a user’s zip code.
ON THIS PAGE
Why Implement a Nearest Store Locator?
Implementing the nearest store locator offers several benefits:
- Improved Customer Experience: Helps customers find the nearest physical stores easily.
- Increased Foot Traffic: Encourages online shoppers to visit physical stores.
- Brand Trust: Provides transparency and convenience, enhancing customer trust in your brand.
10 Steps to Implement Magento 2 with the Google Maps API
Step 1: Create a Google Maps API Key
- Google Maps API Key: You need a Google Maps API key to access Google Maps services. You can obtain it from the Google Cloud Platform.
- Magento 2 Setup: Ensure you have a Magento 2 installation running.
- Visit the Google Cloud Console.
- Create a new project or select an existing one.
- Navigate to the “API & Services” section.
- Enable the following APIs:
- Maps JavaScript API
- Places API
- Geocoding API
7. Generate an API key and restrict its usage to your domain for security purposes.
Step 2: Create a “registration.php”
app/code/DCKAP/NearInstallationStore/registration.php
<?php
<!--
* @package DCKAP_NearInstallationStore
* @copyright Copyright (c) 2023 DCKAP Inc (http://www.dckap.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
-->
use Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(ComponentRegistrar::MODULE, DCKAP_NearInstallationStore, __DIR__);
Step 3: Create a “Module.xml”
app/code/DCKAP/NearInstallationStore/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="DCKAP_NearInstallationStore" setup_version="1.0.7">
</module>
</config>
Step 4: Create a “routes.xml”
app/code/DCKAP/NearInstallationStore/etc/frontend/routes.xml
<?xml version="1.0"?>
<!--
* @package DCKAP_NearInstallationStore
* @copyright Copyright (c) 2023 DCKAP Inc (http://www.dckap.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
<router id="standard">
<route id="dckap_nearinstallationstore" frontName="dckap_nearinstallationstore">
<module name="DCKAP_NearInstallationStore" />
</route>
</router>
</router>
</config>
Step 5: Setup Google Map API Credentials
First, configure your Google Map API credentials in Magento 2, and here’s how you can do it:
app/code/DCKAP/NearInstallationStore/etc/adminhtml/system.xml
<?xml
Copy code
<?xml version="1.0" ?>
<!--
* @package DCKAP_NearInstallationStore
* @copyright Copyright (c) 2023 DCKAP Inc (http://www.dckap.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
<system>
<section id="dckap_nearinstallationstore" translate="label" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Google Map Services</label>
<tab>dckap</tab>
<resource>DCKAP_NearInstallationStore::config_nearinstallationstore</resource>
<group id="api_credentials" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Google Map API Credentials</label>
<field id="google_map_key" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Google Map Key</label>
</field>
</group>
</section>
</system>
</config>
Step 6: Create the Helper Class
Create a helper class to fetch the Google Map API key from the configuration:
app/code/DCKAP/NearInstallationStore/Helper/Data.php
<?php
<!--
* @package DCKAP_NearInstallationStore
* @copyright Copyright (c) 2023 DCKAP Inc (http://www.dckap.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
-->
namespace DCKAP\NearInstallationStore\Helper;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Store\Model\ScopeInterface;
class Data extends AbstractHelper
{
const XML_PATH_GOOGLE_MAP_KEY = dckap_nearinstallationstore/api_credentials/google_map_key';
/**
* @param null $store
* @return mixed
*/
public function getGoogleMapKey($store = null)
{
return $this->scopeConfig->getValue(self::XML_PATH_GOOGLE_MAP_KEY, ScopeInterface::SCOPE_STORE, $store);
}
}
Step 7: Controller for Ajax Request
Create a controller to handle the Ajax request and fetch the nearest store locations:
app/code/DCKAP/NearInstallationStore/Controller/Ajax/GetNearestStoresLocations.php
<?php
<!--
* @package DCKAP_NearInstallationStore
* @copyright Copyright (c) 2023 DCKAP Inc (http://www.dckap.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
-->
<!--
* @package DCKAP_NearInstallationStore
* @copyright Copyright (c) 2023 DCKAP Inc (http://www.dckap.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
-->
namespace DCKAP\NearInstallationStore\Controller\Ajax;
use Magento\Framework\App\Action\Action;
use Magento\Framework\Controller\Result\JsonFactory;
use DCKAP\NearInstallationStore\Model\StoreFactory;
use DCKAP\NearInstallationStore\Helper\Data;
class GetNearestStoresLocations extends Action
{
protected $resultJsonFactory;
protected $storeFactory;
protected $helperData;
public function __construct(
\Magento\Framework\App\Action\Context $context,
JsonFactory $resultJsonFactory,
StoreFactory $storeFactory,
Data $helperData
) {
$this->resultJsonFactory = $resultJsonFactory;
$this->storeFactory = $storeFactory;
$this->helperData = $helperData;
parent::__construct($context);
}
public function execute()
{
if ($this->getRequest()->isAjax()) {
$id = $this->getRequest()->getParams('q');
$zipCode = $id['q'];
$googleMapKey = $this->helperData->getGoogleMapKey();
$result = $this->resultJsonFactory->create();
$installationStore = $this->storeFactory->create();
$installationStoreDet = $installationStore->getCollection();
$array = [];
foreach ($installationStoreDet as $installationStore) {
$locDet = [];
$locDet = $installationStore->getAddress();
array_push($array, $locDet);
}
$List = implode('|', $array);
$distanceDurationUrl = "https://maps.googleapis.com/maps/api/distancematrix/json?origins=".$zipCode."&destinations=".urlencode($List)."&units=imperial&key=".$googleMapKey;
$response_a = $this->curlDetails($distanceDurationUrl);
$status =$response_a['status'];
$origin_addresses =$response_a['origin_addresses'];
$destination_addresses =$response_a['destination_addresses'];
if (isset($origin_addresses[0]) && !empty($origin_addresses[0])){
$element = $response_a['rows'][0]['elements'];
$storeDistanceArray = [];
foreach($element as $key => $ele){
if($ele['status'] == 'ZERO_RESULTS'){
$dataMessage = ['message' => 'No Distance Found'];
$result->setData($dataMessage);
return $result;
} else {
$durArray = [];
$durArray['distance_text'] = $ele['distance']['text'];
$durArray['distance_value'] = $ele['distance']['value'];
$durArray['duration_text'] = $ele['duration']['text'];
$durArray['duration_value'] = $ele['duration']['value'];
$durArray['i_key'] = ['key' => $key, 'dest_addr' => $response_a['destination_addresses'][$key]];
array_push($storeDistanceArray, $durArray);
}
}
$key_values = array_column($storeDistanceArray, 'distance_value');
array_multisort($key_values, SORT_ASC, $storeDistanceArray);
$destinationStoreArray = [];
foreach($storeDistanceArray as $storeDistanceAr){
$destaddrArray = [];
$destaddrArray['dest_addr'] = $storeDistanceAr['i_key']['dest_addr'];
$destaddrArray['distance_text'] = $storeDistanceAr['distance_text'];
$destaddrArray['duration_text'] = $storeDistanceAr['duration_text'];
array_push($destinationStoreArray, $destaddrArray);
}
$firstThreeShortDistance = array_slice($destinationStoreArray, 0, 5);
$firstThreeShortDistanceStoreArray = [];
foreach($firstThreeShortDistance as $firstThreeShortDist){
$collectionData = $this->installationStoreDetailsByAddress($firstThreeShortDist);
array_push($firstThreeShortDistanceStoreArray, $collectionData);
}
$firstThreeShortData = [];
foreach($firstThreeShortDistanceStoreArray as $firstThreeShortDistanceStoreA){
$firstThreeShortDataStore = [];
$firstThreeShortDataStore['getaddress'] = $firstThreeShortDistanceStoreA['getaddress'][0];
$firstThreeShortDataStore['installation_name'] = $firstThreeShortDistanceStoreA['getaddress'][0]['installation_name'];
$firstThreeShortDataStore['location_number'] = $firstThreeShortDistanceStoreA['getaddress'][0]['location_number'];
$firstThreeShortDataStore['address'] = $firstThreeShortDistanceStoreA['getaddress'][0]['address'];
$firstThreeShortDataStore['getdistancetext'] = $firstThreeShortDistanceStoreA['getdistancetext'];
$firstThreeShortDataStore['getdurationtext'] = $firstThreeShortDistanceStoreA['getdurationtext'];
$response_b = $this->getPlaceId($firstThreeShortDataStore);
$firstThreeShortDataStore['responseB'] = $response_b;
foreach($firstThreeShortDataStore['responseB']['results'] as $firstThreeShortDatas){
$response_c = $this->getPlaceOpenCloseHours($firstThreeShortDatas);
$firstThreeShortDataStore['openinghours'] = $response_c['result']['opening_hours']['weekday_text'];
}
array_push($firstThreeShortData, $firstThreeShortDataStore);
}
$result->setData($firstThreeShortData);
return $result;
} else {
$data = ['message' => 'No Zipcode Found'];
$result->setData($data);
return $result;
}
}
}
public function curlDetails($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_PROXYPORT, 3128);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
public function getPlaceId($firstThreeShortDataStore){
$addressString = $firstThreeShortDataStore['address'];
$encodedAddressString = urlencode($addressString);
$googleMapKey = $this->helperData->getGoogleMapKey();
$getPlaceIdUrl = "https://maps.googleapis.com/maps/api/place/findplacefromtext/json?input=".$encodedAddressString."&inputtype=textquery&fields=place_id,name,geometry&key=".$googleMapKey;
return $this->curlDetails($getPlaceIdUrl);
}
public function getPlaceOpenCloseHours($firstThreeShortDatas){
$placeId = $firstThreeShortDatas['place_id'];
$googleMapKey = $this->helperData->getGoogleMapKey();
$getPlaceOpenCloseHoursUrl = "https://maps.googleapis.com/maps/api/place/details/json?place_id=".$placeId."&fields=name,opening_hours&key=".$googleMapKey;
return $this->curlDetails($getPlaceOpenCloseHoursUrl);
}
public function installationStoreDetailsByAddress($firstThreeShortDist){
$installationStore = $this->storeFactory->create();
$collection = $installationStore->getCollection();
$collection->addFieldToFilter('address', $firstThreeShortDist['dest_addr']);
$dataArray = [];
$dataArray['getaddress'] = $collection->getData();
$dataArray['getdistancetext'] = $firstThreeShortDist['distance_text'];
$dataArray['getdurationtext'] = $firstThreeShortDist['duration_text'];
return $dataArray;
}
}
Step 8: Creating the Model
Create a model to manage the stored data:
app/code/DCKAP/NearInstallationStore/Model/Store.php
<?php
<!--
* @package DCKAP_NearInstallationStore
* @copyright Copyright (c) 2023 DCKAP Inc (http://www.dckap.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
-->
namespace DCKAP\NearInstallationStore\Model;
use Magento\Framework\Model\AbstractModel;
class Store extends AbstractModel
{
protected function _construct()
{
$this->_init('DCKAP\NearInstallationStore\Model\ResourceModel\Store');
}
}
Step 9: Create a resource model for the store:
app/code/DCKAP/NearInstallationStore/Model/ResourceModel/Store.php
<?php
<!--
* @package DCKAP_NearInstallationStore
* @copyright Copyright (c) 2023 DCKAP Inc (http://www.dckap.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
-->
namespace DCKAP\NearInstallationStore\Model\ResourceModel;
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
class Store extends AbstractDb
{
protected function _construct()
{
$this->_init('dckap_store', 'entity_id');
}
}
And create a collection class for the resource model:
app/code/DCKAP/NearInstallationStore/Model/ResourceModel/Store/Collection.php
<?php
<!--
* @package DCKAP_NearInstallationStore
* @copyright Copyright (c) 2023 DCKAP Inc (http://www.dckap.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
-->
namespace DCKAP\NearInstallationStore\Model\ResourceModel\Store;
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use DCKAP\NearInstallationStore\Model\Store as Model;
use DCKAP\NearInstallationStore\Model\ResourceModel\Store as ResourceModel;
class Collection extends AbstractCollection
{
protected function _construct()
{
$this->_init(Model::class, ResourceModel::class);
}
}
Step 10: Frontend Implementation
Once we enter the zip code in the input text box and submit it, this will call the AJAX controller to fetch all the nearest stores available for the customer. Implement the frontend part to make the AJAX call and display the results. Now, create the necessary JavaScript and HTML files to complete this part.
Enhanced User Experience Magento 2 and Google Maps API
1. Quick and Accurate Store Locator
Customers no longer need to manually browse through a list of addresses to find the closest stores. To deliver the most precise and current information, this feature takes advantage of real-time data
2. Real-time Distance and Duration
Customers can see the nearest stores and also get real-time distance and travel duration, open, and closing times of the store to help them make informed decisions about which store to visit.
Find the Nearest Stores using Magento 2 and Google Maps API with Klizer
Integrating Google Maps API with Magento 2 can significantly enhance your ecommerce store’s functionality by providing real-time location-based services. By following the steps outlined in this blog post, you can offer your customers a seamless experience in finding the nearest store locations.
If you are looking to integrate Google Maps API with Magento 2 and need an expert consultation, get in touch with our team at Klizer.