, , , , , , ,

google-store-locator-in-fb-using-drupalUsually we have used the google store locator in our site or in any web pages. But have you ever think that if we could be able to integrate the google store locator with the Facebook and our server ? What if we could be able to save our desired stores into our server and we could be able to show that dynamically into FB page. Wake up! It’s pretty easy and it’s available for you…

So lets meet the so long desired wishes…

– Here we’ll send the data to FB and will create the magic over there.
– Then we’ll use Drupal for server side. We will go for some third party modules to prepares the store locator list. From that store list we will collect/filter them according to the sent data from FB side through ajax call.

FB side configuration and procedure:
choose-static-html-fb-app– First we have to know how we could add a html page with an app. So login to FB account then in search field search with the key word “static HTML: iframe tabs”, you’ll get an app at the first with the same name. So choose it and add in your account.
– Now create a page going to here and the choice is yours what kind of page you will create.
– Then after page creation navigate to the page and choose the ‘Welcome’ tab( check with the screen shots ).open-page-edit-option
– Now put you html in html part, put your css, js in separate parts. Lets take a look to the pic and the example.fb-side-editing-section
– Here we are providing a static location’s lat/lng and we will collect the stores of it’s surrounding area. Apart from that we will provide an option to search with location name and the region range.



HTML part:

<!DOCTYPE html>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />

<!-- Include custom CSS file -->

<!-- Include jQuery library from google storage -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>

<!-- Include Google Map API with API Key -->
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyA8r8RqY3PD-5Zx40dLqiU5UXcEZPTPLHc&sensor=false"></script>

<!-- Include custom scrip file -->

<!-- Google Map search option section -->
<div id="serct-section">
<input id="address" type="textbox" value="">
<select  id="region">
<option value="0">- Select Region -</option>
<option value="50">50 km</option>
<option value="100">100 km</option>
<option value="150">150 km</option>
<input type="button" value="Search" onclick="searchByName()">

<!-- GMap integration section -->
<div id="map-canvas"></div>

JS part:

* @file
* - This ja file provides the main functionality of the store loactor.
*   From this file we are collecting the user provided data for searching
*   the store of the mentionewd location along with the rigion and then
*   call the Google Map APIs to retrive the maps. Apart from that, it calls
*   ajax call to retrive the db stored store locations and then return here.
* - Sevaral Google Map API calls are being done here.

// Global variable declaration.
var geocoder = null;
var map = null;
var circle = null;
var searchedLocation = null;
var positionDetails = null;
var markerPlaces;

* Method Name: initialize()
* - Prepares user mentioned location map.
* @param:
* - No parameter are being passed.
function initialize() {
// Specifices the user mentioned location's latitude and longitude.
var lat = 20.2960587; // Latitude of the mentioned location.
var lng = 85.8245398; // Longitude of the mentioned location.
var combLoc = lat + ',' + lng;
var region = 50; // Provides the user defined region.

// Ajax call to the server to collect the nearby store locations.
ajax_nearby_store_collection(combLoc, region);

* Method Name: createMap()
* - Prepares the GMap according to the current place location's
*   latitude and longitude.
* @param:
*   lat(numeric(float)): Holds location latitude.
*   lng(numeric(float)): Holds location longitude.
*   region(numeric(float/integer)): Holds search region(km/miter).
function createMap(lat, lng, region) {
// Assign G-Map geocoder object into the global variable.
geocoder = new google.maps.Geocoder();

// Prepares the Latitude and Longitude variable to use building map.
var latLong = new google.maps.LatLng(lat, lng);

// Calculate the zoom level according to the selected rigion range.
var zoomLevel; // Zoom level varible declaration.
switch(region) {
case '50':
zoomLevel = 8;
case '100':
zoomLevel = 7;
case '150':
zoomLevel = 6;
zoomLevel = 9;

// Prepares the map options and stores in a variavle.
var mapOptions = {
center: latLong,
zoom: zoomLevel

// Creates the map.
map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);

// Creates the rigion circulated circle to highlight the surounding area.
circle = new google.maps.Circle({
center: latLong,
radius: region*1000, // Converts kilomoters to meters.
fillColor: '#FF0000',
fillOpacity: 0.1,
map: map

* Method Name: setMarkers()
* - Prepares markers and plced it in the map.
* @param:
*   map(object): Holds the map object.
*   locations(array): Holds store places.
function setMarkers(map, locations) {
// Search for the consecutive marker places.
jQuery.each(locations, function(i, item) {
// Collect the sent stores latitude and longitude of individual stores
var myLatLng = new google.maps.LatLng(item.gsl_geofield_lat, item.gsl_geofield_lon);

// Set the markers in the G Map.
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
zIndex: i

// Attach separate markers to separate locations.
attachSecretMessage(marker, item.title, item.gsl_addressfield_thoroughfare);

* Method Name: attachSecretMessage()
* - Prepares markers info window.
* @param:
*   marker(object): Holds the marker object.
*   title(string): Holds the store's name.
*   info(string): Holds the store's address.
function attachSecretMessage(marker, title, info) {
// Attach the info window with the G-Map.
var contentString = '<div id="content">'+ '<div id="siteNotice">'+ '</div>'+ '<h2 id="firstHeading" >' + title + '</h2>'+ '<div id="bodyContent">'+ '<p>' + info + '</p></div>' + '</div>';
var infowindow = new google.maps.InfoWindow({
content: contentString

// Integrates the click event feature for the info window.
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(marker.get('map'), marker);

* Method Name: codeAddress()
* - processes the searched location's position in the map.
* @param:
* - No parameter is being passed.
function searchByName() {
// Collects the requested place's address and the mentioned region area.
var address = document.getElementById("address").value;
var selectedRegion = document.getElementById("region").value;

if ( address != '' && selectedRegion != 0 ) {
// Get the geo location off the requested place and through an ajax call get the nearby store locations.
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var searchedLocation = results[0].geometry.location;
searchedLocationVal = searchedLocation.toString();

// Filteres the latitude and langitude.
var locationPos = searchedLocationVal.substring(1);
locationPos = locationPos.substring(0, locationPos.length - 1)
locationPos = locationPos.split(', ');
var lat = locationPos[0];
var lng = locationPos[1];
var combLoc = lat + ',' + lng;

// Ajax call to the server to collect the nearby store locations.
ajax_nearby_store_collection(combLoc, selectedRegion);
} else {
alert("Please provide a specific place address and try again.");
else {
alert('Please try again with providing proper location name and region for bettter search!');

* Method Name: ajax_nearby_store_collection()
* - Processes nearby stores and plce them in the map with maarker.
* @param:
*   combLoc(object): Holds all the stores locations.
*   region(numeric(integer)): Holds all mentioned location's rigion area.
function ajax_nearby_store_collection(combLoc, region) {
// Ajax call with the 'jsonp' data type.
type: "POST",
datatype: "jsonp",
crossDomain: true,
cache: false,
data: { searchedLocPos: combLoc, region: region }, // Pass the location's lat/lng along with the rigion.
url: "",
xhrFields: {
withCredentials: false
success: function(data) {
// Processes the returned data( stores locations ).
positionDetails = jQuery.parseJSON(data);

if ( positionDetails != null ) {
// Send the data for set the store locations as markers.
markNearbyStores(combLoc, positionDetails, region);
else {
alert("We are sorry! There is no desired stores in this area.");
error: function() {
alert("We are sorry! There are some technical errors. Please come again later!");

* Method Name: markNearbyStores()
* - Processes nearby stores and plce them in the map with maarker.
* @param:
*   requestedLocation(object): Holds the requested location's position.
*   positionDetails(object): Holds all the nearby stores locations.
function markNearbyStores(requestedLocation, storePositionDetails, region) {
// Create the map for the requested map first.
var locationPos = requestedLocation.split(',');
var requestedLocLat = locationPos[0];
var requestedLocLng = locationPos[1];

// Send data to create the Map.
createMap(requestedLocLat, requestedLocLng, region);

// Set the nearby store markers on the G Map.
setMarkers(map, storePositionDetails);

/* Call the showlocation function while loading the page every time to collect the current location and
prepares the GMap with the help of GMap JS V3 API. */
google.maps.event.addDomListener(window, 'load', initialize);

CSS part:

html {
height: 100%;
body {
height: 100%;
margin: 0;
padding: 0;
#map-canvas {
height: 50%;

Server side configuration:
For this purpose we have to first download the Drupal third party modules mentioned below:
– Google Store Locator(https://drupal.org/project/google_store_locator). For this we need the storelocator library. Use git to clone the ‘storelocator’ library into /sites/all/libraries. Create the libraries directory if it doesn’t already exist. Path should read /sites/all/libraries/storelocator. Checkout Link: http://code.google.com/p/storelocator/source/checkout
Address Field
Geofield (requires geoPHP)
Libraries API
Views GeoJSON

store-locator-content-typeNow we have install the above mentioned modules and need to place the library. After installing the modules we would be having a content type named “Store Locator”. Now to add a store, we have to add a content of ‘Store Locator’ content type and your stores are added now. Now while adding your places with all address details it internally calculate the latitude and longitude of that location and stores in the ‘field_data_gsl_geofield’ table and the address details stores into the ‘field_data_gsl_addressfield’ table.
So we will collect the data according to the region and the location sent from the FB side. Here we have created a custom module to perform the ajax call. So lets take a look to the example.

// Assign custom header to handle the situation due to CORS.
 header("Access-Control-Allow-Origin: *");
* Integration of hook_menu()
* - Provides the custom drupal menu callback functionality.
* @param:
* - No parameter is being passed.
function storecollector_menu() {
$items = array();

$items['storecollector/gmap-store-locator'] = array (
'page callback' => 'gmap_store_locator_storecollector',
'access callback' => TRUE,

return $items;

* Integration of gmap_store_locator_storecollector()
* - Calculates the nearby place location of the requested place and find out the
*   number of places and returns the location latitude and longitude.
* @param:
* - No parameter is being passed.
* $return:
* - Returns latitudes and longitudes of the nearby store locations.
function gmap_store_locator_storecollector() {
// Collects the requested place location.
$requested_location = explode(",", $_POST['searchedLocPos']);
$lat = trim($requested_location[0]); // Latitude of the requested location.
$lng = trim($requested_location[1]); // Longitude of the requested location.
$region = trim($_POST['region']); // The surounding region of the requested location.

// Collects store locations from the database. Collects those locations which
//   comes on between the requested location range.
$query = db_select('field_data_gsl_geofield', 'g');
$query->join('field_data_gsl_addressfield', 'a', 'g.entity_id = a.entity_id');
$query->join('node', 'n', 'g.entity_id = n.nid');
$query->fields('g', array('gsl_geofield_lat', 'gsl_geofield_lon'));
$query->addExpression("(6371 * acos( cos( radians(" . $lat . ") ) * cos( radians(`gsl_geofield_lat`) ) * cos(radians(`gsl_geofield_lon`) - radians(" . $lng . ") ) + sin( radians(" . $lat . ") ) * sin( radians(`gsl_geofield_lat`) ) ) )", 'test');
$query->fields('a', array('gsl_addressfield_thoroughfare'));
$query->fields('n', array('title'));
$query->havingCondition('test', $region, '<');

$result = $query->execute(); // Executes the query.

// Collects the associated data.
while($record = $result->fetchAssoc()) {
$location_collector[] = $record;

// Returns the filtered data in json format.
print json_encode($location_collector);

So this is all about. Please try to have an integration by yourself. Open conversation is always warmly acceptable.
You could be able to check the LIVE DEMO of this integration HERE.

allow-cross-domain-ajax-call-in-firefoxNOTE: In Chrome, this works perfectly. But as we are doing a cross domain ajax call we need to disable the protection security. Please have a look how to disable that and allow cross domain ajax call for firefox.
Happly knowledge sharing 🙂