Discount if product A and product B are ordered together?

I've looked around the forum and the docs quite a bit, and I've seen this question asked before, but I'm having trouble comprehending the answers! Bundling and product-level discounts have both been recommended as solutions, but I can't figure out how to apply either of those things to this situation.

Basically, we want to offer an incentive for ordering product A and product B together. If both items are present in the cart, there would be a $5 discount applied, which could be a line item like a coupon, or could be applied to the price of one of the items, it doesn't matter.

I get how to apply a product-specific discount to product A, but rather than the tier being the price or quantity of product A, I'd need to check if product B was present, and I'm not sure how to make that work.

Bundling seems to me to require two products to be bought together, which is not what I want either. A and B could each be bought on their own, it's just that the discount wouldn't apply. But maybe I'm not understanding the bundling concept correctly!

Any suggestions or clarification would be greatly appreciated!
Comments
  • fc_adamfc_adam FoxyCart Team
    @dustystrings,

    You're right that bundling probably wouldn't be the answer for you here, it wouldn't quite solve your issue. Unfortunately our discounts don't have any logic for checking for the presence of other specific products either - so there isn't currently a native solution for exactly what you're after.

    Instead, what you'd need to look at is a javascript based solution. On cart/checkout load - loop through the products that are present and check if both product A and B are present. If they are, and the coupon isn't present, then add the coupon. If they're both not present, but the coupon is - then you would remove the coupon.

    How comfortable are you with javascript? We have an example of adding a coupon to the cart on this page: https://wiki.foxycart.com/v/2.0/json, let us know if anything else needs clarification though.
  • I'm not that great at javascript... Often I can look at an example and modify it to work for me, but that's about it. The example of adding a coupon makes sense to me, but I could use help figuring out how to check if product A and product B are in the cart. I think checking by product code probably makes the most sense.

    Thanks!
  • fc_adamfc_adam FoxyCart Team
    edited May 2016
    @dustystrings,

    Sure thing! This code is untested, so you'll want to give it some solid testing to ensure it's working as it should. You'll just need to set the coupon_code variable at the top of the script.
    <script>
    function productCheck() {
    var productA = 0;
    var productB = 0;
    var coupon_code = "YOUR-COUPON-CODE";
    for (var i = 0; i < FC.json.items.length; i++) {
    if (FC.json.items[i].code == "product-a") {
    productA += FC.json.items[i].quantity;
    } else if (FC.json.items[i].code == "product-b") {
    productB += FC.json.items[i].quantity;
    }
    }
    var coupon_id = 0;
    if(!jQuery.isEmptyObject(FC.json.coupons)) {
    jQuery.each(FC.json.coupons, function(code, coupon){
    if(code == coupon_code) {
    coupon = coupon.id;
    }
    });
    }

    if (productA > 0 && productB > 0 && coupon_id == 0) {
    // has the products but no coupon
    FC.client.request('https://'+FC.settings.storedomain+'/cart?coupon=' + coupon_code).done(function(dataJSON) {
    FC[FC.json.context].render();
    });
    } else if ((productA == 0 || productB == 0) && coupon_id > 0) {
    // doesn't have both products but has the coupon
    FC.client.request('https://'+FC.settings.storedomain+'/cart?cart=remove_coupon&coupon_code_id=' + coupon_id).done(function(dataJSON) {
    FC[FC.json.context].render();
    });
    }
    }
    FC.client.on("ready.done", productCheck);
    FC.client.on("cart-submit.done", productCheck);
    FC.client.on("cart-item-quantity-update.done", productCheck);
    FC.client.on("cart-item-remove.done", productCheck);
    </script>
  • Sorry for the delay, and thank you for the help! Unfortunately, so far it doesn't seem to be working.

    I set up my coupon "wrench-holder-5" as single|1-5, for lack of any other ideas.

    And here's your code with my modifications:
    <script>
    function productCheck() {
    var wrench = 0;
    var holder = 0;
    var coupon_code = "wrench-holder-5";
    for (var i = 0; i < FC.json.items.length; i++) {
    if (FC.json.items[i].code == "duo-custom" || FC.json.items[i].code == "duo-concert" || FC.json.items[i].code == duo-universal" || FC.json.items[i].code == "standard-harp-wrench" || FC.json.items[i].code == "custom-wrench-maple" || FC.json.items[i].code == "custom-wrench-bubinga" || FC.json.items[i].code == "universal") {
    wrench += FC.json.items[i].quantity;
    } else if (FC.json.items[i].code == "tuning-wrench-holder") {
    holder += FC.json.items[i].quantity;
    }
    }
    var coupon_id = 0;
    if(!jQuery.isEmptyObject(FC.json.coupons)) {
    jQuery.each(FC.json.coupons, function(code, coupon){
    if(code == coupon_code) {
    coupon = coupon.id;
    }
    });
    }

    if (wrench > 0 && holder > 0 && coupon_id == 0) {
    // has the products but no coupon
    FC.client.request('https://'+FC.settings.storedomain+'/cart?coupon=' + coupon_code).done(function(dataJSON) {
    FC[FC.json.context].render();
    });
    } else if ((wrench == 0 || holder == 0) && coupon_id > 0) {
    // doesn't have both products but has the coupon
    FC.client.request('https://'+FC.settings.storedomain+'/cart?cart=remove_coupon&coupon_code_id=' + coupon_id).done(function(dataJSON) {
    FC[FC.json.context].render();
    });
    }
    }
    FC.client.on("ready.done", productCheck);
    FC.client.on("cart-submit.done", productCheck);
    FC.client.on("cart-item-quantity-update.done", productCheck);
    FC.client.on("cart-item-remove.done", productCheck);
    </script>
    I can successfully type in the coupon code to add it manually, but it doesn't appear automatically when both items are in the cart, nor does it disappear when I remove one of the items. I'm wondering if I messed something up with the "wrench" variable by trying to check for a bunch of different product codes...
  • fc_adamfc_adam FoxyCart Team
    @dustystrings,

    Two small issues. One was a missing quotation on one of your conditions - duo_universal" - missing the quotation at the start. The other issue was I used an incorrect variable when saving the coupon ID when it existed in the cart, should have been coupon_id instead of coupon. Fixing those two things should get it working for you:
    <script>
    function productCheck() {
    var wrench = 0;
    var holder = 0;
    var coupon_code = "wrench-holder-5";
    for (var i = 0; i < FC.json.items.length; i++) {
    if (FC.json.items[i].code == "duo-custom" || FC.json.items[i].code == "duo-concert" || FC.json.items[i].code == "duo-universal" || FC.json.items[i].code == "standard-harp-wrench" || FC.json.items[i].code == "custom-wrench-maple" || FC.json.items[i].code == "custom-wrench-bubinga" || FC.json.items[i].code == "universal") {
    wrench += FC.json.items[i].quantity;
    } else if (FC.json.items[i].code == "tuning-wrench-holder") {
    holder += FC.json.items[i].quantity;
    }
    }
    var coupon_id = 0;
    if(!jQuery.isEmptyObject(FC.json.coupons)) {
    jQuery.each(FC.json.coupons, function(code, coupon){
    if(code == coupon_code) {
    coupon_id = coupon.id;
    }
    });
    }

    if (wrench > 0 && holder > 0 && coupon_id == 0) {
    // has the products but no coupon
    FC.client.request('https://'+FC.settings.storedomain+'/cart?coupon=' + coupon_code).done(function(dataJSON) {
    FC[FC.json.context].render();
    });
    } else if ((wrench == 0 || holder == 0) && coupon_id > 0) {
    // doesn't have both products but has the coupon
    FC.client.request('https://'+FC.settings.storedomain+'/cart?cart=remove_coupon&coupon_code_id=' + coupon_id).done(function(dataJSON) {
    FC[FC.json.context].render();
    });
    }
    }
    FC.client.on("ready.done", productCheck);
    FC.client.on("cart-submit.done", productCheck);
    FC.client.on("cart-item-quantity-update.done", productCheck);
    FC.client.on("cart-item-remove.done", productCheck);
    </script>
  • @fc_adam,

    Yes!! That works like a charm. Thank you so much for the help!
  • Thanks for this code. I have adpated it successfully for my situation: item A is discounted if there are two or more items (of any type) in the cart.

    One thing though, if someone manually adds the coupon code, then it is not checked to see if it is valid.

    So I added

    FC.client.on("cart-coupon-add.done", productCheck);

    to the code, to check that situation.

    I realise they couldn't checkout without the coupon being checked by the code, but it is confusing for it to look as though you have a discount when you don't.

    Potentially you may need to add

    FC.client.on("cart-coupon-remove.done", productCheck);

    as well if you have other (manual) coupons that are not allowed to be combined.





  • fc_adamfc_adam FoxyCart Team
    @njwfx,

    Great thoughts - you would indeed want to account for cart-coupon-add.done and cart-coupon-remove.done if the customer may know the coupon to add it themselves. Thanks for posting that!
Sign In or Register to comment.