WooCommerce guide

How to add an FAQ tab with FAQ schema to WooCommerce products

An FAQ tab answers the questions shoppers ask before they buy, right on the product page. FAQPage structured data describes those questions to search engines. Here is what the markup does today, and how to add both with code or with a plugin.

What FAQ schema does, and what it doesn’t

FAQPage is a schema.org type for a list of questions that each have one answer. You add it to the page as a JSON-LD script, and search engines and other tools can read the questions and answers as data instead of guessing from the layout.

For a few years, FAQ markup could make a search result show expandable questions in Google. In August 2023 Google limited FAQ rich results to well-known, authoritative government and health websites. For a typical store, adding FAQPage markup will not bring back those dropdowns. Check Google’s FAQPage documentation for the current status before you plan around them, and be wary of anyone who promises FAQ rich results for a shop.

So is it worth it? The FAQ content is what matters most: clear answers about sizing, compatibility, care or shipping help shoppers decide without emailing you. The markup is a small extra: it states the questions and answers in a standard, machine-readable form, it costs a few hundred bytes, and it’s easy to switch off.

If you add it, follow Google’s guidelines for FAQPage:

The code way

The snippet below adds an FAQ tab to products in the “coffee” category and prints matching FAQPage JSON-LD. The questions live in one function, so the tab and the markup can’t drift apart. Add it with a child theme or a snippets plugin, as in how to add a custom product tab.

// Questions and answers for a product. Replace with your own,
// or load them from product meta.
function mystore_product_faqs( $product ) {
    if ( has_term( 'coffee', 'product_cat', $product->get_id() ) ) {
        return array(
            'Is this whole bean or ground?' => 'Whole bean. Choose "Ground" in the options for a medium grind.',
            'How long does it stay fresh?'  => 'Best within six weeks of the roast date printed on the bag.',
        );
    }
    return array();
}

add_filter( 'woocommerce_product_tabs', 'mystore_add_faq_tab', 98 );
function mystore_add_faq_tab( $tabs ) {
    global $product;
    if ( $product instanceof WC_Product && mystore_product_faqs( $product ) ) {
        $tabs['faq'] = array(
            'title'    => __( 'FAQ', 'mystore' ),
            'priority' => 25,
            'callback' => 'mystore_faq_tab_content',
        );
    }
    return $tabs;
}

function mystore_faq_tab_content( $key, $tab ) {
    global $product;
    foreach ( mystore_product_faqs( $product ) as $question => $answer ) {
        printf(
            '<details><summary>%s</summary>%s</details>',
            esc_html( $question ),
            wp_kses_post( wpautop( $answer ) )
        );
    }
}

add_action( 'wp_footer', 'mystore_faq_schema' );
function mystore_faq_schema() {
    if ( ! is_product() ) {
        return;
    }
    $product = wc_get_product( get_queried_object_id() );
    $faqs    = $product ? mystore_product_faqs( $product ) : array();
    if ( ! $faqs ) {
        return;
    }
    $questions = array();
    foreach ( $faqs as $question => $answer ) {
        $questions[] = array(
            '@type'          => 'Question',
            'name'           => wp_strip_all_tags( $question ),
            'acceptedAnswer' => array(
                '@type' => 'Answer',
                'text'  => wp_strip_all_tags( $answer ),
            ),
        );
    }
    $schema = array(
        '@context'   => 'https://schema.org',
        '@type'      => 'FAQPage',
        'mainEntity' => $questions,
    );
    echo '<script type="application/ld+json">' . wp_json_encode( $schema ) . '</script>';
}

Some notes on the choices:

The limits are the usual ones for code: questions are edited in PHP, product-specific questions need their own storage (for example product meta), and nothing stops a second FAQPage block if an SEO plugin adds one too.

The plugin way: the Tabwright Pro FAQ tab

Tabwright Pro, the paid add-on to the free Tabwright plugin, has an FAQ tab type:

  1. Under WooCommerce → Product Tabs, create a saved tab and set its Type to FAQ.
  2. Click Add question for each question and answer. Any text in the normal tab content shows above them as an introduction.
  3. Attach the tab: add it to one product for product-specific questions, bulk assign it, or give it display rules so it appears on a whole category automatically.

On the product page the questions render as a <details> accordion. Tabwright Pro prints one FAQPage JSON-LD block per page, only for FAQ tabs that are actually shown on that page, and drops repeated questions if two FAQ tabs share one. If your SEO plugin already outputs FAQPage, or you don’t want the markup on shared FAQs, turn it off with one line:

add_filter( 'tabwright_pro_faq_schema', '__return_null' );

To be clear about scope: FAQ tabs are saved tabs, so a product’s own custom tabs can’t be FAQ tabs; for product-specific questions you create a saved FAQ tab and add it to that product. The free plugin has no FAQ type. You can still write questions and answers in a normal free tab, just without the accordion and the markup.

FAQ

Will FAQ schema give my products FAQ rich results in Google?

Almost certainly not. Since August 2023 Google shows FAQ rich results only for well-known, authoritative government and health websites. Stores can still add the markup; it just doesn’t produce the dropdowns in Google results.

Does FAQPage conflict with WooCommerce’s Product schema?

No. WooCommerce prints its own Product structured data (price, availability, ratings) on product pages. FAQPage is a separate block that describes the questions on the same page.

Can I have the FAQ tab without the markup?

Yes. In code, leave out the wp_footer function. In Tabwright Pro, return null from the tabwright_pro_faq_schema filter.

Get it free on WordPress.org: coming soonAbout Tabwright