A small primer on theme mods

Oh, the many things I encounter while doing reviews is amazing.

One of the reasons I love contributing to the review team is to get a better understanding of how WordPress at its core works and it is because of this I feel like there are some things that still are not being mentioned or shared.

A fairly good example of this is what I saw today. I’ve seen this on several themes but I think I finally reached a point where it really, truly irks me.

What are settings?

WordPress themes can use two things to save user inputs – or better yet theme mods. The neat part is there are two ways those can be saved. Using option or theme_mod when registering a setting in the customizer. What I want to focus on for this is the use of theme_modsince it is the recommended method for most themes. Notice I say most. There are cases where it makes sense to use option but that’s for another time. The WordPress theme mods are saved and retrieved using a few functions.

  • get_theme_mods() – gets all theme settings
  • get_theme_mod() – gets a single setting
  • set_theme_mod() saves a theme setting

Now, there are two other functions for theme mods.

  • remove_theme_mod() – remove a single theme setting
  • remove_theme_mods() – removes all theme settings

Those are least likely to be used but they are good to know.

How it works

The WordPress customizer is magic. Okay, not completely and I only say that because if you look at how things work in the JavaScript file it quite literally says, “return magic;

The way the customizer saves things is by using a few object methods. It uses the save() method, which calls the update() method, and tfinally the set_root_value() method of the Setting class. It’s here where our setting actually gets saved.

If we look over the highlighted code we can see what is actually happening.

protected function set_root_value( $value ) {
	$id_base = $this->id_data['base'];
	if ( 'option' === $this->type ) {
		$autoload = true;
		if ( isset( self::$aggregated_multidimensionals[ $this->type ][ $this->id_data['base'] ]['autoload'] ) ) {
			$autoload = self::$aggregated_multidimensionals[ $this->type ][ $this->id_data['base'] ]['autoload'];
		return update_option( $id_base, $value, $autoload );
	} elseif ( 'theme_mod' === $this->type ) {
		set_theme_mod( $id_base, $value );
		return true;
	} else {
		 * Any WP_Customize_Setting subclass implementing aggregate multidimensional
		 * will need to override this method to obtain the data from the appropriate
		 * location.
		return false;

The default setting for registering a theme option is theme_mod and what this means is that when the user clicks that save button, the function set_theme_mod() will be triggered and the setting will be saved to the database. Super cool! Now, what does that little function actually do?

Well, let’s take a look over it:

function set_theme_mod( $name, $value ) {
	$mods = get_theme_mods();
	$old_value = isset( $mods[ $name ] ) ? $mods[ $name ] : false;

	 * Filters the theme mod value on save.
	 * The dynamic portion of the hook name, `$name`, refers to the key name of
	 * the modification array. For example, 'header_textcolor', 'header_image',
	 * and so on depending on the theme options.
	 * @since 3.9.0
	 * @param string $value     The new value of the theme mod.
	 * @param string $old_value The current value of the theme mod.
	$mods[ $name ] = apply_filters( "pre_set_theme_mod_{$name}", $value, $old_value );

	$theme = get_option( 'stylesheet' );
	update_option( "theme_mods_$theme", $mods );

It gets all the theme mods, then creates a filter for us to use, gets the name of the currently active theme, and finally updates an option.

An option?

Yes. An option. I know. I know. We were talking about theme mods but the way the customizer works with theme_mods is by creating an associative array per theme. For example, if my theme were called For Real Yo, the $theme would be for-real-yo.

WordPress then turns it to a slug. So, the best way to get those options would be to get the option or use the core functions get_theme_mod() and get_theme_mods() to do things for me and because we like using good practices we use get_theme_mod() in order to get the single setting – or rather theme_mod.

You are probably wondering what get_theme_mods() does. I know I did when I first read the code.

function get_theme_mods() {
	$theme_slug = get_option( 'stylesheet' );
	$mods = get_option( "theme_mods_$theme_slug" );
	if ( false === $mods ) {
		$theme_name = get_option( 'current_theme' );
		if ( false === $theme_name )
			$theme_name = wp_get_theme()->get('Name');
		$mods = get_option( "mods_$theme_name" ); // Deprecated location.
		if ( is_admin() && false !== $mods ) {
			update_option( "theme_mods_$theme_slug", $mods );
			delete_option( "mods_$theme_name" );
	return $mods;

From the core code, we can see that it gets the theme slug, gets the option ( from the options table ) for the active theme, then it checks to see if it is populated or not, and finally returns the array of theme_mods.

So, why this post?

I am making this because the code that I stumbled across looked a little like:

 *  Default theme options
if ( ! function_exists( 'for_real_yo_default_options' ) ) :
	function for_real_yo_default_options() {
		$default_options = array(
			/* super long list of "defaults" */
		return apply_filters( 'for_real_yo_defaults', $default_options );

*  Get theme options
if ( ! function_exists( 'for_real_yo_theme_options' ) ) :

	function for_real_yo_theme_options() {

		$for_real_yo_defaults = for_real_yo_default_options();

		$for_real_yo_option_values = get_theme_mod( 'for_real_yo' );

		if ( is_array( $for_real_yo_option_values ) ) {
			return array_merge( $for_real_yo_defaults ,$for_real_yo_option_values );
		} else {
			return $for_real_yo_defaults;

Looks rather harmless, right? It is until you realize how they were registering the setting.

		'default' 			=> 'title-text',
		'sanitize_callback' => 'for_real_yo_sanitize_select'

If you can spot the issue, awesome. If not, it is creating an array for one setting of a setting. Yes, a little odd to say the least but I’ll show a quick example.

Let’s say we are comparing one of the core themes with our above code. Okay, let us look at the returned array from each one. Twenty Seventeen would yeild something like:

    [header_image] => path/to/file
    [header_image_data] => stdClass Object
            [attachment_id] => id
            [url] => path/to/file
            [thumbnail_url] => path/to/file
            [height] => 1198
            [width] => 2000

    [page_layout] => one-column
    [header_textcolor] => cfe23d
    [colorscheme] => light
    [colorscheme_hue] => 0

Now, if we look at the above example’s way of registering you can see the difference much better.

    [for_real_yo] => Array
            [some_setting] => 
            [another_setting] => 
            [top_bar_left] => menu
            [right_social] => 
            [right_hours] => 


Hopefully this does help in understanding how theme_mods are saved and retrieved and does at least help out one person.

Filtering the page links

Nothing is ever truly perfect. There are some things that do come close though. In the mean time we can make just a few changes to get our desired result. The photo above is a quick comparison of a photo I took a few years back while at Yosemite National Park.

As you can see there is a huge difference between the two. One is more vibrant and full of color while the other is just a little flat with little to no contrast. Yeah, I critique my own photos constantly. The left is the raw untouched file taken with my camera and the right is the edited version. As you can see it made it better by correcting some color and adding a little more light to the overall image.

Now, in WordPress one way of altering is by using filters. Recently I’ve been messing with one in particular that I feel can be a good practice for any theme developer. Filtering the arguments of wp_link_pages() to style post pagination.


Yes, pagination in posts. Often times when a tutorial or a written work is far too long that it needs to be divided into segments of easy to read, easy to consume blocks of text. In WordPress the


tag is used in the text editor to create another page within that post. WordPress handles this in one of two ways. The first is by listing the pages and the other is by using simple next/previous links. All themes tend to style that in different ways. The default Twenty Thirteen handles it like:


The way it is styled uses the same code throughout all the content related files. The reason I say it that way is because 2013 has support for all the post formats available within WordPress, which is amazing! Now the downside to that is that it can mean you have to copy/paste, type out a lot more code than you’d want to. I know I can be that way. I just want to be able to set it once and be done. I mean who doesn’t, right?

So, the way 2013 is coded is by calling wp_link_pages and then passing to it an array with some settings.

                'before' => '<div class="page-links"><span class="page-links-title">' . __( 'Pages:', 'twentythirteen' ) . '</span>',
                'after' => '</div>',
                'link_before' => '<span>',
                'link_after' => '</span>'
        ) );

As you can see you would copy and paste that code on all the files depending on how you have all your content files setup. While it does create that nice little HTML structure for us to style it may be tedious to have to copy and paste over and over. I know I got tired of it.


What I did was looked at the source code for the function. I took notice at one particular line of code that made me happy. That line was:

$r = apply_filters( 'wp_link_pages_args', $r );

The reason it made me happy was because I realized that I could filter the arguments and not have to type out all that code over and over again or even have to copy and paste it all. So all I now had to do was create a callback function and hook it through a filter.

add_filter( 'wp_link_pages_args', 'theme_link_pages_args' );
function theme_link_pages_args( $args ){
    $args = array(
        'before'           => '<div class="link-pages">Page ',
        'after'            => '</div>',
        'link_before'      => '',
        'link_after'       => '',
        'next_or_number'   => 'number',
        'separator'        => '<span>',
        'nextpagelink'     => 'Next Page',
        'previouspagelink' => 'Previous Page',
        'pagelink'         => '%',
        'echo'             => 1
    return $args;

*If you are going to filter the $args make sure you use all the settings or you may end up getting some errors.

There we have it! Keep in mind that if you want the theme to be translation ready don’t forget to add the proper functions where needed and prefix the function with your theme’s name.