More Tabs

Adding Custom Tabs to WooCommerce Products with ACF

Easily personalize your product pages with dynamic tabs using ACF. Improve UX and SEO with this quick setup guide.

By ♟ Maggew.comUpdated   78 Views
dall·e 2024 12 10 11.25.35 a stylish and futuristic tech themed blog header image for a wordpress tutorial. the scene features a sleek interface showcasing tabs and panels with

Are you looking to enhance your WooCommerce product pages with custom information tabs? With WordPress, WooCommerce, and Advanced Custom Fields (ACF), you can do just that. Here’s how to add dynamic custom tabs to your products.

How do I set this up?

  1. Setup ACF and import the JSON
  2. Add the Code to your Theme using Snippets
  3. Add Data to WooCommerce Products
  4. Check your Product Page

What Does This Tutorial Do?

ACF Setup

  • Create Field Group Add extra tabs to your product pages
  • Repeater Field with Field Name custom_tab
  • Sub field with Field Name custom_tab_title
  • Sub field with Field Name custom_tab_content
  • Location rule Post Type > Product > Product
[
    {
        "key": "group_67579797aa357",
        "title": "Add extra tabs to your product pages",
        "fields": [
            {
                "key": "field_67579797ce07a",
                "label": "Easy tab manager",
                "name": "custom_tab",
                "aria-label": "",
                "type": "repeater",
                "instructions": "Boost your product pages by adding custom tabs containing extra information. Grow your sales by giving customers all the details they need - everyone wins 💪",
                "required": 0,
                "conditional_logic": 0,
                "wrapper": {
                    "width": "",
                    "class": "",
                    "id": ""
                },
                "layout": "row",
                "pagination": 0,
                "min": 0,
                "max": 0,
                "collapsed": "",
                "button_label": "Add Row",
                "rows_per_page": 20,
                "sub_fields": [
                    {
                        "key": "field_675797b2ce07b",
                        "label": "Tab Title",
                        "name": "custom_tab_title",
                        "aria-label": "",
                        "type": "text",
                        "instructions": "",
                        "required": 0,
                        "conditional_logic": 0,
                        "wrapper": {
                            "width": "",
                            "class": "",
                            "id": ""
                        },
                        "default_value": "",
                        "maxlength": "",
                        "allow_in_bindings": 0,
                        "placeholder": "",
                        "prepend": "",
                        "append": "",
                        "parent_repeater": "field_67579797ce07a"
                    },
                    {
                        "key": "field_675797b3ce07c",
                        "label": "Tab Content",
                        "name": "custom_tab_content",
                        "aria-label": "",
                        "type": "wysiwyg",
                        "instructions": "",
                        "required": 0,
                        "conditional_logic": 0,
                        "wrapper": {
                            "width": "",
                            "class": "",
                            "id": ""
                        },
                        "default_value": "",
                        "allow_in_bindings": 0,
                        "tabs": "all",
                        "toolbar": "full",
                        "media_upload": 1,
                        "delay": 0,
                        "parent_repeater": "field_67579797ce07a"
                    }
                ]
            }
        ],
        "location": [
            [
                {
                    "param": "post_type",
                    "operator": "==",
                    "value": "product"
                }
            ]
        ],
        "menu_order": 0,
        "position": "normal",
        "style": "default",
        "label_placement": "top",
        "instruction_placement": "label",
        "hide_on_screen": "",
        "active": true,
        "description": "",
        "show_in_rest": 0
    }
]

Code Snippet — Link ACF to show on site front-end

  • Retrieves data from ACF repeater field
  • Hooks data into product template
  • Matches same pretty URL naming convention as stock
add_filter( 'woocommerce_product_tabs', 'multiple_custom_acf_tabs', 98 );
function multiple_custom_acf_tabs( $tabs ) {
    global $post;

	// Fetch the repeater field
    $custom_tabs = get_field('custom_tab', $post->ID); // Use the correct repeater field name

    if( $custom_tabs ) {
        $tab_priority = 50;
        foreach( $custom_tabs as $index => $tab ) {
            if( isset($tab['custom_tab_title']) && isset($tab['custom_tab_content']) ) {
                // Use a sanitized version of the title for the key, ensuring uniqueness
                $sanitized_title = sanitize_title( $tab['custom_tab_title'] );
                $tabs[$sanitized_title] = array(
                    'title'    => esc_html( $tab['custom_tab_title'] ),
                    'priority' => $tab_priority + $index,
                    'callback' => function() use ( $tab ) {
                        echo wp_kses_post( apply_filters( 'the_content', $tab['custom_tab_content'] ) );
                    }
                );
            }
        }
    }
    return $tabs;
}

Something to think about…

You've got a choice: load up with a feature-heavy, premium plugin you'll only half-use, or keep it simple with something basic.

I once got inspired by the WooCommerce Product Tabs plugin from Barn2. But then I saw the size – over 6MB compressed! That's a lot of extra code for my site.

It's like when I was looking for a PayPal gateway for WooCommerce. The official one from Woo was a hefty 9MB, but a third-party option was just 500KB. What is going on with the world where you need that much extra heft? Pff… I know people have excuses but I'm not listening.

One more bonus snippet!

This will rename the tab title, and also unload and remove it from the hook.

// Rename the tab title Description
add_filter( 'woocommerce_product_tabs', 'custom_rename_description_tab', 98 );
function custom_rename_description_tab( $tabs ) {
    global $post;
    $page_title = get_the_title($post->ID);
    if ( isset( $tabs['description'] ) ) {
        $tabs['description']['title'] = sprintf( __( 'Overview: %s', 'woocommerce' ), $page_title );
    }
    return $tabs;
}

// Remove the H2 heading inside the description tab
add_filter( 'woocommerce_product_description_heading', '__return_empty_string' );

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

// Rename the tab title and heading "Additional Information" to "Info"
add_filter( 'woocommerce_product_tabs', 'rename_additional_info_tab', 98 );
function rename_additional_info_tab( $tabs ) {
    if ( isset( $tabs['additional_information'] ) ) {
        $tabs['additional_information']['title'] = __( 'Info', 'woocommerce' );
    }
    return $tabs;
}

// Rename the heading inside the Additional Information tab
add_filter( 'woocommerce_product_additional_information_heading', 'rename_additional_info_heading' );
function rename_additional_info_heading( $heading ) {
    return __( 'Info', 'woocommerce' );
}

Are you looking to enhance your WooCommerce product pages with custom information tabs? With WordPress, WooCommerce, and Advanced Custom Fields (ACF), you can do just that. Here’s how to add dynamic custom tabs to your products.

How do I set this up?

  1. Setup ACF and import the JSON
  2. Add the Code to your Theme using Snippets
  3. Add Data to WooCommerce Products
  4. Check your Product Page

What Does This Tutorial Do?

ACF Setup

  • Create Field Group Add extra tabs to your product pages
  • Repeater Field with Field Name custom_tab
  • Sub field with Field Name custom_tab_title
  • Sub field with Field Name custom_tab_content
  • Location rule Post Type > Product > Product
[
    {
        "key": "group_67579797aa357",
        "title": "Add extra tabs to your product pages",
        "fields": [
            {
                "key": "field_67579797ce07a",
                "label": "Easy tab manager",
                "name": "custom_tab",
                "aria-label": "",
                "type": "repeater",
                "instructions": "Boost your product pages by adding custom tabs containing extra information. Grow your sales by giving customers all the details they need - everyone wins 💪",
                "required": 0,
                "conditional_logic": 0,
                "wrapper": {
                    "width": "",
                    "class": "",
                    "id": ""
                },
                "layout": "row",
                "pagination": 0,
                "min": 0,
                "max": 0,
                "collapsed": "",
                "button_label": "Add Row",
                "rows_per_page": 20,
                "sub_fields": [
                    {
                        "key": "field_675797b2ce07b",
                        "label": "Tab Title",
                        "name": "custom_tab_title",
                        "aria-label": "",
                        "type": "text",
                        "instructions": "",
                        "required": 0,
                        "conditional_logic": 0,
                        "wrapper": {
                            "width": "",
                            "class": "",
                            "id": ""
                        },
                        "default_value": "",
                        "maxlength": "",
                        "allow_in_bindings": 0,
                        "placeholder": "",
                        "prepend": "",
                        "append": "",
                        "parent_repeater": "field_67579797ce07a"
                    },
                    {
                        "key": "field_675797b3ce07c",
                        "label": "Tab Content",
                        "name": "custom_tab_content",
                        "aria-label": "",
                        "type": "wysiwyg",
                        "instructions": "",
                        "required": 0,
                        "conditional_logic": 0,
                        "wrapper": {
                            "width": "",
                            "class": "",
                            "id": ""
                        },
                        "default_value": "",
                        "allow_in_bindings": 0,
                        "tabs": "all",
                        "toolbar": "full",
                        "media_upload": 1,
                        "delay": 0,
                        "parent_repeater": "field_67579797ce07a"
                    }
                ]
            }
        ],
        "location": [
            [
                {
                    "param": "post_type",
                    "operator": "==",
                    "value": "product"
                }
            ]
        ],
        "menu_order": 0,
        "position": "normal",
        "style": "default",
        "label_placement": "top",
        "instruction_placement": "label",
        "hide_on_screen": "",
        "active": true,
        "description": "",
        "show_in_rest": 0
    }
]

Code Snippet — Link ACF to show on site front-end

  • Retrieves data from ACF repeater field
  • Hooks data into product template
  • Matches same pretty URL naming convention as stock
add_filter( 'woocommerce_product_tabs', 'multiple_custom_acf_tabs', 98 );
function multiple_custom_acf_tabs( $tabs ) {
    global $post;

	// Fetch the repeater field
    $custom_tabs = get_field('custom_tab', $post->ID); // Use the correct repeater field name

    if( $custom_tabs ) {
        $tab_priority = 50;
        foreach( $custom_tabs as $index => $tab ) {
            if( isset($tab['custom_tab_title']) && isset($tab['custom_tab_content']) ) {
                // Use a sanitized version of the title for the key, ensuring uniqueness
                $sanitized_title = sanitize_title( $tab['custom_tab_title'] );
                $tabs[$sanitized_title] = array(
                    'title'    => esc_html( $tab['custom_tab_title'] ),
                    'priority' => $tab_priority + $index,
                    'callback' => function() use ( $tab ) {
                        echo wp_kses_post( apply_filters( 'the_content', $tab['custom_tab_content'] ) );
                    }
                );
            }
        }
    }
    return $tabs;
}

Something to think about…

You've got a choice: load up with a feature-heavy, premium plugin you'll only half-use, or keep it simple with something basic.

I once got inspired by the WooCommerce Product Tabs plugin from Barn2. But then I saw the size – over 6MB compressed! That's a lot of extra code for my site.

It's like when I was looking for a PayPal gateway for WooCommerce. The official one from Woo was a hefty 9MB, but a third-party option was just 500KB. What is going on with the world where you need that much extra heft? Pff… I know people have excuses but I'm not listening.

One more bonus snippet!

This will rename the tab title, and also unload and remove it from the hook.

// Rename the tab title Description
add_filter( 'woocommerce_product_tabs', 'custom_rename_description_tab', 98 );
function custom_rename_description_tab( $tabs ) {
    global $post;
    $page_title = get_the_title($post->ID);
    if ( isset( $tabs['description'] ) ) {
        $tabs['description']['title'] = sprintf( __( 'Overview: %s', 'woocommerce' ), $page_title );
    }
    return $tabs;
}

// Remove the H2 heading inside the description tab
add_filter( 'woocommerce_product_description_heading', '__return_empty_string' );

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

// Rename the tab title and heading "Additional Information" to "Info"
add_filter( 'woocommerce_product_tabs', 'rename_additional_info_tab', 98 );
function rename_additional_info_tab( $tabs ) {
    if ( isset( $tabs['additional_information'] ) ) {
        $tabs['additional_information']['title'] = __( 'Info', 'woocommerce' );
    }
    return $tabs;
}

// Rename the heading inside the Additional Information tab
add_filter( 'woocommerce_product_additional_information_heading', 'rename_additional_info_heading' );
function rename_additional_info_heading( $heading ) {
    return __( 'Info', 'woocommerce' );
}

Was this helpful?

Yes! 🎉 No! 😑

Not quite what you're looking for? Get Help

1 thought on “Adding Custom Tabs to WooCommerce Products with ACF”

  1. I just added a bonus snippet to remove and rename default tabs “Description” and “Additional Information” at the bottom of the post!

    Reply

Leave a Comment

Item added to cart.
0 items - $0