WP Manifestindependent plugin directory
manifest / ecommerce / free-shipping-meter

Free Shipping Meter

Tells the customer how much more is needed for free shipping, read from the shipping zone that actually applies and counted the way WooCommerce counts it, on the classic pages and on the blocks alike.

by George Vasiliades · github.com/poseidonas/free-shipping-meter · website

0stars
1release downloads
0forks

Install

The author publishes release zips, so WP-CLI can install straight from GitHub:

wp plugin install https://github.com/poseidonas/free-shipping-meter/releases/download/v1.0.0/free-shipping-meter.zip

Declares an update source (https://github.com/Poseidonas/free-shipping-meter), so updates arrive through the plugin's own updater.

Readme

Free Shipping Meter

Latest release WordPress 6.7+ WooCommerce 9.0+ PHP 8.0+ License GPL-2.0-or-later

Tells the customer how much more is needed for free shipping. The amount is read from the shipping zone that actually applies to their address, and it is counted exactly the way WooCommerce counts it, so the sentence is never a guess. Works on the classic pages and on the cart and checkout blocks alike.

  • Author: George Vasiliades - https://github.com/Poseidonas
  • License: GPL-2.0-or-later
  • Requires WordPress 6.7 or newer
  • Requires PHP 8.0 or newer
  • Requires WooCommerce 9.0 or newer, tested up to 11.0
  • Compatible with High-Performance Order Storage and with the cart and checkout blocks
  • Settings live in WooCommerce > Settings > Shipping > Free shipping meter

What was measured before writing this

Measured on WooCommerce 11.0.1:

Question Result
Does the core say how much is missing? No. There is no function, no hook and no template for it
How does the core decide free shipping is due? WC_Shipping_Free_Shipping::is_available(), using get_displayed_subtotal() minus the discount, and minus the discount tax when prices are shown including tax, rounded to the store's decimals
Is that per method? Yes. ignore_discounts is a setting on each free shipping method, so two zones can answer differently for the same cart
Where does the amount live? On the shipping method instance inside a zone, so it changes with the customer's address
Can the blocks show it without a build step? Yes. Verified in a real headless browser: wp.data.select( 'wc/store/cart' ) is available on the page and carries the cart data including extensions

Two of those rows are why most free shipping bars are wrong.

They count the wrong number. A bar that reads get_cart_contents_total() or get_subtotal() disagrees with WooCommerce the moment a coupon is applied or prices are shown including tax. This plugin uses the same lines the core uses:

$total = $cart->get_displayed_subtotal();
if ( ! $ignore_discounts ) {
    $total -= $cart->get_discount_total();
    if ( $cart->display_prices_including_tax() ) {
        $total -= $cart->get_discount_tax();
    }
}

Checked against is_available() across seven combinations of threshold, coupon and ignore_discounts: seven agreements out of seven.

They use a number typed by hand. A threshold written into a plugin setting is a copy of the truth, and it goes stale the day you change your shipping. This plugin reads the free shipping methods of the zone that matches the customer's package, so a shop with 50 for Greece and 120 for Europe gets the right sentence in both without configuring anything twice.

What the customer sees

One sentence, and a progress bar drawn with the browser's own <progress> element so it takes the colours of your theme rather than importing someone else's.

Both are yours to change: {remaining}, {threshold} and {total} can be placed in your own wording, and the bar can be switched off if the sentence is enough.

Where it appears

Place Classic Blocks
Cart yes yes
Checkout yes yes
Product page yes not applicable
Mini cart yes not applicable
Bar across the site yes yes, it sits outside the block

On the blocks the sentence updates as the cart changes, with no page reload. Verified in a real browser: at 36 the meter read Add €14.00 more, the quantity was raised to 54 and it became Your order qualifies for free shipping, then lowered to 18 and it read Add €32.00 more, with the bar following each time.

There is also a shortcode, [icxcnika_free_shipping_meter], for placing it anywhere else on a classic page.

When a zone has no answer

A zone may have no free shipping at all, or offer it only with a coupon. There is no amount to count towards in that case, and the meter stays quiet rather than inventing a number.

If your shop gives free shipping some other way, a fallback amount can be set. It is used only where the matching zone says nothing, and the settings page states plainly which zones fall back and which stay silent.

What each zone offers

A table under the settings lists every zone, where it applies, what its free shipping requires, and what the meter will therefore show. It is how you find out that the zone you care about only gives free shipping with a coupon, before a customer does.

Honest limits

  • The meter follows the zone that matches the customer's address. Before they enter one, WooCommerce uses the store's default customer address, so the first sentence a visitor sees is the one for that address.
  • Only free shipping methods are read. A zone that gives free delivery through a flat rate priced at zero is not free shipping as far as WooCommerce is concerned, and the meter will not claim otherwise.
  • Where several free shipping methods exist in one zone, the one the customer is closest to reaching is used.
  • The product page, the mini cart and the shortcode render on the server, so on a fully block-based theme they show the figure as it was when the page loaded. The cart and checkout, where the decision is actually made, update live.
  • The sentence is about shipping cost only. It says nothing about delivery time.

Filters

add_filter( 'icxcnika_fsm_state', function ( array $state ): array {
    return $state;
} );

add_filter( 'icxcnika_fsm_settings', function ( array $settings ): array {
    return $settings;
} );

icxcnika_fsm_state receives active, threshold, current, remaining, reached and message, and is the last word before anything is drawn. icxcnika_fsm_registry_payload receives the data sent to the installation registry.

Data stored

  • Options, one per settings field, all prefixed icxcnika_fsm_settings_.
  • Option icxcnika_fsm_registry_key (random installation key of 48 characters, created only if installation reporting is active).
  • Transient icxcnika_fsm_release (cached GitHub release lookup, 12 hours).
  • Cron event icxcnika_fsm_registry_ping (weekly, only if installation reporting is active).

Nothing is written to carts, orders or shipping settings.

Installation reporting

On activation, on deactivation and once a week the plugin sends a small JSON message to the author's installation registry: plugin slug, plugin version, home URL, site URL, WordPress version, WooCommerce version, PHP version, locale and whether the site is a multisite. Each report carries a random installation key generated locally on first use. No customer, cart or order data is ever sent.

The reporting address is empty by default, which means nothing is sent at all. Add define( 'ICXCNIKA_REGISTRY_DISABLE', true ); to wp-config.php to turn the reporting off, or define( 'ICXCNIKA_REGISTRY_URL', '...' ); to point it elsewhere.

Updates

Updates are delivered from GitHub Releases through the Update URI header of WordPress. The Plugins screen shows View details and allows automatic updates to be enabled, exactly as for a plugin from the directory.

Uninstall

Deleting the plugin removes every option it wrote, the installation key, the cached release check and the scheduled report. Shipping zones and methods are left exactly as they were.


Free Shipping Meter (Ελληνικά)

Λέει στον πελάτη πόσα ακόμα χρειάζονται για δωρεάν μεταφορικά. Το ποσό διαβάζεται από τη ζώνη αποστολής που πραγματικά ισχύει για τη διεύθυνσή του, και μετριέται ακριβώς όπως το μετράει το WooCommerce, οπότε η πρόταση δεν είναι ποτέ εικασία. Λειτουργεί τόσο στις κλασικές σελίδες όσο και στα μπλοκ καλαθιού και ταμείου.

  • Δημιουργός: George Vasiliades - https://github.com/Poseidonas
  • Άδεια: GPL-2.0-or-later
  • Απαιτεί WordPress 6.7 ή νεότερο
  • Απαιτεί PHP 8.0 ή νεότερη
  • Απαιτεί WooCommerce 9.0 ή νεότερο, δοκιμασμένο έως 11.0
  • Συμβατό με το High-Performance Order Storage και με τα μπλοκ καλαθιού και ταμείου
  • Οι ρυθμίσεις βρίσκονται στο WooCommerce > Ρυθμίσεις > Αποστολή > Μετρητής δωρεάν μεταφορικών

Τι μετρήθηκε πριν γραφτεί

Μετρήθηκε σε WooCommerce 11.0.1:

Ερώτημα Αποτέλεσμα
Λέει ο πυρήνας πόσα λείπουν; Όχι. Δεν υπάρχει συνάρτηση, ούτε hook, ούτε πρότυπο για αυτό
Πώς αποφασίζει ο πυρήνας ότι δικαιούνται δωρεάν μεταφορικά; WC_Shipping_Free_Shipping::is_available(), με get_displayed_subtotal() μείον την έκπτωση, και μείον τον φόρο της έκπτωσης όταν οι τιμές δείχνονται με φόρο, στρογγυλοποιημένα στα δεκαδικά του καταστήματος
Ισχύει ανά μέθοδο; Ναι. Το ignore_discounts είναι ρύθμιση κάθε μεθόδου δωρεάν μεταφορικών, οπότε δύο ζώνες μπορούν να απαντήσουν διαφορετικά για το ίδιο καλάθι
Πού βρίσκεται το ποσό; Στο στιγμιότυπο της μεθόδου μέσα σε μια ζώνη, οπότε αλλάζει με τη διεύθυνση του πελάτη
Μπορούν τα μπλοκ να το δείξουν χωρίς build step; Ναι. Επαληθεύτηκε σε πραγματικό headless browser: το wp.data.select( 'wc/store/cart' ) υπάρχει στη σελίδα και μεταφέρει τα δεδομένα του καλαθιού μαζί με τις επεκτάσεις

Δύο από αυτές τις γραμμές είναι ο λόγος που τα περισσότερα free shipping bars είναι λάθος.

Μετράνε λάθος αριθμό. Μια μπάρα που διαβάζει get_cart_contents_total() ή get_subtotal() διαφωνεί με το WooCommerce τη στιγμή που μπαίνει κουπόνι ή που οι τιμές δείχνονται με φόρο. Αυτό το πρόσθετο χρησιμοποιεί τις ίδιες γραμμές με τον πυρήνα:

$total = $cart->get_displayed_subtotal();
if ( ! $ignore_discounts ) {
    $total -= $cart->get_discount_total();
    if ( $cart->display_prices_including_tax() ) {
        $total -= $cart->get_discount_tax();
    }
}

Ελέγχθηκε απέναντι στο is_available() σε επτά συνδυασμούς κατωφλιού, κουπονιού και ignore_discounts: επτά συμφωνίες στις επτά.

Χρησιμοποιούν αριθμό γραμμένο με το χέρι. Ένα κατώφλι γραμμένο σε ρύθμιση πρόσθετου είναι αντίγραφο της αλήθειας, και παλιώνει τη μέρα που θα αλλάξετε τα μεταφορικά σας. Αυτό το πρόσθετο διαβάζει τις μεθόδους δωρεάν μεταφορικών της ζώνης που ταιριάζει στο πακέτο του πελάτη, οπότε ένα κατάστημα με 50 για Ελλάδα και 120 για Ευρώπη παίρνει τη σωστή πρόταση και στα δύο χωρίς καμία διπλή ρύθμιση.

Τι βλέπει ο πελάτης

Μία πρόταση, και μια γραμμή προόδου σχεδιασμένη με το ίδιο το στοιχείο <progress> του browser, ώστε να παίρνει τα χρώματα του θέματός σας αντί να εισάγει ξένα.

Και τα δύο αλλάζουν: τα {remaining}, {threshold} και {total} μπαίνουν στη δική σας διατύπωση, και η γραμμή μπορεί να απενεργοποιηθεί αν αρκεί η πρόταση.

Πού εμφανίζεται

Θέση Κλασικά Μπλοκ
Καλάθι ναι ναι
Ταμείο ναι ναι
Σελίδα προϊόντος ναι δεν ισχύει
Μικρό καλάθι ναι δεν ισχύει
Μπάρα σε όλο τον ιστότοπο ναι ναι, βρίσκεται εκτός του μπλοκ

Στα μπλοκ η πρόταση ενημερώνεται καθώς αλλάζει το καλάθι, χωρίς επαναφόρτωση σελίδας. Επαληθεύτηκε σε πραγματικό browser: στα 36 ο μετρητής έλεγε «Add €14.00 more», η ποσότητα ανέβηκε στα 54 και έγινε «Your order qualifies for free shipping», έπειτα κατέβηκε στα 18 και έγραψε «Add €32.00 more», με τη γραμμή να ακολουθεί κάθε φορά.

Υπάρχει και shortcode, το [icxcnika_free_shipping_meter], για τοποθέτηση οπουδήποτε αλλού σε κλασική σελίδα.

Όταν μια ζώνη δεν έχει απάντηση

Μια ζώνη μπορεί να μην έχει καθόλου δωρεάν μεταφορικά, ή να τα δίνει μόνο με κουπόνι. Σε αυτή την περίπτωση δεν υπάρχει ποσό προς το οποίο να μετρήσει, και ο μετρητής σωπαίνει αντί να επινοήσει αριθμό.

Αν το κατάστημά σας δίνει δωρεάν μεταφορικά με άλλον τρόπο, μπορεί να οριστεί εφεδρικό ποσό. Χρησιμοποιείται μόνο όπου η ζώνη που ταιριάζει δεν λέει τίποτα, και η σελίδα ρυθμίσεων δηλώνει καθαρά ποιες ζώνες πέφτουν στην εφεδρεία και ποιες σωπαίνουν.

Τι προσφέρει κάθε ζώνη

Ένας πίνακας κάτω από τις ρυθμίσεις δείχνει κάθε ζώνη, πού ισχύει, τι απαιτούν τα δωρεάν μεταφορικά της, και τι θα δείξει επομένως ο μετρητής. Έτσι ανακαλύπτετε ότι η ζώνη που σας ενδιαφέρει δίνει δωρεάν μεταφορικά μόνο με κουπόνι, πριν το ανακαλύψει πελάτης.

Τίμιοι περιορισμοί

  • Ο μετρητής ακολουθεί τη ζώνη που ταιριάζει στη διεύθυνση του πελάτη. Πριν εκείνος δώσει διεύθυνση, το WooCommerce χρησιμοποιεί την προεπιλεγμένη διεύθυνση πελάτη του καταστήματος, οπότε η πρώτη πρόταση που βλέπει ένας επισκέπτης είναι εκείνης της διεύθυνσης.
  • Διαβάζονται μόνο μέθοδοι δωρεάν μεταφορικών. Μια ζώνη που δίνει δωρεάν παράδοση μέσω σταθερού συντελεστή με τιμή μηδέν δεν είναι δωρεάν μεταφορικά για το WooCommerce, και ο μετρητής δεν θα ισχυριστεί το αντίθετο.
  • Όπου υπάρχουν πολλές μέθοδοι δωρεάν μεταφορικών σε μία ζώνη, χρησιμοποιείται εκείνη που ο πελάτης είναι πιο κοντά να πετύχει.
  • Η σελίδα προϊόντος, το μικρό καλάθι και το shortcode αποδίδονται στον server, οπότε σε θέμα εξ ολοκλήρου με μπλοκ δείχνουν τον αριθμό όπως ήταν κατά τη φόρτωση της σελίδας. Το καλάθι και το ταμείο, όπου πραγματικά λαμβάνεται η απόφαση, ενημερώνονται ζωντανά.
  • Η πρόταση αφορά μόνο το κόστος αποστολής. Δεν λέει τίποτα για τον χρόνο παράδοσης.

Read the full README on GitHub →

Releases

TagPublishedAssetDownloads
v1.0.0 Aug 19, 2026 free-shipping-meter.zip 1