Prerequisites

  • You have read the doc WebApps - Searching by location
  • You have WebApp items prepared with location data
  • You have a Google Projects API Key - You can either hardcode this, or add it to the 'Integrations' area in Siteglide, please ensure the following settings are enabled:

    - Must have billing enabled on Google Cloud API account
    - Must have "Maps JavaScript API" enabled
    - Must have "Geocoding API" enabled

For more information on setting up Google accounts and projects, see here.


Introduction

In this example we'll show you how to add a location search to a Page, and then output the results of that search both in a list and on a map. Items will display in the result set when they are within the radius of a chosen location. One example of how you can use this is as a Store Locator for a franchise of Shops.


Step by Step

<script src="https://maps.googleapis.com/maps/api/js?key={{context.exports.integrations.properties.google_api_key}}{%- if context.params.distance and context.params.longlat -%}&callback=initMap{%- endif -%}">
</script>




Step 2) Add an HTML Form and JavaScript to take User input to decide starting position and search radius


Two different options are provided in this example:


a) Current location (using browser default functionality) and desired search radius

Add HTML

<form>

<h3 style="margin-bottom: 5rem;">Current Location</h3>
<h5 class="mb-3">Change search distance</h5>
<div class="row">
<div class="col-12">
<input class="form-control mb-3" type="number" id="current_locations_distance" placeholder="10"/>
<button class="btn btn-secondary float-none" onclick="getMyLocation()" >Find stores near me <i class="fas fa-arrow-right"></i></button>
</div>
</div>
</form>

Add JavaScript

<script>
function getMyLocation() {
event.preventDefault();
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition(showMyPosition);
}else{
alert("Geolocation is not supported by this browser.");
}
function showMyPosition(position){
var distance = document.querySelector('#current_locations_distance').value ? document.querySelector('#current_locations_distance').value : 10;
window.location.replace(window.location.pathname+"?longlat="+position.coords.longitude+","+position.coords.latitude+"&distance="+distance);
}
}
</script>


b) A location of their choice and desired search radius


Add HTML

<form>

<h3 class="mb-3">Search by Location</h3>
<div class="row">
<div class="col-12">
<input class="form-control mb-3" type="text" id="address" placeholder="Postcode, town or area" />
</div>
</div>
<h5 class="mb-3">Change search distance</h5>
<div class="row">
<div class="col-12">
<input class="form-control mb-3" type="number" id="search_locations_distance" placeholder="10"/>
<button class="btn btn-secondary" onclick="getLocation()" value="Encode">Search stores by location <i class="fas fa-arrow-right"></i></button>
</div>
</div>
</form>

Add JavaScript

<script>
function getLocation() {
var geocoder;
event.preventDefault();
var address = document.getElementById('address').value;
geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == 'OK') {
var setCenter = results[0].geometry.location;
var dist = document.querySelector('#search_locations_distance').value ? document.querySelector('#search_locations_distance').value : 10 ;
window.location.replace(window.location.pathname+"?longlat="+ results[0].geometry.location.lng()+","+results[0].geometry.location.lat()+"&distance="+dist);
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
</script>

Step 3) Output the results on the Page in a simple list

Use a Layout of your choice.

{%- include 'webapp', id: '1', use_location_search: 'true', layout: 'default' -%}

Step 4) Output the results on a map

This relies on there being a layout named 'json'. See the contents of 'json' in the 2nd block of code.

Add HTML + Liquid

The Liquid makes sure the map is only outputted after the Page has been refreshed by the JavaScript and the correct parameters are available in the URL for filtering the results.

{%- if context.params.distance and context.params.longlat -%}

<div class="map-container" style="background: #f5f5f5;">
<h2 class="text-center">Store Locations</h2>
<div id="map" style="height:800px"></div>
<span id="map_content" style="display:none">{%- include 'webapp', id: '2', use_location_search: 'true', layout: 'json', type: 'list' -%}</span>
</div>
{%- endif -%}

Add JavaScript

The following function is triggered by the script from step 1, only after it has finished loading- this occurs because the function's name is referenced in the URL parameter fetching the Script. The code must be placed above the <script> tag from step 1.

<script>
function initMap() {
window.addEventListener('DOMContentLoaded', function() {
var distance = {{context.params.distance | default: 10 }};
var center = "{{context.params.longlat}}".split(',');
console.log(center)
center = { lat: parseFloat(center[1]), lng: parseFloat(center[0]) };
var map = new google.maps.Map(
document.getElementById('map'), {zoom: 8, center: center}
);
new google.maps.Circle({
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35,
map: map,
center: center,
radius: distance*1000
});
var locations = "{"+document.querySelector('#map_content').innerText.trim().slice(0, -1)+"}";
locations = JSON.parse(locations);
console.log(locations)
Object.keys(locations).forEach(function(k){
var marker = { lat: locations[k].latlong.coordinates[1], lng: locations[k].latlong.coordinates[0] };
new google.maps.Marker({position: marker, map: map});
});
});
}
</script>

Layout 'json':

"{{this.id}}": {

"name": "{{this.name}}",
"latlong": {{this.location | json}},
"address": "{{this.address}}"
},


Full example

<script>

function getLocation() {
var geocoder;
event.preventDefault();
var address = document.getElementById('address').value;
geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == 'OK') {
var setCenter = results[0].geometry.location;
var dist = document.querySelector('#search_locations_distance').value ? document.querySelector('#search_locations_distance').value : 10 ;
window.location.replace(window.location.pathname+"?longlat="+ results[0].geometry.location.lng()+","+results[0].geometry.location.lat()+"&distance="+dist);
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
function initMap() {
window.addEventListener('DOMContentLoaded', function() {
var distance = {{context.params.distance | default: 10 }};
var center = "{{context.params.longlat}}".split(',');
console.log(center)
center = { lat: parseFloat(center[1]), lng: parseFloat(center[0]) };
var map = new google.maps.Map(
document.getElementById('map'), {zoom: 8, center: center}
);
new google.maps.Circle({
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35,
map: map,
center: center,
radius: distance*1000
});
var locations = "{"+document.querySelector('#map_content').innerText.trim().slice(0, -1)+"}";
locations = JSON.parse(locations);
console.log(locations)
Object.keys(locations).forEach(function(k){
var marker = { lat: locations[k].latlong.coordinates[1], lng: locations[k].latlong.coordinates[0] };
new google.maps.Marker({position: marker, map: map});
});
});
}
function getMyLocation() {
event.preventDefault();
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition(showMyPosition);
}else{
alert("Geolocation is not supported by this browser.");
}
function showMyPosition(position){
var distance = document.querySelector('#current_locations_distance').value ? document.querySelector('#current_locations_distance').value : 10;
window.location.replace(window.location.pathname+"?longlat="+position.coords.longitude+","+position.coords.latitude+"&distance="+distance);
}
}
</script>
<section class="sg-form sg-form-08">
<div class="container text-center">
<h1 class="mb-3 h2 sg-h2">Search for Stores within your area</h1>
<div class="alert alert-warning mb-5"><strong>The map demo bellow requires a Google API key, which can be added to Site Manager/ Integrations.</strong><br>Please fill one of the Forms above to view the map demo.</div>
<div class="row">
<div class="col-12 col-lg-6">
<div class="card">
<div class="card-body text-center">
<i class="fas fa-crosshairs fa-2x mb-2"></i>
<form>
<h3 style="margin-bottom: 5rem;">Current Location</h3>
<h5 class="mb-3">Change search distance</h5>
<div class="row">
<div class="col-12">
<input class="form-control mb-3" type="number" id="current_locations_distance" placeholder="10"/>
<button class="btn btn-secondary float-none" onclick="getMyLocation()" >Find stores near me <i class="fas fa-arrow-right"></i></button>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="col-12 col-lg-6">
<div class="card">
<div class="card-body text-center">
<i class="fas fa-search fa-2x mb-2"></i>
<form>
<h3 class="mb-3">Search by Location</h3>
<div class="row">
<div class="col-12">
<input class="form-control mb-3" type="text" id="address" placeholder="Postcode, town or area" />
</div>
</div>
<h5 class="mb-3">Change search distance</h5>
<div class="row">
<div class="col-12">
<input class="form-control mb-3" type="number" id="search_locations_distance" placeholder="10"/>
<button class="btn btn-secondary" onclick="getLocation()" value="Encode">Search stores by location <i class="fas fa-arrow-right"></i></button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="sg-content sg-content-02">
<div class="container">
{%- include 'webapp', id: '1', use_location_search: 'true', layout: 'default' -%}
</div>
</section>
<style>
.sg-form.sg-form-08 {
background: #f5f5f5;
}
@media screen and (min-width: 992px) {
.sg-form.sg-form-08 {
padding: 80px 0;
}
}
/*custom stying*/
.sg-form.sg-form-08 .card-body {
padding: 25px;
}
.sg-form.sg-form-08 .card {
height: 375px;
}
.sg-form.sg-form-08 input {
width: 100%;
}
.sg-form.sg-form-08 .btn-secondary {
width: 100%;
}
@media only screen and (max-width: 992px) {
.sg-form.sg-form-08 .card {
height: 395px;
}
.sg-form.sg-form-08 .col-lg-6:first-of-type .card {
height: 375px;
}
}
@media only screen and (max-width: 334px) {
.sg-form.sg-form-08 .card {
height: 450px !important;
}
.sg-form.sg-form-08 .card .btn {
padding: 12px 17px !important;
}
}
</style>
<script
src="https://maps.googleapis.com/maps/api/js?key={{context.exports.integrations.properties.google_api_key}}{%- if context.params.distance and context.params.longlat -%}&callback=initMap{%- endif -%}">
</script>
{%- if context.params.distance and context.params.longlat -%}
<div class="map-container" style="background: #f5f5f5;">
<h2 class="text-center">Store Locations</h2>
<div id="map" style="height:800px"></div>
<span id="map_content" style="display:none">{%- include 'webapp', id: '2', use_location_search: 'true', layout: 'json', type: 'list' -%}</span>
</div>
{%- endif -%}
Did this answer your question?