Up to this point, a fair amount of work has been done in terms of introducing Google Maps in WordPress:
- Twentyfifteen is setup to communicate with the Google Maps API
- A map is being displayed in a custom template
- There are two markers that are placed on the map
- Each marker has its own InfoWindow used to display some information
There’s still more content that could be covered, and I’ll talk about some of the advanced content in another article but, for now, it’s time to refactor some of the code so that it’s more manageable, is organized in more of the “WordPress way,” and lays the foundation to more easily introduce new features.
Namely, all of the work that’s been done up to this point can be moved into a child theme and all of the code that’s been placed in the template can be abstracted out into its own files.
A Child Theme Google Maps in WordPress
I’m going to continue moving forward with working on a child theme for WordPress by introducing a child theme based off of Twentyfifteen.
Naturally, you can use whatever theme you’d like but for the purposes of this series, I’m going to continue with the theme that that’s been used throughout this series.
Create The Child Theme
This series of article assumes that you know the basics of creating a child theme. If not, the Codex has a good article on where to start.
From here, we’re going to create a directory in wp-content
called twentyfifteen-maps
and we’ll introduce a few files and subdirectories. Specifically, add the following files:
- `functions.php`
- `style.css`
- `template-maps.php`
And then add the following subdirectories
- `css`
- `js`
Ultimately, the directory structure for the child theme should look something like this:
Of course, this won’t actually work (let alone even show up in WordPress right now), but we’ve got the necessary files in place in order to create the child theme.
Define The Stylesheet
In order to make the theme accessible via the WordPress Dashboard, we need to add some information to style.css
.
This will display the theme in the dashboard; however, there still won’t be a lot of functionality to the theme beyond what the base Twentyfifteen theme offers.
Next, the base theme styles need to be included in the child theme. To do this, adding the following function to the child theme’s functions.php
file:
Now we can start actually moving the functionality that we’ve added to the base theme into the new theme.
The Google Maps API Library
Up until this point, the Google Maps API has been added using a normal script
tag, but a better way to do it would be to use wp_enqueue_script
so add this to functions.php
:
Next, the code that’s been powering Google Maps can be added to its own file:
And then it can be included in functions.php
:
If you’re new to child theming, notice the call to get_stylesheet_directory_uri()
. This is being used in place of get_template_directory_uri()
because we’re including files that are in the context of the child theme.
The rule of thumb is this:
If you’re working with files in a theme or in a base theme, use `get_template_directory_uri()`. If you’re working with files in a child theme, then use `get_stylesheet_directory_uri()`.
Anyway, notice that these two files pass true
as to whether or not to load them in the footer of the page or not. This is because the library and the Google Maps code need to be loaded and fired after the page has loaded (this also improves page performance, but that’s a topic outside the scope of this article).
Add The Stylesheet
There’s a small bit of styling that exists in the template file from previous articles in this series that can be moved into its own file. In the css
directory, create style.css
and then add the following code to it:
Next, updating functions.php
so that the add_twentyfifteen_maps_styles
function includes the file as well:
This will ensure that the map looks the same in the child theme as it did in the parent theme.
Introduce The Template
Finally, add the template file to the child theme’s root directory. To do this, add template-maps.php
– the file should be really simple and include nothing but the following:
Now the child theme can be activated, a page can be created, the template can be applied, and the Google Map will load.
Is That All?
In terms of the basics of using Google Maps within the context of WordPress, yes. This provides a way to keep all of the code abstracted into its own files, uses the proper WordPress APIs to include theme all, and also retains the same functionality that’s been used throughout this series.
There are plenty of advanced topics as it relates to Google Maps in terms of what can be achieved (such as calculating distances, getting directions, and so on) which may be interesting for a future set of article. If you’re interested, leave a comment; otherwise, that brings this [rather long] series to an end.
Where are you including the script in the functions file? I only see the stylesheets.
See the section “The Google Maps API Library” and let me know if that clears it up. If not, I can explain further :).
I’m wondering if she’s asking where you are including public.js. I don’t see where you’re including that, and my map isn’t rendering. Any assistance would be appreciated! Thanks!
Ah, good point! See the gist right under the line that reads:
As it shows where it should be enqueued. If this doesn’t help, let me know!
Hey, thanks for taking the time to write this. It’s definitely helpful as I’m finding myself using the JS API more and more with each project. How do you tend to get all of the marker information and display it on the map generally?
Lately I’ve been running the query on the wordpress backend when a user saves a relevant post and saving it as a super long JSON string with update_option(). (So that I don’t run the same exact query every time somebody sees the map.)
But even then that still leaves me with echoing out this HUGE string (2000+ locations sometimes) onto like a data-attribute. Is there a better way to go about doing this? Having my SQL database and JS interact feels like I’m just doing janky things with PHP as my middleman.
I guess what I’m asking is, in a situation where, lets say you have a custom post type “store” with location data on each post, how do you generally go about grabbing that information and displaying it?
Cheers,
Andrew
Personally, this depends on how many markers that I need to display. If it’s a low number or something that’s not too taxing on the browser, then I’ll load them all up at once.
If, on the other hand, then I’ll normally load what’s available for a given viewport size and cache it (like maybe in the transients table). That way, the data is available more quickly and can be grabbed via caching plugins.
If things get really complicated, then I’ll use an async process either via Ajax or an entire cron job for grabbing location information on the server side, saving it, and then just rendering it using Ajax.
So it really depends on the situation for me.
I get what you’re trying to do with the general post, but I’d refine it a bit.
First, rather than having a super long JSON string, why not separate it into chunks via some type of metric? Perhaps by zip code or postal code, perhaps by just an arbitrary number, or based on some other relevant aspects of your code so you can pull information at a fine-tuned level rather than getting everything back at once?
Secondly, I’d recommend storing the results in the options table and the transients table. Then, check to see if it’s in the transients table. If so, use that; otherwise, execute the query on demand, store it in the options table and in the transients table. This is basically what happens during cache invalidation. But only do this after you’ve improved performance with the options table.
Finally, and I suppose this is my attempt to answer your final question:
This would depending on a metric like postal code, area code, geographic boundaries, etc. (it really depends on the area that you’re that metric.
I can’t give a definitive answer because I know this really matters on what you’re mapping. I can do things for the US that I can’t do for, say, Canada and vice versa. One other thing is that if you really want to control something like this, then you can also display viewport zooming, but that’s kind of a hack depending on what your needs are.
I hop this helps or at least gives some ideas on how to approach this another way!
Awesome series. Really great!! I appreciate you taking the time to write this long and detailed explanation.
I kept getting API key error and I can’t understand why I could not get it to work without adding my API key this way: http://stackoverflow.com/questions/16203618/google-maps-api-javascript-in-wordpress as per Josh’s answer.
I am using this plugin as well https://wordpress.org/plugins/address-geocoder/ where I have added the API key. I was hoping that would have been enough but it was not.
May I ask how you have added the API key?
Thank you
If you look at this gist, you’ll see where I have
API_KEY
. This is where your API key could go.Hope this helps!
Hey Tom, as always awesome work. really helped a lot
I have a small issue that I was hoping you could assist with. I have everything enqueued and can see the section being added into the source but all I get on the frontend is a grey box.
Any ideas on what may be causing the lack of map
This usually happens when there’s a problem with the JavaScript or something isn’t enqueued in the right order.
Make sure that your scripts are in the right order, that there are no errors in the console, and that the scripts are in the footer. I’ve found that to be much more useful than trying to include them in the header.
OK great thanks got that working OK. I have another question about displaying multiple markers.
I am adding data to my public.js using wp_localize script and it works very well. I am getting the data for the locations from a plugin in the backend. All data great but I can get the markers to display in a for loop.
I am outputting the data from the “marker = new google.maps.Marker” and the data is the same but in the loop I don’t get the marker on the page.
Any ideas? How would you iterate an array of data to display several markers?
Thanks again for an awesome series of posts.
Sorry Tom, I seriously thought I was going mad but after putting on my glasses and taking a closer look, realised I had used the Lat variable in both the lat & lng position in the loop.
Always the smallest thing that gets you.
Always.
Hello Tom,
Thanks for this extremely well explained tutorial about Google Maps.
The only thing I want to know is when do you need to incorporate the Google API key? So far it all works fine without.
Or have I overlooked a step somewhere?
Best Regards, Grietje Goedkoop
Great question! If you look at this code you’ll see where you’ll need to add it.
Thanks so much for taking the time to write this series!
It was exactly what I needed and I’ve managed to follow along and build a map within my WordPress theme with no prior knowledge of the Google Maps API.
That’s fantastic! I love to hear that :).