Ask SkyVerge

Back in action this week with some tutorials scheduled! First up, we have an Ask SkyVerge question today from Rebecca:

You’ve got a great article on how to move product upsells to a widget. But what about moving them to a tab? I’d love your ideas on how to make the tab disappear if there are no upsells.


Definitely possible! By default, the upsells are shown on the product page below the product description:

WooCommerce Product Tabs; Default

We can move them to another location (in this case, within a tab), but we’ll need a few steps to do this:

  • A way to check if there are upsells
  • A way to add the tab if so
  • Remove upsells from the current location
  • Output the upsells content in the tab

All of these is pretty straight-forward, as WooCommerce has a filter that lets us modify product tabs, and some template functions to output related items.

I am going to tweak this just a bit though — I’m going to move both upsells and related products (cross-sells) into a new product tab instead of just upsells. This is a personal preference since I think it looks weird to have the cross-sells constantly at the bottom of the page, but it’s not required and you could remove those portions of the code snippet we’re about to put together 🙂

Step 1: Check for Upsells & Cross-Sells

First, we need a way to check for upsells and cross-sells for a product. We’re going to hook into the woocommerce_product_tabs filter, so we’ll have access to the global product object when we attach a function to this.

The product object has a couple helpers to get upsells and cross-sells, but we should note that WooCommerce 3.0 is going to deprecate these helpers. Let’s set up a check that will account for both the upcoming and existing helpers. My preferred method for this is to use is_callable() on the new method name, and if the method isn’t callable, use the old one:

is_callable( array( $object, 'method_name' ) )

Here’s what that looks like in practice:

global $product;

// compatibility check for pre / post WC 3.0
$upsells = is_callable( array( $product, 'get_upsell_ids' ) )     ? $product->get_upsell_ids()     : $product->get_upsells();
$related = is_callable( array( $product, 'get_cross_sell_ids' ) ) ? $product->get_cross_sell_ids() : $product->get_cross_sells();

Part 1 down! Now in my snippet, I can check if these are empty before adding my new tab:

if ( empty( $upsells ) && empty( $related ) ) {
    return $tabs;
}

Step 2: Remove Current Output

This is also an easy step. If our empty checks pass, we know we have at least upsells or cross-sells to work with. As such, we’re going to add our new tab. But first, we’ll want to remove the current way upsells and cross-sells are output. We can do that by removing the actions that output them by default:

remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_upsell_display', 15 );
remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20 );

Easy peasy 🙂

Step 3: Add a New Tab

Now all that’s left is to add a new tab with our related items in it.

function maybe_add_tab( $tabs ) {

    $tabs['related_items'] = array(
        'title'    => __( 'Related Items', 'textdomain' ),
        'priority' => 25,
        'callback' => 'sv_wc_output_upsells_related_items',
    );

    return $tabs;
}
add_filter( 'woocommerce_product_tabs', 'maybe_add_tab' );

That’s all it takes to add a new tab for a product — the tab title, priority, and a callback function (a method that outputs the tab content). However, notice the callback name I have is something that does exist yet. Let’s give ourselves a helper method that outputs the content (upsells and cross-sells) we’ve already removed from the page:

// Callback to output related products and upsells
function sv_wc_output_upsells_related_items() {
    woocommerce_upsell_display();
    woocommerce_output_related_products();
}

Final Round: WooCommerce Related Items Tab

Now we can put it all together! We’ll have a function hooked into woocommerce_product_tabs that checks for upsells and cross-sells, and if present, removes them from the current location and re-adds them in the tab content. We’ll also have our small helper function to output both of these with WooCommerce template functions. (View the full gist here.)

function sv_wc_maybe_add_upsell_tab( $tabs ) {
    global $product;

    // compatibility check for pre / post WC 3.0
    $upsells = is_callable( array( $product, 'get_upsell_ids' ) )     ? $product->get_upsell_ids()     : $product->get_upsells();
    $related = is_callable( array( $product, 'get_cross_sell_ids' ) ) ? $product->get_cross_sell_ids() : $product->get_cross_sells();

    // if we have no related items, don't add a new tab
    if ( empty( $upsells ) && empty( $related ) ) {
        return $tabs;
    }

    // green light! remove the current upsells and related items
    remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_upsell_display', 15 );
    remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20 );

    // first, make sure that we're dealing with an array rather than null
    $new_tabs = is_null( $tabs ) ? array() : $tabs;

    // now let's get in tabulated formation, 'cause I slay ?
    $new_tabs['upsells'] = array(
        'title'    => __( 'Related Items', 'woocommerce-upsells-tab' ),
        'priority' => 25,
        'callback' => 'sv_wc_output_upsells_related_items',
    );

    return $new_tabs;
}
add_filter( 'woocommerce_product_tabs', 'sv_wc_maybe_add_upsell_tab' );


// Callback to output related products and upsells
function sv_wc_output_upsells_related_items() {
    woocommerce_upsell_display();
    woocommerce_output_related_products();
}

When you’ve implemented this on your site, you’ll now see that the upsells and cross-sells have been removed from the product description:

WooCommerce Product Tabs: description modified

And they’re now only present in our custom tab:

WooCommerce Product Tabs: related items tab

If the product has no upsells or cross-sells, the product page is unchanged and no tab is added!

Published by Beka Rice

Beka leads product direction for SkyVerge and technical documentation. She spends a lot of time on research and interviews, but likes to write so she has an excuse to spend more time jamming out to anything from The Clash to Lady Gaga.

2 Comments

  1. Looks great! One problem: I want to show only Cross-sells in the tab. If the product has a Cross-sell, the tab is made, but displays only ‘Related items’, not the Cros-sell.

    Reply
  2. Unfortunately this didn’t work for me. It removed all tabs from the back end, and didn’t create the new tabs (with content) on the front end.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *