Product Types

Welcome to a complete WooCommerce product types tutorial, here we are going to dive into the details on how to get product type, create a custom product type and hide the default ones.

Get Product Type of a WooCommerce Product

In case you forget there are four default WooCommerce product type and a custom one can be created as well. So, how you can check a product type easily in code?

There are actually two of doing it:

  1. get_type() method of WC_Product class.
  2. is_type() method of the same class.

So in order to get a product type by ID you can use either this code:

$product_id = 541;
$product = wc_get_product( $product_id );
// check if variable product
if( 'variable' === $product->get_type() ) {
	// doing some stuff for variable products	
}

Or this one:

$product_id = 541;
$product = wc_get_product( $product_id );
// check if variable product
if( $product->is_type( 'variable' ) ) {
	// doing some stuff for variable products	
}

So both of these methods are going to work. You can also check if product is Simple simple, Grouped grouped or Affiliate/External external.

Check if product is Downloadable or Virtual

“Downloadable” and “Virtual” are not exactly the types of products, so you can not check them using get_type() or is_type() methods. But you can use is_downloadable() to check if product is a downloadable one and is_virtual() method for virtual product check.

$product_id = 541;
$product = wc_get_product( $product_id );

if( $product->is_downloadable() ) {
	// seems like it is a downloadable product!	
}
if( $product->is_virtual() ) {
	// it is a virtual one	
}

Remove Default Product Types

Before doing it you basically need to understand that product_type is a custom taxonomy with hidden UI. And each product type like “Simple”, “Grouped”, “Variable” etc are its taxonomy terms.

Well, you might think – if product types are taxonomy terms, I just have to remove a certain term from the database? You could try, but know what? Product types are hardcoded in WooCommerce files and we have to use product_type_selector to hook them.

Let’s remove “Grouped” and “External” product types:

add_filter( 'product_type_selector', 'rudr_remove_grouped_and_external' );
function rudr_remove_grouped_and_external( $product_types ){
	
	unset( $product_types[ 'grouped' ] );
	unset( $product_types[ 'external' ] );
	//unset( $product_types[ 'variable' ] );
	return $product_types;
}

What exactly will happen?

Of course products on your website won’t magically become Simple products or whatever, but you are no more able to edit removed product types, you have to re-save each product as another type.

You won’t be able to select the removed product types from the dropdown in the Product data metabox:

Removing product types in WooCommerce

They’ll also disappear from the “Filter by product type” on the All products page:

Filter products by product type in WooCommerce

By the way, if you’re eager to know how to remove “→ Downloadable” and “→ Virtual” options from this filter, check this tutorial.

How to Create Custom Product Type for WooCommerce

Ok, the question is – why you would ever need to create a custom product type? To improve user experience of course. I don’t know if you are familiar with WooCommerce Subscriptions plugin, but a subscription product is a product of a custom type. It is very convenient because:

  1. You could easily configure what product settings (and tabs) are going to be available in Product Data metabox.
  2. Additional filters on All Products page.
  3. You could type parameter when querying the products with wc_get_products() and WC_Product_Query.
  4. It is also possible to condition product types with is_type() or get_type() method, which has been already discussed above.
  5. Oh yes, and you can override default WC_Product methods, we will talk about it as well.

Register Custom Product Type as an extension to WC_Product class

You maybe know of maybe not, but every default WooCommerce product type has its own PHP class that extends WC_Product default product class, for example WC_Product_Simple, WC_Product_Variable, WC_Product_External, WC_Product_Grouped, so it is kind of obvious, that in order to create a custom product type we need to create another PHP class.

add_action( 'init', function() {

	class WC_Product_Gift extends WC_Product {
		public function get_type() {
			return 'gift';
		}
	}
	
} );

add_filter( 'woocommerce_product_class', function( $php_classname, $product_type ) {
	
	if ( 'gift' === $product_type ) {
		$php_classname = 'WC_Product_Gift';
	}
	return $php_classname;
	
}, 10, 2 );

As you can see from the above code, I decided that my custom product type would be gift and its classname would be WC_Product_Gift.

I have already refactored get_type() method of WC_Product class, but it is possible to refactor some other methods like get_price(). But before we do any other custom stuff, let’s add our custom type into the list.

We can do it the same way we removed the default ones, with product_type_selector filter hook.

add_filter( 'product_type_selector', 'rudr_add_gift_type' );
function rudr_add_gift_type( $product_types ){
	
	$product_types[ 'gift' ] = 'Gift';
	return $product_types;
	
}

Wait, do you know where to insert all the code? In case you don’t, this tut is for you.

That’s the result, “Gift” custom product type is available to use:

WooCommerce custom product type

Show “General” tab and hide “Attributes” for a custom product type

If look at the screenshot above one more time, you will see that product settings are different when you switch between product types. Even product data tabs are changing. Why this is happening is already described in another tutorial, but now we are going to look at some practical examples.

And my practical example would be to put back “General” tab with prices and to hide “Attributes” for our custom product type.

The long story short this whole chapter is about using show_if_{type} and hide_if_{type} CSS classes, or to say exactly show_if_gift and hide_if_gift classes.

So let’s begin with the easy one – hiding “Attributes” tab. In my product data metabox tutorial I already mentioned woocommerce_product_data_tabs filter hook. So, here we are:

add_filter( 'woocommerce_product_data_tabs', function( $tabs ){
	// add hide_if_gift class for "Attributes" tab
	$tabs[ 'attribute' ][ 'class' ][] = 'hide_if_gift';
	return $tabs;
} );

You can find all default tab names here as well.

But unfortunately the same method doesn’t work when we are talking about “General” tab. This tab only shows up if it contains any HTML fields available for a certain product type. We have two options here:

  • Add another section with fields with woocommerce_product_options_general_product_data filter hook with show_if_gift CSS class. How to do it.
  • Add this show_if_gift CSS class to pricing fields using JavaScript, here is the code:
jQuery( document ).ready( function() {
	jQuery( '#general_product_data .pricing' ).addClass( 'show_if_gift' );
});

Overriding methods

I added only get_type() method to the class, but you can redefine other methods too, for example, you can calculate the price of your custom product type another way:

public function get_price( $context = 'view' ) {
	// for website contributers we have a special price
	if ( current_user_can( 'contributor' ) ) {
		return $this->get_meta( 'contributor_price', true );
	}
	return $this->get_prop( 'price', $context );
}
Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 10 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

Follow me on X