Creating a Google Maps shortcode for WordPress

This week we’ll be extending WordPress by adding a custom shortcode. This shortcode will allow us to add a Google Map to a post using a simple piece of text in a post or page. Shortcodes are a quick and easy way to add functionality to a post in WordPress. They look something like this:

[ gallery ids="1,2,3,4"]

We’ll also using PHP based Object Orientated Programming (OOP) to create our shortcode. We’ll create a basic class, that has some static functions with in. We’ll be using static methods because we want some level of state to be kept.

map

Getting started

Our basic class will be pretty simple, it needs to register the shortcode and provide functions to render the shortcode and add the API JavaScript file.

class GoogleMap_Shortcode {
    static function init() {
    }

    static function render_shortcode($atts) {      
    }
	
    static function enqueue_map_javascript() {
    }
}

To create our shortcode we’ll need to first register it and then define it how it works and what HTML it creates. We’ll also need to figure out a way to add in the Google Maps API JavaScript. To add a shortcode to WordPress we use the add_shortcode function. This function takes 2 parameters, the name of the shortcode and the function to call when we want to render the shortcode. We’re going to call our shortcode “map” and our render function “render_shortcode”. Since we’re using a class, we’re going to take advantage of the PHP Magic Constant “__CLASS__”, this will maintain a reference to our class and ensure our function can be called.

add_shortcode('map', array(__CLASS__, 'render_shortcode'));

The add_shortcode needs to be called only once, so we’re going to call it from our “init” function, and then immediately after our class definition call it.

class GoogleMap_Shortcode {
    static function init() {
        wp_enqueue_script( 'jquery' );
        add_shortcode('map', array(__CLASS__, 'render_shortcode'));
    }

    static function render_shortcode($atts) {
    }
    static function enqueue_map_javascript() {
    }
}

GoogleMap_Shortcode::init();

Now we have to start getting our shortcode to render. First up we need to define the attributes of the shortcode. One of these will be the Google Maps API key, you can sign up for one here, we’ll also want to be able to specify map related settings like the map type, zoom and naturally the co-ordinates we want to center on. We can define their default values using the shortcode_atts and extract functions.

extract( shortcode_atts( array(
    'api_key' => false,
    'id' => 'map-canvas-1',
    'class' => '',
    'zoom' => '18',
    'coords' => '53.339381, -6.260405',
    'type' => 'roadmap',
    'width' => '480px',
    'height' => '480px'
), $atts ) );

Here you can see I’m defaulting all the possible attributes, this means the user doesn’t have to specify them all in the shortcode if they don’t need to. The API key is needed for all instances of the shortcode, but we can cache the key from the 1st call so it does not need to be specified on all shortcodes on a page. If we declare a static variable inside the class and use it where ever we are in the class it will only need to be set once.

class GoogleMap_Shortcode {
    static $api_key = false;

    static function init() {
        wp_enqueue_script( 'jquery' );
        add_shortcode('map', array(__CLASS__, 'render_shortcode'));
    }

    static function render_shortcode($atts) {
        extract( shortcode_atts( array(
            'api_key' => false,
            'id' => 'map-canvas-1',
            'class' => '',
            'zoom' => '18',
            'coords' => '53.339381, -6.260405',
            'type' => 'roadmap',
            'width' => '480px',
            'height' => '480px'
        ), $atts ) );
        
        if(!self::$api_key && $api_key) {
            self::$api_key = $api_key;
        }      
    }
    static function enqueue_map_javascript() {
    }
}

GoogleMap_Shortcode::init();

There are four default map types, to simplify the specification of which one we want to use we can use a switch statement

$map_type_id = "google.maps.MapTypeId.ROADMAP";
switch ($type) {
    case "roadmap":
        $map_type_id = "google.maps.MapTypeId.ROADMAP";
        break;
    case "satellite":
        $map_type_id = "google.maps.MapTypeId.SATELLITE";
        break;
    case "hybrid":
        $map_type_id = "google.maps.MapTypeId.HYBRID";
        break;
    case "terrain":
        $map_type_id = "google.maps.MapTypeId.TERRAIN";
        break;
}

Now we have everything we need to actually render our shortcode. First we’ll need to specify the div we are going to wrap the map in, and then we’ll need some JavaScript to initialize the map.

class GoogleMap_Shortcode {
    static $api_key = false;

    static function init() {
        wp_enqueue_script( 'jquery' );
        add_shortcode('map', array(__CLASS__, 'render_shortcode'));
    }

    static function render_shortcode($atts) {
        extract( shortcode_atts( array(
            'api_key' => false,
            'id' => 'map-canvas-1',
            'class' => '',
            'zoom' => '18',
            'coords' => '53.339381, -6.260405',
            'type' => 'roadmap',
            'width' => '480px',
            'height' => '480px'
        ), $atts ) );
        
        if(!self::$api_key && $api_key) {
            self::$api_key = $api_key;
        }
        
        $return = "";
        
        $map_type_id = "google.maps.MapTypeId.ROADMAP";
        
        switch ($type) {
            case "roadmap":
                $map_type_id = "google.maps.MapTypeId.ROADMAP";
                break;
            case "satellite":
                $map_type_id = "google.maps.MapTypeId.SATELLITE";
                break;
            case "hybrid":
                $map_type_id = "google.maps.MapTypeId.HYBRID";
                break;
            case "terrain":
                $map_type_id = "google.maps.MapTypeId.TERRAIN";
                break;
        }
        
        if(self::$api_key) {
            $return = '<div id="'.$id.'" class="map-canvas '.$class.'" style="width:'.$width.';height:'.$height.';" ></div>';
            
            $return .= '<script type="text/javascript">';
            $return .= 'jQuery(document).on("ready", function(){ ';
            $return .= 'var options = { center: new google.maps.LatLng('.$coords.'),';
            $return .= 'zoom: ' . $zoom . ', mapTypeId: ' . $map_type_id . ' };';
            $return .= 'var map = new google.maps.Map(document.getElementById("'.$id.'"), options);';
            $return .= 'var marker = new google.maps.Marker({ position: new google.maps.LatLng('.$coords.'), map: map });';
            $return .= '});</script>';
        } else {
            $return = "<div><p>Please specify your Google Maps API key</p></div>";
        }
        
        return $return;        
    }
    static function enqueue_map_javascript() {
    }
}

GoogleMap_Shortcode::init();

I’ve also added a check here to see if the api key is set, and if not display a message to that effect. Next up we need to include the actual Map API JavaScript, to do that we’re going to use the wp_enqueue_script function. Because we’re checking that the api key is we are by default preventing the JavaScript from being loaded when the shortcode is not being used.

static function enqueue_map_javascript() {
    if ( ! self::$api_key )
        return;

    wp_enqueue_script( 'map-js', 
        "https://maps.googleapis.com/maps/api/js?key=" . self::$api_key . "&sensor=true"
    );
}

To make sure this script is included in the right place, we’re going to add an action to the wp_footer hook. We’ll add this to our init function

add_action('wp_footer', array(__CLASS__, 'enqueue_map_javascript'));

And that’s it, add this to your functions.php or use an include/require and you’ll be able to add Google Maps to your posts. To actually add it to a post, you can use the following:

[map api_key="INSERT YOUR API KEY"]

[map api_key="INSERT YOUR API KEY" id="map-2" coords="52.339381, -4.260405"]

[map api_key="INSERT YOUR API KEY" id="map-2" coords="52.339381, -4.260405" zoom="5" type="satellite"]

It was pointed out to me that I forgot to include the pointer for the map. I’ve updated the sample above and the download. This is the new line to add a marker.

$return .= 'var marker = new google.maps.Marker({ position: new google.maps.LatLng('.$coords.'), map: map });';

Here’s the updated full class.

Author: Jonathan Schnittger
A battle hardened software developer with a mixed and colorful background, who can't come up with a decent author bio
  • Владимир Шевченко

    Hello!
    how to add a marker on a map?

    • Jonny Schnittger

      I completely forgot to include that! I’ll update the tutorial now… it’s this though
      var marker = new google.maps.Marker({ position: new google.maps.LatLng(‘.$coords.’), map: map });

      • http://www.minecraftgames.co/ Minecraft Games

        hi Jonny. When will you update the tutorial, I’m waiting for it

        • Jonny Schnittger

          The fix has already been added to in the download and the text of the post has been updated, The above line is added just after the map is declared.

  • Craig Francis

    As the API key is often for the website, should’nt it be in the wp-config file? Then it does not need to be set per use of the shortcode (especially if the key system was to change).

    • Jonny Schnittger

      Having it in the wp-config would negate its portability, this way it can be included in a theme or plug-in and does not require a potentially inexperienced user from editing core WordPress files.

      • Craig Francis

        Fair point, and for some that would be an advantage… but if you need to change the key, it would only mean changing it in 1 location, plus you can copy the shortcode (which is now much shorter) between websites without having the key included… that and setting up WP usually involves editing the wp-config file anyway (at least for the database connection details).

        • Jonny Schnittger

          A even better way would be to create an admin page and have the basic default configuration including API key configured there. It’s quiet easy to do and then you just use the Option functions to get/set/update as needed.

          • Jonny Schnittger

            I’ve added a new tutorial that extends this by adding an admin/settings page, I won’t link it now as the comment would need to be approved.

  • http://www.spinxwebdesign.com/ Alan Smith

    Is there any Google maps plugin for wordpress?

    • Jonny Schnittger

      Sorry for the delay Alan, I’ve been off on holidays… what do you want the plugin to do? Is the shortcode above sufficient or are you looking for more customization/functionality?

  • Tony

    This is a nice replacement for plugins, but my lack of experience with Javascript has left me with a small problem: I want to include this piece of code (to make business names invisible): var styles = [{ “featureType”: “poi.business”,”stylers”: [{ “visibility”: “off” } ] } ]; but I can’t figure out how to include it. Can you help?