You’ve probably noticed that WordPress blocks come organized in categories. But did you know you don’t have to live with those categories? You can change them around, to make them work for you.
You can rename them. Reorder them. Add completely new categories, including new categories for your custom blocks. And probably do things you or I haven’t even thought of yet.
And you can do all of that with one hook: block_categories_all
The hook is a versatile tool that allows developers to customize the way block categories are organized. Throughout this article you will learn how to use this hook and build functions to add, reorder and rename single or multiple block categories.
Before you dive in it’s important to note that each function accepts a single parameter which is expected to be an array of existing block categories. This is defined as $categories
throughout this article.
Table of Contents
Adding categories
If you build custom blocks, you might want to put them in some custom categories. You could also have other uses for custom categories—maybe you’re building some sections that have custom styling. Whatever your reasons, here are three approaches:
Creating a new category
Here’s how you can use array_merge
to add a new category named Custom Blocks to the end of the existing categories array.
add_filter( 'block_categories_all', 'add_block_category', 10, 2 );
function add_block_category( $categories ) {
$custom_category = array(
array(
'slug' => 'custom-blocks',
'title' => __( 'Custom Blocks', 'your-text-domain' ),
'icon' => null,
),
);
return array_merge( $categories, $custom_category );
}
Start by creating a function that accepts a single parameter—remember, it’s expecting the list of existing $categories
. Inside the function create a variable named $custom_category
and assign an array with these key-value pairs:
slug
— a unique identifier for the categorytitle
— the display name of the categoryicon
— a Dashicon or custom SVG
Note: to my knowledge we’re not using or showing the icon
anywhere so in this example you can set this as null.
Then you’ll use the array_merge function to combine $custom_category
with the existing $category list
. You can position your new category before or after $categories
based on the order that you pass each variable into the array_merge
.

Positioning a new category
Here’s how to use array_splice
to add a new category named Custom Blocks to $categories
in the second position (index 1).
add_filter( 'block_categories_all', 'add_order_block_category', 10, 2 );
function add_order_block_category( $categories ) {
$custom_category = array(
'slug' => 'custom-blocks',
'title' => __( 'Custom Blocks', 'your-text-domain' ),
'icon' => null,
'position' => 1,
);
// Extract position from the custom category array.
$position = $custom_category['position'];
// Remove position from the custom category array.
unset( $custom_category['position'] );
// Insert the custom category at the desired position.
array_splice( $categories, $position, 0, array( $custom_category ) );
return $categories;
}
Start by creating a function and a new category array, much like you did in the previous example. But this time you will add a key for position
letting the value specify where you want your new category to live inside $categories
.
Then you will extract the position
and set it as a variable to use in an array_splice
, but before that, use unset
to pull the position out of the array—you don’t need it.
Finally, use an array_splice
function, which accepts 4 parameters:
- Array: the array you want to modify
- Offset: the position where you wish to insert
- Length: specify the number of items to remove after the offset
- Replacement: an array of elements to add in the specified position
In your array_splice
, pass in $categories
, the position you specified in your new category array, a length (in this case 0
as we do not want to remove anything), then your new category array.

Adding and positioning multiple new categories
Now let’s add and position some categories all at once. Here’s how you can insert two custom categories into $categories
at positions two and four.
add_filter( 'block_categories_all', 'add_order_multiple_block_categories', 10, 2 );
function add_order_multiple_block_categories( $categories ) {
$custom_categories = array(
array(
'slug' => 'custom-category-1',
'title' => __( 'Custom Category 1', 'your-text-domain' ),
'icon' => null,
'position' => 1,
),
array(
'slug' => 'custom-category-2',
'title' => __( 'Custom Category 2', 'your-text-domain' ),
'icon' => null,
'position' => 3,
),
);
$added_categories = array();
// Prepare an associative array with positions as keys.
foreach ( $custom_categories as $custom_category ) {
$position = $custom_category['position'];
unset( $custom_category['position'] );
$added_categories[ $position ] = $custom_category;
}
// Sort the categories to insert by their positions/key.
ksort( $added_categories );
// Insert the sorted categories into the existing categories array.
foreach ( $added_categories as $position => $custom_category ) {
array_splice( $categories, $position, 0, array( $custom_category ) );
}
return $categories;
}
Create a function. Inside, create an array of new categories named $custom_categories
, including the desired position for each item. Create an empty array to store data in the next step, name this $added_categories
.
Next, iterate through $custom_categories
to extract and unset the position and store it in $added_categories
with the new position as its key. Then add a ksort
function to make sure the categories that were stored in $added_categories
are sorted by their keys.
Finally add foreach
and iterate over the $added_categories
and use an array_slice
to insert each category into the desired position. Finally, reindex the categories using array_values
to ensure things are in the correct order in the new category list.

Reordering categories
You can also use the block_categories_all hook to reorder the existing list of categories in the block editor. Whether you want to move a single category or rearrange multiple, here are some ways to get more control over both.
Reordering a single category
Here’s how to reorder the Design category in the existing array by removing it and reinserting it in the second position using array_splice
PHP function.
add_filter( 'block_categories_all', 'reorder_design_category', 10, 2 );
function reorder_design_category( $categories ) {
$design_category = null;
$new_position = 1;
// Remove the design category from the existing categories.
foreach ( $categories as $key => $category ) {
if ( 'design' === $category['slug'] ) {
$design_category = $category;
unset( $categories[ $key ] );
break;
}
}
// If the design category exists, insert it at the new position.
if ( $design_category ) {
array_splice( $categories, $new_position, 0, array( $design_category ) );
}
// Reindex the array.
return array_values( $categories );
}
Start by setting two variables inside your function, one named $design_category
set as null that you’ll use later to store the design category, or whichever category you wish to move, and another named $position
that specifies the position you want to move the category into. Then, add a foreach
that will iterate through the existing categories to find a match for the category slug, store it in $design_category
, and use unset
to remove it from the existing list.
Now check if any data was stored in your variable and use array_splice
to insert the category into the desired position, just as you did in the new category functions above. Finally, re-index the categories using array_values
to ensure things are in the correct order.

Reordering multiple categories
Here’s how to reorder both the Design and Text categories to positions one and four by removing and reinserting them using array_splice
.
<?php
add_filter( 'block_categories_all', 'reorder_multiple_categories', 10, 2 );
function reorder_multiple_categories( $categories ) {
$reorder_categories = array(
'design' => 0,
'text' => 3,
);
$moved_categories = array();
// Iterate through the existing categories and add/remove the ones to be reordered.
foreach ( $categories as $key => $category ) {
if ( array_key_exists( $category['slug'], $reorder_categories ) ) {
$moved_categories[ $reorder_categories[ $category['slug'] ] ] = $category;
unset( $categories[ $key ] );
}
}
// Sort the moved categories by their new positions.
ksort( $moved_categories );
// Insert the moved categories at their new positions.
foreach ( $moved_categories as $position => $category ) {
array_splice( $categories, $position, 0, array( $category ) );
}
// Reindex the array.
$categories = array_values( $categories );
return $categories;
}
Start by creating an associative array named $reorder_categories
inside your function. The keys can be of the categories you want to reorder, and the value is their new position. You will also need to create an empty array to store data in the next step, name this $moved_categories
.
When the check finds a match, the function adds the category to $moved_categories
, in the position you specified as its key. The unset function drops the category from $categories
.
Now add a ksort
function to, well, sort the categories by their keys.
Add a foreach
to iterate over the $moved_categories
, using array_splice
to insert each category into its proper position. Finally, re-index the categories with array_values
, so things are in the right order in the new $categories
list.

Renaming categories
You can also use block_categories_all to rename the list of categories in the block editor. Want to rename one category? Want to rename them all? Here are some approaches that will give you control over the whole thing..
Renaming one category
Maybe you’d like to rename the Text category to Text Elements.
add_filter( 'block_categories_all', 'rename_text_category', 10, 2 );
function rename_text_category( $categories ) {
foreach ( $categories as &$category ) {
if ( $category['slug'] === 'text' ) {
$category['title'] = __( 'Text Elements', 'your-text-domain' );
}
}
return $categories;
}
Start by using a foreach
. Iterate through $categories
, looking for a category with a slug
equal to text
. If text
exists, rename the category title to Text Elements
.

Renaming multiple categories
Or maybe you really wanted to rename the Text and Media categories to Text Elements and Media and Text Elements.
add_filter( 'block_categories_all', 'rename_multiple_categories', 10, 2 );
function rename_multiple_categories( $categories ) {
foreach ( $categories as &$category ) {
if ( $category['slug'] === 'text' ) {
$category['title'] = __( 'Text Elements', 'your-text-domain' );
}
if ( $category['slug'] === 'media' ) {
$category['title'] = __( 'Media and Text Elements', 'your-text-domain' );
}
}
return $categories;
}
To rename multiple categories in one function, follow the same steps as you did for renaming a single category. Only add as many checks for the category slug
as you need.

Bringing it all together
Finally. Here you have it all— complete control over the names and position of existing categories, and the power to add new ones.
add_filter( 'block_categories_all', 'modify_block_categories', 10, 2 );
function modify_block_categories( $categories ) {
$new_category_order = array(
array(
'slug' => 'media',
'title' => __( 'Media and Text Elements', 'your-text-domain' ),
'position' => 0,
),
array(
'slug' => 'custom-blocks',
'title' => __( 'Custom Blocks', 'your-text-domain' ),
'position' => 1,
),
array(
'slug' => 'text',
'title' => __( 'Text Elements', 'your-text-domain' ),
'position' => 2,
),
array(
'slug' => 'embed',
'position' => 3,
),
array(
'slug' => 'design',
'position' => 4,
),
);
// Create an associative array of block categories with the slug as the key.
$current_block_categories = array_column( $categories, 'title', 'slug' );
// Check if the new category order has a title set, otherwise use the default title.
foreach ( $new_category_order as &$new_category ) {
$new_category['title'] = $new_category['title'] ?? $current_block_categories[ $new_category['slug'] ] ?? __( 'Untitled', 'your-text-domain' );
}
// Create an array of slugs from the new category order.
$new_category_slugs = array_column( $new_category_order, 'slug' );
// Filter out the remaining block categories that are not in the new order.
$remaining_categories = array_filter( $categories, function ( $category ) use ( $new_category_slugs ) {
return ! in_array( $category['slug'], $new_category_slugs, true );
} );
// Merge the new category order with the remaining categories.
return array_merge( $new_category_order, $remaining_categories );
}
Start by defining an array of categories you want to add, reorder or rename named $new_category_order
. Now, the slug
is required to identify each entry. The title
and position
are optional based on what you want to modify.
First, update any category titles by using array_column
to create an associative array named $current_block_categories
from $categories
, using the category slug as the key. Then use a foreach
to iterate through $new_category_order
, checking whether or not a new title is set for any of the items in the array and updating them if necessary. If no new title
is set, it will be extracted from $current_block_categories
based on the slug
. If for whatever reason no slug is found, then Untitled
will be used.
Now build an associative array of categories by iterating over $new_category_order
, checking for any categories with a new position, then adding it as the key in an array named $moved_categories
.
Then use ksort
to sort the $moved_categories
based on their position. Add a foreach
and iterate over the $moved_categories
and use an array_slice
to insert each category into position.
Now that the new titles and positions are handled it’s time to filter out the remaining categories so you can bring everything back together. First, create an array of slugs named $new_category_order
from array_column
. Then create a variable named $remaining_categories
that uses an array_filter
to remove any items from $categories
whose slugs do not exist in $new_category_order
.
Finally, use an array_merge
to combine the new category order with the $remaining_categories
to return a full list of modified Block Categories.

Conclusion
The block_categories_all hook lets you make block categories work any way you need them to—for your project and for your users, and all the content they’ll create.
And, really, these functions are just the beginning. How are you going to use them? Do you have others, or can you see creative twists on them? Leave a comment!
Props to @psykro and @marybaum for reviewing this article and offering feedback.
Leave a Reply