Show 4 woocommerce products with highest discount

Hello, i hope everyone is good ! I have a question, i hope someone can provide a solution to it, I'm trying to show 4 wooommerce products using a shortcode but the 4 products needs to be the ones with the highest discount. Thanks in advance !

  • Adam
    • Support Gorilla

    Hi Anders

    I hope you’re well today and thank you for your question!

    This should be doable with a small bit of additional code but to make sure first: by “discount” do you mean the “Sale price” set in Product Data or some other “discount type” (like e.g. some custom attribute or some other option coming from some WooCommerce extension)?

    Let me know, please.

    Best regards,

    Adam

  • Adam
    • Support Gorilla

    Hello Anders

    Thanks for response!

    I think the code snippet below along with a standard products shortcode should do the trick. Try doing this:

    1) put this code into your site’s theme functions.php file:

    add_filter( 'woocommerce_shortcode_products_query', 'woocommerce_shortcode_products_orderby' );

    function woocommerce_shortcode_products_orderby( $args ) {

    $standard_array = array('menu_order','title','date','rand','id');

    if( isset( $args['orderby'] ) && !in_array( $args['orderby'], $standard_array ) ) {
    $args['meta_key'] = $args['orderby'];
    $args['orderby'] = 'meta_value_num';
    }

    return $args;
    }

    2) use this shortcode on page where you want to display those discounted products

    [products limit="4" orderby="_sale_price" order="DESC" on_sale="true"]

    Give it a try please and let’s see if it works for you as expected.

    Best regards,

    Adam

  • Anders
    • The Incredible Code Injector

    [attachments are only viewable by logged-in members] [attachments are only viewable by logged-in members]

    Unfortunetly only 1 product appears, even though i have alot of products with discount/sale_price as you can see in the imgs attached, i can grant support if that would be easier.

  • Adam
    • Support Gorilla

    Hi Anders

    Thank you for your response!

    i can grant support if that would be easier.

    Yes, I think that might be helpful so it would be great if you could enable access. Just let me know here once it’s done, please, as I won’t get any automatic notification about it.

    Best regards,

    Adam

  • Adam
    • Support Gorilla

    Hi Anders

    Thanks, it did actually help!

    There are four products shown now and the only change that was needed was to remove the “onsale” attribute from the shortcode. Apparently only one of these products was marked as “sale” and that’s why it showed only that one – now it’s just taking taking four products ordered by sale price.

    But I realized then that this solution, unfortunately, still won’t work. I’m sorry for this, I made a “logic error”.

    This shortcode will show four products and they’ll be sorted by the sale price but not by the “discount amount”. In fact, there’s no way to sort it this way without additional customization.

    The point is: the “discount amount” would be the difference between the regular and sale price. That’s not stored in the WP database out of the box so there are two ways to achieve that:

    1. either it would have to be calculated “on the fly”

    2. or it would have to actually be saved in the database as yet additional custom field/attribute

    As for 1)

    i would rule that out. That would be insanely “resource intensive” as we’d need to actually fetch all the products first, calculate all the price differences (so for each and every single product) then sort the product list by that difference and then only display four of them.

    Doing that upon each and every page load would be a “killer” for the site/server.

    As for 2)

    That actually seems to be doable but it would need an additional code. Let’s try it then :slight_smile:

    – first add following code (in addition to the one you already added) to your theme’s functions.php file:

    // calculate and save discount amount on product save/edit
    add_action('woocommerce_process_product_meta', 'woo_calc_my_discount', 99);
    function woo_calc_my_discount( $product_id ) {

    $_product = wc_get_product( $product_id );

    $regular = (float) $_product->get_regular_price();
    $sale = (float) $_product->get_sale_price();

    $discount = round( 100 - ( $sale / $regular * 100), 2 );

    update_post_meta( $product_id, '_discount_amount', $discount );

    }

    – second, go through your products and just re-save them (enter product edit screen or use “quick edit” on product list and click “update) – this is so the discounts were actually calculated and saved to the database; it has to be done only once – for any future product edits and new products added the discount will be calculated and saved “out of the box” automatically when you just save the prouduct

    – third, head on to your page and edit shortcode so instead of

    [products limit="4" orderby="_sale_price" order="DESC"]

    it becomes

    [products limit="4" orderby="_discount_amount" order="DESC"]

    That should do the job now and should show four products sorted by the biggest discount amount. The discount amount calculated is a percentage so that gives a reliable comparison, I believe.

    Best regards,

    Adam

  • Anders
    • The Incredible Code Injector

    Hello, i've did the steps you said:

    Added that code to functions.php

    Updated 13 products with quick-edit mode

    Added new shortcode you provided

    The result is, no product is showing, i've attached images to see what i curently have. Thanks !

    [attachments are only viewable by logged-in members]

    [attachments are only viewable by logged-in members]

    [attachments are only viewable by logged-in members]

  • Adam
    • Support Gorilla

    Hello Anders

    Thanks for feedback!

    I tested this before on my own site and it seemed to work fine so I accessed your site again and I tested that. I found out that I actually gave you a slightly wrong information! I’m sorry for this!

    Apparently, it’s not enough to re-save product using “quick edit” but you actually need to open regular “edit” page for the product and click “update” there. There’s no need to make any changes, just click update and let it save – but it has to be done on a standard “edit” screen and not “quick edit”.

    When I tested it on my end, I was doing it exactly that way and I assumed that “quick edit” would work the same, hence the information in my previous post. It turns out though that with “quick edit” the action hook that triggers function that does these calculations, doesn’t work.

    The bottom line is: there are currently two products being displayed because I simply opened two of them for editing and clicked “update” (without doing any changes). If you go through all the products and do this, it should start showing all necessary four and accurately select/sort them from the whole set.

    Like I explained before – any new products that you’ll be adding, should have that discount percentage calculated automatically and saved into database so no additional steps will be necessary.

    Best regards,

    Adam

  • Anders
    • The Incredible Code Injector

    Hi again, everything works as expected, i got one more question tough, it seems if i import products they don’t seem to be taken in consideration, wich probably is normal, is there a way to force update all products using an action/filter something ? without me doing manually like you said previously ? cause this will solve 2 problems with one “go” Thanks alot for all the help !

  • Adam
    • Support Gorilla

    HI Anders

    That’s a fair question but must say I’m not sure. It’s possible that upon import that process product meta action is not triggered and in such case that wouldn’t work and you’d need some additional hook.

    I don’t think it’s a matter of function execution order as in the code that I shared with you the hook is already executed quite late (the priority value is set to 99) so the entire “calculation” should be done after any things that are possibly hooked to the same action hook are done.

    That import – are you using some specific plugin for this? Could you point me to it if it’s free or share it with me if it’s not free? If latter – please upload it as a zip package to some Google Drive or Dropbox or similar account of yours and share direct download link with me here (I’ll then mark this ticket as private so we wouldn’t distribute premium plugin).

    I would then take a look to see if there’s anything we could do to solve this (though I’d rather not make promises on this at this point).

    Best regards,

    Adam