In today’s guide we will be creating a custom tab for single products which will display after the additional information tab. The new tab will pull and display the content from a user selected page, this will allow complex layouts created with the block editor or your favorite page builder to be displayed right inside the product tab.

Install and activate a child theme

As always the first step on our process here is to create and install a child theme. If you are using one of our themes you can easily grab its child theme from our downloads section. If not, you can read our beginner’s guide on child themes to create your own. This step is essential in order to preserve our changes throughout theme updates.

All code below will be placed in our child theme’s functions.php file. If the file is empty the code will go just below the opening <?php tag, otherwise, if it has contents, the code should be placed at the end of the file, before the closing ?> PHP tag if it exists.

Add a tab to the product data metabox

First we need to create a couple of custom fields required to store our data. The first one will store the custom tab’s title and the second one will hold the ID of the page we’ll use to pull content from. We have gone through the process of creating and displaying custom fields for WooCommerce in a previous article so some of the following might look familiar.

In this scenario we will be creating a custom tab in the product data metabox since our options don’t really fit in one of the existing tabs. To achieve this we filter the existing tabs using woocommerce_product_data_tabs and add our new one with this code:

add_filter( 'woocommerce_product_data_tabs', 'cssigniter_add_product_data_tab' );
function cssigniter_add_product_data_tab( $tabs ) { $tabs['cssigniter'] = array( 'label' => __( 'CSSIgniter custom tab', 'your-text-domain' ), 'target' => 'cssigniter_product_data_panel', 'priority' => 100, ); return $tabs; }
Add a custom tab to the product data metabox

We have set the priority to 100 in order for our new tab to appear after the default Advanced tab.

Next up we need to add content to the tab, the tab’s content will be the two custom fields mentioned earlier, one for the custom tab’s title and one for the selected page’s ID. To do that we will use the woocommerce_product_data_panels hook.

add_action( 'woocommerce_product_data_panels', 'cssigniter_add_product_data_panels' );
function cssigniter_add_product_data_panels() { echo '<div id="cssigniter_product_data_panel" class="panel woocommerce_options_panel hidden">'; woocommerce_wp_text_input( array( 'id' => 'cssigniter_tab_title', 'value' => get_post_meta( get_the_ID(), 'cssigniter_tab_title', true ), 'label' => __( 'Tab title', 'your-text-domain' ), 'description' => __( 'Set a title for the tab in the front end.', 'your-text-domain' ), ) ); woocommerce_wp_select( array( 'id' => 'cssigniter_tab_content', 'value' => get_post_meta( get_the_ID(), 'cssigniter_tab_content', true ), 'label' => __( 'Tab content', 'your-text-domain' ), 'description' => __( 'Select a page to display its content in the custom tab.', 'your-text-domain' ), 'options' => wp_list_pluck( get_pages(), 'post_title', 'ID' ), ) ); echo '</div>'; }
Adding the two custom fileds

As mentioned we create a text input for the custom tab’s title, leaving this custom field empty will stop your custom tab from appearing in the front end. We also added a drop down of all published pages for the user to select which one they want to pull content from in the tab. Now let’s add some code to save our data.

add_action( 'woocommerce_process_product_meta', 'cssigniter_save_custom_tab_data' );
function cssigniter_save_custom_tab_data( $post_id ) { $cssigniter_tab_title = $_POST['cssigniter_tab_title']; $cssigniter_tab_content = $_POST['cssigniter_tab_content']; if ( ! empty( $cssigniter_tab_title ) ) { update_post_meta( $post_id, 'cssigniter_tab_title', esc_html( $cssigniter_tab_title ) ); } if ( ! empty( $cssigniter_tab_content ) ) { update_post_meta( $post_id, 'cssigniter_tab_content', absint( $cssigniter_tab_content ) ); }
}

We are done with the back end configuration, now when editing a product we’ll be able to see our new tab and custom fields under the product data metabox.

In our example we will be pulling content from the default WordPress sample page and we’ll name our tab My custom tab.

Add the custom tab to the front end

It’s time to display our custom tab. We need to use the woocommerce_product_tabs hook to filter the existing tabs and add our own.


add_filter( 'woocommerce_product_tabs', 'cssigniter_new_wc_product_tab' );
function cssigniter_new_wc_product_tab( $tabs ) { global $product; $title = get_post_meta( $product->get_ID(), 'cssigniter_tab_title', true ); if ( empty( $title ) ) { return $tabs; } $tabs['desc_tab'] = array( 'title' => $title, 'priority' => 50, 'callback' => 'cssigniter_new_wc_product_tab_content', ); return $tabs;
}
Add the front end tab

As you can see in lines 8-10, if the tab title metabox is left empty, the custom tab will not be displayed. In line 15 we add our callback function which will pull and display the content of our selected page. The callback function looks like this:

function cssigniter_new_wc_product_tab_content() { global $product; $page = get_post_meta( $product->get_ID(), 'cssigniter_tab_content', true ); $content = apply_filters( 'the_content', get_post_field( 'post_content', $page ) ); echo $content;
}

It is designed to pull the metadata with the selected page ID from the current product and using that ID get and display the page’s content in the custom tab. This is what the final result looks like.

Wrapping up

We have successfully added a custom tab to single WooCommerce products which can pull and display the content of any user selected page. This means that complex layouts built with the block editor or any page builder can be displayed in a product’s single view. Let us know in the comments below if you have found this guide useful and leave your suggestions for future guides.

The post How to add a custom tab on single WooCommerce products appeared first on CSSIgniter.