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:
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:
And they’re now only present in our custom tab:
If the product has no upsells or cross-sells, the product page is unchanged and no tab is added!
Need some help taking this code further? We recommend Codeable for small custom projects.
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.
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.
Very helpful and well written explanation. I would like to add this to our product pages but would also like to remove, or at least change the text ‘you might also like’. I can’t see where I would add this, any advice?
Thanks
Hey Emily, to change text I’d recommend using the Say What plugin as outlined here.
Thanks very much Beka! I have been trying to find a solution to this for days but this is by far the most flexible and simple solution.
Sure thing! Glad it helped. 🙂