Zen Cart custom software development, Zen Cart modules, Zen Cart Expert eCommerce with Zen Cart!

Zen Cart BOGO discount

BOGO Discount for Zen Cart

A Zen Cart™ discounting module for bulk purchases.

My Better Together module solves a particular problem: allowing you to offer a "Buy One Get One Free" discount on particular items or categories of items.

But what if what you want is Buy One, Get One Free across the entire cart? Or Buy Two, Get One free, or Buy Two, Get One Half off? This is what BOGO does.

The BOGO Discount extension permits you to offer discounts that are structured as:

Buy <M> items, get a discount on <N> items of <X> percent or dollars each.

BOGO settings are global and apply to all your products. Specific exclusions may be created, but otherwise the settings are universally applied. If you do not want all (or most of) your products subject to the rule Buy <M> items, get a discount on <N> items, look at Better Together instead.

Background: See the Zen Cart Matrix-o-discounts

Example Discounts: I have provided several examples of Zen Cart BOGO Discount discounts.

Relevance: Zen Cart™ 1.3.5 - 1.3.9, 1.5.x

Current Version: 1.3 (version history)

Support Thread: My commercial software is not supported on the Zen Cart forum. Please email me questions instead.

Cost: $25 (Note: this low price covers software only for self-installation.)

Buy Now

Would you like to ask me questions before buying? I'm happy to help likely purchasers make the right decision. Please use my contact form.

Installed Cost: $125.00 (Professional installation by That Software Guy)

Installation Difficulty: Easy

Installation Instructions: click here

Tax Notes: Notes on tax handling

Buy: Buy BOGO Discount!
Pre-purchase questions? No problem! Just Please contact me with your question.

FAQ: click here

Configuration: BOGO is configured on the Admin > Modules > Order Total screen. A single configuration is used for the entire cart; if you want to selectively offer buy-one get-one discounts or buy-two-get-one discounts without needing to make code changes by hand, you may wish to consider Better Together or Combination Discounts. Alternatively, you can do make some code changes described in Limited BOGO.

Marketing Text: click here

Add-Ons:
Normally, the BOGO discount is not shown until the second page of checkout. If you want to show the discount on the shopping cart page, look at Discount Preview.




Alternatives: BOGO Discount configuration applies to the entire cart - all items are set to buy-one, get-one, or buy-two, get-one (or whatever your configuration specifies). (There are ways to restrict this further, but they require code changes; they cannot be done using an admin panel. See Limited BOGO.) Sometimes this is not a good match for a shop owner's requirements; if you want to selectively offer buy-one get-one discounts, take a look at Better Together. If your discounts require the purchase of more than one item (for example, buy-two, get one, etc.), take a look at Combination Discounts or Zen Cart Free Gift Chooser.

Bugs: click here

Overview:

This mod permits a shop to define "Buy some-number, get some-number at a discount" style discounts across the entire inventory. Discounts can be applied to items of the same category, product id or without restriction. The discounts may be expressed in percentage or currency units. Various user exits are provided to make it easy to extend the mod to meet shop requirements.

Detailed Description:

  1. Configuration
    Configuration of Zen Cart BOGO Discount
    BOGO Discount is configured through the Admin interface (Admin > Modules > Order Total > BOGO Discount).

    The image above shows a shop which gives a "Buy 2 Get 1 100% off" (i.e. "Buy 2 Get 1 Free") for all items in the store.

    Items which are counted to meet the condition ("Buy 2") are counted from most to least expensive, and items which are to be discounted ("Get 1 Free") are from least to most expensive. So BOGO Discount always discounts the least expensive items possible.

    Discount Basis has five possible values:
    • Same Item
    • Same Item, Same Attributes
    • Same Parent Category
    • Same Top Level Category
    • No Restriction
    Using the example below:

    Men's Clothing 
         |
         ---->  Shirts
                |
                -------> shirt A     
                         shirt B
                         shirt C 
         ---->  Pants 
                |
                -------> pants A     
                         pants B
                         pants C 
         ---->  Neckwear 
                |
                -------> Bow Ties 
                         |
                         -------> bow tie A     
                                  bow tie B
                -------> Neck Ties 
                         |
                         -------> necktie A     
                                  necktie B
    Women's Clothing 
         |
         ----> Dresses  
                |
                -------> dress A     
                         dress B
    
    
    Let's assume for this example that Buy This Many is 1, and Get This Many is 1.

    If Discount Basis was "Same Item" and one shirt A size Medium and one shirt A size Large were purchased, the less expensive shirt would be discounted.

    If Discount Basis was "Same Item, Same Attributes" and one shirt A size Medium and one shirt A size Large were purchased, there would be no discount.
    If two size Medium were purchased, one of the shirts would be discounted.

    If Discount Basis was "Same Parent Category" and shirt A and shirt B were purchased, the less expensive shirt would be discounted.
    If shirt A and pants A were purchased, there would be no discount.

    If Discount Basis was "Same Top Level Category" and shirt A and pants A were purchased, the less expensive item would be discounted.
    If shirt A and dress A were purchased, there would be no discount.

    If Discount Basis was "Same Top Level Category" and shirt A and dress A were purchased, the less expensive item would be discounted.

    Note that your only options for categories are top level category and parent category. So the category "Neckwear" (which is the grandparent category of bow tie A, bow tie B, necktie A and necktie B) would not be considered a parent category.

    Specifying "include tax = true" will gross the discount up by the amount of tax that would have been paid on the goods prediscount. This is appropriate for shops under a price inclusive sales tax system, such as the UK VAT. Specifying Re-calculate tax = Standard will recalculate the entire tax based on the original subtotal minus the bogo discount. Even more information about tax is provided at the bottom of this file.

  2. User Exits
    Some shops will want to further customize their discounting policy. Additional user exits are provided to permit the following customizations:
    • Exclude certain categories from discounting.
    • Exclude certain products from discounting.


    Specifically:

    • The function exclude_category() shows you how to add categories to a list of categories to not be discounted. You may specify a parent category id.
    • The function exclude_top_category() shows you how to add categories to a list of top level categories to not be discounted. You may specify a top level category id.
    • The function exclude_product() shows you how to add products to a list of products to not be discounted.

    Each of these functions contains a simple example of how to use it using item and category numbers like 99999, 99998, etc. See the FAQ below for more examples.

    The user exits are within the BOGO Discount contribution, in includes/modules/order_total/ot_bogo_discount.php

    BOGO Discount discounts off the *gross* price of the goods. This can result in a larger than expected discount if other discounts are added (such as coupons or group discounts), so bear this in mind when creating your discount strategy.

  3. Checkout Page User Interface
    BOGO Discount is an "Order Total" module, which means that by default, the discount is not shown until the second page of checkout (Payment Information). However, using the Discount Preview module will allow you to show the discount in the shopping cart.

    Depending on your configuration, the second page of checkout will look something like this:

    Zen Cart Checkout Payment Information Page with BOGO Discount

Installation Instructions:

  1. Back up everything! Try this in a test environment prior to installing it on a live shop.
  2. If you already have the BOGO Discount module installed, please deinstall your old copy by going to Admin > Modules > Order Total, selecting "BOGO Discount" and pressing the "Remove" button. Make a note of your settings so you can apply them to the new version.
  3. Copy the contents of the unzipped folder to the root directory of your shop. NOTE that these files assume your template name is "custom," so any file with "custom" in its path name will need to be renamed if you are using a different template name. Note: If you are using Zen Cart 1.5.5 or higher, your template name will be "responsive_classic" if you have not changed it.
  4. Login to admin and in Modules > Order Total you will see 'BOGO Discount' listed along with all the other modules available.
  5. Click on 'BOGO Discount' to highlight the module and click on 'Install'
  6. Decide on the parameters you wish to use. The easiest way to do this is to open a shopping cart in another window, and just try different discounting models. The discounts are shown on the second step of checkout in "Your Total" under "BOGO Discount."
  7. Customization: If you have a single discounting policy for your shop, you're all set. If you wish to tailor the policy, you will have to add code to the user exits as described above.
  8. If you wish, follow the guidelines in marketing to advertise your discounts.


Optional Installation Instructions:

  1. I highly recommend Discount Preview with all my discounting modules. Without Discount Preview, your customers cannot see the price reductions they are entitled to until the second page of checkout (checkout confirmation). Obviously this is a disadvantage, particularly for new customers who need to go through the additional step of creating an account before they can see this information. Sometimes seeing is believing, so here's a video showing Discount Preview in action.


Marketing

BOGO Discount may be automatically displayed on the product info page, using the built in marketing template.

Customize the tpl_product_info_display.php file to advertise your discounts. Copy the file includes/templates/template_default/templates/tpl_product_info_display.php into includes/templates/<YOUR_TEMPLATE>/templates
Then add this block of code to the new copy of tpl_product_info_display.php:
<?php 
require($template->get_template_dir('/tpl_bogo_marketing.php',DIR_WS_TEMPLATE, 
   $current_page_base,'templates'). '/tpl_bogo_marketing.php');
?>
The placement of this code is a matter of personal preference; try placing it below the product description and adjust to your tastes. It creates a message on your page to promote your discounts.

Buy any 1 item(s), get another 1 item(s) $5 off


Only one div block of text will be produced, with the div id bogoDiscountPolicy.

If you have used exclude_category() or exclude_product(), you will need to change the marketing text code to wrap it in a check for the exclusion. For category exclusions, change tpl_product_info_display.php from
  if ($discount->check() > 0) {

to
  if ( ($discount->check() > 0) &&
       (!$discount->exclude_category($current_category_id)) ) {
For product exclusions, use
  if ( ($discount->check() > 0) &&
       (!$discount->exclude_product($_GET['products_id'])) ) {

More Examples

In the first configuration example, you saw "Buy any 2 items, get 1 more free." Here are some more examples.

"Buy one, get another identical item half off."

Configuration of Zen Cart BOGO Discount
"Buy one, get another from the same category free."

Configuration of Zen Cart BOGO Discount
"Buy any one, get three more lesser or equal value half off."

Configuration of Zen Cart BOGO Discount


BOGO and Discount Preview

Discount Preview makes BOGO Discount pop! It shows the discount on the shopping cart page, instead of making your customers wait until the checkout payment page to see their discounts. Here's a screenshot of the shopping cart page on a cart using Discount Preview and BOGO Discount. The discount was Buy 3, get the least expensive free. Notice that the Description has been changed to "3 for 2 Discount."

Zen Cart BOGO and Discount Preview

Discount Preview is sold separately. Buy Discount Preview Now!

Limited BOGO

By default, BOGO is offered on all categories, with counting performed as specified by the Discount Basis. But this doesn't meet the needs of all shops.

Suppose you only want to discount categories 19, 62 and 50. Update the function setup() in includes/modules/order_total/ot_bogo_discount.php as follows:
   function  setup() {
      $this->allowed_categories = [19, 62, 50]; // only allow BOGO on these categories
   }
With "Buy this Many" set to 2 and "Get this Many" set to 1, and "Discount Basis" Same Parent Category, you have created the following discounts:
  • Buy any 2 category 19, get 1 from category 19 free
  • Buy any 2 category 62, get 1 from category 62 free
  • Buy any 2 category 50, get 1 from category 50 free
Setting the allowed_categories array is the same as using the exclude_category() function to narrow the products available for BOGO. The allowed_categories array is provided as a convenience to keep all the configuration information in the setup() function.

The allowed_categories array only takes parent categories.

This feature was added in version 1.3.

Grouped BOGO

By default, BOGO is offered on all categories, with counting performed as specified by the Discount Basis. But this doesn't meet the needs of all shops.

Suppose you want categories 19, 62 and 50 treated as a single category. Update the function setup() in includes/modules/order_total/ot_bogo_discount.php as follows:
   function  setup() {
      $this->set_cat_equivalent(19, 62, 50); // Group these categories 
   }
With "Buy this Many" set to 2 and "Get this Many" set to 1, and "Discount Basis" Same Parent Category, you have created the following discount:
  • Buy any 2 category 19, 62 or 50, get 1 from category 19, 62 or 50 free
This feature was added in version 1.3.

Here are some examples. Assume the configuration of the BOGO module is Buy 2, get 1 at 100% discount, with Discount Basis Same Parent Category.

Suppose the cart contains the following items:
Mouse - Parent Category 9, price $39.99
Keyboard - Parent category 8, price $69.99

Example 1:
Cart contains 2 Mouse, 1 Keyboard
No changes to setup() function.
Discount $0

Example 2: 
Cart contains 2 Mouse, 1 Keyboard 
setup() function contains $this->set_cat_equivalent(9, 8);
Discount $39.99

Combining Grouped And Limited BOGO

Update the function setup() in includes/modules/order_total/ot_bogo_discount.php as follows:
   function  setup() {
      $this->allowed_categories = [19, 62, 50, 12, 17]; // only allow BOGO on these categories
      $this->set_cat_equivalent(19, 62, 50); // Group these categories 
   }
With "Buy this Many" set to 2 and "Get this Many" set to 1, and "Discount Basis" Same Parent Category, you have created the following discounts:
  • Buy any 2 category 19, 62 or 50, get 1 from category 19, 62 or 50 free
  • Buy any 2 category 12, get 1 category 12 free
  • Buy any 2 category 17, get 1 category 17 free
  • All other categories not discounted.
What if you decide to also group category 12 and 17? Update the function setup() in includes/modules/order_total/ot_bogo_discount.php as follows:
   function  setup() {
      $this->allowed_categories = [19, 62, 50, 12, 17]; // only allow BOGO on these categories
      $this->set_cat_equivalent(19, 62, 50); // Group these categories 
      $this->set_cat_equivalent(12, 17); // Group these categories 
   }
With "Buy this Many" set to 2 and "Get this Many" set to 1, and "Discount Basis" Same Parent Category, you have created the following discounts:
  • Buy any 2 category 19, 62 or 50, get 1 from category 19, 62 or 50 free
  • Buy any 2 category 12 or 17, get 1 category 12 or 17 free
  • All other categories not discounted.

Notes on Taxes


If you don't use embedded taxes, and don't have a mix of taxable and tax-free products, and don't have a different rate of tax for shipping, please skip this section.
However, if you any of the above apply to you, please read my Notes on Taxes.

Be sure that the sort order for the Tax module (set in Admin->Modules->Order Total->Tax) is greater than the largest order total sort order, so that your taxes are shown after all discounts. 399 is a good value for most stores.


Files

(new) includes/languages/english/modules/order_total/ot_bogo_discount.php
(new) includes/modules/order_total/ot_bogo_discount.php

Major Versions

  • 1.3 07/01/2022 Added allowed_categories and set_cat_equivalent.
  • 1.2 12/21/2018 PHP 7
  • 1.1 03/04/2013 Fixed issue with multiple discounts; code inspection; checked for exclusions in marketing text
  • 1.0 09/01/2012 First Release

Bugs

  • For recalculate tax = Standard, carts using Edit Orders 4.3.1 will need to change the process() function in the code file in includes/modules/order_total as follows:
    Change
                   if ($this->calculate_tax != 'VAT') {
                      $order->info['total'] -= $od_amount[$key];
                   }
    
    to
                   if (!IS_ADMIN_FLAG) {
                      if ($this->calculate_tax != 'VAT') {
                         $order->info['total'] -= $od_amount[$key];
                      }
                   }
    
  • In version 1.0, for Discount Basis other than No Restriction, BOGO would stop after the first discount.
  • Users wishing to sort native discounts (such as Coupons or Group Discounts) after my discounts, with tax recalculation, should look at this page.

FAQ

Q: I have different levels and/or amounts for different categories. How can I handle this using BOGO Discount?
A: If you have multiple discounting schedules with different levels or amounts, you should look at Table Discounts.

Q: I'm using Discount Basis "Same Parent Category" or "Same Top Level Category" and it's not working!
A: Please see the Category Issues page for solutions.

Q: How do I install this software?
A: If you've never installed a Zen Cart mod before, please read my Guide to Mod Installation on Zen Cart.

Q: I can't seem to get BOGO Discount to work. What am I doing wrong?
A: Please check the following things:
  1. Go to Admin > Modules > Order Total. Do you see BOGO Discount? If not, then you haven't installed it. Follow the README.
  2. If you do see it, the circle at the right hand end of the row for BOGO Discount should be green. If it's not green, reinstall it.
  3. Click on BOGO Discount. The Discount Amount field is numeric. Do not use dollar or percent signs in this field.
  4. If you're using Discount Basis "Same Parent Category" or "Same Top Level Category," see the previous FAQ question.
  5. Re-read my Guide to Mod Installation on Zen Cart.

Q: How do I tell if my stock is organized into subcategories?
A: In the Admin page, go to Catalog > Categories/Products, and click on the category you're not sure about. If the entries that appear on the next page have file folders to the left of their names, then these are subcategories. If the products are directly below these folders, then these folders are the parent folder numbers you will use for category inclusions, exclusions and special discounts. If what is below these subcategories is more subcategories, continue drilling down until you get to products, and then go back one level. This is the "parent" category you will need to use.

Q: Why is there a BOGO Discount contribution in the first place?
A: Each of my discounting modules is different (sometimes in a subtle way), and meets a need that people in the Zen Cart community have expressed.
If you're not sure whether BOGO Discount is for you, take a look at the Zen Cart Matrix-o-discounts to see some example discounts that other people have created with my software.

Q:What does BOGO Discount do that is different from my other discounts?
A: A partial list is:

Other Software BOGO Discount
Better Together allows specific products or categories to be discounted. BOGO Discount discounts all items in the store using the rule you set up. (Exceptions can be made for items not to be discounted.)
Better Together and Combination Discounts must be configured for every product on which you want to offer quantity discounts. Big Chooser can do global discounts but must be configured in code. BOGO Discount applies to all products (except those you specifically exempt)
Big Chooser and Combination Discounts allow multiple rules for BOGO discounting based on product or category, but each rule must be specified in code. BOGO Discount has one global rule which is specified by an admin panel.
Better Together can only do "Buy 1, Get 1 at a Discount." BOGO Discount can do "Buy some-number, get some-number at a discount."
Changing behavior (from "Buy One Get One free" to "Buy Two, Get One Free") involves modifying core code Changing behavior involves changing admin panel parameters.


Q: I would like my discounts to show up in the shopping cart. Why don't they?
A: The way the Order Total modules work is that they show up at checkout time. However, if you require the discounts to show up in the shopping cart, you may wish to consider purchasing the Discount Preview module for $30.

Alternately, you can indicate that you have a discount policy by adding to TEXT_INFORMATION in includes/languages/english/shopping_cart.php, and inform the user that the discounts will be calculated (and visible) at checkout time. Additionally, changing SUB_TITLE_SUB_TOTAL in the same file to something like 'Sub-Total BEFORE Discount' will emphasize the fact that a discount will be added at checkout time.

Q: I only want discounts applied to items in category 11 and 12. How do I do this?
A: Update the function exclude_category() in includes/modules/order_total/ot_bogo_discount.php as follows:
    function exclude_category($category) {
        switch($category) {
           case 11:
           case 12:
                return false;
        }
        return true;
    }


Q: I don't want discounts applied to items in category 7 or 8. How do I do this?
A: Update the function exclude_category() in includes/modules/order_total/ot_bogo_discount.php as follows:
    function exclude_category($category) {
        switch($category) {
           case 7:
           case 8:
                return true;
        }
        return false;
    }


Q: I only want discounts applied to product numbers 17 and 19. How do I do this?
A: Update the function exclude_product() in includes/modules/order_total/ot_bogo_discount.php as follows:
    function exclude_product($prid) {
        $id = (int)$prid;
        switch($id) {
           case 17:
           case 19:
                return false;
        }
        return true;
    }


Q: I am discounting by parent category, and only want to do a limited number of categories, but want them all counted together. How do I do this?
A: See Grouped BOGO.

Q: I want discounts applied to all products except products 12 and 13. How do I do this?
A: Update the function exclude_product() in includes/modules/order_total/ot_bogo_discount.php as follows:
    function exclude_product($prid) {
        $id = (int)$prid;
        switch($id) {
           case 12:
           case 13:
                return true;
        }
        return false;
    }


Q: How can I present my discounting schedule on the product page?
A: Create your custom template if you haven't already done so. Then customize the file includes/templates/template_default/templates/tpl_product_info_display.php Look at the instructions in marketing.

Q: Can you explain how sales tax works?
A: Yes. See this page.
Q: If I use exclude_category() or exclude_product(), what changes do I need to make so the marketing text reflects this?
A: For category exclusions, change tpl_product_info_display.php from
  if ($discount->check() > 0) {

to
  if ( ($discount->check() > 0) &&
       (!$discount->exclude_category($current_category_id)) ) {
For product exclusions, use
  if ( ($discount->check() > 0) &&
       (!$discount->exclude_product($_GET['products_id'])) ) {
Another more detailed example is given here.

Extensions

The following BOGO Discount extension is available:


I charge $25 for the BOGO Discount Zen Cart. Buy BOGO Discount!
The fee covers software only; installation is extra if you require help.