PHPwoocommerceintermediate

WooCommerce Custom Product Tabs

Add custom tabs to WooCommerce product pages with dynamic content

Faisal Yaqoob
#woocommerce#product-tabs#ui#product-display
Share this snippet:

Code

php
1// Add a new custom tab
2add_filter('woocommerce_product_tabs', 'add_custom_product_tab');
3function add_custom_product_tab($tabs) {
4 // Specifications tab
5 $tabs['specifications'] = array(
6 'title' => __('Specifications', 'woocommerce'),
7 'priority' => 50,
8 'callback' => 'specifications_tab_content'
9 );
10
11 // Sizing guide tab
12 $tabs['sizing_guide'] = array(
13 'title' => __('Sizing Guide', 'woocommerce'),
14 'priority' => 60,
15 'callback' => 'sizing_guide_tab_content'
16 );
17
18 // Shipping info tab
19 $tabs['shipping_info'] = array(
20 'title' => __('Shipping Info', 'woocommerce'),
21 'priority' => 70,
22 'callback' => 'shipping_info_tab_content'
23 );
24
25 return $tabs;
26}

WooCommerce Custom Product Tabs

Add custom tabs to WooCommerce product pages to display additional information like specifications, sizing guides, shipping info, and more.

// Add a new custom tab
add_filter('woocommerce_product_tabs', 'add_custom_product_tab');
function add_custom_product_tab($tabs) {
    // Specifications tab
    $tabs['specifications'] = array(
        'title'    => __('Specifications', 'woocommerce'),
        'priority' => 50,
        'callback' => 'specifications_tab_content'
    );

    // Sizing guide tab
    $tabs['sizing_guide'] = array(
        'title'    => __('Sizing Guide', 'woocommerce'),
        'priority' => 60,
        'callback' => 'sizing_guide_tab_content'
    );

    // Shipping info tab
    $tabs['shipping_info'] = array(
        'title'    => __('Shipping Info', 'woocommerce'),
        'priority' => 70,
        'callback' => 'shipping_info_tab_content'
    );

    return $tabs;
}

Tab Content Callbacks

// Specifications tab content
function specifications_tab_content() {
    global $product;

    $specifications = get_post_meta($product->get_id(), '_product_specifications', true);

    echo '<h2>' . __('Specifications', 'woocommerce') . '</h2>';

    if ($specifications) {
        echo '<div class="specifications-content">' . wp_kses_post($specifications) . '</div>';
    } else {
        echo '<p>' . __('No specifications available.', 'woocommerce') . '</p>';
    }
}

// Sizing guide tab content
function sizing_guide_tab_content() {
    global $product;

    // Check for product-specific sizing guide
    $sizing_guide = get_post_meta($product->get_id(), '_sizing_guide', true);

    // Fall back to category-specific guide
    if (empty($sizing_guide)) {
        $categories = wp_get_post_terms($product->get_id(), 'product_cat', array('fields' => 'ids'));
        if (!empty($categories)) {
            $sizing_guide = get_term_meta($categories[0], 'category_sizing_guide', true);
        }
    }

    // Fall back to global sizing guide
    if (empty($sizing_guide)) {
        $sizing_guide = get_option('global_sizing_guide');
    }

    echo '<h2>' . __('Sizing Guide', 'woocommerce') . '</h2>';

    if ($sizing_guide) {
        echo '<div class="sizing-guide-content">' . wp_kses_post($sizing_guide) . '</div>';
    } else {
        echo '<p>' . __('Sizing information coming soon.', 'woocommerce') . '</p>';
    }
}

// Shipping info tab content
function shipping_info_tab_content() {
    echo '<h2>' . __('Shipping Information', 'woocommerce') . '</h2>';
    echo '<div class="shipping-info-content">';
    echo '<p>' . __('We offer the following shipping options:', 'woocommerce') . '</p>';
    echo '<ul>';
    echo '<li><strong>Standard Shipping:</strong> 5-7 business days</li>';
    echo '<li><strong>Express Shipping:</strong> 2-3 business days</li>';
    echo '<li><strong>Overnight Shipping:</strong> 1 business day</li>';
    echo '</ul>';
    echo '<p>' . __('All orders are processed within 24 hours.', 'woocommerce') . '</p>';
    echo '</div>';
}

Add Custom Fields for Tab Content

// Add custom fields to product admin for tab content
add_action('woocommerce_product_options_general_product_data', 'add_product_tab_fields');
function add_product_tab_fields() {
    global $post;

    echo '<div class="options_group">';

    // Specifications field
    woocommerce_wp_textarea_input(array(
        'id'          => '_product_specifications',
        'label'       => __('Specifications', 'woocommerce'),
        'placeholder' => __('Enter product specifications', 'woocommerce'),
        'desc_tip'    => true,
        'description' => __('Content for the specifications tab. HTML allowed.', 'woocommerce'),
    ));

    // Sizing guide field
    woocommerce_wp_textarea_input(array(
        'id'          => '_sizing_guide',
        'label'       => __('Sizing Guide', 'woocommerce'),
        'placeholder' => __('Enter sizing guide', 'woocommerce'),
        'desc_tip'    => true,
        'description' => __('Product-specific sizing guide. Leave empty to use category or global guide.', 'woocommerce'),
    ));

    // Custom tab title field
    woocommerce_wp_text_input(array(
        'id'          => '_custom_tab_title',
        'label'       => __('Custom Tab Title', 'woocommerce'),
        'placeholder' => __('e.g., Care Instructions', 'woocommerce'),
        'desc_tip'    => true,
        'description' => __('Optional custom tab title.', 'woocommerce'),
    ));

    // Custom tab content field
    woocommerce_wp_textarea_input(array(
        'id'          => '_custom_tab_content',
        'label'       => __('Custom Tab Content', 'woocommerce'),
        'placeholder' => __('Enter custom tab content', 'woocommerce'),
        'desc_tip'    => true,
        'description' => __('Content for custom tab. HTML allowed.', 'woocommerce'),
    ));

    echo '</div>';
}

// Save custom tab fields
add_action('woocommerce_process_product_meta', 'save_product_tab_fields');
function save_product_tab_fields($post_id) {
    $specifications = isset($_POST['_product_specifications']) ?
        wp_kses_post($_POST['_product_specifications']) : '';
    update_post_meta($post_id, '_product_specifications', $specifications);

    $sizing_guide = isset($_POST['_sizing_guide']) ?
        wp_kses_post($_POST['_sizing_guide']) : '';
    update_post_meta($post_id, '_sizing_guide', $sizing_guide);

    $custom_tab_title = isset($_POST['_custom_tab_title']) ?
        sanitize_text_field($_POST['_custom_tab_title']) : '';
    update_post_meta($post_id, '_custom_tab_title', $custom_tab_title);

    $custom_tab_content = isset($_POST['_custom_tab_content']) ?
        wp_kses_post($_POST['_custom_tab_content']) : '';
    update_post_meta($post_id, '_custom_tab_content', $custom_tab_content);
}

Dynamic Custom Tab Based on Product Meta

// Add dynamic custom tab if content exists
add_filter('woocommerce_product_tabs', 'add_dynamic_custom_tab', 98);
function add_dynamic_custom_tab($tabs) {
    global $product;

    $custom_tab_title = get_post_meta($product->get_id(), '_custom_tab_title', true);
    $custom_tab_content = get_post_meta($product->get_id(), '_custom_tab_content', true);

    // Only add tab if both title and content exist
    if ($custom_tab_title && $custom_tab_content) {
        $tabs['custom_dynamic'] = array(
            'title'    => $custom_tab_title,
            'priority' => 80,
            'callback' => 'dynamic_custom_tab_content'
        );
    }

    return $tabs;
}

function dynamic_custom_tab_content() {
    global $product;

    $custom_tab_title = get_post_meta($product->get_id(), '_custom_tab_title', true);
    $custom_tab_content = get_post_meta($product->get_id(), '_custom_tab_content', true);

    echo '<h2>' . esc_html($custom_tab_title) . '</h2>';
    echo '<div class="custom-tab-content">' . wp_kses_post($custom_tab_content) . '</div>';
}

Modify or Remove Existing Tabs

// Rename, reorder, or remove default tabs
add_filter('woocommerce_product_tabs', 'customize_default_tabs', 98);
function customize_default_tabs($tabs) {
    // Rename the description tab
    $tabs['description']['title'] = __('Product Details', 'woocommerce');

    // Rename the reviews tab
    if (isset($tabs['reviews'])) {
        $tabs['reviews']['title'] = __('Customer Reviews', 'woocommerce');
    }

    // Rename additional information tab
    if (isset($tabs['additional_information'])) {
        $tabs['additional_information']['title'] = __('Attributes', 'woocommerce');
    }

    // Change priority (lower number = higher priority)
    $tabs['description']['priority'] = 5;
    if (isset($tabs['reviews'])) {
        $tabs['reviews']['priority'] = 90;
    }

    // Remove additional information tab
    // unset($tabs['additional_information']);

    return $tabs;
}

Conditional Tabs

// Add tabs conditionally based on product attributes
add_filter('woocommerce_product_tabs', 'add_conditional_tabs', 98);
function add_conditional_tabs($tabs) {
    global $product;

    // Add warranty tab only for specific categories
    $categories = wp_get_post_terms($product->get_id(), 'product_cat', array('fields' => 'slugs'));

    if (in_array('electronics', $categories) || in_array('appliances', $categories)) {
        $tabs['warranty'] = array(
            'title'    => __('Warranty', 'woocommerce'),
            'priority' => 65,
            'callback' => 'warranty_tab_content'
        );
    }

    // Add video tab only if product has video
    $video_url = get_post_meta($product->get_id(), '_product_video_url', true);
    if ($video_url) {
        $tabs['video'] = array(
            'title'    => __('Video', 'woocommerce'),
            'priority' => 55,
            'callback' => 'video_tab_content'
        );
    }

    return $tabs;
}

function warranty_tab_content() {
    echo '<h2>' . __('Warranty Information', 'woocommerce') . '</h2>';
    echo '<div class="warranty-content">';
    echo '<p>' . __('This product comes with a 1-year manufacturer warranty.', 'woocommerce') . '</p>';
    echo '<p>' . __('For warranty claims, please contact our customer service.', 'woocommerce') . '</p>';
    echo '</div>';
}

function video_tab_content() {
    global $product;

    $video_url = get_post_meta($product->get_id(), '_product_video_url', true);

    echo '<h2>' . __('Product Video', 'woocommerce') . '</h2>';
    echo '<div class="video-content">';

    if ($video_url) {
        // If it's a YouTube or Vimeo URL, embed it
        if (preg_match('/youtube\.com|youtu\.be|vimeo\.com/', $video_url)) {
            echo wp_oembed_get($video_url);
        } else {
            // Otherwise show video tag
            echo '<video controls width="100%">';
            echo '<source src="' . esc_url($video_url) . '" type="video/mp4">';
            echo __('Your browser does not support the video tag.', 'woocommerce');
            echo '</video>';
        }
    }

    echo '</div>';
}

Tab with Accordion Content

// Add FAQ tab with accordion
add_filter('woocommerce_product_tabs', 'add_faq_tab');
function add_faq_tab($tabs) {
    $tabs['faq'] = array(
        'title'    => __('FAQ', 'woocommerce'),
        'priority' => 75,
        'callback' => 'faq_tab_content'
    );

    return $tabs;
}

function faq_tab_content() {
    global $product;

    echo '<h2>' . __('Frequently Asked Questions', 'woocommerce') . '</h2>';
    echo '<div class="faq-accordion">';

    $faqs = array(
        array(
            'question' => __('What is the return policy?', 'woocommerce'),
            'answer'   => __('You can return products within 30 days of purchase.', 'woocommerce')
        ),
        array(
            'question' => __('Is this product in stock?', 'woocommerce'),
            'answer'   => $product->is_in_stock() ? __('Yes, in stock.', 'woocommerce') : __('Currently out of stock.', 'woocommerce')
        ),
        array(
            'question' => __('Do you offer international shipping?', 'woocommerce'),
            'answer'   => __('Yes, we ship to most countries worldwide.', 'woocommerce')
        ),
    );

    foreach ($faqs as $index => $faq) {
        echo '<div class="faq-item">';
        echo '<button class="faq-question" data-index="' . $index . '">';
        echo esc_html($faq['question']);
        echo '<span class="toggle">+</span>';
        echo '</button>';
        echo '<div class="faq-answer" id="faq-' . $index . '" style="display: none;">';
        echo '<p>' . esc_html($faq['answer']) . '</p>';
        echo '</div>';
        echo '</div>';
    }

    echo '</div>';
}

JavaScript for FAQ Accordion

// Add to your theme's JavaScript file
jQuery(document).ready(function($) {
    $('.faq-question').on('click', function(e) {
        e.preventDefault();

        var index = $(this).data('index');
        var answer = $('#faq-' + index);
        var toggle = $(this).find('.toggle');

        answer.slideToggle(300);

        if (toggle.text() === '+') {
            toggle.text('-');
        } else {
            toggle.text('+');
        }
    });
});

Styling

/* Product tabs styling */
.woocommerce-tabs ul.tabs {
    margin: 0;
    padding: 0;
    list-style: none;
    border-bottom: 2px solid #e0e0e0;
}

.woocommerce-tabs ul.tabs li {
    display: inline-block;
    margin: 0 5px -2px 0;
}

.woocommerce-tabs ul.tabs li a {
    padding: 12px 20px;
    display: block;
    text-decoration: none;
    border: 1px solid transparent;
    border-bottom: 0;
    background: #f5f5f5;
    color: #666;
    transition: all 0.3s ease;
}

.woocommerce-tabs ul.tabs li a:hover {
    background: #fff;
    color: #333;
}

.woocommerce-tabs ul.tabs li.active a {
    background: #fff;
    border-color: #e0e0e0;
    color: #0073aa;
    font-weight: 600;
}

.woocommerce-tabs .panel {
    padding: 30px 20px;
    background: #fff;
    border: 1px solid #e0e0e0;
    border-top: 0;
}

/* FAQ accordion styling */
.faq-accordion {
    margin: 20px 0;
}

.faq-item {
    margin-bottom: 10px;
    border: 1px solid #e0e0e0;
    border-radius: 4px;
}

.faq-question {
    width: 100%;
    padding: 15px 20px;
    text-align: left;
    background: #f9f9f9;
    border: none;
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-weight: 600;
    transition: background 0.3s ease;
}

.faq-question:hover {
    background: #f0f0f0;
}

.faq-question .toggle {
    font-size: 20px;
    font-weight: bold;
}

.faq-answer {
    padding: 15px 20px;
    background: #fff;
}

Features

  • Multiple Tab Types: Specifications, sizing guides, shipping info, FAQs, videos
  • Dynamic Content: Tabs from custom fields or global settings
  • Conditional Display: Show tabs based on product attributes or categories
  • Accordion Support: Interactive FAQ accordions within tabs
  • Flexible Priority: Control tab order easily
  • Custom Fields: Admin interface for tab content
  • HTML Support: Rich content with HTML formatting
  • Video Embedding: Support for YouTube, Vimeo, and direct video files
  • Fallback System: Product-specific, category-specific, or global content
  • Fully Styled: Professional CSS for tabs and accordions

Dependencies

  • WooCommerce

Related Snippets