Title: How to modify theme.json data using server-side filters
Author: Nick Diego
Published: July 5, 2023
Last modified: July 13, 2023

---

 * [Showcase](https://wordpress.org/showcase/)
 * [Plugins](https://wordpress.org/plugins/)
 * [Themes](https://wordpress.org/themes/)
 * [Hosting](https://wordpress.org/hosting/)
 * [News](https://wordpress.org/news/)
    - [Learn WordPress](https://learn.wordpress.org/)
    - [Documentation](https://wordpress.org/documentation/)
    - [Education](https://wordpress.org/education/)
    - [Forums](https://wordpress.org/support/forums/)
    - [Developers](https://developer.wordpress.org/)
    - [Blocks](https://wordpress.org/blocks/)
    - [Patterns](https://wordpress.org/patterns/)
    - [Photos](https://wordpress.org/photos/)
    - [Openverse ︎](https://openverse.org/)
    - [WordPress.tv ︎](https://wordpress.tv/)
 *  - [About WordPress](https://wordpress.org/about/)
    - [Make WordPress](https://make.wordpress.org/)
    - [Events](https://events.wordpress.org/)
    - [Five for the Future](https://wordpress.org/five-for-the-future/)
    - [Enterprise](https://wordpress.org/enterprise/)
    - [Gutenberg ︎](https://wordpress.org/gutenberg/)
    - [Job Board ︎](https://jobs.wordpress.net/)
 * [Swag ︎](https://mercantile.wordpress.org/)
 * [Get WordPress](https://wordpress.org/download/)

Search in WordPress.org

 [ Get WordPress ](https://wordpress.org/download/)

[WordPress Developer Blog](https://developer.wordpress.org/news)

 * [Snippets](https://developer.wordpress.org/news/snippets/)
    - [Blocks](https://developer.wordpress.org/news/category/blocks/)
    - [Concepts](https://developer.wordpress.org/news/category/concepts/)
    - [Common APIs](https://developer.wordpress.org/news/category/common-apis/)
    - [Design](https://developer.wordpress.org/news/category/design/)
    - [Playground](https://developer.wordpress.org/news/category/playground/)
    - [Plugins](https://developer.wordpress.org/news/category/plugins/)
    - [Themes](https://developer.wordpress.org/news/category/themes/)
 *  - [About this site](https://developer.wordpress.org/news/about/)
    - [Updates](https://developer.wordpress.org/news/category/updates/)
    - [How to contribute](https://developer.wordpress.org/news/how-to-contribute/)
    - [Tips and guidelines](https://developer.wordpress.org/news/tips-and-guidelines-for-writers/)
 * [Subscribe](https://developer.wordpress.org/news/subscribe/)
 * [Developer Resources](https://developer.wordpress.org/)

 * [Snippets](https://developer.wordpress.org/news/snippets/)
    - [Blocks](https://developer.wordpress.org/news/category/blocks/)
    - [Concepts](https://developer.wordpress.org/news/category/concepts/)
    - [Common APIs](https://developer.wordpress.org/news/category/common-apis/)
    - [Design](https://developer.wordpress.org/news/category/design/)
    - [Playground](https://developer.wordpress.org/news/category/playground/)
    - [Plugins](https://developer.wordpress.org/news/category/plugins/)
    - [Themes](https://developer.wordpress.org/news/category/themes/)
 *  - [About this site](https://developer.wordpress.org/news/about/)
    - [Updates](https://developer.wordpress.org/news/category/updates/)
    - [How to contribute](https://developer.wordpress.org/news/how-to-contribute/)
    - [Tips and guidelines](https://developer.wordpress.org/news/tips-and-guidelines-for-writers/)
 * [Subscribe](https://developer.wordpress.org/news/subscribe/)
 * [Developer Resources](https://developer.wordpress.org/)

# 󠀁[How to modify theme.json data using server-side filters](https://developer.wordpress.org/news/2023/07/how-to-modify-theme-json-data-using-server-side-filters/)󠁿

By [Nick Diego](https://profiles.wordpress.org/ndiego/)

July 5, 2023

[Advanced](https://developer.wordpress.org/news/category/advanced/)

In recent years, theme.json has transformed how themes define styles and settings
in WordPress, bringing centralized control to design and Editor functionality. And
theme.json continues to receive new features with every release.

However, configuring theme.json data solely through a theme’s theme.json file can
be challenging, especially if you need dynamic functionality or advanced Editor 
customization that is not supported. To overcome these limitations, the WordPress
project has introduced powerful tools like server-side theme.json filters, offering
greater flexibility.

Throughout this guide, you’ll: 

 * Explore the intricacies of theme.json data layers
 * See practical examples of those filters in use
 * Learn to curate Editor functionality to suit your needs

From dynamically modifying color palettes to restricting block controls based on
user permissions, you’ll discover a world of options that these server-side filters
can offer.

**Table of Contents**

 * [Understanding theme.json data layers](https://developer.wordpress.org/news/2023/07/how-to-modify-theme-json-data-using-server-side-filters/#understanding-theme-json-data-layers)
 * [Getting started with theme.json filters](https://developer.wordpress.org/news/2023/07/how-to-modify-theme-json-data-using-server-side-filters/#getting-started-with-theme-json-filters)
 * [Modifying theme.json based on login status](https://developer.wordpress.org/news/2023/07/how-to-modify-theme-json-data-using-server-side-filters/#modifying-theme-json-based-on-login-status)
 * [Restricting theme.json settings by user permissions](https://developer.wordpress.org/news/2023/07/how-to-modify-theme-json-data-using-server-side-filters/#restricting-theme-json-settings-by-user-permissions)

## Understanding theme.json data layers

When using a WordPress theme that includes a theme.json file, there are four layers(
origins) of theme.json data that contribute to the overall configuration:

 * `default` – Data that includes default settings and styles that come with WordPress.
 * `block` – Data that comes from blocks.
 * `theme` – Data that comes from the theme.
 * `custom`  – Data that is user-generated from Global Styles. Whenever you change
   a color, font, block style, etc., in the Site Editor, these are stored as custom(
   user) data.

All these layers combine to create the final theme.json data object, which controls
how the Editor works and the ultimate look and feel of your website.

You can find a detailed overview of general theme.json concepts in the [Block Editor Handbook](https://developer.wordpress.org/block-editor/explanations/architecture/styles/#global-styles).
To see the source code that controls each data layer, refer to the [class-wp-theme-json-resolver.php](https://github.com/WordPress/WordPress/blob/master/wp-includes/class-wp-theme-json-resolver.php#L535)
file in WordPress Core.

WordPress 6.1 introduced four server-side filters that let you modify these different
layers of theme.json data:

 * `wp_theme_json_data_default` – Hooks into default data provided by WordPress.
 * `wp_theme_json_data_blocks` – Hooks into data provided by blocks.
 * `wp_theme_json_data_theme` – Hooks into data provided by the theme.
 * `wp_theme_json_data_user` – Hooks into data provided by the user (custom).

These layers have their own hierarchy: the `custom` (user) layer is the highest 
priority. The lowest is the `default` layer.
For instance, you can define default
theme.json settings and styles with the `wp_theme_json_data_default` filter and 
still let blocks, themes, or users override this data. On the other hand, if you
want to override all other potential data sources completely, you can apply specific
theme.json settings with the `wp_theme_json_data_user` filter. 

Now, let’s dive into some practical examples.

## Getting started with theme.json filters

Filtering theme.json data works pretty much like any other PHP hook. 

You register a callback with the [`add_filter()`](https://developer.wordpress.org/reference/functions/add_filter/)
function. That callback function will receive an instance of the `WP_Theme_JSON_Data`
class, which contains the data for the layer you’re filtering. Then you can modify
that data and return an updated theme.json.

Here’s a simple example, slightly modified from the original [Dev Note](https://make.wordpress.org/core/2022/10/10/filters-for-theme-json-data/),
that changes the color palette of the current theme and disables the text color 
control in the Editor:

    ```php
    <?php
    /**
     * This function modifies the theme JSON data by updating the theme's color
     * palette to just black or white and disables text color.
     *
     * @param object $theme_json The original theme JSON data.
     * @return object The modified theme JSON data.
     */
    function example_filter_theme_json_theme( $theme_json ){
    	$new_data = array(
    		'version'  => 2,
    		'settings' => array(
    			'color' => array(
    				'text'       => false,
    				'palette'    => array(
    					array(
    						'slug'  => 'base',
    						'color' => 'white',
    						'name'  => __( 'Base', 'theme-domain' ),
    					),
    					array(
    						'slug'  => 'contrast',
    						'color' => 'black',
    						'name'  => __( 'Contrast', 'theme-domain' ),
    					),
    				),
    			),
    		),
    	);

    	return $theme_json->update_with( $new_data );
    }
    add_filter( 'wp_theme_json_data_theme', 'example_filter_theme_json_theme' );
    ```

This is how the applied filter will appear for users in the Editor.

![The default color palette in the Editor are available when the filter is not applied.](
https://developer.wordpress.org/news/files/2023/07/restrict-editor-settings-default-
1024x888.png)

![With the filter applied, the color palette is updated to black and white and the
text color control is disabled.](https://developer.wordpress.org/news/files/2023/
07/restrict-editor-settings-filtered-1024x888.png)

Keep in mind a few important things as you work with server-side filters:

 1. To update the original theme.json data with your modifications, use the `update_with(
    $new_data )` method and make sure your custom data follows a valid theme.json-like
    structure.
 2. New data also requires a version number. If your data uses a different version 
    than the data from the filtered layer, WordPress will properly migrate it at runtime—
    even if the structure of theme.json changes in the future. 

Now, the code provided above is designed to be placed inside your theme’s `functions.
php` file. 

If you want to use a utility plugin, you need to wait for the theme to load before
the filter can run. In that case, you’ll want to use the [`after_setup_theme`](https://developer.wordpress.org/reference/hooks/after_setup_theme/)
hook. It’s also a good practice to check if the theme has a theme.json file using
the [`wp_theme_has_theme_json()`](https://developer.wordpress.org/reference/functions/wp_theme_has_theme_json/)
function. 

The modified code would look something like this:

    ```php
    // For the filter to work properly, it must be run after theme setup.
    function example_apply_theme_json_theme_filters() {

    	// Check to make sure the theme has a theme.json file.
    	if ( wp_theme_has_theme_json() ) {
    		add_filter( 'wp_theme_json_data_theme', 'example_filter_theme_json_theme' );
    	}
    }
    add_action( 'after_setup_theme', 'example_apply_theme_json_theme_filters' );
    ```

Now that you know the basics, let’s explore some more interesting examples.

## Modifying theme.json based on login status

Let’s say you want to change the color of a theme depending on whether a user is
logged in. Perhaps this could be a visual cue to let customers know they are receiving
a loyalty discount.

One of the benefits of server-side filtering is that it works well with standard
WordPress PHP functions, like `[is_user_logged_in()](https://developer.wordpress.org/reference/functions/is_user_logged_in/)`.
This function allows you to quickly determine the login status of a user. You can
then use this information to change theme.json settings when combined with the `
wp_theme_json_data_theme` filter. 

The following example shows how to change the color palette and a few button styles
in the Twenty Twenty-Three theme. This code is specifically designed for the color
naming conventions used in Twenty Twenty-Three, so you will need to adapt it accordingly
for other themes.

    ```php
    <?php
    /**
     * This function modifies the theme JSON data by updating the theme's color
     * palette based on the user's login status.
     *
     * @param object $theme_json The original theme JSON data.
     * @return object The modified theme JSON data.
     */
    function example_modify_color_palette_if_logged_in( $theme_json ) {
    	if ( is_user_logged_in() ) {
    		$new_data = array(
    			'version'  => 2,
    			'settings' => array(
    				'color' => array(
    					'palette' => array(
    						array(
    							'color' => '#ffffff',
    							'name'  => __( 'Base' ),
    							'slug'  => 'base',
    						),
    						array(
    							'color' => '#00131C',
    							'name'  => __( 'Contrast' ),
    							'slug'  => 'contrast',
    						),
    						array(
    							'color' => '#3858E9',
    							'name'  => __( 'Primary' ),
    							'slug'  => 'primary',
    						),
    						array(
    							'color' => '#1D35B4',
    							'name'  => __( 'Secondary' ),
    							'slug'  => 'secondary',
    						),
    						array(
    							'color' => '#ECF6FA',
    							'name'  => __( 'Tertiary' ),
    							'slug'  => 'tertiary',
    						),
    					),
    				),
    			),
    			'styles'  => array(
    				'elements' => array(
    					'button' => array(
    						'color' => array(
    							'background' => 'var(--wp--preset--color--primary)',
    							'text'       => 'var(--wp--preset--color--base)',
    						),
    					),
    				),
    			),
    		);

    		// Return the modified theme JSON data.
    		return $theme_json->update_with( $new_data );
    	}

    	// Return the original theme JSON data.
    	return $theme_json;
    }

    // For the filter to work properly, it must be run after theme setup.
    function example_apply_theme_json_theme_filters() {

    	// Check to make sure the theme has a theme.json file.
    	if ( wp_theme_has_theme_json() ) {
    		add_filter( 'wp_theme_json_data_theme', 'example_modify_color_palette_if_logged_in' );
    	}
    }
    add_action( 'after_setup_theme', 'example_apply_theme_json_theme_filters' );
    ```

Notice that this code modified both styles and settings. In the Twenty Twenty-Three
theme, buttons have dark text on a light background. The filter changes the color
palette making the `primary` color blue, so the button text needs to be changed 
to `base`.

Here’s what this applied filter will look like for users on the front end.

![When the user logs in, the color palette is updated.](https://developer.wordpress.
org/news/files/2023/07/theme-json-filter-login.gif)

While this example may not be relevant to your specific use case, it demonstrates
the flexibility of PHP filters. One of the most important differences between [client-side](https://developer.wordpress.org/news/2023/05/curating-the-editor-experience-with-client-side-filters/)
and server-side filters is that server-side filters update the theme.json data at
the server level. This data is then processed and used to create CSS variables.

You can inspect the page’s HTML and CSS to see the explicit changes. The CSS variables
for the color palette have been updated, which are then used to style the page.

![The CSS color variables are updated when the filter is applied.](https://developer.
wordpress.org/news/files/2023/07/color-by-logged-in-status.png)

This functionality has many implications. For example, you could add or modify [custom theme.json settings](https://developer.wordpress.org/block-editor/reference-guides/theme-json-reference/theme-json-living/#custom).
These settings generate custom CSS variables that you could use to create sophisticated
design systems or provide specific functionality to a theme or block.

Here’s a callback function you could use to add custom settings that output CSS 
variables for viewport, media, or other breakpoints. The variables will take the
form `--wp--custom--breakpoint--[size]`, which can be used to adjust the look of
your theme based on each breakpoint.

    ```php
    /**
     * This function modifies the theme JSON data by creating a custom
     * CSS variables for various breakpoints.
     *
     * @param object $theme_json The original theme JSON data.
     * @return object The modified theme JSON data.
     */
    function example_create_custom_breakpoint_variables( $theme_json ) {

    	$new_data = array(
    		'version'  => 2,
    		'settings' => array(
    			'custom' => array(
    				'breakpoint' => array(
    					'small'  => '360px',
    					'medium' => '780px',
    					'large'  => '1080px',
    				),
    			),
    		),
    	);

    	// Return the modified theme JSON data.
    	return $theme_json->update_with( $new_data );
    }
    ```

Next up, let’s look at ways you can use server-side filters to restrict user functionality
in the Editor.

## Restricting theme.json settings by user permissions 

By default, the theme.json file lets you control how the Editor works for everyone
on your site. But what if you want to give users different permissions? Maybe you
want to disable color controls for content creators but let Administrators modify
colors sitewide. You can’t do that with the theme.json file, but you can use server-
side or client-side filters.

Both client-side and server-side filters have their pros and cons. Client-side filters
provide more flexibility to adjust settings directly within the Editor. Server-side
filters make changes to theme.json data on the server, letting you configure settings
and styles and even create CSS variables, as explained in the previous section.

Client-side filters are beyond the scope of this article but refer to [Curating the Editor experience with client-side filters](https://developer.wordpress.org/news/2023/05/curating-the-editor-experience-with-client-side-filters/)
if you would like to learn more.

Now, imagine you manage multiple websites using different themes with unknown theme.
json file configurations.

Your goal is to maintain a consistent Editor experience across all sites using a
utility plugin. To keep things simple, let’s say you want to turn off color controls
for everyone but Administrators (who should have access to everything). Since you
don’t know what themes have enabled or disabled certain features sitewide, you also
need to ensure there are no restrictions for admins.

You could use the same filter as the examples above, but let’s use `wp_theme_json_data_user`,
guaranteeing that the custom settings always take priority over any theme configurations.

    ```php
    <?php
    /**
     * This function modifies the theme JSON data by disabling color settings
     * for all users and then specifically enabling settings for users with the 
     * capability to edit_theme_options (Administrators).
     *
     * @param object $theme_json The original theme JSON data.
     * @return object The modified theme JSON data.
     */
    function example_restrict_color_settings_to_administrators( $theme_json ) {

    	// First disable color settings for everyone. This will override
    	// any settings that might have been supplied by the theme.
    	$default_settings = array(
    		'version'  => 2,
    		'settings' => array(
    			'color' => array(
    				'text'       => false,
    				'background' => false,
    				'link'       => false,
    			),
    		),
    	);

    	$theme_json->update_with( $default_settings );

    	// If the current user has the correct permissions, enable color settings.
    	if ( current_user_can( 'edit_theme_options' ) ) {
    		$administrator_settings = array(
    			'version'  => 2,
    			'settings' => array(
    				'color' => array(
    					'text'       => true,
    					'background' => true,
    					'link'       => true,
    				),
    			),
    		);

    		$theme_json->update_with( $administrator_settings );
    	}

    	// Return the modified theme JSON data.
    	return $theme_json;
    }

    // For the filter to work properly, it must be run after theme setup.
    function example_apply_theme_json_user_filters() {

    	// Check to make sure the theme has a theme.json file.
    	if ( wp_theme_has_theme_json() ) {
    		add_filter( 'wp_theme_json_data_user', 'example_restrict_color_settings_to_administrators' );
    	}
    }
    add_action( 'after_setup_theme', 'example_apply_theme_json_user_filters' );
    ```

By applying this filter, only users who have permission to `edit_theme_options` 
can view the color controls in the Editor. Unless you have made customizations to
your WordPress installation, this will typically include only Administrators. For
further information on checking roles and capabilities, you can refer to the [Plugin Handbook](https://developer.wordpress.org/plugins/security/checking-user-capabilities/).

Here’s how the outcome will appear for both Editors and Administrators.

![Color controls are disabled for Editors when the filter is applied.](https://developer.
wordpress.org/news/files/2023/07/restrict-by-role-editor-new-1024x888.png)

![Color controls remain available for Administrators when the filter is applied.](
https://developer.wordpress.org/news/files/2023/07/restrict-by-role-admin-new-1024x888.
png)

Now that you know how to modify theme.json data using these four server-side filters,
you can start thinking about other applications of this functionality.

Say you’re using Twenty-Three but want to avoid creating and managing a child theme
for a few minor changes. You could write a small utility plugin that overrides theme.
json’s settings and styles using the `wp_theme_json_data_theme` filter.

Or you could use the `wp_theme_json_data_block` filter to apply styles to your custom
blocks. This would provide a better default experience while allowing themes and
users to override this configuration.

The possibilities are nearly endless.

For more information and a working plugin that explores the examples in this article,
you can check out the [Editor Curation Examples](https://github.com/ndiego/editor-curation-examples)
plugin on GitHub. The Block Editor Handbook also includes a [fantastic resource](https://developer.wordpress.org/block-editor/how-to-guides/curating-the-editor-experience/)
of additional curation methods, and every WordPress release adds more.

So what will you build using the server-side theme.json filters? Is there functionality
that’s missing that you would like to see? Add your thoughts in the comments.

_Props to [@marybaum](https://profiles.wordpress.org/marybaum/), [@greenshady](https://profiles.wordpress.org/greenshady/),
[@bph](https://profiles.wordpress.org/bph/), [@juanmaguitar](https://profiles.wordpress.org/juanmaguitar/),
and [@mburridge](https://profiles.wordpress.org/mburridge/) for feedback and review._

**Categories:** [Advanced](https://developer.wordpress.org/news/category/advanced/)

**Tags:** [Editor Curation](https://developer.wordpress.org/news/tag/editor-curation/),
[theme.json](https://developer.wordpress.org/news/tag/theme-json/)

## One response to “How to modify theme.json data using server-side filters”

 1. ![Grégoire Noyelle Avatar](https://secure.gravatar.com/avatar/2ad809959fb7c1e8824ae3338f0ee87458a68cfee3fba9260dae7d29d60d8c9d?
    s=40&d=identicon&r=g)
 2. [Grégoire Noyelle](https://www.gregoirenoyelle.com)
 3. [November 29, 2024](https://developer.wordpress.org/news/2023/07/how-to-modify-theme-json-data-using-server-side-filters/#comment-14037)
 4. Hello,
     Thanks a lot you for this post. I’m experimenting with these filters just
    now, and they work perfectly—what a relief! It’s challenging to create well-proportioned
    patterns and then see the editors change all the paddings. So, I’ve removed those
    settings for this role.
 5. [Reply](https://developer.wordpress.org/news/2023/07/how-to-modify-theme-json-data-using-server-side-filters/?replytocom=14037#respond)

### Leave a Reply 󠀁[Cancel reply](https://developer.wordpress.org/news/2023/07/how-to-modify-theme-json-data-using-server-side-filters/?output_format=md#respond)󠁿

Your email address will not be published. Required fields are marked *

Comment *

Name *

Email *

Website

 Save my name, email, and website in this browser for the next time I comment.

 Notify me of follow-up comments by email.

 Notify me of new posts by email.

Δ

## Have an idea for a new post?

### 󠀁[Learn how to contribute](https://developer.wordpress.org/news/how-to-contribute/)󠁿

Share your knowledge with fellow WordPress developers.

Search

### 󠀁[Review tips and guidelines](https://developer.wordpress.org/news/tips-and-guidelines-for-writers/)󠁿

Everything you need to know about writing for the Blog.

## Subscribe to the Blog

  Email Address

 Join 1,771 other subscribers

 * [About](https://wordpress.org/about/)
 * [News](https://wordpress.org/news/)
 * [Hosting](https://wordpress.org/hosting/)
 * [Privacy](https://wordpress.org/about/privacy/)

 * [Showcase](https://wordpress.org/showcase/)
 * [Themes](https://wordpress.org/themes/)
 * [Plugins](https://wordpress.org/plugins/)
 * [Patterns](https://wordpress.org/patterns/)

 * [Learn](https://learn.wordpress.org/)
 * [Documentation](https://wordpress.org/documentation/)
 * [Developers](https://developer.wordpress.org/)
 * [WordPress.tv ](https://wordpress.tv/)

 * [Get Involved](https://make.wordpress.org/)
 * [Events](https://events.wordpress.org/)
 * [Donate ](https://wordpressfoundation.org/donate/)
 * [Swag ](https://mercantile.wordpress.org/)

 * [WordPress.com ](https://wordpress.com/?ref=wporg-footer)
 * [Matt ](https://ma.tt/)
 * [bbPress ](https://bbpress.org/)
 * [BuddyPress ](https://buddypress.org/)

 * [Visit our X (formerly Twitter) account](https://www.x.com/WordPress)
 * [Visit our Bluesky account](https://bsky.app/profile/wordpress.org)
 * [Visit our Mastodon account](https://mastodon.world/@WordPress)
 * [Visit our Threads account](https://www.threads.net/@wordpress)
 * [Visit our Facebook page](https://www.facebook.com/WordPress/)
 * [Visit our Instagram account](https://www.instagram.com/wordpress/)
 * [Visit our LinkedIn account](https://www.linkedin.com/company/wordpress)
 * [Visit our TikTok account](https://www.tiktok.com/@wordpress)
 * [Visit our YouTube channel](https://www.youtube.com/wordpress)
 * [Visit our Tumblr account](https://wordpress.tumblr.com/)

![Code is Poetry](https://s.w.org/style/images/code-is-poetry-for-dark-bg.svg)

 The WordPress® trademark is the intellectual property of the WordPress Foundation.