Wordpress Plugins: The User-Facing Map
Tags: wordpress, javascript, tutorial
Published: 2020-09-16 00:53:14

*In part 4 of our WordPress series, learn how to create the user-facing map and a WordPress shortcode that makes inserting the map easier.*

#WordPress Plugins and TomTom – Part 4

In this series of articles, we're using the TomTom Map Display API and Search API to display a map of storefront locations on a business website through an easy to configure WordPress Plugin. 

In the previous article we finished building the WordPress admin panel interface of the Plugin. At this point the map appears in the admin panel, we can add store locations to a database of stores, we can fetch the location coordinates of the stores by using the Search API, and we can display the store locations on the admin panel map. 

In this article we'll: 

* Develop the public side of the WordPress Plugin: the map that appears on the website itself.  
* Create a WordPress shortcode that lets site administrators embed the Plugin's map into any web page.  
* Demonstrate using the shortcode, along with some HTML and JavaScript, to embed a map on a page with both the classic Wordpress editor and the new Gutenberg editor. 

#WordPress Shortcodes

As a security measure, WordPress limits the kinds of HTML and scripting automation that authors are allowed to directly code into a web page. Instead, WordPress provides shortcodes, which operate like macros, allowing you to add files, media, or script-generated content to a page via a simple tag. 

Wordpress.com offers a variety of [preconfigured shortcodes](https://en.support.wordpress.com/shortcodes/). For example, the [audio] shortcode lets you display an audio file player into a page by simply embedding the shortcode text and specifying the file to play. 

In addition to these pre-configured shortcodes, the WordPress [Shortcode API](https://codex.wordpress.org/Shortcode_API) gives you the ability to create entirely custom shortcodes. We're going to use the Shortcode API to create a custom [tomtom-store-locator] shortcode that allows you to embed a map and stores list onto any web page. When the TomTom Stores Map Creator Plugin is activated for the Wordpress site, the [tomtom-store-locator] shortcode will display the map and any store locations configured through the admin panel. 

#Creating a Custom Map Shortcode

In the plugin directory, you can find all of the PHP for creating our end-user-facing shortcode in store-locator-user.php.  

At the bottom of the file, you’ll see a call to **WordPress’ add_shortcode()** function: 

```javascript
add_shortcode('tomtom-store-locator', 'ttlocator_user_map');
```

This defines a shortcode named “tomtom_store_locator”. The second parameter — **ttlocator-user-map** — is the name of the function that will be called when WordPress sees our new shortcode referenced in a page or post.  

As we can see, our shortcode calls the **ttlocator_user_map()** function. Taking a look at that function shows the following code:

```javascript
function ttlocator_user_map() {
   $plugin_directory = plugin_dir_url(__FILE__);
   $stylesheet = $plugin_directory . "styles/styles.css";
   $locator_js = $plugin_directory . "scripts/locator-user.js";
   $tomtom_sdk_dir = $plugin_directory . "tomtom-sdk/";
   $map_stylesheet = $tomtom_sdk_dir . "map.css";
   $tomtom_js = $tomtom_sdk_dir . "tomtom.min.js";
   $locations = ttlocator_get_locations();

   wp_enqueue_script("jquery");
   wp_enqueue_style("ttlocator-styles", $stylesheet);
   wp_enqueue_style("ttlocator-tomtom-map-styles", $map_stylesheet);
   wp_enqueue_script("ttlocator-tomtom-sdk", $tomtom_js);
   wp_enqueue_script("ttlocator-locator-page-user-script",
       $locator_js, array("jquery"), false, true);
   ?>
   <div style="width: 100%; text-align:left">
   <div id="map" style="width: 100%; height:500px"></div>
   <script>
       var tomtomSdkKey = '<?php echo esc_attr(get_option("tomtom_locator_api_key")); ?>';
       var tomtomSdkPath = '<?php echo $tomtom_sdk_dir; ?>';
       var storeLocations = <?php echo json_encode($locations); ?>;
   </script>
   <h4>Store Locations</h4>
   <?php
   ttlocator_user_store_table_html($locations);
   ?>
   </div>
<?php
}
``` 

This probably looks familiar because it is very similar to the code we used to generate the map and store locations on the admin page. The user-facing map page doesn’t need to be as complex, though, so there are a couple of changes:

* Our page doesn’t have a title, because it is going to be added to a WordPress page that already has a title of its own. 
* We’re including **locator-user.js** instead of **locator.js**. Since our user-facing map won’t need most of the JavaScript the admin page needed, including it all would be inefficient. The JavaScript code we use to add the store markers to our map is identical to the code we used on the admin side of our plugin. 
* Instead of calling functions to generate the store list table and a page to add new stores, we only make a single call to **ttlocator_user_store_table_html()**. 

Let’s take a look at what the code for **ttlocator_user_store_table_html()** does: 

```javascript
function ttlocator_user_store_table_html($locations) {
   ?>
   <table id="ttlocator-stores-user-table">
       <thead>
       <tr>
           <th>Name</th>
           <th>Address</th>
           <th>City</th>
           <th>State/Province</th>
           <th>Post/Zip Code</th>
       </tr>
       </thead>
       <tbody>
       <?php foreach($locations as $location): ?>
           <tr>
               <td><?php echo esc_attr($location->name); ?></td>
               <td><?php echo esc_attr($location->address); ?></td>
               <td><?php echo esc_attr($location->city); ?></td>
               <td><?php echo esc_attr($location->state); ?></td>
               <td><?php echo esc_attr($location->postcode); ?></td>
           </tr>
       <?php endforeach; ?>
       </tbody>
   </table>
   <?php
}
```

Again, this is very similar to the code we used to generate the list of stores on our admin page. The function receives a list of store locations as its only parameter and generates an HTML table to display them.

Notice that we removed all of the CSS classes that were included on the store table on our admin page. We did this because all of those classes we used on the admin page are part of the WordPress admin styles and are only available on admin pages. Including them here would have no effect.  

We do give the table an ID, however. This will make it easy for users of the plugin to add custom CSS to ensure they can style the store list table any way they’d like to. Aside from setting a default text size, we avoid applying any styling of our own to the table. WordPress themes typically apply their own custom styles to tables, so we want to make sure our table is able to adapt to whatever styles might be applied to it.  

With so much code in common between the admin-facing and user-facing maps, you might be wondering why we don’t factor the common code out into functions to avoid duplication. The answer is that it was a judgment call based on past Plugin development experience.  

While it’s common for the admin and user-facing sides to have much in common initially, as the Plugin grows and is customized, the two sides of the Plugin start to diverge. As a result, effort spent factoring out common code early on is often wasted. To prevent this, we’ve kept the markup generation completely separate between our admin and user pages. 

#Using a Map Shortcode

Now that we’ve created a shortcode, how do we actually use it? 

The answer depends on whether you’re using the classic WordPress editor or the new Gutenberg editor. Fortunately, it’s easy either way.  

If you’re using the old editor,  just place the **[tomtom-store-locator]** tag in the text of your page: 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/hs2hcq95dsed78siobcj.png)

And if you’re using the Gutenberg editor, place the tag inside a paragraph block:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/y2pbr5gmu7qras51k7wj.png)

The end result will be a page that looks like this:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/n1sro4i0zx00k6xhhr83.png)

The exact appearance of your page will depend on which WordPress theme you are using.

#Next Steps

We’ve come a long way! Our Plugin now allows us to add stores to a TomTom map and display those locations to users of our WordPress site. 

In the final article of this series, we’ll look at how to improve our store locator with some advanced TomTom API features. 

First, we’ll learn we can use geolocation to center the map on the user’s location so they can see which stores are near them. We will then use the TomTom Routing API to generate driving directions from the user’s current location to their chosen store location. To finish up our Plugin, we will use the TomTom Traffic API to determine when the user should leave if they want to arrive at the store by a given time.

Visit our [developer portal](https://developer.tomtom.com/) and check out our documentation and examples for [Web](https://developer.tomtom.com/maps-sdk-web-js/functional-examples), [iOS](https://developer.tomtom.com/maps-sdk-ios/map-examples), and [Android](https://developer.tomtom.com/maps-android-sdk/map-examples). Lastly, don't forget to connect with us on [Twitter](https://twitter.com/tomtomdevs), [Twitch](https://twitch.tv/tomtomdevs), and [YouTube](https://www.youtube.com/channel/UCL-ZtGd70Khd_9OJACd6rXA/videos), and check out our [blog](https://developer.tomtom.com/blog) for more tutorials and [developer forum](https://devforum.tomtom.com/) for any questions you may have.

Happy mapping!

*With nearly 30 years of experience, TomTom is the leading location technology specialist, developing the most reliable maps, navigation software, traffic and live services for the automotive industry, enterprises and developers worldwide. We are committed to creating precision technology that brings us closer to our vision of a safer, cleaner, congestion-free world.*

*This article originally appeared on https://developer.tomtom.com. The original author is Gregory De Jans.*