Skip to main content

Sitecore

SXA Map Component Part 8 Google Ratings and Reviews in Search Results

Glacier

Challenge:

While using the SXA Map with Search Results to explore nearby locations or businesses, I want to include Google ratings and reviews in the search results. This addition will allow me to gather valuable insights about each location or business without clicking on individual markers to open an info window.

Solution:

A quick look at the following output of the implementation discussed in this post so we get more clarity.

Quick Look Google Rating And Reviews In Search Results With SXA Map

Quick Look – Google Rating And Reviews In Search Results With SXA Map

Here, we have multiple renderings like Location Finder (Location Filter), SXA Map, and Search results. This time, we don’t need to supply a POI item or POI folder in the Map data source’s POI field. Yes, it should be empty.

To set up a page with these three components, please check the post: SXA Map component Part 2 With Search results and Location Finder.

To add Google average rating and total reviews in the info window of the markers and to show the Modal to view the most relevant reviews, please check the following posts. Simply implement the steps, excluding the page setup part, since we will consider the page from the above post.

SXA Map component Part 6 Google average rating and total reviews

SXA Map component Part 7 Most Relevant Google reviews

Once we finish the implementation discussed in the above posts, we proceed with the remaining page setup part configured from the post: SXA Map component Part 2 With Search results and Location Finder. In my case, I have considered the page path as /sitecore/content/<tenant>/<site> /Home/Location Demo/Google review and rating demo/Location Search Result.

Error due to Google Maps JavaScript API Script Being Included Multiple Times and its Fix

Now, once we browse the page URL for /sitecore/content/<tenant>/<site> /Home/Location Demo/Google review and rating demo/Location Search Result, we get below Google error.

Google Maps JavaScript API Multiple Times On This Page Error

Google Maps JavaScript API Multiple Times On This Page Error

We get an error – “You have included the Google Maps JavaScript API multiple times on this page. This may cause unexpected errors”.

This is because the script “https://maps.googleapis.com/maps/api/js?v=3.exp” gets added twice. Initially, this is included in google-maps-connector.js at /sitecore/media library/Base Themes/Google Maps JS Connector/Scripts/google-maps-connector, and we have overridden this file logic in our custom-google-maps-connector.js. We get this error only on this page where we have the “Location Finder” component. This component’s JS file – component-search-location-filter.js at /sitecore/media library/Base Themes/SearchTheme/Scripts/component-search-location-filter, calls the “XA.connector.mapsConnector.scriptsLoaded” function from the default google-maps-connector.js which includes the Google Map JavaScript API  script file and later our custom-google-maps-connector.js does the same job itself and hence the error results.

To resolve this error, let’s download the file custom-google-maps-connector.js. Traverse to item path – /sitecore/media library/Base Themes/Google Maps JS Connector/Scripts/google-maps-connector. Attach the downloaded file to this path. Basically, we override the original file itself. Please consider the source controlling this item or journal it somewhere since we updated the base theme item. Secondly, disable the custom-google-maps-connector.js in the Theme script folder, i.e., rename it to the “. disabled” extension, or it can be deleted.

Build and upload the Site Theme folder, or build with your custom command, if any. Or we build later in some time.

The “Google Maps JavaScript API multiple times” error should be resolved now post SXA Theme build.

Add a new Search Result Variant

Traverse to the currently assigned variant to Search results. In my case, it is /sitecore/content/<Tenant>/<Site>/Presentation/Rendering Variants/Search Results/Locations.

Duplicate this item and rename it “Locations with Rating and Reviews”. Now we have /sitecore/content/<Tenant>/<Site>/Presentation/Rendering Variants/Search Results/Locations with Rating and Reviews. Right-click this item > Insert > Scriban. Name it as “Rating and Review”. Move down the Scriban item to last so Rating and Review info appears at the end of the variant output. Update its “Template” field value with the below code.

{{ divid =  i_item.id | string.remove '{' | string.remove '}' }}
<div id='{{divid}}-rating-and-review-search-result' class='rating-and-review-search-result'>
    <div class='title'>
        {{i_item.title}}
    </div>
    <div class='description'>
        {{i_item.description}}
    </div>
    <div class='rating-and-review d-none' id='{{divid}}-rating-and-review'>
        Average Rating #average_rating# Review count #review_count#
    </div>
    <div class='no-rating-and-review' id='{{divid}}-no-rating-and-review'>
        No reviews
    </div>
</div>

Traverse to the page item and update the variant to this new one for Search Results rendering.

Mapping new POI Variant to Map

Traverse to the data source item of the SXA Map on the page, update the “POI type to rendering variant mapping” field as below, i.e., “Simple POI” POI type maps to “Marker with Rating and Review”.

3 Poi Type To Rendering Variant Mapping

Add Modal for Google Rating and Reviews

Let’s add a Plain HTML (Reusable) rendering on the page and update its data source’s code field value with code given in the section “Create a Modal Template for the most relevant Google reviews and other general data of the Business or Location” of the post – SXA Map component Part 7 Most Relevant Google reviews.

Google Ratings and Reviews in Search Results

Let’s perform the critical implementation of adding Google ratings and reviews in Search Results. Here, we show the Google average rating and total reviews and bind the click event on the search result item to open the Modal for the most relevant reviews with other general data.

Download the file  custom-location-rating-and-review.js and upload it to the site theme script folder /sitecore/media library/Themes/{tenant}/{site}/{theme}/Scripts or copy to your <RootThemeFolder>\ <SiteTheme>\scripts folder.

Following is the code update we made in custom-location-rating-and-review.js to support the Google Rating and review binding for Search results rendering.

api.listenSearchResultLoaded = function() {
    XA.component.search.vent.on("results-loaded", function(i) {
        var searchResultItemRatingReviewDiv = $('.rating-and-review-search-result');
        if(searchResultItemRatingReviewDiv.length > 0) {
            //XA.connector.mapsConnector.loadScript is function that accepts key and a function which is called once the Google Map API JavaScript file is loaded
            XA.connector.mapsConnector.loadScript(searchResultItemRatingReviewDiv.attr("id"), function(){
                searchResultItemRatingReviewDiv.each(function() {
                var ratingReviewMainDivId = $(this).attr("id");
                var poiId = ratingReviewMainDivId.replace('-rating-and-review-search-result','');
                var ratingReviewDivId = `${poiId}-rating-and-review`;
                var noRatingReviewDivId = `${poiId}-no-rating-and-review`;
                var locationTitleText = $(`#${ratingReviewMainDivId} .title`).text();
                    api.setRatingAndReviewBySearchText(ratingReviewDivId,noRatingReviewDivId,locationTitleText);
                });                     
            });
        }               
    });     
}

setRatingAndReviewBySearchText() function has been used in listenInfowindowOpenEvent() for Info Window already, and we have reused the same code here for search results when the results are loaded.

listenSearchResultLoaded() function is called in the init() of custom-location-rating-and-review.js.

Click event in getRatingAndReviewByPlaceID() is updated with the below code to support the Location name shown in the Modal opened upon click from both the Info window and the search results item.

var locationName = $(`#${ratingAndReviewDiv.attr('id')}-main .title`).text() || $(`#${ratingAndReviewDiv.attr('id')}-search-result .title`).text(); //supporting both the clicks binded for map marker info window and search results items
4 Custom Location Rating And Review Js Code Update

custom-location-rating-and-review.js code update

XA.connector.mapsConnector.loadScript() Code Enhancement

We have enhanced the custom-google-maps-connector.js code to ensure it calls the callback appropriately, as shown below. It ensures to call the callback function if the Google Maps API is loaded. Meaning if “typeof google” is defined, it calls the callback function. This improvement prevents potential issues where XA.connector.mapsConnector.loadScript() in listenSearchResultLoaded() might occasionally fail to run the callback function.

api.loadScript = function(key, callback) {
    //save each callback and call them all when script will be loaded - protection for loading maps twice
    callbacks.push(callback);

    if (!loading) {
        loading = true;
        if (typeof google === "undefined") {
            var script = document.createElement("script"),
                src = "https://maps.googleapis.com/maps/api/js?v=3.exp";
            script.type = "text/javascript";
            if (typeof key !== "undefined" && key !== "") {
                src += "&key=" + key + "&v=3.exp&signed_in=false";
            } else {
                src += "&signed_in=false";
            }
            src += "&libraries=places&callback=XA.connector.mapsConnector.scriptsLoaded";
            script.src = src;
            script.onload = function () {
                console.log("Google loader has been loaded, waiting for maps api");
            };
            document.body.appendChild(script);
        }
        else
        {
            // Google Maps API has already been loaded, no need to add it again
            console.log("Google Maps API is already loaded");
            callback.call(); //call the callback if the google is defined 
        }
    }
    else if(typeof google !== "undefined") 
    {
        callback.call(); //call the callback if the google is defined and the loading has finished
    }
};

If our custom code depends on the Google Maps API script being loaded, we can pass our custom function as a callback to XA.connector.mapsConnector.loadScript() with a unique key. When the Google Maps API script is loaded, our custom function will execute. Also, the enhanced code ensures that our function is called, even if the Google Maps API script is already loaded.

Run the following commands in PowerShell from the Site Theme folder, or build with your custom command, if any.

gulp buildAll

sxa upload All

Demo

Final demo showing the items and page.

Demo Google Rating And Reviews In Search Results With SXA Map

Demo Google Rating And Reviews In Search Results With SXA Map

Hope this helps, and please do check out other SXA Map component posts for more enhancements around Map.

Happy Sitecore Learning!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Sandeepkumar Gupta

Sandeepkumar Gupta is a Lead Technical Consultant at Perficient. He enjoys research and development work in Sitecore. He has contributed to Sitecore projects based on SXA, ASP.NET MVC, and Web Forms. He has also contributed to Sitecore upgrade projects.

More from this Author

Categories
Follow Us