Add Fields into WooCommerce New Product Editor
Since I have a plugin that allows you to share products between different WooCommerce stores, I’ve been keeping an eye on the New Product Editor for quite a long time.
I know that people have different opinions about it, but this post is not about whether you like this new product editing experience or not, it is all about adding your custom product fields into it.
As a result of this tutorial, we will have a custom checkbox field in the “Organization” tab:

Let’s dive into this whole process step by step.
Before we start developing a Gutenberg block, which is going to represent a section with fields (kind of a meta box) in the new WooCommerce product editor, let’s talk a little bit about the project setup.
If you check any other guides and recommendations about it, everyone suggests using @wordpress/create-block tool with the following configuration:
npx @wordpress/create-block --template @woocommerce/create-product-editor-block example-block-nameThe question is what do we need to do if you’re going to implement it into an existing project?
In theory, we need to install @wordpress/scripts and then @woocommerce/product-editor but unfortunately it doesn’t work the way I expected it to work, if you have your ideas about it, please let me know in the comments section.
block.json
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "rudr/crosspost-to",
"title": "Publish to",
"attributes": {},
"supports": {
"html": false,
"inserter": false
},
"editorScript": "file:./index.js"
}As you can see it is very similar to a block.json of a regular Gutenberg block, but anyway there are a couple of things to keep in mind here:
insertershould be set tofalse, otherwise, your WooCommerce product field may appear in the Block Editor which we don’t want.- You can also include some custom CSS using
editorStyleandstyle, but using justeditorScriptis going to be enough in most cases. - In some examples over the internet I also found a block category set to
woocommercewhich will throw a warning for you in the browser console.
Once finished with the block.json, let’s include it in the main plugin PHP file:
use Automattic\WooCommerce\Admin\Features\ProductBlockEditor\BlockRegistry;
add_action( 'init', function() {
// probably this condition isn't really necessary
if( empty( $_GET[ 'page' ] ) || 'wc-admin' !== $_GET[ 'page' ] ) {
return;
}
BlockRegistry::get_instance()->register_block_type_from_metadata( __DIR__ );
} );This snippet is crucial and if for some reason you forget about it, be ready to get an error like on the screenshot:

If you’re going to use just a register_block_type_from_metadata() function, then you probably get a notice like “Scripts that have a dependency on [wc-block-templates, wc-product-editor] must be loaded in the footer” and the fields aren’t going to work.
registerBlockType
Before adding any fields let’s just start with some random static text content. It will simplify the process a lot and it will be much easier to understand.
import { registerBlockType } from '@wordpress/blocks';
// const { useWooBlockProps } = window.wc.blockTemplates;
import { useWooBlockProps } from '@woocommerce/block-templates';
import metadata from './block.json';
registerBlockType(
metadata,
{
edit: ( { attributes, context } ) => {
return (
<div {...useWooBlockProps( attributes )}>
<p>Some content will go here...</p>
</div>
)
}
}
)I want to remind you that we need to create a src folder and put the code above into the index.js file inside it. But even if you run npm run build at this moment, nothing is going to work, because we need to register our custom “block” in PHP as well.
Another hint for you – if you’re going to get useWooBlockProps from wc.blockTemplates, then you would probably need to register the index.js with enqueue_block_editor_assets and add the following dependency there: wc-product-editor.
Groups and Sections
The same way how we could decide where to add fields into a classic product editor with hooks, here we can also choose a specific tab (or group) and a section within it.
If we’re going to do it in code, our code snippet is going to look like this:
add_action( 'woocommerce_layout_template_after_instantiation', 'rudr_new_product_editor_fields', 10, 3 );
function rudr_new_product_editor_fields( $template_id, $template_area, $template ) {
$organization = $template->get_group_by_id( 'organization' );
if( $organization ) {
// create a new section, but you can use an existing one
$misha_section = $organization->add_section(
array(
'id' => 'misha_section',
'order' => 1,
'attributes' => array(
'title' => 'Publish to',
'description' => 'You can crosspost this product to the following stores.',
),
)
);
$misha_section->add_block(
array(
'blockName' => 'rudr/crosspost-to',
)
);
}
}Once we use the code above, everything should start to work:

In my example I created a section within a group organization and put the fields there, but of course it is not necessary to create a custom section, you can add your fields into any existing section.
And now I am going to take a look at both standard groups and sections.
Groups
Let’s start with the groups or, in other words, tabs:
general– General,variations– Variations,organization– Organization,inventory– Inventory,shipping– Shipping,linked-products– Linked products.
Sections
| Section name | Group |
|---|---|
basic-details | General |
product-description-section | General |
product-images-section | General |
product-variation-options-section | Variations |
product-variation-section | Variations |
tutorial-section | Organization |
product-catalog-section | Organization |
product-attributes-section | Organization |
product-inventory-section | Inventory |
product-fee-and-dimensions-section | Shipping |
product-linked-upsells-section | Linked products |
product-linked-cross-sells-section | Linked products |
A long story short if we would like to add our custom fields into an existing section, we will need to use a get_section_by_id method and slightly change this part of the code snippet:
$section = $template->get_section_by_id( 'product-catalog-section' );
$section->add_block(
array(
'blockName' => 'rudr/crosspost-to',
)
);Add Fields and Save Product Meta
And here we go, the complete code for the index.js file:
import { registerBlockType } from '@wordpress/blocks';
import { useWooBlockProps } from '@woocommerce/block-templates';
// const CheckboxControl = window.wc.productEditor.__experimentalCheckboxControl
// const useProductEntityProp = window.wc.productEditor.__experimentalUseProductEntityProp
import {
__experimentalCheckboxControl as CheckboxControl,
__experimentalUseProductEntityProp as useProductEntityProp,
} from '@woocommerce/product-editor';
import metadata from './block.json';
registerBlockType(
metadata,
{
edit: ( { attributes, context } ) => {
const [value, setValue] = useProductEntityProp( 'meta_data.rudr_key', {
postType: context.postType,
fallbackValue: false,
} );
return (
<div {...useWooBlockProps( attributes )}>
<CheckboxControl
label="Site 2"
value={ value || false }
onChange={ setValue }
/>
</div>
)
}
}
)Let’s deconstruct it:
- We can not use
CheckboxControlcomponent from@wordpress/components, it will not work, so we need to import it from@woocommerce/product-editorinstead. useProductEntityProp()is a super-nice hook, because it allows us to get and save a product custom field, in my specific case – withrudr_keymeta key.
And that’s the result field which of course works when you hit the “Update” button:

My first opinion about the new WooCommerce product editor – it is clean and nice, not very difficult to customize, a little bit slow on its initial load, but I think it is temporary.
Misha Rudrastyh
Hey guys and welcome to my website. For more than 15 years I've been doing my best to share with you some superb WordPress guides and tips for free.
Need some developer help? Contact me
It is absolutely crazy to me how much more complex this is to do compared to the existing metabox stuff.
A little bit unusual, that’s all 🙃