Update 20190225: Dawid reminded me about the use of IPOI instead of POI if you want pages to inherit the template for geospatial search support. I've updated the article to reference the IPOI template. This makes sense because I have no plans on using the extra fields provided by POI.
Update 20180830: Realized that in this example the search results are not linked to any actual page. Added details below to describe how one might do that.
Here's a preview in case you don't want to read the rest of the post.
Isn't the kitty cute? Moving on...
SXA is bundled with quite a number of search components. Let us see what is in use.
- Location Finder - essentially a search box with label and button.
- Search Results - just like it sounds.
- Filter (Radius) - used to reduce the search results by geospatial comparison.
- Map - a map using the Google Maps JavaScript API.
When you add search components to the page, they automatically interact with one another. In the event you want to have multiple searches on the same page, change the signature property on the components.
I have no need to make the search signature unique for this page so I will leave it empty.
Another interesting part about these components is the use of the hash parameters. In this example, I changed the distance filter to 500 miles and the data was automatically populated in the url.
In the above image, the hash query contains an entry for the geolocation (g), order (o), and distance (DistanceMi).
Let's have a look at each of the search components in greater detail.
Location Finder
This control deals with accepting search criteria from the user in the form of a city, state, or zip code.
As you enter data in the field you'll see the Google Autocomplete feature activate. Selecting the city will immediately trigger the hash query to update with the new location which in turn runs a search.
As of version 1.1 there is no out of the box way to limit the results by country or city.
Note: Before adding this component to the page you'll need to create a few settings.
Distance Facet
I created a new DistanceFacet item to specify that the filter will use the unit of miles. Add a new facet under Settings -> Facets.
Location Filter
Next I created a new LocationFilter item to be used as the data source. This item makes use of the DistanceFacet. Go ahead and set the placeholder text, label text, and finally the button text. Add a new filter under Data -> Search -> Location Filter.
Search Results
This control is responsible for rendering the queried items. We will need an item to specify the search scope.
Scope
The Scope item uses a Sitecore query to get the appropriate data. The query needs to return items that inherit from the POI template which contains fields like Latitude and Longitude. Add a new scope under Settings -> Scopes.
I used this query to get the job done. The default scope is the entire site so be sure to do this. Further down in this post you'll see how I created the POI items returned by this query.
location:{BE88BF74-BBD1-4BB0-A4ED-1E34F477F985};+custom:_templatename|poi
While you are there make sure that the Search Results component has a default data source for use when no results are found under Data -> Search -> Search Results.
Edit the component properties to make use of the scope and default result.
Filter (Radius)
This control enhances the results by filtering our the specified radius (miles or kilometers).Radius Filter
The Radius Filter item specifies which distance facet to use. Add it under Data -> Search -> Radius Filter.
Radius Scheme
The Radius Scheme item specifies which options are available for filtering.
Note: I was not quite sure where to place the Radius Scheme item because no insert option existed so I placed it under Data -> Search -> Radius Filter. I also didn't know the Radius Scheme existed until I dug around to see what I needed to create. Looking forward to the detailed documentation for each of this features in the near future.
Map
This control renders the search results on a map with location markers. The search results need to have the Latitude and Longitude populated for this to work properly. Be sure to create a Map item under Data -> Maps before adding this control to the page.POI Type
The POI Type item provides a way to customize the marker icon. For this demo I created a new POI type under Presentation -> POI Types, which allowed me to specify the awesome SPE custom marker icon.
POI
The POI item as mentioned before contains the Latitude and Longitude necessary for the spatial search to function. I used the POI Group item to help organize the POI items by state. Notice that the Type field uses the custom SPE POI.
Each of the cities are represented by the base POI which comes with a title, description, and image field.
Note: You can also make your pages inherit from the IPOI template. Rather than your locations appearing below the POIs node they would exist in your content tree, somewhere underneath the Home item.
For this to function, create a "Location" feature template which inherits from the IPOI template. Then create a "Location Detail" project template which inherits from "Location". The scope created above then can be adjusted to narrow the results to the tree of location pages as seen below.
Rendering Variants
The creation of new Rendering Variants for these controls is the last piece to making this work. The following should be added or updated to meet your visual needs.
For the POI rendering variant I set the Default Variant on the custom SPE POI. This should influence the presentation of the InfoWindow that appears on the map.
For the Search Results rendering variant I created a new Location Variant and applied it in the Experience Editor for the component.
I styled the rendering variant to help position the title, description, latitude, longitude, and image into the beautiful structure seen above.
Update
After I rolled out a new website using the information in this article, I discovered that I need to use a *VariantTemplate* for the distance.Since the template is using NVelocity, you can add some additional checks so that the markup will be empty with the distance has no value.
#if ($geospatial && $geospatial.Distance) $geospatial.Distance miles #end
Conclusion
That's pretty much all it takes to build a custom Location Finder on your website. The only code required was using SPE to siphon all of the geo data and images into Sitecore.Additional Resources
If you haven't checked out Reinoud's post on Partial Designs and Page Designs I would highly recommend you do that today as it will give you some clue at how to build up the page in this article. Looks like there was even a refresh on the icons too!
I've chosen to use the Basic provided with SXA rather than the Wireframe theme so all my images show up.