Quantity Deals & Promo Badges: documentation
Set up quantity promotions and promo badges on PrestaShop 8 and 9: offer types, targeting, badge customisation and how the cart discount is calculated.
Installation
The module installs like any other PrestaShop module, from the back office or over FTP.
- Go to Modules then Module Manager, click Upload a module and drop the
dfquantitydeal.zipfile. - Over FTP, extract the archive into your shop’s
/modules/folder, then install DataFirefly – Quantity Deals & Promo Badges from the module manager. - Clear the cache under Advanced Parameters then Performance.
Installation creates eight tables prefixed ps_df_quantity_deal, registers seven hooks and adds the Quantity deals tab to the Catalog menu.
No class or controller override is installed. Uninstalling removes the tables, the configuration keys and the tab.
Global settings
The Configure button on the module page opens the settings that apply to every offer.
- Enable the module: switches off badge display and discount calculation without uninstalling.
- Badges on listings: shows the badge on thumbnails in category pages, search results and product blocks.
- Badge on the product page: a separate switch, so you can keep the badge on listings only.
- Offers table on the product page: lists the offers that apply to the product, under the add-to-cart button.
- Offer breakdown in the cart: adds the amount contributed by each offer under the cart summary.
- Calculate discounts with tax: when on, the cart rule carries a tax-inclusive amount. When off, the amount is net and PrestaShop applies VAT following your rules.
- Cart discount label: the text shown on the discount line of the cart and the order. Defaults to “Quantity deals”.
- Badge font size: in pixels, 13 by default.
Creating an offer
Open Catalog then Quantity deals, and click New offer. The form is split into three tabs.
Offer tab
- Offer name: translated field, used in the back office list and in the offers table on the product page.
- Offer type: the five mechanics described below. The form hides the fields that do not apply to the chosen type.
- Purchased quantity (X) and Free quantity (Y): for the buy X get Y free type, and X alone for pack pricing.
- Rank of the discounted item (N): 2 for “2nd at -25%”, 3 for “3rd at -50%”.
- Discount value: percentage, amount off or imposed price depending on the type. The field label changes on its own.
- Repeatable offer: when on, the offer applies as many times as the quantity allows. When off, it applies once per cart.
- Quantity grouping: per product, per combination, or mix and match.
- Priority: lower values run first.
- Enable the offer: same as the toggle in the list view.
Conditions tab
- Scope: whole catalogue, selected products, selected categories or selected manufacturers. The matching selector appears according to your choice.
- Products covered: type at least two characters to start the search. It covers name, reference and ID. Click a result to add it to the list.
- Categories covered: category tree with checkboxes. A product attached to any checked category triggers the offer.
- Manufacturers covered: list of the shop’s manufacturers.
- Customer groups: leave everything unchecked to apply the offer to all groups, visitors included.
- Exclude products already on sale: products carrying a specific price are left out of the calculation.
- Start date and End date: leave empty for a permanent offer. A date on its own is completed with 00:00:00 for the start and 23:59:59 for the end.
- Shops: only visible when multistore is active.
Badge & display tab
- Badge text: translated field. Leave it empty for automatic generation from the offer values.
- Background colour and Text colour: colour pickers, red and white by default.
- Shape: square, rounded corners, pill, tilted ribbon, round dot.
- Position on the thumbnail: top left, top right, bottom left, bottom right, or inline under the price.
- Show on listings, on the product page, in the offers table: three per-offer switches, on top of the global settings.
- Offer description: translated rich text, shown under the explanatory sentence in the offers table.
The five offer types
Buy X, get Y free
The classic 2+1, 3+1 or 4+2 format. The engine splits the eligible cart units into sets of X plus Y. For every complete set, the Y cheapest units are free.
Example: a 4+2 offer, six items at 4.49 in the cart. One complete set, two free units, a discount of 8.98. With only five items no set is complete and the discount is zero.
Nth item at -X%
The engine splits the units into sets of N. In each set, the unit at rank N gets the percentage off. Because units are sorted by descending price, the discounted item is the cheapest of the set.
Example: a “2nd at -25%” offer, four items at 20. Two sets of two, two items discounted by 5, a total discount of 10.
Nth item at a fixed amount off
Same split, but the discount is a fixed amount. It is capped at the item price: an amount of 30 off an item priced 8 gives 8, not 30.
Nth item at an imposed price
The item at rank N is brought down to the price you set. The discount is the difference. For “2nd at 1” on two items at 12, the discount is 11.
Pack price
For every set of X units, the total is brought down to the price you advertise. On a 3 for 10 offer with six items at 5, the engine forms two sets and applies 10 of discount in total.
Which item is free
The engine sorts eligible units by descending price, then applies the benefit to the cheapest of each set. This is the rule supermarkets use and the one customers expect.
On a 3+1 set made of items at 20, 15, 10 and 5, the free item is the one at 5. The customer pays 45 instead of 50.
Quantity grouping
- Per product: every combination of the same reference counts together. Six bottles of the same shower gel trigger a 4+2 offer even across three scents.
- Per combination: each variant counts on its own. Six units of the same scent are needed to trigger the same offer.
- Mix and match: every unit of the products attached to the offer feeds the same count. Useful to run a 4+2 across a whole range.
Priority and stacking
Offers are evaluated in priority order, from the lowest value to the highest. Each offer consumes the units it uses, and the next one works on what is left. The same unit is never discounted twice.
Example: seven items in the cart and a 4+2 offer at priority 10. Six units are consumed by the set, the seventh stays available for a priority 20 offer targeting the same product.
Give your most generous offers a low priority if you want them applied first. At equal priority, the order follows the offer ID.
The badge
Text variables
The badge text field accepts five variables, replaced at display time with the offer values.
{x}: purchased quantity{y}: free quantity{n}: rank of the discounted item{value}: discount value, without trailing zeros{price}: discount value formatted as a price, in the customer’s currency
You can also write the text out: “buy 4 get 2 free”, “3+1 free”, “2nd at -25%”. The field is translated, so each language gets its own wording.
If the field stays empty, the module builds a short label from the type and the values: 4+2 for a buy X get Y free offer, -25% x2 for a percentage Nth.
Position and thumbnail integration
The badge is rendered inside the price block, through the displayProductPriceBlock hook. A front script then moves it into the thumbnail container so it sits over the image. The placement is replayed after Ajax refreshes from faceted search, pagination and quick view.
The Inline (under the price) mode disables that move and leaves the badge in the flow, under the price. Pick this mode if your theme uses a non-standard thumbnail structure.
How the cart discount is calculated
On every cart change, the engine recalculates the discount total and syncs a private cart rule. Its internal code starts with DFQD followed by the cart ID. The customer sees a single discount line and has no code to enter.
The rule is only updated when the amount has changed, which avoids recreating it on every page load. If the total falls back to zero, the rule is detached from the cart and deleted.
When the order is placed, the rule is deactivated and its end date is pushed into the past so it cannot be reused. It stays attached to the order, so it remains visible in your accounting exports and usable for a credit note.
The discount amount cannot exceed the cart’s product total. PrestaShop caps it automatically in that case.
Adapting the display to your theme
Three templates can be overridden. Copy them from /modules/dfquantitydeal/views/templates/hook/ to /themes/your-theme/modules/dfquantitydeal/views/templates/hook/.
badge.tpl: the badge itselfoffers.tpl: the offers table on the product pagecart.tpl: the breakdown under the cart
The CSS is namespaced under the dfqd prefix. For a small adjustment, target the classes from your theme stylesheet rather than editing views/css/front.css, which would be overwritten on update.
Multistore and multilingual
Each offer is attached to the shops you tick in the Conditions tab. An offer created on one shop does not appear on the others until it is attached to them.
The Name, Badge text and Description fields are translated into the installed languages. The badge shown follows the customer’s language.
Troubleshooting
The badge does not appear
- Check that both the module and the offer are active, and that today falls within the validity period.
- Check the scope: a product must be explicitly attached to the offer, or belong to a ticked category or manufacturer.
- Review the display switches, in the global settings and in the offer’s Badge tab.
- If the customer group is restricted, test with an account in the right group.
- Clear the Smarty cache and your server cache.
The discount is not applied in the cart
The quantity has to reach the offer threshold under the chosen grouping mode. In Per combination mode, six units spread across three variants do not trigger a 4+2 offer. Check as well that the product is not excluded by the already-on-sale option.
Two offers get in each other’s way
That behaviour is expected: a unit consumed by the first offer leaves the calculation of the second. If you want one offer to run before the other, lower its priority.
The badge shows in the wrong place
Some custom themes do not use the standard thumbnail structure. Switch the position to Inline (under the price), or override badge.tpl to place the badge where you want it.
Uninstalling
Uninstalling removes the module’s eight tables, its configuration keys and the Catalog menu tab. Cart rules already attached to past orders are kept, so your accounting history stays intact.