Adding Theme Options in Genesis

If you’re customizing your site in a way that require site-wide options to be managed in the backend, it’s a good idea to use the Genesis Theme Settings page rather than create a separate backend page specifically for your feature. This keeps all theme-related settings in a single location.

I’m going to walk you through creating your own theme options for Genesis. I’ll be adding a Social Settings box that allows you to specify a Twitter and Facebook URL, to be used in the nav menu of the theme.

Set up Defaults

The default values are what the fields will be set to when a user clicks “Reset Settings”. I’m just going to use blank values, but you could use whatever you like.

Sanitization

One of the major improvements to Genesis in the 1.7 release is the addition of a Sanitizer class. Mark Jaquith, a lead developer of WordPress, was hired by StudioPress to conduct a security audit, and this was one of the results.

The Sanitizer class makes it easy to ensure only the specific types of data you want can be saved in your theme settings. This prevents someone from dropping malicious scripts into one of your theme settings. For more information, watch this Theme & Plugin Security presentation.

By default, Genesis comes with four sanitization filters: one_zero, no_html, safe_html, and requires_unfiltered_html. These should cover almost anything you need to do, but if you did want to add something to this list you could use the genesis_available_sanitizer_filters filter (see /lib/classes/sanitization.php).

We’re going to use the no_html filter.

Register Metabox

We’ll use the add_meta_box() function to add a metabox to the Theme Settings page. You can look in /lib/admin/theme-settings.php for more examples:

Create Metabox

Our add_meta_box() function basically says “Stick the metabox the the be_social_settings_box() function on the Theme Settings page.” Now we have to create that function.

For more examples of metaboxes, see /lib/admin/theme-settings.php.

Putting it all together

Since there’s a lot code, I recommend putting it in a single file. Inside my child theme I’ve created /lib/functions/social-settings.php, and this is the contents:

Bill Erickson

Bill Erickson is the co-founder and lead developer at CultivateWP, a WordPress agency focusing on high performance sites for web publishers.

About Me
Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk

Reader Interactions

Comments are closed. Continue the conversation with me on Twitter: @billerickson

Comments

  1. Vivek Parmar says

    Thanks for the useful guide, never use filters always using hooks as i do not have to done major customization.
    Thanks a ton, will try to ad more things using this tut.

  2. slhomme says

    Thank Bill for this quick walk through, It’s not an easy thing to find good articles about adding or customizing theme options for Genesis even in the official support forum!

  3. kirkoconnor says

    This article helps us in an area that is really important to us – customising our Genesis installs to make them even quicker and simpler to produce in record times.

    i have one question though – what sort of protection do the options you create have when Genesis versions change when you update the parent theme in the future?

    • Bill Erickson says

      Since all of the customizations are done in your child theme, they are perfectly save from an upgrade. The only thing that could cause problems is if Genesis drastically changes how the settings are registered, but I don’t see that happening. They add the filters and hooks so that you can extend the theme settings without worrying about an upgrade.

      In the past the only way to customize it was to unhook the Genesis function that registered all the theme settings and create your own. The problem here is your settings page is now “frozen” at the version you originally built it on, since any new metaboxes added to Genesis won’t be included in your function. Now that they have a hook inside the function that registers Genesis metaboxes, this isn’t a problem.

  4. Greg Rickaby says

    Bookmarked. (I’m pretty sure that’s the highest form of compliment one can receive) 🙂

  5. Jon Brown says

    This is excellent and totally opens my eyes to lots of new possibilities, so glad SP added this and that you told us about it.

    Personally for social media button I usually create a “social media menu” using WP 3.0 menus with custom links inserted, link classes assigned to each item and then apply images with CSS. I like this method in part because it keeps the drag and drop functionality of rearranging the icons at will.

    As for the Genesis Theme Settings menu however I have a request to the universe… would someone with far superior skills then me… please considering making the Genesis Theme Settings page meta boxes flexible the way the WP dashboard is? I personally hate the new single column layout, and the fact that it’s fixed width… it ought to be flexible and stretchy/fluid just like the Dashboard.

    • Bill Erickson says

      I agree, if you’re just adding the social icons to the menu just add them directly to the menu and use a class to set the image. For this project the links we had social icons in the menu, a sidebar widget, and the footer, but to keep the example simple I just did the menu (and to show off the great filter wp_nav_menu_{menu-name}_items to customize a specific menu).

  6. Chris Cree says

    Heya Bill! You’re tutorials and code examples for Genesis themes are fantastic! You’ve helped me think about creating custom child themes in a whole new way that has sped up my development time considerably. Thanks so much for that!

    Have a question about this tutorial, though. I’m curious how you would modify this to add a child theme settings page rather than adding the settings to the Genesis –> Theme Settings since that’s the preference for the folks at StudioPress when it comes to creating new settings.

    • Bill Erickson says

      Wow, I’ve never seen that link before. In that case I’d recommend you just copy how Genesis does it in /lib/admin/theme-settings.php, but for your own page.

      • Register your defaults
      • Register the actual settings field (store all your settings in one field)
      • Sanitize your settings
      • Create a subpage to Genesis with a do_meta_boxes() hook
      • Create your metaboxes

      I’ll revisit the tutorial or create a new one specifically about this.

  7. Dee says

    Bill, I love that every time I’m looking for a thing I need to do with Genesis, there you are with the answer… thanks!

  8. Cathy Tibbles says

    Putting this into practice now. And learning from your code int he core functions plugin and then the child theme – and trying to put it all into practice. One thing has me confused – I’ve added custom meta boxes to a file in child theme and called the file from the genesis setup hook in the child functions file, but the defaults aren’t working? And in looking for answers, I’m running into the CMB plugin you co-wrote, we do NOT need that with the genesis options right? It looks like I’ve written most ofthe code into the admin file, so I want to confirm that I dont need that core function plugin with the genesis theme options page?

    Thanks for any tips you can give me!

    • Bill Erickson says

      The CMB code is only for post-specific metaboxes (postmeta). This code is for site-wide metaboxes. So no, it isn’t required.

      The defaults will only work the first time the option is loaded. It basically says, if there’s no value in the database for this option, put the default value in there. Once you save the page (if you didn’t have defaults) then the option will now exist in the database as empty. So even if you specify a default, it won’t work.

      Try dropping your theme in a brand new WordPress website and see if it loads.

  9. Ade says

    Nice tutorial, Bill!

    Just a comment – but you should add the new settings directly to the $defaults array, not as a sub-array, eg like this:
    $defaults['new_setting'] = 'some text';
    $defaults['another_setting'] = 'some other text';
    etc