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

osCommerce Better Together

Better Together for osCommerce

An osCommerce ™ discounting module allowing vendors to create "buy one, get one" style discounts.

Important Version Information: This product is for osCommerce Phoenix only. If you are looking for osCommerce 2.2, 2.3 or 3.0, please see the link in the Relevance section below.

Donate: This is free software. Show your appreciation by supporting my efforts. Donate

Background: See the osCommerce Matrix-o-discounts

Relevance: osCommerce™ Phoenix only.

If you are looking for osCommerce 2.2, 2.3 or 3.0, please see the Legacy Better Together page.

Cost: Free, but donation appreciated

Location: osCommerce Community Add-Ons page, under Order Total Modules

osCommerce Phoenix Download:
Better Together for osCommerce Phoenix

Installation for osCommerce Phoenix: click here

Payment Gateway Integration Note that some payment modules, including PayPal, do not natively work with Order Total discounts (mine or anyone else's). See Payment Modules below.

Installed Cost: $90.00 Buy Professional Installation by That Software Guy. Note that this does not include payment gateway integration - see above.

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

Promotional Page Download:
The Better Together Promotional Page allows you to easily display your discounts. It's free!

Current Version: 1.2
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.

osCommerce Phoenix Support Thread:
Better Together for osCommerce Support Thread

FAQ: click here

Configuration: The basic configuration of Better Together involves adding PHP code to the setup() function in the module, as shown below. For people who would prefer not to do this, a Better Together Admin panel is available.

Marketing Text for osCommerce Phoenix: click here

See it Live: You can watch a discount get created in this video:



If you don't like the idea of editing files, you can also configure Better Together using the Better Together Admin panel.

Here's a video showing discounts getting created with Better Together Admin:



Add-Ons:
Like Better Together? Take a look at Discount Preview .

Overview:

The gold standard of online retailing is Amazon.com. osCommerce 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 osCommerce.

You may specify
  • Buy item X, get item Y at a discount
  • Buy item X, get an item from category A at a discount
  • Buy an item from category A, get an item from category B at a discount
  • Buy an item from category A, get item X at a discount

Discounts may be specified as percentages of the latter item's price or as absolute values in the currency your cart uses.

These discount specifications are called "linkages," because they "link" one product or category to another. 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.

In addition, Better Together may be used to facilitate two-for-one offers for identical items. Although it may be argued that this is simply a special case of "buy item X, get item Y at a discount," this capability was added to facilitate two for one offers for an entire category of goods with a single statement. You may specify two-for-one type specials such as
  • Buy item X, get another item X free
  • Buy an item from category A, another identical item free
Better Together is an order total module, so in osCommerce Phoenix, it appears on the Order Confirmation page of your checkout as a discount, (unless Discount Preview is used, which allows the discount to be shown in the cart).

Please note that Better Together only provides a discount; it does not automatically add items to the cart.

Order Confirmation Page displaying Better Together Discount

osCommerce Order Confirmation Page showing Better Together discount

Detailed Description:

Better Together is configured by modifying the setup() function at the bottom of the file includes/modules/order_total/ot_better_together.php
This still works, but now another available option is the Better Together Admin panel (a separate module which is sold commercially). Better Together Admin is easy to use and fast - and it's a great way to show your support for Better Together.



If you wish to continue editing the setup function, several examples are provided.
Four types of linkages may be performed. The format of each of these is the same:
  • first identifier (product or category)
  • second identifier (product or category)
  • "%" or "$" to indicate how discounting is to be done
  • a number, indicating the discount amount.
The four calls for the four types of discounting are
  • add_prod_to_prod()
  • add_prod_to_cat()
  • add_cat_to_cat()
  • add_cat_to_prod()
If a straight two for one discount is what is desired, the calls are
  • add_twoforone_prod()
  • add_twoforone_cat()
Let's consider two products: product 5 from category 3, and product 2 from category 1.

Suppose you want to offer a 50% discount on product 5 with the purchase of product 2. Make the setup() function look like this:
   function setup() { 
      $this->add_prod_to_prod(2,5,"%", 50); 
   }

Want to make it buy product 2, get product 5 free?
   function setup() { 
      $this->add_prod_to_prod(2,5,"%", 100); 
   }

How about buy one product 2, get one free?
   function setup() { 
      $this->add_prod_to_prod(2,2,"%", 100); 
   }

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, use
   function setup() { 
      $this->add_prod_to_cat(2,3,"%", 20); 
   }

Discount can be done in currencies as well. To offer $7 (or 7 of whatever currency your cart uses), use
   function setup() { 
      $this->add_prod_to_cat(2,3,"$", 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
   function setup() { 
      $this->add_cat_to_cat(1,3,"%", 20); 
   }

Any number of these discounts may be offered; discount computation will be done in the order in which your discounts are specified in setup(), and items will be processed in the order in which they appear in the cart.

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:
   function setup() { 
      $this->add_prod_to_prod(2,5,"$", 7); 
      $this->add_cat_to_cat(1,3,"%", 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
   function setup() { 
      $this->add_cat_to_cat(1,3,"%", 25); 
      $this->add_prod_to_prod(2,5,"$", 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
   function setup() { 
      $this->add_twoforone_prod(5);
   }
And to create two for one discount for all products in category 3, code
   function setup() { 
      $this->add_twoforone_cat(3);
   }


Note the difference between
   function setup() { 
      $this->add_twoforone_cat(3);
   }
and
   function setup() { 
      $this->add_cat_to_cat(3,3,"%", 100); 
   }
The latter says, "buy any item from category three, and get 100% off any other item from category three." The former says, "all items in category three are buy one, get an identical item free." So if a customer bought items 20 and 30 from category three, a discount would only be given in the latter case.

To make these discounts visible on your product info page, follow the direction in marketing below. This step will create text like this:

Buy this item, get a Microsoft Intellimouse Explorer at 50% off
Buy this item, get an item from Memory 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 in osCommerce (all versions)

The "category" in add_cat_to_cat(), add_prod_to_cat() add_cat_to_prod() and add_twoforone_cat() may be any of the product's parent categories.

Men's Clothing 
     |
     ---->  Dress Shirts
            |
            -------> shirt A     
                     shirt D
     ... 
     ---->  Shirts
            |
            -------> shirt A     
                     shirt B
                     shirt C 
                     shirt D 

In this example, the parent categories of "shirt A" are "Shirts" and "Dress Shirts" (note that "Men's Clothing" is not considered a parent category).


How Discounts are Selected

Better Together 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 second 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

Better Together 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_cat_to_cat(12,12,"%", 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_cat_to_cat(12,18,"%", 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 in linkages, they are no longer available for subsequent in linkages. 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_prod_to_prod(5,8,"%", 100); 
   }
you will only get one of product 8 for free. The second product 8 has no matching 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 add_cat_to_cat discounts. If the condition and the discount have the same category, then the price based sorting that Better Together does will ensure the lower priced item will be discounted.
  • Select high value categories (with only high priced items) as your first (condition) category, and lower value categories (with lower priced items) as your second (discount) category.
  • Use Big Chooser, which allows you to enforce this condition on any discount using the condition_price_gte command.


Installation Instructions for osCommerce Phoenix:

These installation instruction are for osCommerce Phoenix.
  1. Back up everything! Try this in a test environment prior to installing it on a live shop.
  2. If you already have the Better Together module installed, please deinstall your old copy by going to Admin > Modules > Order Total, selecting "Better Together" and pressing the "Remove" button. Make a note of your settings so you can apply them to the new version. Copy the contents of the unzipped folder to the root directory of your shop.
  3. Copy the contents of the unzipped folder to the root directory of your shop.
  4. Login to admin and go to Modules > Order Total. Click on the "Install Module" button on the upper right. Select the row that says "Better Together." Press the "Install Module" button on the right hand side of the screen.
  5. Ensure that the sort order that you have selected for Better Together is not already used by another module. If necessary, change the sort orders of other modules to ensure that Better Together displays where you want it, with a unique sort order. Also, if you are using Re-calculate Tax = Standard, be sure the Tax sort order is larger than the Better Together sort order.
  6. Decide on the linkages you wish to use, and add them to the setup() function in catalog/includes/modules/order_total/ot_better_together.php Open a shopping cart in another window to test these discounts. They are shown on the Order Confirmation page of checkout.
  7. Displaying Product and Category IDs: For products, open the catalog, drill down to the category the product is in, and hover over the image for the product. You'll see a link in your browser's status bar that looks like:
    catalog/product_info.php?products_id=27
    
    This means the product id is 27. For categories, drill down to the category or look at the categories sidebox, and hover over the category name of interest. You will see a link in the browser's status bar that will look like:
    index.php?cPath=3_11
    
    This means the category id is 11.
  8. If you wish, follow the guidelines in marketing
  9. Test a transaction and ensure the discount goes all the way through. For PayPal and some other payment methods, you may need to make additional changes, as outlined below in Payment Modules in osCommerce.
  10. Donate! Show your appreciation by supporting my efforts.


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.



Notes on Taxes for osCommerce 2.3


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.




Payment Modules in osCommerce Phoenix

Some contributed payment modules in osCommerce Phoenix are not naturally aware of the existence of discounts (mine or any other contribution or extension). For this reason, you must ensure any payment module you use takes discounts into account.

For some carts, PayPal Website Payments Standard has been changed to accommodate these osC discounts, but in a bizarre way. If you have
Subtotal: $30
Postage: $7.69
Discount: -$12.00
Tax (7%): $1.26
-----------------------------
Total:   $26.95
PayPal turns this into
Subtotal: $17.16
Tax (7%): $2.10
Shipping: $7.69
-----------------------------
Total:   $26.95
The final number is correct (and your actual order total figures as shown in osC admin will be correct per the checkout confirmation page).

I have seen this work on some carts and not on others depending on mods and settings; please test your own cart carefully.

PayPal Express in osCommerce Phoenix still has problems with osCommerce discounts. Here is one way to fix it:

In ./ext/modules/payment/paypal/express.php, right above the block on line 544-545 that sets the item and tax amounts:
      $params['ITEMAMT'] = $items_total;
      $params['TAXAMT'] = $tax_total;
insert the discount computation. Here's an example for Quantity Discounts. Pull in the module and its language file. Then compute the discount and add it in as a line item.
      // Add OT
      require('includes/modules/order_total/ot_quantity_discount.php');
      include(DIR_WS_LANGUAGES . $language . '/modules/order_total/ot_quantity_discount.php');
      $discount = new ot_quantity_discount();
      if ($discount->check()) {
         $qd = $discount->calculate_deductions();
         if ($qd['total'] > 0) {
            $amt = $qd['total'] * -1;
            $params['L_NAME' . $line_item_no] = 'Discount';
            $params['L_AMT' . $line_item_no] = $amt;
            $params['L_NUMBER' . $line_item_no] = 0;
            $params['L_QTY' . $line_item_no] = 1;
    
            $product_tax = 0; 
            $params['L_TAXAMT' . $line_item_no] = $paypal_express->format_raw($product_tax);
            $items_total += $paypal_express->format_raw($amt);
            $line_item_no++;
         }
      }

For other modules, here are the filenames. The object to be created is the filename without the .php suffix.
ModuleFile Name
Quantity Discountsot_quantity_discount.php
Better Togetherot_better_together.php
Discount Chooserot_freegift_chooser.php



Installation Problems:

The most common installation problems for this module are as follows:
  1. In osCommerce, you must be very careful not to duplicate sort orders in Order Total modules. Check the sort order you have used for Better Together (in Admin > Modules > Order Total), and make sure it's not being used by another Order Total module. If it is, modify the sort orders so they are all unique. Also, if you are using Re-calculate Tax = Standard, be sure the Tax sort order is larger than the Better Together sort order.
  2. Not donating often causes problems. Donate! Show your appreciation by supporting my efforts.

If you are having trouble installing this module, you should also refer to my Guide to Mod Installation on osCommerce. I'm also happy to install most of my mods for a fee.


Marketing

osCommerce Phoenix Marketing Text for Better Together

Donate! Show your appreciation by supporting my efforts.

What good is having cross selling and upselling specials if you don't advertise them? To show your Better Together discounts on the product info page, add the Content Module for Better Together Marketing.

Go to Admin > Modules > Content, and Click Install Module. Select Better Together Marketing Text, and press Install Module.

The marketing text will appear like this on your product info page:

Buy this item, get a Microsoft Intellimouse Explorer at 50% off





osCommerce Phoenix Files

./catalog/includes/languages/english/modules/content/product_info/cm_pi_swguy_bt_marketing.php ./catalog/includes/languages/english/modules/order_total/ot_better_together.php ./catalog/includes/modules/order_total/ot_better_together.php ./catalog/includes/modules/content/product_info/templates/tpl_cm_pi_swguy_bt_marketing.php ./catalog/includes/modules/content/product_info/cm_pi_swguy_bt_marketing.php


Major Versions

  • 1.2 08/19/2019 - Added Marketing Text.
  • 1.1 08/04/2019 - Updated for osC Phoenix.

FAQ

Q: How do I install this software?
A: Installation instructions for osCommerce Phoenix are here. If you've never installed an osCommerce mod before, please read my Guide to Mod Installation on osCommerce.

Q: How do I set up Better Together discounts?
A: Decide on the linkages you wish to use, and add them to the setup() function in catalog/includes/modules/order_total/ot_better_together.php ("Linkages" are what "add_prod_to_prod," etc. are called.) Don't want to edit code? Get the Better Together Admin panel.

Q: Can I start and stop my Better Together discounts on certain dates in the future?
A: Please see Timing Discounts in osCommerce for an explanation of how to do this.

Q: How do I determine what the category id is?
A: In Admin > Catalog, single click on the category you're interested in. In the address bar of your browser, you will see something like
categories.php?cPath=3&cID=11
If you were to double click on it, you'd see something like
categories.php?cPath=3_11
The category you want to use is "11".

In the same way, in the catalog you can hover over this category in the categories sidebox and see
catalog/index.php?cPath=3_11
This re-confirms that the category is "11."

Q: I am using the CCGV (Coupon Code/Gift Voucher) Contribution. On the Checkout Payment Page, I get the error:
"Fatal error: Call to undefined method ot_better_together::use_credit_amount() in 
  ......../httpdocs/includes/classes/order_total.php on line nnn"
A: Make the following fix to the file includes/classes/order_total.php
Change
          if ($GLOBALS[$class]->enabled && $GLOBALS[$class]->credit_class) 
to
          if ($GLOBALS[$class]->enabled && $GLOBALS[$class]->credit_class 
            && (method_exists($GLOBALS[$class], 'use_credit_amount'))) 
The location of this line will depend on how many changes you've made to the file order_total.php.


Q: Can I start and stop my Better Together discounts on certain dates?
A: Please see the Timing Discounts for an explanation of how to do this.

Q: Why do you have to add PHP code to setup()? Why didn't you put this in the Admin panel?
A: When I created Better Together, I wanted it to be as flexible as possible, and I focused on functionality, not ease of use. Over time, the demand grew for an admin panel, and when the project got funded, I did it.

Creating the Better Together Admin panel was a significant amount of work and represents my main revenue stream for Better Together (the support for which consumes hours of my time every week); please show your support for my software by purchasing it.

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 Better Together by purchasing the Discount Preview module.

Q: How can I present my Better Together discounts on the product page?
A: Follow the directions in marketing in the installation instructions for details on the changes that are required.

Q: OK, I have the Better Together 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 discount policy information you created above. This way it will show up every time there is Better Together 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 Better Together discounts will show up at checkout time as discussed above.

Q: OK, I have Better Together specials, but my customers aren't biting. How can I re-enforce the promotion?
A: My Checkout Candy module can be configured to show available Better Together discounts both on the Shopping Cart page and on the first page of checkout. Please consider showing your support for Better Together by purchasing this module.

Q: I don't want Discount Preview, but I'd still like to make a contribution to show my appreciation for Better Together - how do I do this?
A: Click here! All donations are greatly appreciated.

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


This provides a two for one discount on identical items in category 1:
  function setup() { 
      $this->add_twoforone_cat(1);
  }


Q: What would my setup() look like if I wanted to give 2 for 1 on all items 5, 8, 12, 17 and 31? What about buy one get one half off?
A: Here's what you would do for 2 for 1:
  function setup() { 
      $this->add_prod_to_prod(5,5,"%", 100); 
      $this->add_prod_to_prod(8,8,"%", 100); 
      $this->add_prod_to_prod(12,12,"%", 100); 
      $this->add_prod_to_prod(17,17,"%", 100); 
      $this->add_prod_to_prod(31,31,"%", 100); 
  }
Here's buy one get one half off:
  function setup() { 
      $this->add_prod_to_prod(5,5,"%", 50); 
      $this->add_prod_to_prod(8,8,"%", 50); 
      $this->add_prod_to_prod(12,12,"%", 50); 
      $this->add_prod_to_prod(17,17,"%", 50); 
      $this->add_prod_to_prod(31,31,"%", 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." If you wish to give a buy one get one free for only precisely the same item for items 5 and 8, and not permit mixing and matching, you would use:
  function setup() { 
      $this->add_twoforone_prod(5);
      $this->add_twoforone_prod(8);
  }


For example, if you sell sweaters with the attribute "color," then buying a red sweater and a blue sweater would not produce a discount if add_twoforone_prod() were used, but it would if add_prod_to_prod() were used.

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_prod_to_cat(5,2,"$", 5); 
      $this->add_prod_to_cat(5,7,"$", 5); 
      $this->add_prod_to_cat(5,9,"$", 5); 
  }

Q: What if I want to do offers on all my products?
A: The setup() function is in a php file, so you can write software to configure your discounts. For instance, if you have 600 products, and you want to do "buy one get one 50% off" on all of them, you can do:
function setup() {
   for ($i = 1; $i <= 600; $i++) {
      $this->add_prod_to_prod($i,$i,"%", 50);
   }
}
Obviously you could do this for add_twoforone_prod, etc. just as well.

Another approach would be to inspect the cart and call add_prod_to_prod (or whatever) on all items in the cart. The downside with this is that the marketing text then wouldn't work.