Free Shipping Bar (dffreeshipbar) — Complete guide
Install and configure the free shipping bar for PrestaShop 8 and 9: per-country and per-state thresholds, territory exclusion, carrier rules, delivery address requirement, display positions, multistore and troubleshooting.
Complete guide to the dffreeshipbar module for PrestaShop 8 and 9: installation, per-country and per-state thresholds, carrier filtering, display positions, multistore and troubleshooting. Every resolution rule is documented, edge cases included.
Overview
dffreeshipbar displays a progress bar telling customers how much more they need to spend to qualify for free shipping. Once the threshold is reached, the message switches to a confirmation.
The module works from its own thresholds, stored in its own tables. It never reads the native PS_SHIPPING_FREE_PRICE setting: you can leave it at 0 and drive free shipping through carrier ranges without any conflict.
What sets the module apart is its two-level territorial resolution. A threshold can be set at country level, but also at PrestaShop state level — which lets you treat differently territories that are administratively attached to the same country, such as overseas departments attached to mainland France.
Requirements
- PrestaShop 8.0 to 9.x
- PHP 7.4 minimum (8.0 to 8.3 supported)
- Classic, Hummingbird or any custom theme calling the standard hooks
- Back office administrator access
Installation
- In the back office, go to Modules → Module Manager → Upload a module.
- Upload the
dffreeshipbar-2.1.0.zipfile. - Click Install then Configure.
On installation the module creates two tables and registers its hooks:
PREFIX_dffreeshipbar_country— country-level thresholds, with anid_shopcolumn.PREFIX_dffreeshipbar_state— state-level thresholds, with anid_shopcolumn.
Registered hooks: displayHeader, displayBanner, displayNav2, displayNavFullWidth, displayShoppingCartFooter, displayCheckoutSummaryTop, actionCarrierUpdate.
General settings
The configuration screen sits under Modules → DataFirefly – Free Shipping Bar → Configure. It has three panels: general settings, carrier rules, territory thresholds.
Global fallback threshold
Two linked settings:
- Use a global fallback threshold: when set to No, the bar only appears in territories you configured explicitly. When set to Yes, any unconfigured territory receives the amount below.
- Global fallback threshold: the amount applied as a last resort.
Leave the fallback off if free shipping only covers a few destinations. Turn it on if free shipping is universal and exceptions are rare.
Calculation basis
- Compare tax included totals: decides whether the cart total is evaluated with or without tax. This must match the basis your carrier ranges use, otherwise the bar and the checkout will disagree.
- Count cart rules in the total: when enabled, cart discounts are deducted before comparing against the threshold. A 70 € cart with a 10 € voucher is then evaluated at 60 €.
The evaluated total maps to a native call:
Cart::getOrderTotal(
$with_taxes = (bool) DFFREESHIPBAR_TAX_INCL,
$type = DFFREESHIPBAR_INCLUDE_DISCOUNTS
? Cart::BOTH_WITHOUT_SHIPPING
: Cart::ONLY_PRODUCTS
);
Shipping costs and gift wrapping never count towards progress.
Require a delivery address
Until the customer enters an address, the destination is only a guess and the state is unknown. Three modes:
- Never: the bar shows from catalogue browsing onwards, based on the guessed country.
- For countries with states (recommended): the bar stays visible everywhere except in countries whose states may carry different terms. A visitor guessed in Belgium sees the bar; a visitor guessed in France only sees it after entering an address, since their state determines the real threshold.
- Always: nothing until an address exists on the cart.
Positions and appearance
- Show at the top of the page: banner visible site-wide.
- Show on cart and checkout: block displayed at decision time.
- Enable animation: animated stripes while progress is running. The animation is automatically suppressed for visitors who set
prefers-reduced-motion. - Four colours: background, bar, text, success message.
For free placement in your theme, the module implements WidgetInterface:
{widget name='dffreeshipbar'}
{widget name='dffreeshipbar' position='cart'}
Territory thresholds
This is the heart of the module. The table lists every active country in the shop, and beneath each country that has states, its states, indented.
Resolution order
For a given delivery address the module looks in this order and stops at the first match:
- The state of the address, when a rule exists for it.
- The country of the address, when a rule exists for it.
- The global fallback, if enabled.
If none of these three steps yields an amount, the bar is not displayed.
Checkbox and amount field: two different effects
This is the most important part of the configuration, and the most commonly misread:
- Checkbox cleared → the bar is hidden for that territory. It inherits neither the parent country nor the global fallback. Resolution stops there.
- Checkbox ticked, amount empty → the rule is deleted, the territory inherits from the level above.
- Checkbox ticked, amount filled → that amount applies.
Example: mainland only
A common case for a French shop offering free shipping at 65 € on the mainland and Corsica, but not overseas:
- France: ticked, amount
65. - Corsica: ticked, amount empty — it inherits France’s 65 €.
- Guadeloupe, Martinique, French Guiana, Réunion, Mayotte: checkboxes cleared. No bar on these destinations.
- Global fallback: disabled, so no other country accidentally receives a bar.
A customer in Guadeloupe will therefore never see the free shipping promise, even though their address belongs to the country “France” in PrestaShop.
Filter and search
The search field filters countries and states by name. The Show configured territories only checkbox reduces the table to rows that already have a rule — useful on a shop open to a hundred countries.
The two save buttons are independent: Save countries and Save states.
Carrier rules
If free shipping is only granted by some carriers, restrict the display accordingly. Three modes:
- All carriers: no filtering.
- Show only for the carriers ticked below: allow list.
- Hide for the carriers ticked below: deny list.
id_reference, not its id_carrier. PrestaShop marks the old carrier as deleted and creates a new one on every edit: an ID-based configuration would be lost the first time you change a rate. The reference stays stable.Before carrier selection
The carrier is unknown until the delivery step. The Before carrier selection setting decides what happens before that point:
- Show: the bar appears on catalogue and cart, then disappears if the customer picks an excluded carrier.
- Hide: the bar only appears once an eligible carrier has been selected.
Real-time updates
The bar is recomputed server-side and refreshed without a page reload on every cart event: add, remove, quantity change, address change, checkout step change.
The script listens to the PrestaShop events updatedCart, updateCart, updatedAddressForm, changedCheckoutStep and updateDeliveryForm. You can trigger a manual refresh from your own code:
document.dispatchEvent(new Event('dffreeshipbar:refresh'));
The server decides visibility: if the territory or carrier no longer qualifies, the bar is removed from the DOM rather than left showing a stale value.
Multistore
Thresholds are stored with an id_shop column. Each shop therefore has its own country and state rules, fully independent of one another.
To configure a given shop, select its context at the top of the back office before opening the configuration screen. The thresholds panel displays the current shop name as a reminder.
Translations
The module ships translated into English, French, German, Spanish, Italian and Polish.
To adapt customer-facing text, go to International → Translations, select “Module translations”, choose dffreeshipbar and the language, then look for the Modules.Dffreeshipbar.Shop domain. Available strings:
- “Only %amount% away from free shipping!” — cart in progress.
- “Free shipping from %amount%.” — empty cart.
- “Congratulations! Your order qualifies for free shipping.” — threshold reached.
The %amount% token is replaced with the amount formatted according to the active currency and locale. Keep it in your translations.
Upgrading from version 1.0
Upgrading happens automatically when the ZIP is replaced. The upgrade scripts do the following:
- Create the states table.
- Rename the
activecolumn toenabledon the countries table. Your existing thresholds are preserved. - The global fallback is enabled if you had one in 1.0, so what your customers see does not change.
- The address requirement mode is set to Never, matching 1.0 behaviour. Switch it to the recommended mode when you decide to.
Troubleshooting
The bar shows nowhere
- Is the module enabled? (Enable module switch).
- Have you configured at least one territory, or enabled the global fallback? Without either, the bar never appears.
- Is the address requirement set to Always while you test without a delivery address?
- Are the positions enabled? (banner and/or cart).
- Does your theme call the hooks used? Check under Modules → Positions. On a custom theme, use the widget instead.
The bar shows where it should not
The typical case is a territory inheriting when it should be excluded. Check that the territory’s checkbox is actually cleared, and not merely that its amount was emptied — the two actions have opposite effects.
The displayed threshold does not match checkout
- Check that Compare tax included totals matches the basis of your carrier ranges.
- Check the cart rules setting: a discounted cart can fall below the threshold.
- The module does not read your carrier ranges. If you changed a range, carry the new value into the module.
The bar does not update after adding to cart
Refreshing relies on PrestaShop’s JavaScript events. Some themes or third-party cart modules do not emit them. Two checks:
- Does the browser console report a JavaScript error on another resource? A blocking error upstream prevents the listener from being installed.
- Does your ajax cart module actually emit
prestashop.emit('updatedCart')? If not, dispatchdffreeshipbar:refreshfrom your code.
Carrier rules seem ignored
Check that the selected carrier is the one you think: after a rate change, PrestaShop creates a new carrier. The module follows the reference, so the rule should follow too — but if the carrier was recreated from scratch rather than edited, its reference is new and you need to tick it again.
Uninstalling
Go to Modules → Module Manager → DataFirefly – Free Shipping Bar → Uninstall. Uninstalling drops both threshold tables and every configuration key prefixed DFFREESHIPBAR_.
Quick FAQ
- Does the module read
PS_SHIPPING_FREE_PRICE? Never. You can leave it at 0 and manage free shipping through carrier ranges. - Does the module read my carrier ranges to derive the threshold? No. Thresholds are entered manually. Automatic synchronisation from ranges is possible as custom development.
- My free shipping also depends on weight. Is that handled? No, the module only measures an amount. A weight condition is custom development.
- Can I display the bar outside the offered positions? Yes, through
{widget name='dffreeshipbar'}in any template. - Does the module work with the Hummingbird theme? Yes. The
displayNavFullWidthanddisplayCheckoutSummaryTophooks are registered for it, and the widget covers custom placements. - Are thresholds independent per shop? Yes, every row carries an
id_shop.
Support and updates
The module includes 12 months of updates and support from the purchase date. Email support in French or English, answered within 24 business hours.
For any question or issue, contact DataFirefly support with:
- PrestaShop and PHP versions
- Installed module version
- Theme in use
- Territory and carrier involved in the observed behaviour
- Observed vs expected behaviour