Weight-Based Products for WooCommerce
Sell products by weight with predefined packages or a free-weight slider. Ideal for meat, deli, cheese, coffee, loose-leaf tea, and any goods sold by weight. This documentation covers installation, configuration, user-facing features, admin settings, and the developer API.
What is Weight-Based Products?
Weight-Based Products adds a new "Weight-Based Product" type to WooCommerce. Instead of selling items by fixed quantity, you sell by weight. Customers select predefined packs or type an exact weight, and the price calculates automatically based on your price-per-unit configuration.
The plugin supports two ordering modes per product:
- Fixed Packs — Define available package sizes (e.g. 200 g, 500 g, 1 kg). Customers select packs and the plugin uses a best-combination algorithm to match a desired weight.
- Free Weight — Customers drag a slider or type any weight. Price is calculated live as they adjust.
Key Features
- Two ordering modes — Fixed Packs with combination matching, and Free Weight with animated slider and typed input
- Multi-unit support — kg/g and lb/oz per product, with extensible unit registry for custom units (ml/L, etc.)
- Live price preview — Price updates in real time during weight selection
- Tiered pricing — Global or per-product price brackets (e.g. 0–2 kg at $10/kg, 2–5 kg at $8/kg)
- Role-based pricing — Different rates for wholesalers, members, etc.
- Product Options — Customisable add-on options (grind type, texture, etc.) organised in categories and groups
- Accessories & Bundles — Cross-sell items shown below the weight selector
- Cart consolidation — Matching weight-based selections merge into one cart line automatically
- Stock management — By package quantity or total weight; low-stock badges and email alerts
- Marketing badges — Per-pack badges like "Recommended" or "Best Seller"
- Appearance presets — One-click style themes (Default, Glass, Nature, Elegant) plus granular colour/typography controls
- WooCommerce Blocks compatible — Works with the block-based cart and checkout
- HPOS compatible — Supports High-Performance Order Storage (custom order tables)
- REST API — Dedicated
wc-wbp/v1namespace for headless and mobile integrations - Developer hooks — Comprehensive actions and filters for customisation
- Data tools — Export/import JSON, sample product generator, cache management
- Full i18n — All strings are translatable
Requirements
| Software | Minimum | Recommended |
|---|---|---|
| WordPress | 6.8 | 6.9+ |
| WooCommerce | 5.0 | 10.6+ |
| PHP | 7.4 | 8.1+ |
This plugin requires WooCommerce to be installed and active. If WooCommerce is deactivated, the plugin will show an admin notice and disable itself.
Installation
Install Weight-Based Products in minutes using the WordPress admin, manual upload, or WP-CLI.
Go to WP Admin → Plugins → Add New. If you have the plugin as a .zip, click Upload Plugin.
Choose weight-based-products.zip and click Install Now.
Click Activate Plugin. Ensure WooCommerce is already active.
Navigate to WooCommerce → Weight Based Products to configure global defaults.
Extract weight-based-products.zip into /wp-content/plugins/weight-based-products/.
Go to WP Admin → Plugins and activate Weight-Based Products.
wp plugin install weight-based-products.zip --activate
Verifying Installation
After activation:
- A new Weight Based Products submenu appears under WooCommerce in the admin sidebar.
- When editing any product, "Weight-Based Product" appears in the Product Type dropdown.
- If WooCommerce is not active, a red admin notice will explain the dependency.
Quick Start
Create your first weight-based product in 5 minutes.
Go to Products → Add New. In the Product data dropdown, select Weight-Based Product.
In the General Options tab, select Fixed Packs or Free Weight.
Enter a Base Price per unit (e.g. $10.00 per kg). Optionally set a sale price.
Fixed Packs: Add package weights (e.g. 200 g, 500 g, 1 kg) with stock quantities.
Free Weight: Set min, max, and step size for the slider.
Click Publish and visit the product page to see the weight selector, live pricing, and Add to Cart button.
Go to WooCommerce → Weight Based Products → Advanced / Tools and click Create Sample Products to generate 15 demo products covering both modes, tiered pricing, options, and accessories.
Fixed Packs Mode
Customers select from predefined package sizes. The plugin calculates the optimal combination to match a desired total weight.
How It Works
You define specific package weights (e.g. 200 g, 500 g, 1 kg, 2.5 kg). On the product page, customers see each available pack as a selectable card or row. They use +/− buttons to set the quantity for each pack, or they can enter a desired total weight and let the algorithm suggest the best combination.
Package Cards
Packages display in two layouts (configurable globally in Appearance or per-product):
- List Rows — Compact horizontal rows with weight, price, stock badge, and quantity stepper.
- Card Grid — Visual cards with bold weight labels, prices, and hover effects. Clicking a card selects it with quantity 1.
Each card can show:
- Weight label (e.g. "500 g"), price per package, and unit price (e.g. "$10.00/kg")
- Stock badge (e.g. "Only 2 left!", "Out of stock")
- Marketing badge (e.g. "Recommended", "Best Seller") — set per pack in the admin
Desired Weight Input
When "Allow customer to type a weight" is enabled, a text field appears where customers can enter a target weight (e.g. 2.5 kg). The plugin runs a best-combination algorithm to find the closest match using available packs, respecting:
- Suggestion mode — Always round up, always round down, or closest match
- Tolerance — How far from the target still counts as exact (e.g. ±50 g)
- Max packages in suggestion — Upper limit on the total pack lines (default 25)
Quick-Select Presets
Comma-separated preset values (e.g. 0.2, 0.5, 1, 2, 3) display as clickable chips above the package list. Clicking a chip runs the best-combination algorithm for that weight instantly.
Order Weight Limits
Set minimum and maximum order weight per product. If the customer's total weight falls outside these limits, a warning message is shown (e.g. "⚠ Minimum order: 300 g") and the Add to Cart button is disabled.
Tiered Pricing
Enable tiered pricing to charge different rates per weight bracket. Tiers can be defined globally (Settings → Pricing Rules) or per-product. Product-level tiers always override global tiers. Weights outside any tier range use the base price.
Free Weight Mode
Customers enter any weight using an animated slider or typed input. Price calculates live as they adjust.
Weight Slider
An animated range slider lets customers drag to select a weight between the configured minimum and maximum. The step size controls the increment (e.g. 0.1 kg = 100 g steps). The current weight and calculated price update in real time.
Typed Input
When "Allow customer to type a weight" is enabled, a text field appears alongside the slider. Customers can type an exact weight (e.g. 2.35 kg). A unit toggle lets them switch between sub-units (g/kg or oz/lb) depending on the product's display unit. The value is validated against the min/max limits after entry.
Quick-Select Presets
Preset weight buttons (e.g. 200 g, 500 g, 1 kg, 2 kg) appear above the slider. Clicking a preset sets the slider and typed input to that weight instantly. Configure presets as a comma-separated list in the product editor.
Dual-Unit Display
When enabled, the product shows both units simultaneously (e.g. "2.00 kg (4.41 lb)"). This helps international customers understand the weight in their preferred unit.
Free-Weight Inventory
Optionally set a total available weight pool (e.g. 50 kg of fresh deli meat). As customers add weight to their cart, the remaining pool decreases. When stock drops below the low-weight threshold, a low-stock badge appears. The slider maximum adjusts dynamically to reflect the remaining inventory.
Free Weight Settings
| Setting | Description | Default |
|---|---|---|
| Minimum weight | Minimum the customer can order | 0 |
| Maximum weight | Slider maximum (empty = no limit) | Empty |
| Step size | Slider increment in the product unit | 0.1 |
| Quick-select presets | Comma-separated values (e.g. 0.5, 1, 2, 3) | Empty |
| Show dual-unit | Display both kg and lb simultaneously | Off |
| Allow typed input | Show a text field for exact weight entry | On |
Product Options
Add custom options (grind type, texture, gift wrap, etc.) to weight-based products. Options appear on the product page and in cart/order details.
How Options Work
Option groups are defined globally in WooCommerce → Weight Based Products → Option Groups. Each group belongs to a category (e.g. "Coffee Products", "General"). On each product, you enable/disable specific groups and optionally override labels or choices.
Option Group Categories
Categories organise related option groups. Examples:
- Coffee Products — "Grind Type", "Roast Level"
- Meat Products — "Cut Style", "Marination"
- General — "Gift Wrap", "Store Policy Note"
Each category has a name, optional description, and colour label (blue, green, orange, purple, red, gray).
Option Group Settings
| Setting | Description |
|---|---|
| Display label | Shown on the product page (e.g. "Grind Type") |
| Input type | Chips/buttons, Dropdown, Text area, Single checkbox, Radio buttons |
| Choices | Each choice can have a name and optional price (for paid groups) |
| Helper text | Shown below the field on the product page |
| Default scope | Manual = attach per product; Auto-attach = shown on all weight-based products |
| Required | Customer must select before adding to cart |
| Mark as FREE | Show a "FREE" badge next to the option |
Per-Product Overrides
In the product editor (Product Options tab), you can:
- Enable or disable specific option groups for this product
- Override the section title and description
- Override labels or choices for specific groups
Accessories & Upsell Bundles
Cross-sell products shown below the weight selector. Accessories support per-item quantity; bundles are single-toggle add-ons. Sides do not affect order weight.
Accessories
Accessories are simple WooCommerce products linked to a weight-based product. They appear on the product page in a dedicated section (e.g. "Complete Your Setup" or "Accessories"). Each accessory has:
- Product name, thumbnail (optional), and price
- Quantity stepper — customer can add multiple units
- Optional override price, display label, description, and max quantity per order
- Optional "FREE" badge
Upsell Bundles
Bundles are "Customers Also Bought"-style products. They appear as single-toggle add-ons — click to add, click again to remove. Each bundle product can have a custom price override and display label.
Cart Behaviour
Two modes are available (configurable in Settings → Sides & Add-ons):
- Separate line items (chained) — Each accessory/bundle appears as its own cart row with "Add-on for: [Main Product]" label. Removing the main product automatically removes all its chained sides. Stock and refunds are handled per item.
- Grouped under main product — Sides are stored on the main product and shown as a single line (e.g. "Sides: 1 × Hat, 1 × Shirt"). No separate rows; refunding the main product refunds the full line including sides.
When the same product with the same accessories is added to the cart multiple times, the plugin automatically merges the main product lines and consolidates duplicate accessories by summing their quantities.
Pricing & Order Total
When "Add sides to order total" is enabled, the Add to Cart button shows the cumulative total (weight product + options + all sides). Accessory and bundle prices come from the linked WooCommerce product but can be overridden per product.
Cart & Checkout
How weight-based products appear in the WooCommerce cart, checkout, and order emails.
Cart Display
The main product shows its name, price, and weight details. Depending on the Cart line format setting:
- Full breakdown — e.g. "2× 1 kg + 1× 500 g"
- Weight only — e.g. "2.5 kg total"
- Compact — e.g. "3 packages (2.5 kg)"
Selected options (e.g. "Grind: Full") appear as meta below the product name. The WooCommerce quantity selector and remove button work as normal.
Add-on Lines
In Separate line items mode, each accessory/bundle appears as its own cart row with "Add-on for: [Main Product]" label. In Grouped mode, sides display as a single sub-line under the main product.
Cart Consolidation
When the same weight-based product (same options, same sides configuration) is added to the cart multiple times, the plugin automatically merges them into one cart line. Pack counts or free-weight totals are summed. Duplicate accessories are also consolidated — their quantities are merged rather than creating separate rows.
Weight-based cart lines always show quantity 1. The actual weight is stored in the weight_data cart item field. Changing the WooCommerce quantity is automatically folded into the weight snapshot.
Checkout & Orders
The checkout order summary shows the same breakdown as the cart. After placing an order:
- Order items store the full weight data, selected packages, options, and sides as meta
- Admin order view shows a Weight column when at least one weight-based item exists
- Order confirmation emails include the weight/package breakdown when enabled in settings
- Stock is reduced per package (Fixed Packs) or by total weight (Free Weight)
Email Display
Enable Show breakdown in emails / order view (Settings → General) to include detailed weight/package information in customer and admin emails. Enable Show sides breakdown in emails (Settings → Sides) to include accessory/bundle details.
General Settings
Default units, display format, stock management, cart behaviour, and the package suggestion algorithm. Located at WooCommerce → Weight Based Products → General.
Default Units & Display
| Setting | Description |
|---|---|
| Default unit | Applied to new products: Kilograms (kg/g) or Pounds (lb/oz). Can be overridden per product. No automatic conversion when changed later. |
| Price display format | Per unit (e.g. $10.00/kg) or Both (per-package total + per-unit rate). Legacy "per package only" values auto-migrate to "Both". |
| Weight decimal places | Number of decimals for weight display (0–4). Example: 3 gives "2.500 kg". |
| Show dual units | When enabled, shows the secondary unit in parentheses (e.g. "2.5 kg (5.51 lbs)"). |
Stock Management
| Setting | Description |
|---|---|
| Stock tracking mode | By package quantity — default WooCommerce behaviour. By total weight — stock shown as remaining weight (e.g. "12.5 kg remaining"). |
| Low stock badge threshold | Packages at or below this number show a warning badge. Set to 0 to disable badges. |
| Low stock email alerts | Admin receives an email when package stock drops to the threshold. |
Cart & Order Display
| Setting | Description |
|---|---|
| Cart line format | Full breakdown (e.g. "2× 1 kg + 1× 500 g"), Weight only (e.g. "2.5 kg total"), or Compact (e.g. "3 packages (2.5 kg)"). |
| After add to cart | Use WooCommerce setting, redirect to cart, or stay on product page (reload). |
| Show breakdown in emails / order view | Include detailed weight/package breakdown in order emails and admin order view. |
Package Suggestion Algorithm
Controls how the best-combination search works when a customer enters a desired weight in Fixed Packs mode.
| Setting | Description | Default |
|---|---|---|
| Tolerance (±) | How far from the desired weight counts as "exact match" (in store unit). E.g. 0.05 = ±50 g. | 0.05 |
| Suggestion mode | Always round up (≥ desired), Always round down (≤ desired), or Closest match (either direction). | Closest match |
| Max packages in suggestion | Upper limit on total pack lines in the browser combination search. Range 1–500. | 25 |
Option Groups Settings
Define global option groups organised into categories. Enable them per product in the product editor. Located at WooCommerce → Weight Based Products → Option Groups.
Section Header (Product Page)
Configure the default title and description for the "Product Options" block on the frontend:
- Section title — e.g. "Customise Your Order"
- Section description — e.g. "Free · no extra charge"
These can be overridden per product in the Product Options tab.
Option Group Categories
Create categories to organise related option groups (e.g. "Coffee Products", "General"). Each category has:
- Name and optional description
- Colour label (blue, green, orange, purple, red, gray) for admin visual organisation
Option Groups (Per Category)
Under each category, add option groups. Each group defines a customer-facing input field on the product page. Settings include:
- Display label — e.g. "Grind Type", "Texture"
- Input type — Chips/button select, Dropdown, Text area (free text), Single checkbox, Radio buttons
- Choices — Each with a name and optional price (for paid groups)
- Helper text — Shown below the field on the product page
- Default scope — Manual (attach per product) or Auto-attach to all products
- Flags — Required field; Mark as FREE (show badge)
Sides & Add-ons Settings
Configure accessories and upsell bundles shown below the weight selector. Sides do not affect order weight. Located at WooCommerce → Weight Based Products → Sides & Add-ons.
Accessories
| Setting | Description |
|---|---|
| Enable accessories | Allow weight-based products to have accessory add-ons |
| Default section title | e.g. "Complete Your Setup" — overridable per product |
| Display position | Below weight selector, Below product options, or Directly above Add to Cart |
| Layout | List (toggle rows) or Grid (cards) |
| Show product images | Thumbnail next to each accessory |
| Max accessories per product | Limit how many accessories a product can have |
Upsell Bundles
| Setting | Description |
|---|---|
| Enable upsell bundles | Show "Customers Also Bought"-style products |
| Default section title | e.g. "Customers Also Bought" |
| Display position | Below accessories, Below product options, or Directly above Add to Cart |
| Layout | List (toggle rows) or Horizontal card scroll |
| Show product images | On or off |
| Max bundles per product | Limit number of bundle products shown |
Pricing & Cart Behaviour
| Setting | Description |
|---|---|
| Add sides to order total | Show cumulative total (weight + sides) on the Add to Cart button |
| Sides in cart | Separate line items (chained) — individual cart rows per side; removing main removes all sides. Grouped under main product — single line showing all sides. |
| Show sides in emails | Include sides breakdown in order confirmation and admin emails |
Pricing Rules
Global tiered pricing, role-based pricing, bulk savings badge, and sale countdown. Located at WooCommerce → Weight Based Products → Pricing Rules.
How Tiers Work
- Product-level tiers (set in the product editor) always take precedence when defined
- Global tiers here apply only when a product has tiered pricing enabled but no product-level tier table
- Weights outside any tier range use the product's base price
Tiered / Graduated Pricing
Enable global tiered pricing to define default price brackets. Each tier has: From (weight), To (weight), and Price per unit. Use "Add Tier" to add rows. These tiers are overridden by product-level tiers.
Role-Based Pricing
Enable role-based pricing to set different rates per WooCommerce user role (e.g. Wholesale at 20% off). Prices set here are defaults and can be overridden per product.
Bulk Purchase Incentives
| Setting | Description |
|---|---|
| Show bulk savings badge | Display a badge when the customer orders above a threshold weight |
| Threshold weight | In grams (e.g. 500 g). Badge appears at or above this weight. |
| Badge message template | Use {threshold} and {savings} placeholders |
| Sale price countdown | Show a countdown timer when a sale price is set with an end date |
Appearance Settings
Colours, borders, step numbers, section cards, quantity stepper, buttons, presets, and custom CSS. Located at WooCommerce → Weight Based Products → Appearance.
Appearance Presets
Select from one-click style themes using the preset dropdown at the top of the Appearance tab:
- Default — Restore original plugin styling
- Glass — iOS 26-inspired liquid glass effect with
backdrop-filterblur, translucent backgrounds, inner glow shadows, and shine pseudo-elements - Nature — Fresh green tones for organic/natural product stores
- Elegant — Rich purple accents for premium product displays
After applying a preset, a reminder notice appears. You must click Save to persist the new values. Presets fill all colour, border, shadow, and typography fields automatically.
Colours
Primary colour — Selected package borders, active chip, toggle states. Accent colour — Confirmed selection background tint.
Section Titles & Step Numbers
- Step numbers — Circular badges (1, 2, 3…) next to section titles. Toggle visibility and set badge background colour.
- Section titles — Title colour, description text colour, and title font size (px).
- Section cards — Background, border colour, border width, and card border radius.
Pack Cards (9 Granular Controls)
| Setting | Description |
|---|---|
| Background (Selected) | Background colour of selected pack card |
| Border (Selected) | Border colour of selected pack card |
| Weight Name colour | Text colour of the weight label on cards |
| Text (Selected) colour | Text colour when card is selected |
| Price colour | Price text colour on cards |
| Unit Price colour | Per-unit price text colour |
| Weight Name font size | Font size for the weight label |
| Price font size | Font size for the price |
| Unit Price font size | Font size for the per-unit price |
Buttons & Stepper
- Quantity stepper — +/− buttons: background, border, button colour, hover states
- Add to Cart button — Background, text, border, hover states. Use
{price}and{weight}placeholders in button text. - Clear button — Secondary button to reset weight selection
- Empty state text — Text when no weight is selected (e.g. "Select a Weight to Continue")
Widget Layout
- Quick preset buttons — Show weight preset chips; style: Pills, Rectangular, or Tab strip
- Package card style — List rows or Card grid (overridable per product)
- Show price on package card
- Show low-stock badges
- Highlight selected packages
CSS Isolation & Custom CSS
CSS Isolation mode — When enabled, adds a body class (lf-wbpw-isolated) and all plugin CSS rules are scoped inside it for higher specificity. This prevents themes from overriding plugin styles. Disable if you want your theme to control styling.
Custom CSS — Injected on every page containing the weight selector widget. Override any style (e.g. .wbp-package-card { border-radius: 12px; }).
CSS custom properties — The plugin uses variables like --lf-wbpw-primary, --lf-wbpw-accent, etc. Override them in your theme's CSS for easy customisation.
Advanced & Tools
Data import/export, sample products, reset settings, cache management, and developer options. Located at WooCommerce → Weight Based Products → Advanced / Tools.
Data & Import / Export
| Tool | Description |
|---|---|
| Export All WBP Data | Download a JSON backup of all weight-based product configurations. Use before importing or migrating. |
| Import from JSON | Restore products and settings from a backup. Overwrites existing data — confirm required. |
| Import from CSV | Bulk-import products with package configurations. Coming soon. |
| Create Sample Products | Generates 15 demo weight-based products covering both modes, tiered pricing, options, and accessories. Creates sample option categories, groups, and a "WBP Samples" product category. |
| Reset Plugin Settings | Restore all settings to defaults. Does not affect product data. Requires confirmation. |
Performance
- Enable transient cache — Cache package combination calculations. Recommended for stores with many products.
- Clear cache — Force-clear all cached weight combination results. Use after changing packages.
Developer
- Debug mode — Log weight calculation steps to the browser console. Disable in production.
- Plugin version, links to Developer Docs, Report a Bug, and Support Forum are shown here.
Product Editor
How to configure individual weight-based products in the WooCommerce product editor. Select "Weight-Based Product" from the Product data dropdown to reveal the plugin's tabs.
General Options Tab
The main configuration tab for weight-based products. Settings include:
- Weight display unit — Store default, Kilograms (kg/g), or Pounds (lb/oz). Overrides the global default for this product.
- Ordering mode — Fixed Packs or Free Weight. Determines which fields are visible below.
- Base Price (per kg/lb) — Regular price per weight unit.
- Sale Price (per kg/lb) — Optional sale price. Sale start/end dates are also configurable for countdown timers.
- Tiered pricing toggle — Use Global tiers, or Use Product Level with a custom From/To/Price table.
Fixed Packs Settings
Visible when ordering mode is "Fixed Packs":
- Order weight limits — Min and max order weight with unit selector (g/kg or oz/lb)
- Available weight packages — Add packages with weight, unit, and stock quantity. Packages appear as draggable "pills" that can be reordered. Admin pills show stock-tier colours (green/amber/red) based on the low-stock threshold.
- Edit package dialog — Click a pill to adjust weight, stock, and optional marketing badge (Recommended, Best Seller, or None).
- Pack list display — Sort order (store default, ascending, descending, catalog order) and Package card style (store default, list rows, card grid).
- Quick-select presets — Comma-separated values shown as chips.
- Show dual-unit display and Allow typed weight input
Free Weight Settings
Visible when ordering mode is "Free Weight":
- Minimum weight, Maximum weight, Step size
- Quick-select presets, Show dual-unit, Allow typed input
- Total available weight and Low weight threshold for inventory tracking
Product Options Tab
Enable/disable global option groups for this product. Override section title, description, and individual group labels or choices. Groups are listed by category.
Sides & Add-ons Tab
Add accessories and upsell bundles to this product:
- Accessories section title — Override the global default
- + Add Accessory — Search for simple products; set override price, display label, description, max qty, and FREE badge
- Upsell bundles section title and + Add Bundle Product
- Drag to reorder, X to remove
Only simple WooCommerce products can be added as accessories or bundles. Variable, grouped, and other product types do not appear in the search.
Architecture
File structure, class responsibilities, and boot sequence of the Weight-Based Products plugin.
Core Files
| File | Class / Role |
|---|---|
weight-based-products.php | Bootstrap: constants, HPOS declaration, unit registry early-load, activation/deactivation hooks |
includes/class-lf-wbpw.php | LF_WBPW — Core orchestrator. Registers all hooks, loads admin and public classes. |
includes/class-wc-product-weight-based.php | WC_Product_Weight_Based — Custom WooCommerce product type. Getters for ordering mode, weights, pricing, free-weight settings, package card style. |
public/class-lf-wbpw-public.php | LF_WBPW_Public — Frontend/cart/order flow. Weight selector rendering, cart item data, consolidation, side-item management, order meta. |
includes/class-lf-wbpw-order-handler.php | LF_WBPW_Order_Handler — Stock reduce/restore on order status transitions. Handles both pack-based and free-weight inventory. |
includes/class-lf-wbpw-settings.php | LF_WBPW_Settings — Admin settings page (General, Option Groups, Sides, Pricing, Appearance, Tools). |
includes/class-lf-wbpw-pricing.php | LF_WBPW_Pricing — Central pricing engine. Computes line pricing with tiered, role-based, and options/sides breakdown. |
includes/class-lf-wbpw-rest.php | LF_WBPW_REST — REST API under wc-wbp/v1 namespace. |
includes/class-lf-wbpw-pack-badges.php | LF_WBPW_Pack_Badges — Marketing badge slug registry (recommended, best_seller). |
includes/class-lf-wbpw-sample-products.php | LF_WBPW_Sample_Products — Demo product generator (15 scenarios). |
includes/class-lf-wbpw-units.php | LF_WBPW_Units — Unit formatting, display unit resolution, preset normalisation. |
includes/units/ | Unit family interface + core kg/lb implementations + unit registry singleton. |
admin/class-lf-wbpw-admin.php | LF_WBPW_Admin — Admin scripts, styles, product editor panels. |
Boot Sequence
Constants defined. Unit registry and core kg/lb families loaded so extensions can hook lf_wbpw_register_units on plugins_loaded.
lf_wbpw_init() checks for WooCommerce, loads LF_WBPW, calls $plugin->run().
LF_WBPW::run() registers all WordPress and WooCommerce hooks via the loader class.
WC_Product_Weight_Based is registered as a WooCommerce product type (weight_based).
Pricing Engine
The central pricing API:
LF_WBPW_Pricing::compute_line_pricing( array $context ): array
Input context keys:
product_id,mode,weight,price_per_unit,quantitywbpw_options,wbpw_sides,include_options,include_sides
Returns:
weight_total,options_total,sides_total,line_totalunit_price_effective,regular_reference_totaldiscount_flags.sale_active,tier_applied,role_applied
Order Meta Contracts
| Meta Key | Where Set | Purpose |
|---|---|---|
_weight_data | Checkout item creation | Structured payload for rendering and reporting |
_selected_packages | Packs mode checkout | Stock reduce/restore source data |
_total_weight | Packs and free mode | Total weight snapshot |
_wbpw_display_unit_at_order | Checkout item creation | Locks stock writes to order-time unit bucket |
_wbpw_sides | Checkout item creation | Structured sides payload |
_wbpw_weight_line_total | Checkout item creation | Weight + paid options split for reporting |
_wbpw_sides_total | Checkout item creation | Sides split for reporting |
_weight_based_pack_badges | Product save | Map of pack weight → marketing slug |
_wbpw_package_card_style | Product save | Per-product override: list | grid | inherit |
Hooks & Filters
All actions and filters provided by the plugin for customisation and extension.
Actions
| Hook | Description |
|---|---|
lf_wbpw_register_units | Pass LF_WBPW_Unit_Registry instance. Register custom LF_WBPW_Unit_Family_Interface implementations. See Custom Units. |
lf_wbpw_before_weight_options_panel | Fires before the product editor weight options panel. Use to inject custom admin UI. |
lf_wbpw_after_weight_options_panel | Fires after the product editor weight options panel. |
lf_wbpw_before_weight_input | Fires before the frontend weight selector widget is rendered. |
lf_wbpw_after_weight_input | Fires after the frontend weight selector widget is rendered. |
Filters
Product & Weight
| Filter | Description |
|---|---|
lf_wbpw_product_type_label | Change the product type dropdown label (default "Weight-Based Product") |
lf_wbpw_available_weights | Modify the available pack weights array before display |
lf_wbpw_min_order_weight | Override minimum order weight |
lf_wbpw_max_order_weight | Override maximum order weight |
lf_wbpw_format_weight | Modify the formatted weight display string |
lf_wbpw_display_unit | Override the resolved display unit slug (kg, lb, or extension) |
Pricing
| Filter | Description |
|---|---|
lf_wbpw_active_price | Override the active price per unit |
lf_wbpw_tiered_price | Override the tiered price calculation |
lf_wbpw_price_html | Modify the price HTML on the product page |
lf_wbpw_weight_options | Modify pack combination results |
Cart & Order
| Filter | Description |
|---|---|
lf_wbpw_add_cart_item_data | Modify cart item data when adding a weight-based product to cart |
lf_wbpw_cart_item_price | Override cart item price |
lf_wbpw_cart_price_html | Modify cart price display HTML |
lf_wbpw_cart_item_data | Modify cart item display data (meta shown below product name) |
REST & JS
| Filter | Description |
|---|---|
lf_wbpw_rest_weight_options_response | Modify REST weight-options endpoint response |
lf_wbpw_rest_product_response | Modify REST product endpoint response |
lf_wbpw_rest_product_weight_based_data | Modify weight_based object in WC REST product response |
lf_wbpw_rest_units_response | Modify GET /units payload |
lf_wbpw_js_unit_config | Per-family JS config array |
lf_wbpw_js_unit_configs | Map of all families' JS configs (admin) |
Units & Meta
| Filter | Description |
|---|---|
lf_wbpw_meta_storage_unit | Force pack/free-weight meta suffix to kg or lb |
lf_wbpw_unit_product_select_options | Product editor "Weight display unit" dropdown options |
lf_wbpw_convert_weight_to_meta_base | Convert extension input units to stored kg/lb |
lf_wbpw_convert_weight_from_meta_base | Convert stored kg/lb back to extension display units |
lf_wbpw_effective_package_card_style | Resolved list|grid for storefront (after per-product override) |
lf_wbpw_hidden_order_itemmeta_keys | Hide internal line-item meta in admin order screen |
Example: Custom Price Label
add_filter( 'lf_wbpw_price_html', function ( $html, $product ) {
return '<span class="custom-price">From ' . $html . '</span>';
}, 10, 2 );
REST API
Dedicated REST endpoints under the wc-wbp/v1 namespace for headless and mobile integrations.
GET /wp-json/wc-wbp/v1/products/{id}
Returns product details including ordering mode, unit config, and mode-specific fields.
curl https://your-store.com/wp-json/wc-wbp/v1/products/123
Response includes: id, name, ordering_mode (packs|free), unit_config, price_per_unit, available_weights (packs mode), fw_min/fw_max/fw_step (free mode), package_card_style, and more.
Filter: lf_wbpw_rest_product_response
GET /wp-json/wc-wbp/v1/products/{id}/weight-options
Returns the best package combinations for a given target weight (Fixed Packs mode only).
curl "https://your-store.com/wp-json/wc-wbp/v1/products/123/weight-options?target_weight=2.5"
| Parameter | Type | Description |
|---|---|---|
target_weight | float | Desired weight in the product's base unit |
Response: Array of combination objects, each with packages (array of weight+qty pairs), total_weight, total_price, and is_exact flag.
Filter: lf_wbpw_rest_weight_options_response
GET /wp-json/wc-wbp/v1/units
Lists all registered unit families.
curl https://your-store.com/wp-json/wc-wbp/v1/units
Response: Array of objects with slug, is_core, label, and js_config (sub-unit factors, toggle keys, dual-unit hint, admin input units).
Filter: lf_wbpw_rest_units_response
WooCommerce REST Extension
Standard WooCommerce GET /wp-json/wc/v3/products/{id} responses are extended with a weight_based object for weight-based products containing ordering_mode, unit_config, package_card_style, pack weights, etc.
Filter: lf_wbpw_rest_product_weight_based_data
Since v1.7.0, the API uses the wc-wbp/v1 namespace instead of the previous wc/v3. Update your integrations accordingly.
PHP API
Public methods available on the product model, public class, and units helper for developers building on top of the plugin.
WC_Product_Weight_Based
| Method | Returns | Description |
|---|---|---|
get_ordering_mode() | string | "packs" or "free" |
get_available_weights() | array | Array of available pack weights |
get_weight_options($target, $adj) | array | Best combinations for target weight |
get_active_price() | float | Effective price per unit (considers sale, tier, role) |
get_price_for_weight($weight) | float | Total price for a given weight |
get_min_order_weight() | float | Minimum order weight |
get_max_order_weight() | float | Maximum order weight |
get_fw_min() | float | Free-weight minimum |
get_fw_max() | float | Free-weight maximum |
get_fw_step() | float | Free-weight slider step |
get_fw_presets() | array | Free-weight preset values |
get_fw_total_weight_available_remaining() | float|null | Remaining free-weight inventory (null = unlimited) |
get_fw_low_weight_threshold() | float | Free-weight low-stock threshold |
is_fw_low_weight_stock($adj) | bool | Whether free-weight stock is low |
get_effective_package_card_style() | string | "list" or "grid" (per-product meta → global fallback) |
LF_WBPW_Public (Static)
| Method | Returns | Description |
|---|---|---|
get_cart_adjusted_fw_remaining($product) | float|null | Remaining free-weight stock minus what's already in the cart |
get_fw_effective_max_weight($product) | float | Effective maximum weight for the slider (considering cart) |
LF_WBPW_Units
| Method | Returns | Description |
|---|---|---|
get_display_unit($product_id) | string | Resolved display unit slug (kg, lb, or extension) |
format_weight($value, $product_id) | string | Formatted weight with unit label (e.g. "2.5 kg") |
format_weight_raw($value, $product_id) | string | Formatted weight number without unit label |
normalize_preset_to_base($value, $product_id) | float | Convert preset value to base unit |
Example: Get Product Weights
$product = wc_get_product( 123 );
if ( 'weight_based' === $product->get_type() ) {
$mode = $product->get_ordering_mode(); // "packs" or "free"
$price = $product->get_active_price(); // e.g. 10.00
$weights = $product->get_available_weights(); // [0.2, 0.5, 1, 2.5]
$style = $product->get_effective_package_card_style(); // "list" or "grid"
}
Custom Unit Extensions
Register custom display units (e.g. liters, milliliters) by implementing the unit family interface and hooking into the unit registry.
Registration Hook
add_action( 'lf_wbpw_register_units', function ( LF_WBPW_Unit_Registry $registry ) {
$registry->register_family( new My_Plugin_Liter_Family() );
}, 10, 1 );
LF_WBPW_Unit_Family_Interface
Your class must implement these methods:
| Method | Description |
|---|---|
get_slug() | Unique slug saved in _weight_based_display_unit |
is_core() | Return false for extensions |
get_admin_option_label() | Product editor dropdown label |
format_weight() | Format a weight value with unit label |
format_weight_raw() | Format a weight value without unit label |
normalize_preset_to_base() | Convert preset to base unit |
get_js_config() | Array for frontend/admin JS: sub-unit factors, toggle keys, dual-unit hint, admin input units |
Loading Order
The main plugin loads the unit registry and core families early from weight-based-products.php. Your extension plugin should hook lf_wbpw_register_units on plugins_loaded (priority 20) before the first LF_WBPW_Unit_Registry::instance() call.
Storage & Meta Keys
Product meta keys use suffixes _kg or _lb. For non-core display slugs, the default storage base is kg until you change it:
add_filter( 'lf_wbpw_meta_storage_unit', function ( $meta_unit, $product_id, $display_unit ) {
if ( 'l' === $display_unit ) {
return 'kg'; // map volume to stored kg numbers
}
return $meta_unit;
}, 10, 3 );
Admin Unit Conversion
For custom input units (e.g. ml, L), implement these filters:
lf_wbpw_convert_weight_to_meta_base—( null|float $override, float $value, string $input_unit, string $base_unit )lf_wbpw_convert_weight_from_meta_base— same pattern for admin display
Return a float to override, or null to fall through to core g/kg/oz/lb logic.
REST Integration
Custom units automatically appear in:
GET /wp-json/wc-wbp/v1/units— withjs_configper familyGET /wp-json/wc-wbp/v1/products/{id}—unit_configfor the product's display familyGET /wp-json/wc/v3/products/{id}—weight_based.unit_config
Frequently Asked Questions
Common questions about compatibility, configuration, and troubleshooting.
Does this work with WooCommerce Blocks?
Yes. The plugin integrates with WooCommerce Blocks for cart quantity limits and product grid display. The block-based cart and checkout are fully supported.
Is it HPOS compatible?
Yes. The plugin declares High-Performance Order Storage (custom order tables) compatibility. It works with both the traditional wp_posts storage and the new HPOS tables.
Can I customise the colours to match my theme?
Yes. Multiple approaches:
- Use the Appearance settings tab for visual controls (colours, borders, typography)
- Apply an Appearance Preset (Default, Glass, Nature, Elegant) as a starting point
- Override CSS custom properties (
--lf-wbpw-primary, etc.) in your theme - Add custom rules in the Custom CSS field in Appearance settings
What is CSS Isolation mode?
When enabled, the plugin adds a body class (lf-wbpw-isolated) and all plugin CSS rules are scoped inside it, giving them higher specificity. This prevents themes or other plugins from accidentally overriding the plugin's styles. Disable it if you want your theme to control the styling.
Does changing the unit convert existing data?
No. Prices and weights are stored as entered. Changing the unit (e.g. from kg to lb) on an existing product does NOT automatically convert values. You must manually update all prices and package weights after a unit change.
What changed in the REST API in v1.7.0?
The API now uses the wc-wbp/v1 namespace (previously wc/v3) and the endpoint path changed to GET /wp-json/wc-wbp/v1/products/{id}/weight-options. A new endpoint GET /wp-json/wc-wbp/v1/products/{id} was also added.
Why do my cart items merge?
The plugin automatically consolidates cart lines when the same weight-based product (with identical options and sides) is added multiple times. Pack counts or free-weight values are summed. This is by design to provide a clean cart experience. If you don't want merging, ensure different options are selected each time.
Why does the cart always show quantity 1?
Weight-based products use quantity 1 as a container. The actual weight is stored internally in the weight_data field. If WooCommerce increments the quantity (e.g. to 2), the plugin automatically folds it into the weight snapshot (doubling the packs/weight).
Does it work on WordPress Multisite?
Yes, but each site needs its own WooCommerce installation and plugin activation. Settings and products are per-site.
Changelog
Version history and release notes for Weight-Based Products.
v2.1.3 (Current)
- Stability improvements and bug fixes
- WordPress 6.9 and WooCommerce 10.6.1 compatibility
v2.0.30
- Added Option Group Categories: organise related option groups under parent categories
- Added Premium Pack Cards (Grid View): visual overhaul with bold typography, 16px corners, hover effects
- Added 9 new Appearance Settings for Pack Cards: selected state colours, text colours, font sizes
v2.0.28
- Max packages in suggestion setting (
lf_wbpw_combo_max_items, default 25, range 1–500)
v2.0.27
- Per-product Package card style override (list/grid) for Fixed Packs
- New filter
lf_wbpw_effective_package_card_style
v2.0.26
- Per-pack marketing badges (Recommended, Best Seller)
- Admin pack pill stock-tier colours (green/amber/red)
v2.0.25
- Create Sample Products tool: 15 demo scenarios with option categories, groups, and WBP Samples category
v2.0.24
- Filters
lf_wbpw_convert_weight_to_meta_base/lf_wbpw_convert_weight_from_meta_basefor extension unit conversions - Price and free-weight admin dropdowns use active family's
admin_input_units
v2.0.23
LF_WBPW_Unit_Family_Interface::get_js_config()for localised sub-unit mathGET /wp-json/wc-wbp/v1/unitsendpoint withjs_configper family
v2.0.22
- Unit Registry: extensible unit families via
lf_wbpw_register_units LF_WBPW_Unit_Family_Interfaceand core kg/lb implementations
v2.0.21
- Appearance Presets: Default, Glass, Nature, Elegant one-click themes
Earlier Versions
For the complete changelog including all earlier versions, see the changelog.txt file in the plugin directory.