Settings Pages in WooCommerce

Just a couple days ago I was doing some updates for one of my plugins and I decided to move plugin settings from a regular WordPress options pages to WooCommerce > Settings.

Because why overload WordPress admin menu with links when the plugin is intented to sync product inventory between stores and it is crystal clear that its settings should be in WooCommerce > Settings > Products > Inventory tab. Don’t you think so?

Custom Settings Tabs and Sections

Creating settings tabs

In order to create a new custom WooCommerce settings tab, we have to use the filter hook woocommerce_settings_tabs_array. The thing to keep in mind that WooCommerce default tabs are also using it, so we need to set a hook priority to at least 21, so our custom tab will be added in an appropriate order, otherwise the tab will be always first.

add_filter( 'woocommerce_settings_tabs_array', 'rudr_new_setting_tab', 21 );

function rudr_new_setting_tab( $tabs ) {

	// position (after Products)
	$pos = 2;
	// new tab slug and title
	$new_tab = array( 'misha' => 'Misha' );

	// add into an appropriate position of an existing array
	$tabs = array_slice( $tabs, 0, $pos, true ) + $new_tab + array_slice( $tabs, $pos, NULL, true );

	return $tabs;

}

// add_action( 'woocommerce_settings_{tab}' ...
add_action( 'woocommerce_settings_misha', 'rudr_tab_content' );

function rudr_tab_content() {
	echo 'what is up?';
}

If you insert the above code into your functions.php or something, you will get this:

create custom WooCommerce settings tab

Remove settings tabs

You can also easily remove any of the existing settings tabs using woocommerce_settings_tabs_array with a priority 21… or 9999.

add_filter( 'woocommerce_settings_tabs_array', 'rudr_remove_setting_tab', 9999 );

function rudr_remove_setting_tab( $tabs ) {

	unset( $tabs[ 'general' ] ); // General
	unset( $tabs[ 'products' ] ); // Products
	unset( $tabs[ 'shipping' ] ); // Shipping
	unset( $tabs[ 'checkout' ] ); // Payments
	unset( $tabs[ 'account' ] ); // Accounts & Privacy
	unset( $tabs[ 'email' ] ); // Emails
	unset( $tabs[ 'integration' ] ); // Integration
	unset( $tabs[ 'advanced' ] ); // Advanced

	return $tabs;
	
}

Well, it is going to be a funny one:

how to remove WooCommerce default settings tabs

In case of removing pages – what if you don’t want them to be opened by direct links?

By default if you type something in URL, like ?page=wc-settings&tab=notexistingtab then WooCommerce redirects you to General tab. Let’s do that.

add_action( 'admin_init', function() {
	// do nothing for not-settings pages
	if( empty( $_GET[ 'page' ] ) || 'wc-settings' !== $_GET[ 'page' ] ) {
		return;
	}
	// redirect Products settings page to General
	if( isset( $_GET[ 'tab' ] ) && 'products' === $_GET[ 'tab' ] ) {
		wp_safe_redirect( admin_url( 'admin.php?page=wc-settings' ) );
		exit;
	}
});

Creating custom sections in one of the default tabs

In order to add a custom section in one of the default tabs you can use one of the hooks below depending on what tab you would like to add a section to.

  • woocommerce_get_sections_general – General
  • woocommerce_get_sections_products – Products
  • woocommerce_get_sections_shipping – Shipping
  • woocommerce_get_sections_checkout – Payment
  • woocommerce_get_sections_account – Account & Privacy
  • woocommerce_get_sections_email – Emails
  • woocommerce_get_sections_integration – Integration
  • woocommerce_get_sections_advanced – Advanced

Let’s do that.

// add_filter( 'woocommerce_get_sections_{tab}', ...
add_filter( 'woocommerce_get_sections_shipping', 'rudr_add_setting_section' );

function rudr_add_setting_section( $sections ) {

	$sections[ 'misha' ] = 'Settings by Misha';
	return $sections;

}

// add_action( 'woocommerce_settings_{tab}', ...
add_action( 'woocommerce_settings_shipping', 'rudr_section_content' );

function rudr_section_content() { 
	if( empty( $_GET[ 'section' ] ) || 'misha' !== $_GET[ 'section' ] ) {
		return;
	}
	echo 'what is up?';
}

Please pay attention to a condition on lines 15-17, we need it because WooCommerce doesn’t have action hooks for sections, only for tabs. So, if you skip this condition, then your section content will be displayed on every section of that specific tab.

WooCommerce how to create a custom section
If you don’t want your custom section to be displayed the last, you can use the array_slice() PHP function we have already used in the example above.

Creating custom sections in custom tabs

That’s going to be a little bit more tricky.

When you’re working with sections in custom tabs, unfortunately you can not use so handy woocommerce_get_sections_{tab} hook. Good news – creating custom sections in custom tabs are still possible with woocommerce_sections_{tab}, bad news – you need to do HTML.

add_action( 'woocommerce_sections_misha', 'rudr_new_section_custom_tab' );
function rudr_new_section_custom_tab() {

	global $current_section;

	$sections = array(
		''              => 'Overview',
		'my-section-1'  => 'My section 1',
		'my-section-2'  => 'My section 2',
	);

	echo '<ul class="subsubsub">';

	foreach( $sections as $id => $label ) {
		$url = add_query_arg(
			array(
				'page' => 'wc-settings',
				'tab' => 'misha',
				'section' => $id,
			),
			admin_url( 'admin.php' )
		);

		$current = $current_section == $id ? 'class="current"' : '';

		$separator = end( array_keys( $sections ) ) === $id ? '' : '|';

		echo "<li><a href=\"$url\" $current>$label</a> $separator </li>";
	}

	echo '</ul><br class="clear" />';
}

And… it is working!

How to add custom sections into WooCommerce settings custom tabs

Add Settings Fields (or Any Content)

There are actually two ways (hooks) to add anything into WooCommerce settings tabs.

  1. woocommerce_get_settings_{tab} – this way is amazing if you would like to add just some default fields supported by WooCommerce.
  2. woocommerce_settings_{tab} – this way is more interesting cause it allows you do add anything super-custom into a WooCommerce settings tab, a great example – a custom table that allows to add stores to sync inventory with. But if you’re about to add settings fields that way, do not forget to save them using woocommerce_settings_save_{TAB NAME} hook.

More about each of the methods below. As an example in both cases we are going to add something into a custom section we created here.

Method 1. woocommerce_get_settings_{tab}

This method is dead simple, we just have an array of settings fields and we are about to add a couple of our fields into it. That’s all!

Oh, the only thing, this method doesn’t work for custom tabs (and custom sections inside custom tabs of course) – in that case please use method 2.

I am going to add a text field and a checkbox.

add_filter( 'woocommerce_get_settings_shipping', 'rudr_add_fields', 10, 2 );

function rudr_add_fields( $settings, $current_section ) {
	// we need the fields only on our custom section
	if( 'misha' !== $current_section ) {
		return $settings;
	}

	$settings = array(
		array(
			'name' => 'Custom Shipping Settings by Misha',
			'type' => 'title',
			'desc' => 'Blah blah blah description',
		),
		array(
			'name'     => 'Amazing shipping promo code',
			'desc_tip' => 'You can ask it if you text me',
			'id'       => 'misha_shipping_code',
			'type'     => 'text',
		),
		array(
			'name'     => 'Enabled',
			'desc'     => 'Yes',
			'desc_tip' => 'Some description under the field',
			'id'       => 'misha_shipping_on',
			'type'     => 'checkbox',
		),
		array(
			'type' => 'sectionend',
		),
	);

	return $settings;

}

And that’s all! Our settings fields are pretty much working.

how to add custom option fields into WooCommerce settings pages

Before we jump into the next method, let’s take a more detailed look at $settings array. So, the $settings array is an array of fields, and each field can have the following pair of keys and values.

array(
	// ID of the field, you can use it in get_option()
	'id' => 'misha_field',
	// field <label> or title
	'title' => 'My test field',
	// it is a description which goes under the field
	// for the "checkbox" type it will be displayed on the right
	'desc' => 'My test field description.',
	// it is a description which displays when you hover on (?) mark
	// but for the "checkbox" type it will be displayed under the field
	'desc_tip' => '',
	// type of the field
	// text, password, textarea, checkbox, select, multiselect, title, sectionend
	'type' => 'text',
	'default' => '',
	'class' => 'my-custom-class',
	'css' => '', // will be displayed inside style="" attribute
	// array of options for "select" and "multiselect" types of fields
	'options' => array(
		'key' => 'value'
	)
)

Method 2. woocommerce_settings_{tab}

These method I do not recommend to use for regular WooCommerce fields (unless it is a custom settings tab), use it just in case you need something super-custom.

But just as an example to show you how it works, I will create a simple text field with it 😁

<?php
add_filter( 'woocommerce_settings_shipping', 'rudr_one_field_display' );

function rudr_one_field_display() {
	// exit if it is not our section
	if( empty( $_GET[ 'section' ] ) || 'misha' !== $_GET[ 'section' ] ) {
		return;
	}
	// get option value
	$shipping_code = get_option( 'misha_shipping_code' );
	
	?><input type="text" name="misha_code" placeholder="Amazing shipping promo code" value="<?php echo esc_attr( $shipping_code ) ?>" /><?php
	
}

add_action( 'woocommerce_settings_save_shipping', 'rudr_one_field_save' );

function rudr_one_field_save() {

	$shipping_code = ! empty( $_REQUEST[ 'misha_code' ] ) ? sanitize_text_field( $_REQUEST[ 'misha_code' ] ) : '';
	update_option( 'misha_shipping_code', $shipping_code );

}

As you can see it is also kind of working, but looks much uglier on the screenshot below. In order to make it look good you need to add some HTML like title, <table class="form-table"> and so on or… just continue to read this chapter 🙂

an alternative way of adding field into a WooCommerce settings tab

Do you remember that once I said that only woocommerce_settings_{tab} hook allows you to work with fields in custom tabs. So what to do if you just need some regular fields? To code all of them in HTML?

Luckily we can use WC_Admin_Settings::output_fields() and WC_Admin_Settings::save_fields() to simplify the whole process. In order to make it more interesting let’s add settings fields for a custom section in a custom tab we created before.

class Rudr_Woo_Custom_Settings{

	public function __construct() {
		// it is a slug of our custom slug
		$tab_id = 'misha';

		add_action( 'woocommerce_settings_' . $tab_id, array( $this, 'output' ) );
		add_action( 'woocommerce_settings_save_' . $tab_id, array( $this, 'save' ) );
	}

	private function settings() {

		global $current_section;

		if( 'my-section-1' !== $current_section ) {
			return array();
		}

		$settings = array(
			array(
				'name' => 'Custom Shipping Settings by Misha',
				'type' => 'title',
				'desc' => 'Blah blah blah description',
			),
			array(
				'name'     => 'Amazing shipping promo code',
				'desc_tip' => 'You can ask it if you text me',
				'id'       => 'misha_shipping_code',
				'type'     => 'text',
			),
			array(
				'type' => 'sectionend',
			),
		);
		return $settings;

	}

	public function output() {
		WC_Admin_Settings::output_fields( $this->settings() );
	}

	public function save() {
		WC_Admin_Settings::save_fields( $this->settings() );
	}

}
new Rudr_Woo_Custom_Settings;

This simplifies the whole process a lot! And as a final result we have almost what we had when we used method 1. But for a custom tab!

Add fields to WooCommerce custom sections and custom tabs

I hope you enjoyed this tutorial 🙏

What would you think – should I add the support of WooCommerce settings pages into my Simple Fields plugin?

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 Twitter