WordPress: How to create a distance/radius search using Google Maps API and WordPress custom fields querying post meta by latitude and longitude

We recently worked on a project for a client where they had several locations and needed a search function on their site so a customer can search for their nearest location, then be directed to that location’s dedicated page on the site. So if you need to setup a location/radius search on your WordPress site using custom fields and Google Maps, then you have come to the right place.

Download Code

For example’s sake, we are going to use local McDonalds locations, because, well who doesn’t love McDonalds?

So firstly, we created a custom post type called “locations”. If you don’t know how to setup a custom post type, see our how-to article here.

Now we have setup our custom post type, we will create a post for each location, enter all the relevant content and information you need about these locations and then add custom fields to these posts that store the longitude and latitude of these locations. For this example the meta field names need to be set as “longitude” and “latitude”.

So our three nearest McDonalds branches are:

To get the longitude and latitude of a location, simply find it on Google Maps, hold your mouse down to create a marker and the values will display in the page URL within the “rllag” parameter:

Now we have setup our locations custom post types, we can move onto the location radius/distance search function. If you haven’t got one already, you will need to register for a Google Maps JavaScript API key. You can find more info here: https://developers.google.com/maps/documentation.

Once you have obtained the API key, make sure it’s locked down by IP or referrer (allowed domain(s)) to ensure that it can’t be used and abused by someone else.

Next we are going to add the search function to our functions.php file. Copy and paste the below:

function get_nearby_locations( $lat, $lng, $distance ) {
	global $wpdb;

	$earth_radius = 3959;

	$sql = $wpdb->prepare( "
		SELECT DISTINCT
			p.ID,
			p.post_title,
			latitude.meta_value as locLat,
			longitude.meta_value as locLong,
			( %d * acos(
			cos( radians( %s ) )
			* cos( radians( latitude.meta_value ) )
			* cos( radians( longitude.meta_value ) - radians( %s ) )
			+ sin( radians( %s ) )
			* sin( radians( latitude.meta_value ) )
			) )
			AS distance
		FROM $wpdb->posts p
		INNER JOIN $wpdb->postmeta latitude ON p.ID = latitude.post_id
		INNER JOIN $wpdb->postmeta longitude ON p.ID = longitude.post_id
		WHERE 1 = 1
		AND p.post_type = 'locations'
		AND p.post_status = 'publish'
		AND latitude.meta_key = 'latitude'
		AND longitude.meta_key = 'longitude'
		HAVING distance < %s
		ORDER BY distance ASC",
		$earth_radius,
		$lat,
		$lng,
		$lat,
		$distance
	);

	$nearbyLocations = $wpdb->get_results( $sql );

	if ( $nearbyLocations ) {
		return $nearbyLocations;
	}
}

This function queries posts by post type “locations”, joins the wp_postmeta table and meta_value fields to the query.

Next we need to create a page in WordPress where the search will actually be performed, you can call it whatever you want. Then use the below page template file for this new search page:

<?php
/* Template Name: Location Search */

get_header();

$location_search = sanitize_text_field($_POST&#91;'location_search'&#93;);
$loc_search = urlencode($location_search);
$distance = $_POST&#91;'distance'&#93;;

$distance_select = array(
	5 => '5 miles',
	10 => '10 miles',
	50 => '50 miles',
	100 => '100 miles',
);

?>

<div class="container">
	<form action="" method="POST" id="location-search-form">
		<input type="text" name="location_search" value="<?php echo $location_search; ?>" placeholder="Enter postcode or city">
		<select name="distance">
			<?php
			foreach($distance_select as $distance_option => $key) {
				echo '<option value="'.$distance_option.'"'.($_POST&#91;'distance'&#93; == $distance_option ? ' selected' : '').'>'.$key.'</option>';
			}
			?>
		</select>
		<input type="submit" value="Search">
	</form>
	<?php
	if(!empty($loc_search)) {
		
		// Query the Google Maps API to find the address, postcode or city
		$url = 'https://maps.googleapis.com/maps/api/geocode/json?address=' . $loc_search . '&key=AIzaSyDxasOdDrsgF9Bx5LUR0KVo6y_kTMf3X1w&components=country:GB';
		$json = json_decode(file_get_contents($url));
		
		// Return the longitude and latitude of this location
		$lat = $json->results[0]->geometry->location->lat;
		$lng = $json->results[0]->geometry->location->lng;

		// Perform the search using our search function
		$location_result = get_nearby_locations($lat, $lng, $distance);
		
		echo '<ul>';
		
		if(!empty($location_result)) {
		
			// Display the results
			foreach ($location_result as $result) {
				
				$loc_id = $result->ID;
				$location = $result->post_title;
				$distance = intval($result->distance);
				
				echo '<li><a href="'.get_permalink($loc_id).'">'.$location.' <i>('.$distance.' miles)</i></a></li>';
				
			}
		
		} else {
			
			// No results
			echo '<li>No results found</li>';
			
		}
		
		echo '</ul>';
		
	}
	?>
</div>
<?php
get_footer();
?>

Note: Make sure you replace “**PUT_YOUR_API_KEY_HERE**” with your Google Maps API key.

And that’s it! Now visit your page and perform a search. This search will work with any query including address, postcode and city. For this example, if I search “Portsmouth” (or even our office postcode: PO6 3EZ) and set the distance to 5 miles, then all three McDonalds branches show up. If for example, I search “Southampton” and set the distance to 5 miles, then there aren’t going to be any results.

Another note: WordPress is being annoying and replacing our square brackets in the code with [ and ] – you can perform a search and replace to fix this, or simply download the original files here.

Download Code

Hopefully you have found this tutorial useful, if you have or if you have experienced any issues, please let us know in the comments below.

Free Graphics, Icons, Tutorials
Free Graphics Free Christmas Vector Icon Graphics Pack 2017Free Fitness Vector Icons Graphics PackFree Camping Vector Graphics PackFree Summer Graphics PackFree File Icon PackFree Fast Food Vector Graphics
Sharing is caring...
Like & Follow
Share the love, share this page! Facebook Twitter Digg Reddit LinkedIn Pinterest Email
Close [X]
The Web Taylor
1000 Lakeside North Harbour Portsmouth, Hampshire PO6 3EN
02392 123358