CASE STUDY: ACF Google Map Radius Search

Radius Search ACF Google Map Field

In this case study I’ll walk through how I was able to create a radius search from Google map data for a client.

It’s a bit technical if you just want to see the output, scroll down to the video for a demo of the front end.

My clients requirement was for a user to enter their Zip code and then for the code to search on a custom post type called location and return all locations within a 100 mile radius.

We had attached an ACF google map field to the custom post type so we could save the address data of the location on the post, I created a map and I could output all of the data points on the map, so far so good.

Problem One – Google Maps Latitude and Longitude Data Is Serialised

The data is serialised so it is very hard to search on an ACF google map, so I create two new fields (latitude and longitude) and upon save of the custom post type I grab the ACF field latitude and longitude and save them into their own fields.

function nm_update_lat_long($post_id){
	
	$post_type = get_post_type( $post_id );

    if ( 'location' == $post_type ) {
	
		$xxx_map= get_field('xxx_google_map', $post_id);
	
		$_POST["acf"]["field_65b8c2e984961"]=$xxx_map['lat'];
		$_POST["acf"]["field_65b8c2fb84962"]=$xxx_map['lng'];
	
		return $_POST;
	}
}

add_action('acf/save_post', 'nm_update_lat_long',1);

Convert Zip Code TO Co-Ordinates

Using the Google maps API I can do a search using a zip code and return a set of latitude and longitude co-ordinates I can use to create my search are. The code looks like this.

function nm_get_coords_zip_code($zip){
	
	
	$api_key=get_field('xxx_options_google_map_api_key','options'); 
	$url = "https://maps.googleapis.com/maps/api/geocode/json?address=".$zip."&sensor=false&key=".$api_key;
        $details=file_get_contents($url);
        $result = json_decode($details,true);
        $account_lat=$result['results'][0]['geometry']['location']['lat'];
        $account_long=$result['results'][0]['geometry']['location']['lng'];
	return array($account_lat,$account_long);
	
}

The Search Box

Using maths I’ve not used since school, I was able to return a box which is 100 miles radius of my zip code. Who am I kidding I found it on stack overflow.

function nm_getBoundingBox($lat_degrees,$lon_degrees,$distance_in_miles) {

    $radius = 3963.1; // of earth in miles

    // bearings - FIX   
    $due_north = deg2rad(0);
    $due_south = deg2rad(180);
    $due_east = deg2rad(90);
    $due_west = deg2rad(270);

    // convert latitude and longitude into radians 
    $lat_r = deg2rad($lat_degrees);
    $lon_r = deg2rad($lon_degrees);

    // find the northmost, southmost, eastmost and westmost corners $distance_in_miles away
    // original formula from
    // http://www.movable-type.co.uk/scripts/latlong.html

    $northmost  = asin(sin($lat_r) * cos($distance_in_miles/$radius) + cos($lat_r) * sin ($distance_in_miles/$radius) * cos($due_north));
    $southmost  = asin(sin($lat_r) * cos($distance_in_miles/$radius) + cos($lat_r) * sin ($distance_in_miles/$radius) * cos($due_south));

    $eastmost = $lon_r + atan2(sin($due_east)*sin($distance_in_miles/$radius)*cos($lat_r),cos($distance_in_miles/$radius)-sin($lat_r)*sin($lat_r));
    $westmost = $lon_r + atan2(sin($due_west)*sin($distance_in_miles/$radius)*cos($lat_r),cos($distance_in_miles/$radius)-sin($lat_r)*sin($lat_r));


    $northmost = rad2deg($northmost);
    $southmost = rad2deg($southmost);
    $eastmost = rad2deg($eastmost);
    $westmost = rad2deg($westmost);

    // sort the lat and long so that we can use them for a between query        
    if ($northmost > $southmost) { 
        $lat1 = $southmost;
        $lat2 = $northmost;

    } else {
        $lat1 = $northmost;
        $lat2 = $southmost;
    }


    if ($eastmost > $westmost) { 
        $lon1 = $westmost;
        $lon2 = $eastmost;

    } else {
        $lon1 = $eastmost;
        $lon2 = $westmost;
    }

    return array($northmost, $southmost, $eastmost, $westmost);
}

The Query

I setup a query to search the data looking for locations within the bounds of the co-ordinates I had grabbed from the search box in the previous step. I saved those co-ordinates in an erray $distance_box. Here are the query arguments I used.

$args = array(
	'post_type'	=> 'location',
	'post_status' => 'publish',	
	
	'meta_query'	=> array(
		 'relation' => 'AND', 
		
		array(
			'key'		=> 'xxx_latitude',
		
			'value'		=> array($distance_box[1]),
			'compare'	=> '>=',
			'type' => 'NUMERIC',
		),
		
				array(
			'key'		=> 'xxx_latitude',
			'value'		=> array($distance_box[0]),
			'compare'	=> '<=',
			'type' => 'NUMERIC',
		),
		
		
		array(
			'key'		=> 'xxx_longitude',
		
			'value'		=> array($distance_box[2]),
			'compare'	=> '<=',
			'type' => 'NUMERIC',
		),
		
				array(
			'key'		=> 'xxx_longitude',
			'value'		=> array($distance_box[3]),
			'compare'	=> '>=',
			'type' => 'NUMERIC',
		),
		
		
	)	
		
	
);

Video Demo

Here’s what it looks like on the front end.

Wrap Up – Radius Search ACF Google Map Field

So here’s my case study on how to search ACF google map fields via a 100 mile radius.

If you need help implementing Google maps on your site please get in touch.

Photo by José Martín Ramírez Carrasco on Unsplash

Get A No Obligation Quote

Do You Need Help With Your WooCommerce Site?

Click through to the next page and complete the form to get a free no obligation quote to fix any issue you are having with your WooCommerce site.