combination

Zen Cart Combination Discounts (N-Way Better Together)

A Zen Cart™ order total module that allows you to discount groups of items when purchased together.

Background: See the Zen Cart Matrix-o-discounts

Relevance: Zen Cart™ 1.3.9, 1.5.x
This extension is part of the Zen Cart Combination Discounts World.

Current Version: 1.0.9
Occasionally, new features are documented prior to being publicly available; please check the version history to ensure the feature you want is available in your version.

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

Cost: $60 Buy Now! (Note: this low price covers software only for self-installation.)
Would you like to ask me questions before buying? No problem! Just email your inquiry to . Please be sure to include your cart type and version (e.g. Zen Cart 1.5.1) and the mod you want to buy.

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

Installation Difficulty: Moderate (You must write some PHP to configure this mod unless you purchase the Combination Discounts Admin panel)

Installation Instructions: click here

Common Installation Problems: click here

Tax Notes: Notes on tax handling

Buy: Buy Combination Discounts Now! Or email your pre-purchase question to .

FAQ: click here

Configuration: The basic configuration of Combination Discounts involves adding PHP code to the setup() function in the module, as shown below. For people who would prefer not to do this, a The Combination Discounts Admin panel is available. Many examples of basic configuration are shown in this help file; examples of advanced configuration are also available.

Marketing Text: click here

See it Live: Go to product 26 in my demo shop you will see the upsell message for products 25 and 27. (Going to products 25 or 27 will also produce a similar message.)

The code that created this Combination Discounts linkage was:
         $this->add_linkage(PROD,26,1,PROD,25,1,PROD,27,1,"$", 30);

This discount could also have been created using the Combination Discounts Admin Panel as shown in this video:



Promotional Page: free from my website (you must buy Combination Discounts separately)

Add-Ons:
Combination Discounts is the heart of Combination Discounts World. Be sure to look through the Combination Discounts World to see all the possible add ons for this module.

Combination Discounts is an order total module, so the discount is not visible until the second page of checkout. If you want to see the discount on the shopping cart page (or sidebox), look at Discount Preview.

If you don't want to have to update the setup() function manually, there is now an optional Combination Discounts Admin Panel which is sold separately.

If you try the "See it live" demo above, and you add any of the products used in the linkage to your cart, you will notice that on the shopping cart page (and the first checkout page) that Checkout Candy for Combination Discounts re-enforces the upselling message.

If you go to product 9 in my demo shop you will see it is linked to two other products using Combination Discounts, and there's a button that allows all three products to be purchased with a single click. This is generated by Buy The Set.

If you add all these products to your cart, you will be able to see the discount in your cart because of Discount Preview.

Here is a sample of the Combination Discounts promotional page, which is described in this page. You can even do a single-click add for multi-product discounts with no attributes on the Promotional Page using Add All to Cart.

The Combination Discounts Offers on Listing Pages extension displays the marketing text for your Combination Discounts offers on listing pages such as All Products, Search Results and Manufacturer Pages.

Bugs: click here

Overview:

The gold standard of online retailing is Amazon.com. Zen Cart store operators looking to increase their profitability should constantly be asking, "WWAD?" or "What would Amazon do?"

When you look at an item in Amazon, not only is a cross selling recommendation made, a discount is offered to persuade the customer to accept the recommendation. This mod permits you to offer this type of discounted cross selling in your Zen Cart.

Combination Discounts is based on my Better Together contribution. Better Together provides pairings - one item with another item, one category with another category, etc. I got a lot of positive feedback when Better Together was released, but people wanted more - a three-way (buy item 1 and 2, get a discount on item 3); a four-play (buy items 1, 2 and 3, get item 4 at a discount), and so forth. They also wanted more complex pairings, such as buy 2 of A, get a third one free, or buy 3 of A, get 2 of B free. So rather than add each permutation individually, I created Combination Discounts, that allows a much greater range of mixing and matching possibilities.

Combination Discounts uses the term "linkage" to describe the creation of an association between a group of items for the purposes of a discount. Items may be described in a variety of ways: by their item number, their category or their price.

Like Better Together in the early days, Combination Discounts requires you to add these linkages to the module itself - they are not configured through the admin panel (unless you have purchased the optional Combination Discounts Admin Panel). This sounds complicated, but it's not that bad, and many examples of common discounting practices are provided. Please note that Combination Discounts only provides a discount; it does not automatically add items to the cart. If you need to automatically add your discounted items to the cart, take a look at Auto Add. (Note that several restrictions apply to Auto Add; please read the documentation carefully.)

The calling conventions for building a linkage are that you specify one or more sets of

{indications of product, category or price, and product or category id or price, required item count}

followed by a discounted item in the same format and an indication of the discounting policy ($ or %, and an amount). The discounted item may specify a specific item count (e.g. 1 or 2), to indicate the discount may be taken on a specific number of items, or an unlimited item count ("*"), indicating that the discount may be taken an unlimited number of times.

Let's consider two products: product 5 from category 3, and product 2 from category 1.

In Combination Discounts, saying "Buy product 2, get product 5 at 50% off," would be
   $this->add_linkage(PROD,2,1,PROD,5,1,"%",50); 

Remember product 5 is in category 3. If instead of specifying product 5 in particular, you want to discount any item in category 3 by 20% with the purchase of a product 2 item, you would use
   $this->add_linkage(PROD,2,1,CAT,3,1,"%", 20); 

Discount can be done in currencies as well. To offer $7 (or 7 of whatever currency your cart uses), instead of 20% off, use
   $this->add_linkage(PROD,2,1,CAT,3,1,"$", 7); 

(The "$" is just used to specify currency; your cart's currency settings will be respected when computing the discount.)

Remember product 2 is in category 1. If you want to widen the discount to provide a discount of 20% off any item in category 3 when an item from category 1 is purchased, use
   $this->add_linkage(CAT,1,1,CAT,3,1,"%", 20); 

But these are simple pairings, all of which are possible with the original Better Together. The true power of Combination Discounts becomes obvious when you increase the complexity of the linkages. None of the following discounts would be possible with the original:

"Buy 2 of product 2, get one product 5 at 50% off,"
   $this->add_linkage(PROD,2,2,PROD,5,1,"%",50); 


"Buy product 2 and product 3 get one product 5 at 50% off,"
   $this->add_linkage(PROD,2,1,PROD,3,1,PROD,5,1,"%",50); 


"Buy product 2, product 3 and product 4, get product 5 at 50% off,"
   $this->add_linkage(PROD,2,1,PROD,3,1,PROD,4,1,PROD,5,1,"%",50); 


"Buy product 2, product 3 and product 4, get up to 3 product 5 at $10 off each,"
   $this->add_linkage(PROD,2,1,PROD,3,1,PROD,4,1,PROD,5,3,"$",10); 



"Buy product 2, product 3 and product 4, get as many of product 5 as you want at $10 off each,"
   $this->add_linkage(PROD,2,1,PROD,3,1,PROD,4,1,PROD,5,"*","$",10); 

Note that the asterisk must be in quotes!

New in Combination Discount 1.03 - product identification by price:

"Buy two $10 products, get a third free"
   $this->add_linkage(PRICE,10,2,PRICE,10,1,"%",100); 


"Buy an item from category 15, get two $10 items free"
   $this->add_linkage(CAT,15,1,PRICE,10,2,"%",100); 


"Items are $8.99 each or 3 for $25.00"
   $this->add_linkage(PRICE,8.99,2,PRICE,8.99,1,"$",1.97); 


These linkages are not only used in discount calculations; they are also used to create messages which are automatically displayed on the product_info page. Details on how to do this are provided in marketing.

Combination Discounts is an order total module, so it appears on the second page of your checkout as a discount (unless Discount Preview is used, which allows the discount to be shown in the cart).

Payment Page displaying Combination Discount

Payment page showing Combination Discount

Detailed Description:

Linkages are specified in the setup() method at the bottom of the class. You must modify the file includes/modules/order_total/ot_combination_discounts.php to set up your discount combinations.

If you don't want to have to update the setup() function manually, there is now an optional Combination Discounts Admin Panel, which is sold separately. However, for the remainder of this help file, I will assume you are updating the setup function manually.

Any number of these discounts may be offered; discount computation will be done in the order in which your discounts are specified in setup(). The cart is then sorted by price in descending order. The cart is traversed in this order to determine if a discount threshold has been crossed; once it has, the cart is traversed in the reverse order to determine which item will be discounted. In this way, the least expensive qualifying item is discounted.

Using the examples above, suppose these items are in your cart:

1 - Product 2, category 1
2 - Product 10, category 1
2 - Product 20, category 3
2 - Product 5, category 3

and suppose you have coded these discounts:
   $this->add_linkage(PROD,2,1,PROD,5,1,"$", 7); 
   $this->add_linkage(CAT,1,1,CAT,3,1,"%", 25); 

The following discounts will be computed:
  • $7 off ONE product 5 because of ONE product 2 (rule 1)
  • 25% each off TWO product 20 because of TWO product 10 (rule 2)
To get $7 off the second product 5, the customer would need to add a second product 2 to the cart.

With the same cart, coding
   $this->add_linkage(CAT,1,1,CAT,3,1,"%", 25); 
   $this->add_linkage(PROD,2,1,PROD,5,1,"$", 7); 

Would compute the following discount:
  • 25% off ONE product 20 because of ONE product 2 (rule 1)
  • 25% off ONE product 20 because of ONE product 10 (rule 1)
  • 25% off ONE product 5 because of ONE product 10 (rule 1)
Obviously these could be very different discounts!

To create a two for one discount for product 5, simply code
         $this->add_linkage(PROD,5,1,PROD,5,1,"%",100);

And to create two for one discount for all products in category 3, code
         $this->add_linkage(CAT,3,1,CAT,3,1,"%",100);


To make these discounts visible on your product info page, customize the file includes/templates/template_default/templates/tpl_product_info_display.php as described in marketing below in the installation instructions. This step will create text like this:

Buy 1 Microsoft Intellimouse Explorer, get a Microsoft Keyboard at 50% off

The link is created to facilitate the cross-sell. This step is optional; if you prefer, you can add your own cross-selling text.

Category Handling

Note that CAT has different semantics in Combination Discounts as compared to Better Together. In Better Together, CAT only includes items directly below the specified category (i.e. CAT means "parent category" based on the master_categories_id field in the products table). In Combination Discounts, CAT includes all items below the specified category, whether they are directly below or in subcategories.

Men's Clothing (category 3)
     |
     ---->  Shirts (category 5)
     |      |
     |      -------> shirt A 
     |               shirt B
     |               shirt C 
     ---->  Pants (category 6)
     |      |
     |      -------> pants A 
     |               pants B
     |               pants C 
     ---->  Shoes (category 7) 
            |
            --->  Dress Shoes (category 12) 
            |     |
            |     -------> dress shoes A 
            |              dress shoes B
            |              dress shoes C 
            --->  Casual Shoes (category 18) 
                  |
                  -------> casual shoes A 
                           casual shoes B
                           casual shoes C 

Specifying "Men's Clothing" (CAT 3) as a category in Combination Discounts will include all items in Shirts, Pants and Shoes. This cannot be done in Better Together.

Specifying "Shoes" (CAT 7) as a category will include both dress shoes and casual shoes. This cannot be done in Better Together.

Note that "parent category id" is determined using the master_categories_id field from the products table. So if casual shoes A is also linked into a category called "Hot Products," the parent category is still category 18 (Casual Shoes). For more details on category handling in Combination Discounts, please see the Category Issues page.

How Discounts are Selected

Combination Discounts sorts items by price in descending order, then looks for the condition (the first part of the linkage) from the top going down. Once it has found a match, it looks for the discount (the last part of the linkage) from the bottom going up. So if the following items are in your cart,
Product ID Category ID Price
112$4.00
518$20.00
712$5.00
912$10.00

Combination Discounts sorts them by price like this:
Product ID Category ID Price
518$20.00
912$10.00
712$5.00
112$4.00

It then matches conditions from most expensive items to least (top down), and matches discounts from least expensive items to most (bottom up).
If your discount is
   function setup() { 
      $this->add_linkage(CAT,12,1,CAT,12,1, "%", 100); 
   }
then this means that product 9 will be the condition, and product 1 will be the item which is discounted 100%.

But if your discount is
   function setup() { 
      $this->add_linkage(CAT,12,1,CAT,18,1, "%", 100); 
   }
then this means that product 9 will be the condition, and product 5 will be the item which is discounted 100%. Since product 5 is more expensive than product 9, this may not be what you want.

As items are used as conditions and discounted items, they are no longer available for subsequent use as conditions or discounted items. So if your cart contents are this:
Quantity Product ID Price
15$20.00
28$10.00
112$10.00
and your discount is
   function setup() { 
     $this->add_linkage(PROD, 5, 1, PROD, 8, 1, "%", 100); 
   }
you will only get one of product 8 for free. The second product 8 has no matching pair of product 5. If you need to ensure that the item which is discounted is less than or equal in price to the condition, you have the following options:
  • Use the same category id in your CAT based discounts. If the condition(s) and the discount have the same category, then the price based sorting that Combination Discounts does will ensure the lower priced item will be discounted.
  • Select high value categories (with only high priced items) as your condition category/categories, and lower value categories (with lower priced items) as your discount category.
  • Use Big Chooser, which allows you to enforce this condition on any discount using the condition_price_gte command.

Installation Instructions:

  1. Back up everything! Try this in a test environment prior to installing it on a live shop.
  2. Copy the contents of the unzipped folder to the root directory of your shop.
    The names of these files reflect a template name of "custom." If you are using a different template name, please change file paths using "custom" to use your template name instead.
  3. Login to admin and in Modules->Order Total you will see 'Combination Discounts' listed along with all the other modules available.
  4. Click on 'Combination Discounts' to highlight the module and click on 'Install'
  5. Decide on the discounts you wish to use. The easiest way to do this is to open a shopping cart in another window, and just start adding discounts to the setup() method of includes/modules/order_total/ot_combination_discounts.php. The discounts are shown on the second step of checkout in "Your Total" under "Combination Discounts."
  6. If you wish, follow the guidelines in marketing to advertise your discounts.


Installation Problems:

The most common installation problems for this module are as follows:
  1. For Combination Discounts Admin Panel users: Forgetting to modify includes/modules/order_total/ot_combination_discounts.php as described in the Combination Discounts Admin Panel instructions.
  2. Using CAT may not work the way you think it does - see the Category Issues page.
  3. Some people try deleting the setup function and wind up deleting the final brace in the file, which causes a blank page on checkout. The bottom of the file includes/modules/order_total/ot_combination_discounts.php should look like this:
       function setup() { 
          .. some statements here ....
       }
    }
    ?>
    
    The final brace must not be deleted.
  4. Got a blank page? Review the guidelines for Debugging a blank page in Zen Cart
If you are having trouble installing this module, you should also refer to my Guide to Mod Installation on Zen Cart. I'm also happy to install most of my mods for a fee.

Marketing

What good is having cross selling and upselling specials if you don't advertise them?

Combination Discounts may be automatically displayed in two places: on the product info page, and on a separate promotional page. We'll talk about the product info page first.

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 modify tpl_product_info_display.php in its new location and add this block of code:
<?php 
require($template->get_template_dir('/tpl_combination_discounts_marketing.php',DIR_WS_TEMPLATE, 
   $current_page_base,'templates'). '/tpl_combination_discounts_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 link on your page that looks something like this:

Buy 1 Microsoft Intellimouse Explorer, get a Microsoft Keyboard at 50% off


One or two div blocks of text will be produced depending on whether or not the item is the last second parameter in a linkage. For instance, if
      $this->add_linkage(PROD,8,1,PROD,12,1, "%", 100);
      $this->add_linkage(PROD,12,1,PROD,17,1, "%", 100);
is used, then the product info page for products 8 will have one block of text with the div id combinationDiscountPolicy which will say

"Buy 1 name-of-product-8, get a name-of-product-12 free".

Product 12 will have a block of text with div id combinationDiscountPolicy which will say

"Buy 1 name-of-product-12, get a name-of-product-17 free"
"Buy 1 name-of-product-8, get a name-of-product-12 free"

Because it is a div block with its own id, styling it (changing font, color, etc.) is simply a matter of adding to your stylesheet

#combinationDiscountPolicy {
   font-size: 200%;
   color: #ff0000;
}
This would give you

Buy 1 name-of-product-8, get a name-of-product-12 free

Probably a bit more obnoxious than you would truly want, but you get the idea.

Alternately, you could modify the marketing text template (tpl_combination_discounts_marketing.php) and put the text into a fieldset:

 Combination Discounts 


If all products do not have attributes, and you want to offer a one click buying opportunity, you may wish to upgrade to Buy The Set. You will see the marketing text appear like this:

Buy Both Now

Buy The Set

Buy The Set is sold separately from Combination Discounts; it's a paid add-on.

There are also marketing opportunities on the Shopping Cart page; the Checkout Candy for Combination Discounts module can be configured to show available Combination Discounts discounts both on the Shopping Cart page and on the first page of checkout.

The other available marketing vehicle is the Combination Discounts promotional page. This page is completely optional; it is not included in the Combination Discounts zip file, but it is a free download from my website. It creates a page that looks like this, displaying all discounts.

If you are using linkages based on price with products which use attributes with prices, you must hard code your marketing message for these products; this marketing text will not work. The reason is that on the product info page, full price of the product (with attributes) has not yet been worked out.

The Combination Discounts Offers on Listing Pages extension displays the marketing text for your Combination Discounts offers on listing pages such as All Products, Search Results and Manufacturer Pages.

Category Listing Page - Combination Discounts Offers

Combination Discounts Offers on Category Listing Page


Combination Discounts and Discount Preview

Discount Preview makes Combination Discounts 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 Combination Discounts.

Zen Cart Combination Discounts and Discount Preview

Discount Preview is sold separately. Buy Discount Preview Now!

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.

Files

(new)  includes/languages/english/modules/order_total/ot_combination_discounts.php
(new)  includes/modules/order_total/ot_combination_discounts.php
(new)  includes/templates/custom/templates/tpl_combination_discounts_marketing.php


Formal Syntax of Linkages

Linkages, which are specified in the setup() function of ot_combination_discounts.php, are the mechanism for configuring a store's discounts.

Standard Linkages

The simplest and most common linkage (Standard) is one or more products or categories linked to a product or category discount.

$this->add_linkage(<purchase 1>[,<purchase 2>,...<purchase n>],<discounted purchase>,<"%"|"$">,<amount>);


where:
purchaseis the string PROD, CAT, or PRICE followed by an identifier (product or category id, or product price), followed by a count

<PROD | CAT | PRICE> <product or category identifier or price> <item count>
discounted purchaseuses the same format as purchase
"%" | "$"is an indication that the discount is specified in percentage or currency units
amountis the percent discount (or currency unit discount) to be applied


So for example, the call
   $this->add_linkage(PROD,2,1,PRICE,12.99,1,CAT,3,1,"%", 25); 
is read, "buy product 2 and any item for $12.99, and get one item from category 3 at 25% off."

Major Versions

  • 1.0.9 02/12/2012 - Fix for Buy The Set (others don't need this change)
  • 1.0.8 05/10/2010 - Some PHP5's didn't handle quantities correctly
  • 1.0.7.2 12/03/2009 - Added VAT setting for taxes
  • 1.0.7.1 02/14/2009 - Error in PRICE marketing text
  • 1.0.7 12/14/2007 - 1.3.8 Compatibility
  • 1.0.6 10/17/2007 - Error in reverse discounting text
  • 1.0.5 09/26/2007 - Bad error handler
  • 1.0.4a 09/18/2007 - Google Checkout fix
  • 1.0.4 08/22/2007 - Add any level of category matching; consolidate marketing text to a single div (and only display if appropriate).
  • 1.0.3 07/24/2007 - Add "by price" linkages, put marketing code in a file.
  • 1.0.2 05/31/2007 - Enabling "get lowest price item" type discounts.
  • 1.0.1 05/06/2007 - Integration with Checkout Candy
  • 1.0 04/07/2007 - First Created.

Bugs

  • Users wishing to sort native discounts (such as Coupons or Group Discounts) after my discounts, with tax recalculation, should look at this page.
  • Older versions of Combination Discounts (prior to 1.0.7) require a patch to run under Zen Cart 1.3.8. Take this function and paste it right above the function calculate_deductions() in the file in includes/modules/order_total/ot_combination_discounts.php. The latest versions (1.0.7 and above) include this patch, but if you haven't upgraded, you must manually apply the patch.

FAQ

Q: Why is there an Combination Discounts in the first place?
A: To better facilitate cross selling and upselling. It builds on the success and popularity of the original Better Together.

Q: Why is Better Together free, but Combination Discounts isn't?
A: Because like you, I'm in business to make money.

Q: I'm using a category linkage, and it's not working!
A: This is the most common question of all. Please see the Category Issues page for solutions.


Q: Can I start and stop my Combination Discounts on certain dates in the future?
A: The Combination Discounts Admin panel allows you to set start and end dates for your discounts. Alternately, see Timing Discounts in Zen Cart for an explanation of how to hardcode a date range.

Q: Can I convert my Better Together discounts to use Combination Discounts?
A: Yes. The discount "buy X and get Y at $Z off", which is expressed in Better Together as
$this->add_prod_to_prod(X,Y,"$", Z); 
is expressed in Combination Discounts as
$this->add_linkage(PROD, X, 1, PROD, Y, 1, "$", Z);

Other discounts can be handled similarly.

Q: I like some of the features of Better Together, such as two-for-one discounts on identical items in a category, but I also want to use Combination Discounts. Can I use both?
A: Yes. Combination Discounts was designed to be interoperable with Better Together. But be aware that certain combinations of configurations in the two models may lead to double discounting; always test before deploying.

Q: I like Combination Discounts, but I want to build more complex deals; can it be extended?
A: The syntax of Combination Discounts makes it hard to create more complex deals; for this reason, I created Big Chooser. Here's a comparison.

Q: Why do you have to add PHP code to setup()? Why didn't you put this in the Admin panel?
A: The optional Combination Discounts Admin Panel is now available if you would prefer not to manually add discounts. It is sold separately.

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 show your support for Combination Discounts by purchasing the Discount Preview module for $30.

Alternately, you may indicate that you have a Combination Discounts discount policy by adding to TEXT_INFORMATION in includes/languages/english/shopping_cart.php, and inform the user that Combination Discounts 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: How can I present my Combination Discounts discounts 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 . Follow the directions in marketing in the installation instructions for details on the changes that are required.

Q: OK, I have the Combination Discounts information on my product page, but my customers can't figure out that the discount isn't visible until checkout time
A: Add some explanatory text to the discountPolicy information you created above. This way it will show up every time there is Combination Discounts information on a page. Alternately, you may purchase the Discount Preview module, or you may also add text to the shopping cart page to indicate that Combination Discounts discounts will show up at checkout time as discussed above.

Q: OK, I have Combination Discounts specials, but my customers aren't biting. How can I re-enforce the promotion?
A: My Checkout Candy for Combination Discounts module can be configured to show available Combination Discounts discounts both on the Shopping Cart page and on the first page of checkout.

Q: What would my setup() look like if I wanted to give 2 for 1 on all items in category 4?
A: This provides a two for one discount, allowing you to mix and match items from category 4:
  function setup() { 
      $this->add_linkage(CAT,4,1,CAT,4,1,"%",100); 
  }


Q: What would my setup() look like if I wanted to give 2 for 1 on all items 5, 8, and 12? What about buy one get one half off?
A: Here's what you would do for 2 for 1:
  function setup() { 
      $this->add_linkage(PROD,5,1,PROD,5,1,"%",100); 
      $this->add_linkage(PROD,8,1,PROD,8,1,"%",100); 
      $this->add_linkage(PROD,12,1,PROD,12,1,"%",100); 
  }
Here's buy one get one half off:
  function setup() { 
      $this->add_linkage(PROD,5,1,PROD,5,1,"%",50); 
      $this->add_linkage(PROD,8,1,PROD,8,1,"%",50); 
      $this->add_linkage(PROD,12,1,PROD,12,1,"%",50); 
  }


As in the previous question, mixing and matching is allowed with these discounts - but since these are specific products, what are the semantics of "mixing and matching?"

Well, for add_prod_to_prod() and add_twoforone_prod(), mixing and matching means "having different attributes."

Q: What would my setup() look like if I wanted to do buy one of item 5, get one from category 2, 7 or 9 at $5 off?
A: Here's what you would do:
  function setup() { 
      $this->add_linkage(PROD,5,1,CAT,2,1,"$",5); 
      $this->add_linkage(PROD,5,1,CAT,7,1,"$",5); 
      $this->add_linkage(PROD,5,1,CAT,9,1,"$",5); 
  }

Q: Can I do three for the price of two? Four for the price of three?
A: Yes. Three for the price of two on product 5 would be
   $this->add_linkage(PROD,5,2,PROD,5,1,"%",100); 
Four for the price of three for product 12 would be
   $this->add_linkage(PROD,12,3,PROD,12,1,"%",100); 


Q: I have a lot of products priced at $24.99. Can I offer buy three get one free?
A: Yes. Buy three get one free for $24.99 products would be
   $this->add_linkage(PRICE,24.99,3,PRICE,24.99,1,"%",100); 


Q: My marketing text generally works properly except that I have a price based linkage (like the one above) on a product with attributes which have prices, and it doesn't work there. Why?
A: If you are using linkages based on price with products which use attributes which have prices (whether or not the product is priced by attributes), you must hard code your marketing message for these products; this marketing text will not work.

Customizations

The following Combination Discounts customizations are available: I charge a fee for each of these customizations. Contact me for details.

I charge a fee of $60 for Combination Discounts. Buy Combination Discounts Now.
The fee covers software only; installation is extra if you require help.