SimpleMap Shortcode Reference

I’ve been using a plugin called SimpleMap for clients recently. SimpleMap creates a custom post type for managing locations (think store locations) and displays a Google Map with those locations. It also uses Google Map’s radius search to help people find locations near them. Everything on the front-end is managed using a shortcode. Practically every setting in SimpleMap can overridden in the shortcode, which is really cool for us developers. Plus, they have tons of filters throughout, so any text or label can be customized for your usage. While the “Help” tab in the plugin settings shows you some of the options available with the shortcode, there are tons more and the documentation is practically non-existent. I’m putting this out there, at least for my own reference and I’ll keep adding to it as I learn more and/or have time to expand it.

The gist below explains how to use the shortcode and the more common attributes to use with it.

* Basic shortcode
* Hide the search result list
* @param bool true: hide the list
* false: show the list, this is the default
[simplemap hide_list=true]
* Hide the map
* @param bool true: hide the map
* false: show the map, this is the default
[simplemap hide_map=true]
* Hide the search form
* @param bool true: hide the search form
* false: show the search form, this is the default
[simplemap hide_search=true]
* Limits the search results list to locations from the specified category or categories.
* @param int A comma-separated list of category IDs.
* Do not put spaces between the IDs, just a comma
[simplemap sm_category=8] // one category
[simplemap sm_category=8,9,10] // mutiple categories
* Displays a checkbox for each category as part of the search form.
* Allows the site visitor to filter the search results by category.
* @param bool true: show the category filters
* false: hide the category filters, this is the default
[simplemap show_sm_category_filter=true]
* Specify which fields are included in the search form
* The search form is built in a table.
* Put "||" between each field.
* Here are the options for requesting a field:
* "labelbr_": puts the label with a break return tag afterwards
* "labelsp_": puts the label with a space afterwards
* "labeltd_": puts the label and field in separate table cells.
* "" (blank): puts no label, just the field itself.
* The fields that you can include are:
* street
* city
* state
* zip
* country
* distance: the select menu for the search radius
* empty: puts an empty table cell (useful for formatting the search form properly)
* submit: the submit button. If you don't include this, a hidden button will be added for you.searc
* taxonomy: include the filters for a specific taxonomy. There are four defaults:
* "sm-category"
* "sm-tags"
* "sm-day"
* "sm-time"
[simplemap search_fields=labelbr_street||labelbr_city||labelbr_state||labelbr_zip||labelbr_country||labelbr_distance]
* Changes the name of the search form.
* Default is "Find Locations Near:"
[simplemap search_title="Search this"]
* Changes the number of default table cells.
* Default value is 3.
* NOTE: This one doesn't seem to work for me.
[simplemap search_form_cols=4]
* Changes the field format for the taxonomies.
* Accepts "checkboxes" or "select". Default is "checkboxes".
[simplemap taxonomy_field_type="select"]
* Sets the default latitude. Default is "44.968684".
* Ideally, use with default_lng.
[simplemap default_lat="39.840315"]
* Sets the default longitude. Default is "-93.215561".
* Ideally, use with default_lat.
[simplemap default_lng="-88.954800"]
* Sets the map width. Default is 100%.
[simplemap map_width="60%"]
* Sets the map height. Default is 350px.
[simplemap map_height="300px"]
* Sets the measurement units.
* Accepts "km" for kilometers or "mi" for miles. Default is "mi".
[simplemap units="mi"]
* Sets the radius for the search. Default is 10.
* Use an integer and no unit.
[simplemap radius=12]
* Limits the quantity of how results are returned.
* Use an integer. Default is 20.
[simplemap limit=12]
* Quantity of results to autoload.
* Use an integer. Default is "all".
[simplemap autoload=12]
* Like most shortcodes, to add multiple attributes, put a space between them
[simplemap hide_list=true hide_map=true hide_search=true sm_category=8,9,10]
view raw simplemap-shortcode hosted with ❤ by GitHub

Six Steps to Secure Your WordPress Site

There’s a great breakdancing move called 6-step. If you’ve seen breakdancing, you’ve probably seen this before, but, like me, didn’t know what to call it. Basically, the dancer supports himself on his arms while moving his feet around in a circle. It’s great for getting momentum and launching other moves.

Why do I bring this up? You may have heard about the ongoing attacks against WordPress sites. It appears someone is using up to 90,000 different IP addresses to launch brute-force attacks against sites built with WordPress and are gaining access to some sites. Stupidly, they are trying to gain access with the username “admin” and trying to figure out the password for said user.

Here’s the WP 6-step, which will help secure your WordPress site against attacks:

1) If you have a username “admin” on your site, create another administrator user with a different name, log in as that user, and delete “admin”. If you don’t have a user named “admin”, they will just waste their time attacking your site. From my first-hand experience, changing this is an extremely important to making your site secure. Attackers always start by using the “admin” username and just having it as a valid account will leave you open.

Don’t stop there though!

2) Beef-up your passwords. While standard practice for a secure password is to use eight digits with a mix of lowercase and uppercase letters, numbers, and symbols – there’s a better way. Create a password from a story. Something memorable to you. Something people can’t easily find out without knowing you personally.

As an example: My band and I played a show in Johnson City, TN at a coffee shop and while we played one song, this guy gets up and starts dancing. He was probably in his late 50’s and he’s doing this wiggly, hippie dancing literally feet from us. We were trying not to die laughing while finishing the song. After the show, we discovered the coffee shop owner also owned the laundromat next door and had to go fix a washer. Did I mention it took an hour longer than normal to get there because a bunch of big rigs crashed on the same stretch of highway?

Some passwords one could glean from this story: DanceWasherBigRigCoffee, CoffeeWasherJohnsonLaundry, HighwayCoffeeDanceHippie, etc. See how easy that is to come up with a secure password? You could then throw in the year and an exclamation point, just to have all the traditional password requirements too. Attackers wouldn’t know the story and the length of the password is over 15 digits, making it’s basically impossible to figure out using a brute-force attack.

3) Limit login attempts. Part of this current attack is trying different passwords over and over again until they get it correct. While its silly WordPress allows this, you don’t have to. There are several great security plugins that allow you to limit login attempts before locking that IP address out of your WordPress site:

I’m sure there are more, but those are three I have experience with. Each have their upsides and shortcomings, but anything you can do to thwart an attacker and secure your site is a good thing.

4) Use some kind of caching plugin. WordPress, by itself, is pretty good, but it still needs to talk to the database to load each page. Caching plugins make copies of everything so your site loads faster. While it doesn’t seem like this can help make your site secure, this can prevent certain types of attacks as well as sudden increases in popularity.

5) This is standard WordPress advice: keep WordPress, plugins, and themes up-to-date. I usually advise people to check once a week. You should be adding content each week anyway, so knock out both at the same time.

6) Delete unused plugins and themes. While this won’t help much with the current attack, these unused items could cause problems in the future. And if you’re not using them, why keep them around?

See? Six simple steps and you’re more secure and don’t need to worry about people attacking your site. Yeah ok, I’m not a comedian and the dance thing was random. But seriously, take steps to secure your site before you have to call someone like to me to fix it.

Adding a Custom Class to a Submit Button

While you can hand-code the HTML for a submit button in a form, WordPress has a nice function, submit_button(), that can drop in the correct code for you.

For a recent project, I wanted to restyle some buttons to make them look like links, like on the posts page, rather than buttons. While you don’t NEED an special class to pull this off, it certainly makes it easier and neater in the CSS. I thought this would be achievable in the $other_attributes, but the $type parameter accepts any string, not just the WordPress defaults.

Basically, whatever you put there will be added to the class attribute of the button and you’re good to restyle the button however you want using your custom class.

* Default WordPress submit() parameters
* @param string $text changes the text on the button
* @param string $type determines the style of the button. WordPress styling options:
* primary - the default
* secondary
* delete
* custom - add your custom class for styling here!
* @param string $name sets the name attribute for the button, its "Submit" by default.
* @param string $wrap determines if the button is wrapped in paragraphs tags or not, the default is true.
* @param array $other_attributes sets other attributes for the button.
submit_button( 'Whatever Text', 'my-custom-class' );
view raw wp-submit-button hosted with ❤ by GitHub

Introducing ArtistDataPress 0.5!

Its been a while since ADP was updated and I know lots of people haven’t cared for the previous update that, in some cases, took away their ability to view their plugin settings. That should be resolved with this 0.5 update.

Previously, ADP was using a PHP library called cURL to fetch the XML feed (the raw shows data) from ArtistData. Fortunately, there’s a nice built-in WordPress function called wp_remote_get that uses HTTP’s GET method to fetch an external URL. This means, your server settings really shouldn’t matter because every server supports HTTP. Hopefully, that’s the last we hear of issues getting the XML feed. :)

I also perused the support forums on and found several requests for features. I’ve added some great new features that have been highly requested:

You can now have multiple instances of ADP by using the [artistdatapress] shortcode to specify how many show you want to display and from which url. Use it like this:


[artistdatapress maxshows=20 feedurl=]


The values in the shortcode will override the plugin settings.

I also added the iCal layout for the widget and you choose that on the widget’s settings.

Overall, I streamlined the code and improved the logic and a bunch of other stuff under the hood that should make it easier to update later. Hope you enjoy!

BP Profile Video Widget for BuddyPress updated to 0.3

I released the 0.3 update for BP Profile Video Widget earlier today.  This update includes one big change: the elimination of the Service profile field.  The plugin will auto-detect the service being used based on the video’s URL.  I also included support for the new Youtube short URLs and embedding of Facebook videos.  I’d happily include other video services, but I’ll need some feedback as to which ones, so if you have uggestions, let me know in the comments!  Otherwise, happy updating!

How to Add the jQuery UI Datepicker to a Plugin

Updated – 4/14/2015

I’ve since learned a better way to do this. It essentially does the same thing, the same way, but using better WordPress practices. Use the code in this gist instead of what’s below:

* Adds the datepicker settings to the admin footer.
* Only loads on the plugin-name settings page
function admin_footer() {
$screen = get_current_screen();
if ( $screen->id == 'settings_page_plugin-name' ) {
?><script type="text/javascript">
dateFormat : 'D, m/d/yy'
} // admin_footer()
add_action( 'admin_print_scripts', array( $this, 'admin_footer' ), 1000 );
* Enqueues the built-in Datepicker script
* Only loads on the plugin-name settings page
function enqueue_scripts( $hook_suffix ) {
$screen = get_current_screen();
if ( $screen->id == $hook_suffix ) {
wp_enqueue_script( 'jquery-ui-datepicker' );
} // enqueue_scripts()
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
* Enqueues a Datepicker theme
* Only loads on the plugin-name settings page
function enqueue_styles( $hook_suffix ) {
$screen = get_current_screen();
if ( $screen->id == $hook_suffix ) {
wp_enqueue_style( 'jquery.ui.theme', plugin_dir_url( __FILE__ ) . '/css/datepicker.css' ), array( 'jquery-ui-core', 'jquery-ui-datepicker' ), $this->version, 'all' );
} // enqueue_styles()
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles' ) );



I recently decided to dive into jQuery and figure out how to add a Datepicker to the Seminar system plugin I’m building for the Curb College at Belmont.  Thankfully, I didn’t need to write one from scratch because jQuery UI already makes a great Datepicker and including it in a plugin is super easy.  While I owe a great deal to Zigpress’s great tutorial, the instructions are unfortunately outdated, so I’m going to update them here.

If you’re using WordPress 3.3 or higher, then the jQuery UI Datepicker is already included, otherwise you should update your WordPress install or include the files.  In either case, you will need to include a theme for the Datepicker and add a few lines of code.  FYI, all the following code samples are written within a class, which you should be doing in your plugin, but feel free to adapt as necessary.  First thing, in your __construct() function, you’ll need to add a few lines that tells the plugin to reference a function that will include the jQuery references.

Add Actions

// Add jQuery calender
add_action( 'admin_print_scripts-post.php', array( $this, 'seminar_scripts' ), 1000 );
add_action( 'admin_print_scripts-post-new.php', array( $this, 'seminar_scripts' ), 1000 );
add_action( 'admin_footer', array( $this, 'admin_footer' ) );

In my plugin, I’m using the Datepicker for a meta box on the custom post type pages in the admin area, so I’m using the actions admin_print_scripts-post.php and admin_print_scripts-post-new.php and they both call the ‘seminar_scripts’ function.  I also have the admin_footer action call the admin_footer function.  Calling the Datepicker only on the required admin pages lowers the overhead for loading the Admin pages, keeping things as small as possible without sacrificing functionality.

Enqueue the Script and Theme

Now we have to functions to define two functions: seminar_scripts() and admin_footer().

function seminar_scripts() {
   global $post_type;
   if( 'cemb_seminar' != $post_type ) { return; }
   wp_enqueue_script( 'jquery-ui-datepicker' );
   wp_enqueue_style( 'jquery.ui.theme', plugins_url( '/css/jquery-ui-1.8.17.custom.css', __FILE__ ) );
} // End of seminar_scripts()

Seminar_scripts() starts by checking what post type you’re looking at.  If it’s not cemb_seminar (my custom post type – be sure to change this to match your plugin), then stop.  If it is cemb_seminar, then enqueue the Datepicker and it’s theme.  If you use a different folder structure for your plugin, you’ll need to change the plugins_url() line to match your structure.


For now (2/23/2012), you will need to include a theme for your Datepicker.  WordPress doesn’t include a theme for the Datepicker, but that should be resolved in a coming update.  To get a theme, go to the jQuery UI ThemeRoller, select the Gallery tab on the right sidebar, and choose your theme.  I’m using Smoothness because I think it most closely matches the WordPress Admin UI.


Clicking the Download button under a theme will take you to a page where you can select options for your jQuery UI download.  Select your theme from the Theme drop menu, select the stable version, and click the Download button.


When it finishes downloading, unzip the file and go to the css > smoothness folder.  In my plugin, I’ve got a CSS folder.  Drag the jqery-ui-1.8.17.custom.css file and images folder from the zip file into your plugin’s css folder (or wherever you pointed the plugins_url() line in the enqueue statement in seminar_scripts()).

Add the jQuery Script

function admin_footer() { ?>
   <script type="text/javascript">
            dateFormat : 'D, m/d/yy'
} // End of admin_footer()

Admin_footer() includes the actual jQuery statement to make things happen on the page in the footer of your admin page.  There are two things here you will need to customize for your plugin: the selector and the date format.  jQuery works by looking at the page and finding a part of the page – aka the selector – and performing the script.  My selector is the CSS class (.seminar_date) for the date field in the meta box.  You’ll need to modify that to match the CSS class (or ID) for your date field.  The date format is just how the date is printed on the page.  For my plugin, I choose a format like: Mon 2/22/2012.  You can see all the options on this page.

That’s it!  Once you’ve added all that code and uploaded the jQuery UI theme, test it out and see the Datepicker appear when you click in the field you selected in the selector.

Find User ID by User MetaData

I just wrote this useful function and thought I’d share.  I’m working on a plugin for my employer, Belmont University, and I needed to find a user’s ID by the user’s barcode, which is stored as user metadata.  There’s not a built-in WordPress function to handle that, but this custom function works nicely.  You can add it to your theme’s functions.php file or to a plugin file (in my case, this is part of plugin).  Here’s the function:

Keep in mind, this returns an array, not a string.

Sonicbids buys ArtistData!

Sonicbids, the company that helps you get gigs, has acquired ArtistData, the company that helps you promote gigs.  Brendan Mulligan, CEO of ArtistData, published a letter to ArtistData users talking about the transition and what it means.  When I first read the news, I have to say I was pretty pissed.  I have a Sonicbids membership and while they have some good exclusive gigs, parts of their system desperately need improvement.  My fear was that Sonicbids would screw up ArtistData and/or lock it up for members only.

Fortunately, Brendan relieved these fears.  Part of the acquisition deal was a free option for ArtistData’s services.  The paid parts of ArtistData would become standard issue for Sonicbids members (yea for me!).  He also said he’d be helping improve the Sonicbids system.  If the amazing work he’s done with ArtistData is any indication, we can all look forward to a vastly improved Sonicbids!  I’m very happy about the change in this case.

What does this mean for you?  Since there will still be a free option, we can still publish our gigs through ArtistData for no cost.  If you have a Sonicbids membership as well, like I do, it will mean getting the extra features for free.  I think the biggest thing will be having Brendan and his team working with Sonicbids.  I sincerely hope they are able to help Sonicbids improve their system.

Here are some suggestions for Brendan as he helps improve their system at Sonicbids:

More granular options for gig listings.  Nashville is only a four-hour drive from Cincinnati, so I have to include Ohio in my options for gig listings to see shows there.  Unfortunately, Ohio is lumped in with Michigan and Pennsylvania, so I see tons of gigs that too far away for me to consider.  Not to mention seeing gigs for Cleveland which also too far away.  It would be nice if you could select not only which states you’d like to see, but which parts of states like southern Illinois vs northern Illinois or eastern, middle, or western Tennessee.  Or maybe by city.  I know several musicians who fly back and forth from Nashville and Los Angeles, so it would benefit them to see gig listings from those cities, but not every city & state in between.

Improved email notifications.  I’ve changed my email preferences several times and I still get daily emails with gig listings (I’ve asked for a weekly digest instead).  For the last three weeks, these daily emails have included all the same gigs.  While I understand why you’d relist the same upcoming deadline, if you’re going to send a daily “new listings” email, it should only include actual new listings.  Not listings from two weeks ago that  you’ve already either submitted to or decided to ignore.  Same thing for deadlines.  Maybe try sending a third email when a listing is half way over to remind people about it.

What about listing venues, period?  There’s a site called that lists venues and allows bands to give their feedback about the place and their experiences there.  Sonicbids could allow members to submit venues and their contact info, which could then be verified and listed in the Sonicbids database.  As part of the verification process, SB could contact these venues about possibly accepting peformance offers from their members.  Keeping in regular contact with venues would also give SB the most current, up-to-date venue listings around; that alone would be worth the SB membership fees!  I do the booking for my band and I can’t tell you how many closed venues still have sites up with no news about them closing.

AD improvement:

Have a form to submit media.  I have a habit of picking up out of town newspapers and periodicals and such, but there’s no easy way for me to submit them to your database.  Crowdsource this part of the process to make your life easier!

W3 Total Cache

I just discovered an amazing caching plugin, thanks to  It’s called W3 Total Cache and is available through the WordPress plugins directory.  I’ve endorsed WP Super Cache in Your Band Blog, but frankly, I never really noticed it making my site faster.  When I installed and activated W3TC, I noticed.  I completely believe their claims of a 10x load time improvement.

The best part is, it doesn’t require much tweaking, most of the default settings are great.  I had one minor issue: for some reason the plugin wasn’t able to put its file, advanced-cache.php, in the plugins folder, so it disabled that portion of the plugin.  I manually uploaded the file, reloaded the plugin options page, and all was well.

Here are the settings I changed from the defaults:

Page Cache Settings:

Change HTTP compression to gzip and deflate (best).

Minify Settings:

Change HTTP compression to gzip and deflate (best).

Check the enable box for HTML minify settings.

That’s it.  The plugin will prompt you to empty the cache after each change, just wait until you’ve made all three, then you’re good to go.  You should notice a dramatic increase in your page load times, I know I did.  I have yet to gather any concrete data, like Google Page Speed analytics, but it appears to load much faster than before.  Give this plugin a shot and I think you’ll be happy with the results!