How-to Change Content with location change?

Theory

As WordPress doesn’t have some sort of geolocation detection script built in, we’ll have to make our own. As this script is javascript, we then need to get the resulting location data to php. Then we’re able to do a request or add something to our request.

I’ll now give you parts of code, some explanation and starting points, that will allow you to build a plugin (no need to build such logic into a theme).

Javascript & location

First we need a function, that is able to do the detection. There’re plenty of possibilities out there. You can see one possible solution below. Save it into a file, that you call geo_detection.js and save it into a new plugin folder, in a subdirectory named /js. (You can go with any other solution as well).

/**
 * GLOBAL POSITION VAR
 */
var currentPosition = getCurrentPosition();
/**
 * Gets current position
 * 
 * @return mixed false/position obj
 */
function getCurrentPosition()
{
    // Current position
    if ( navigator.geolocation ) 
    {
        navigator.geolocation.getCurrentPosition ( 
            function( position ) 
            {
                return position;
            }
        );
    }
    return false;
}

This script won’t be able to do a real detection if the user is not on a mobile device, as most providers deny the access, but it’s accurate enough to get the center of a city and find out the country in most cases.

Bringing the Device Data to PHP: Scripts we need

To further process the data, we need it available in php, as else we couldn’t make the DB request (or interact with one).

Gladly WP has a function that we can (miss)use in this case: wp_localize_script();.

/**
 * Register Script
 */
function wpse53244_register_script()
{
    foreach ( array( 'geo_detection', 'geo_ajax' ) as $file )
    {
        wp_register_script( 
             $file
            ,trailingslashit( plugins_url( 'js', __FILE__ ) )."/js/{$file}.js"
            ,array( 'json2', 'jquery' )
            ,filemtime( plugin_dir_path( __FILE__ )."/js/{$file}.js" )
        );
    }
}
add_action( 'admin_enqueue_scripts', 'wpse53244_register_script' );
/**
 * Enqueue & Localize our script
 */
function wpse53244_enqueue_script()
{
    wp_enqueue_script( 'geo_detection' );
    wp_enqueue_script( 'geo_ajax' );
    wp_localize_script( 
         'geo_ajax'
        ,'geo_ajax_object'
        ,array( 
             'ajaxurl'     => admin_url( 'admin-ajax.php' )
            ,'_ajax_nonce' => wp_create_nonce( 'geo_ajax_nonce' )
            ,'action'      => 'geo_ajax'
            ,'location'    => ''
         ) 
    );
}
add_action( 'admin_enqueue_scripts', 'wpse53244_enqueue_script' );

Bringing the Device Data to PHP: Processing the data

First, we want to process the data using another ajax file called geo_ajax.js that needs to get saved in our /js folder as well. The jQuery.ajax() function below contains handlers/functions for all sorts or tasks: success, error and completion. We’ll only use success for now.

jQuery( document ).ready( function($) 
{
    $.ajax( {
         type:     'POST'
        ,url:      geo_ajax_object.ajaxurl
        ,data:     currentPosition
        ,success:  function( response, status, request )
         {
            return currentPosition;
         }
        ,error:    function( jqxhr , settings , exception )
         {
            return false;
         }
        ,complete: function( jqxhr, status )
         {
            return false;
         }
    } );
} );

Then we’re going to add our php AJAX request. This needs some safety checking as well.

/**
 * AJAX Callback
 */
function wpse53244_do_location_request()
{
    header( "Content-Type: application/json" );

    // Valid request type?
    wpse53244_is_save_allowed( $_POST );

    // Get our location
    $location = $_POST['data'];

    // Actually processing the data:
    // This here completely depends on how you implement the localized content.
    // You could add additional meta boxes/custom fields, etc.
    // Whatever you can imagine or code...

    // Then you can here intercept the query with the 'posts_clauses' or
    // 'posts_where' filter and add the additional meta data to the query

    // Feedback
    echo json_encode( array(
         'success' => true
        ,'error'   => false
    ) );
    exit();
}
add_action( "wp_ajax_geo_ajax", 'wpse53244_do_location_request' );

/**
 * Valid request?
 */
function wpse53244_is_save_allowed( $data )
{
    // Safety check
    check_ajax_referer( 'geo_ajax_nonce', '_ajax_nonce' );

    $deny = json_encode( array(
         'success' => false
        ,'error'   => true
    ) );

    // AJAX autosave
    if ( 
        defined( 'DOING_AUTOSAVE' ) 
        AND DOING_AUTOSAVE 
    )
        exit();

    // Some other request
    if ( 
        ! isset( $_POST['action'] )
        OR 'geo_ajax' !== $_POST['action']
        )
    {
        echo $deny;
        exit();
    }
}

Summed up

As you can see from the above, there’re tons of things to consider. What I showed ↑ is just a starting point, as there’re dozens of routes that you can go and writing a complete plugin would more than just exceed the content of an answer. The good thing is: You now got a safe environment to start wrapping up your Database calls. But the actual solution depends on how you want to implement it.