On a listing or directory website, there is a list of businesses such as restaurants, coffee shops, or bookstores. Each business has some information like title, introduction, review, and very important - location. It's a common demand that you want to display all the businesses on a single map, so users can view all of them at once. In this post, I'm going to show you how to do that in WordPress with Meta Box.
To demonstrate the tutorial, I'm going to create a listing website for restaurants and will create a page to show all restaurants on a single map.
I'll use a custom post type for restaurants. Each restaurant will have some information as below:
- Title (post title)
- Description (post content)
- Address (a custom field)
- Location (a custom field type Open Street Map)
- Marker icon for the map (a URL custom field)
Maybe you want more information, but for the demonstration purpose, it's enough.
This is the result. There are 3 listings on the map. Each listing has a custom marker icon. When clicking on the marker, a popup is displayed with the restaurant title and address.

Let's begin!
Create a custom post type
The very first step is creating a custom post type for restaurants. You can do this with register_post_type()
function. But as we're using Meta Box, I'm going to use MB Custom Post Type extension to do this with a friendly UI.
Simply install and activate MB Custom Post Type from the Plugins > Add New screen, then go to Meta Box > Post Type and click Add New button:

Just add the plural, singular, and slug for the post type. You might want to set other labels or justify the settings for the post type if you want. Don't forget to tick the checkboxes for "Title" and "Editor" in the Supports meta box on the right. We need them for the post title and post content.
In case you don't want to install the plugin, try this free online generator to generate code to create custom post types quickly.
Create custom fields for restaurants
To create custom fields for restaurants, I'm going to use Meta Box (of course!). If you're new to Meta Box, then please follow the Quick Start Guide to get started.
Although I'm familiar with writing some PHP code to create custom fields, I'm going to use Meta Box Builder extension to do this job with a friendly UI. It's a premium extension, so you need to buy it to use. Otherwise, just try Online Generator. It's free and has a similar UI. Here is the guide to use this tool.
After installing and activating Meta Box Builder, you'll see a new submenu Custom Fields under the menu Meta Box. Going there and click Add New to add a new field group. I'm going to call this group Settings, and create 3 fields:
- Address: a text field
- Location: an Open Street Map field
- Icon URL: a file input field (which allows you to either enter URL in the input box or choose an image from the Media Library)
Make sure you select Restaurant in the tab Settings → Post Types.
This is what I have:
That's all for the setup part. Now it's time to create sample listings.
Create some listings
After having everything set up, we can create some listings for the demo. Go to Restaurants > Add New and start creating some. Don't forget to fill in all the information in the custom fields that we created.
This is a sample listing:

Please create some listings, so we have many items to display on the map. In this tutorial, I'm going to create 3 listings.
Also, to make the listings appear beautifully, I'll use some icons from Map Icons Collection.

Create a page template
The next step is creating a custom page template to display all restaurants on a map. You can use the archive template for this purpose if you want. But in this tutorial, for the demo purpose, I'm going to use a page template for simplicity.
So, go to your theme and add a new file called page-list.php
(you can name it another way if you want). And enter the following content in the file:
<?php /** * Template Name: List */ get_header(); ?> <div id="map" style="width: 100%; height: 600px"></div> <?php get_footer(); ?>
The page template is very simple. It loads the header and footer just like other template files in your theme. In the main content area, it simply shows a div with a specific width and height. This div will be used to display the map.
Now go to Pages > Add New and create a new page. Select List from the list of available page templates:

You might wonder where is the code for the map or do we need to query all posts to get their data? That will be the next step.
Enqueue JavaScript file with location data
I'll use JavaScript to render the map. So, the next step is enqueuing the JavaScript file. I'll use the wp_enqueue_script
function.
Enter the following code in your theme's functions.php
file:
add_action( 'wp_enqueue_scripts', function() { if ( is_page_template( 'page-list.php' ) ) { wp_enqueue_style( 'leaflet', 'https://unpkg.com/[email protected]/dist/leaflet.css', [], '1.5.1' ); wp_enqueue_script( 'leaflet', 'https://unpkg.com/[email protected]/dist/leaflet.js', [], '1.5.1', true ); wp_enqueue_script( 'list', get_parent_theme_file_uri( 'js/list.js' ), ['jquery', 'leaflet'], '1.0', true ); $locations = []; $query = new WP_Query( [ 'post_type' => 'restaurant', ] ); foreach ( $query->posts as $post ) { $location = rwmb_get_value( 'location', '', $post->ID ); $location['title'] = $post->post_title; $location['address'] = rwmb_get_value( 'address', '', $post->ID ); $location['icon'] = rwmb_get_value( 'icon', '', $post->ID ); $locations[] = $location; } wp_localize_script( 'list', 'Locations', $locations ); } } );
What does this code do? It does the following things:
- Enqueue Leaflet library to render maps. This is a very powerful JavaScript library that we use in Meta Box to render Open Street Maps.
- Enqueue a custom JavaScript file to render our map. The file is put under the
js
folder and is namedlist.js
. - Query all restaurants and get title, location, address, icon.
- Send the restaurants' data to JavaScript via
wp_localize_script
function.
Please note that I'm using rwmb_get_value
here to get location data for each restaurant. This helper function returns an array of latitude and longitude, which is very useful and ready to use in the front end. See more information about this function here.
Render the map with JavaScript
The final step is rendering the Open Street Maps with JavaScript. Create a new file list.js
in the folder js
in your theme and enter the following code:
( function( document, Locations, L ) { // Set map center = first restaurant location. var center = L.latLng( Locations[0].latitude, Locations[0].longitude ); // Map options. var options = { center: center, zoom: 13 }; // Initialize the map. var map = L.map( document.querySelector( '#map' ), options ); // Set tile layer for Open Street Map. var tileLayer = L.tileLayer( 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' } ); map.addLayer( tileLayer ); // Show marker for each location. Locations.forEach( function( location ) { // Marker options. var options = { title: location.title, icon: L.icon( { iconUrl: location.icon } ) }; var center = L.latLng( location.latitude, location.longitude ) var marker = L.marker( center, options ).addTo( map ); // Show name of the restaurant when click on the icon. marker.bindPopup( '<b>' + location.title + '</b><br>' + location.address ).openPopup(); } ); } )( document, Locations, L );
The code is not very long and I already put comments there to explain each line. Let me summarize here:
- Initialize the map. Simply following the Leaflet documentation to create a map. In this code, I set the location of the first restaurant as the initial center of the map.
- Loop through the list of restaurants (variable
Locations
) and for each restaurant, create a marker for it. The code for creating markers is well documented on Leaflet docs page. - For each marker, bind a popup when clicking with the info of the restaurant title and address.
And now, go to the front end and view the page. If nothing goes wrong, here's what you'll see:

Conclusion
This tutorial helps you handling the data created with Meta Box better and outputting this data flexibly on the front end. It also helps you work with Leaflet, a very powerful JavaScript library for rendering maps (Open Street Maps). With that, I hope you can create a listing or directory WordPress website easier.
In case you want to add a Google map for individual restaurants, businesses, shops, ... in a listing page site, this article may help.
If you have any comments, please share them with us in the section below.
Perfect!
Do you have a plan to write about creating filters for this page also? So people can sort, search by fields, categories...?
Yes, that's on the plan!
Looking forward to this too!
Hi! It looks like the OSM field no longer exists, is this correct?
I would like to make use of another Maps solution that was not Google Maps.
Thanks!
Hi Sara, the field OSM is still available. We don't remove any field. Please see this docs for details.
Hi,
How could this be done with Metabox Views? so it may be used as short code?
Thanks
Hi Steve,
In the View, you can just add the HTML code
and assign to the specific page as the template.
This works well for me. I'm wondering if there is a way to do this while using the leaflet.markercluster plugin so that the locations cluster when zoomed out. Anyone know about this?
Will this map be filterable with FacetWP?
Can you please add a tutorial on how to filter this map? Maybe with ElasticPress?
Thanks. We have noted this down and will ask my team about this.
As many have commented over the past 3 years, it would be EXTREMELY helpful to be able to 1) filter/facet posts based on what is shown in the map when you pan and zoom and 2) filter the map's pins for what has been filtered by search/facet tools on the page.
I recognize that this might be able to be done with 3rd party plugins, like facet wp, but I'd like to do it with just Meta Box. Some instructions, such as those you created here (https://metabox.io/create-ota-website-with-meta-box-p2/) would be very helpful.
In fact, this is the single factor that is preventing me from moving to Meta Box from Toolset.
Is it possible to build a Storelocator with Metabox?
For this it would be necessary that you can search e.g. in a radius of 50 miles around a location and all stores are displayed. In addition, the possibility to select by filters, whether the stores are displayed, for example, Chinese food or Italian or Mexican...
With the possibility that the stores themselves can then edit their own data using frontend editing, but only certain ones, the rest should be displayed reading, this would be the absolute best store locator on the market and a killer feature for using Metabox.
Based on the comments, it seems that the feature promised four years ago has unfortunately not yet been implemented. Is it still in the planning stages? Anyway, it would be fantastic if it came in a timely manner.