Affari

Geolocation in a WordPress Based App

August 9, 2015
James Herriott

Recently the Affari Project had the opportunity to build a native iOS application using WordPress as its foundation. Overlaying webviews allowed the WordPress framework to handle a majority of the app functionality. One aspect that was not part of WP core was incorporating geolocation into WordPress search. Users of the app needed the ability to search for posts and in return see only posts within a certain mile radius of where they are located. Accomplishing this seemingly complex process only took five easy steps. Each step is outlined in detail below but for all you coding wizards who don’t need the long explanation here is a quick summary of the entire process of Geolocation in a WordPress based app:

  • Tie a zip code to each post as post meta.
  • Find the user’s longitude/latitude with HTML5 Geolocation http://www.w3schools.com/html/html5_geolocation.asp.
  • Gather zipcodes within a specified mile radius using this tool http://api.geonames.org/.
  • Convert the XML file output by the Geo Names page (above) into an array using the PHP function, simplexml_load_file().
  • Set our WordPress query to return posts using the specified zip codes.

Step 1: Tie each post to a zip code

If you are well versed in WordPress this is a pretty simple task. Create a custom field with the meta key ‘zip_code’ and assign a zip code to every post. If you need help setting up custom fields I recommend the popular Advanced Custom Fields plugin.

Step 2: Pinpoint the user’s location

HTML5 browsers (including iOS webviews) can pinpoint a user’s longitude and latitude coordinates using this function:

navigator.geolocation.getCurrentPosition(showPosition)

Set up a custom page template to drop all this code into. For this example we’ll use a page called Geo. Set $_GET[‘lat’] and $_GET[‘lon’] values in the url of our ‘/geo’ page to use later. This will also allow you to manually specify coordinates for testing purposes. Here is the code:

<?php if (!$_GET['lat'] || !$_GET['lon']) { ?>
  <script>
    if(navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(function(position) {
        var lat = position.coords.latitude;
        var lon = position.coords.longitude;
        document.location = "/geo/?lat=" + lat + "&lon=" + lon;
      });
    }
  </script>
<?php } ?>

Now the ‘/geo’ page redirects users to a version where the url contains their specific longitude and latitude coordinates in $_GET variables.

Step 3: Find all the zipcodes within a certain mile radius of the user

Once you have the longitude and latitude coordinates set you can find the nearby zipcodes using this tool http://www.geonames.org/ Go to the site, click login, and create an account. Their API limits each user of the free version so if you’re planning on hitting this thing more than 2,000 times an hour or 30,000 times a day you may need to sign up for their ‘Premium Webservices’. Once you have an account you can get the nearby zipcodes in XML format with the code below.

if ($_GET['lat'] && $_GET['lon']) {
  $xml = 'http://api.geonames.org/findNearbyPostalCodes?lat='. $lat . '&lng=' .$long . '&radius=30&username=YOURUSERNAME&maxRows=100';
}

Don’t forget to replace ‘YOURUSERNAME’ with the username you’ve created.

Step 4: Convert the XML to an array with simplexml_load_file()

Once you’ve set the $xml variable as a working Geo Names url; use this PHP function to convert your $xml variable (which is essentially an XML file) into an array like so:

simplexml_load_file($xml)

Now you can pull the zip codes out of the complex array this creates with the following code:

$locations = simplexml_load_file($xml);
foreach ($locations as $location) {
  $locationdata[] = get_object_vars($location);
  foreach($locationdata as $data) {
    $zipcodes[] = $data[postalcode];
  }
}

Alternatively you could use print_r($locations) to see all the data your array contains and pull out what you need.

Step 5: Use your array of zip codes in a WP_Query

The original goal was to use geolocation in a WordPress based iOS application so naturally everything comes down to the WordPress query. Since you’ve created a simple array called $zipcodes, containing all of the zip codes within a radius of the user, you can modify your WordPress query like this:

$args['meta_query'] = array(
  'key' => 'zip_code',
  'value' => $zipcodes,
  'compare' => 'IN'
)
WP_Query($args);

Voilà! With a working WP_query() that returns posts within a certain mile radius of the user, we have successfully used geolocation in a WordPress based iOS application.

Get more insights to your inbox

Ideas are what make us great,
let’s talk about yours

(202) 643-9322 | hello@affari.co

© 2017 Affari. Made across the USA with love.