Description
Set your margin once. Import your supplier’s price list. Get finished, well-rounded prices.
Cost & Margin Pricing calculates sale prices from your purchase prices — with support for purchase prices in foreign currencies, daily exchange rates, margin or markup rules, psychological price rounding and a recurring supplier price list import with a full change preview.
Built on WooCommerce core fields: the selected purchase cost is always written back to WooCommerce’s own Cost of Goods Sold (COGS) field, so Woo’s reports, exports and every third-party COGS integration keep working. No parallel cost fields, ever.
Safe by design
- Nothing is ever applied without a preview — you always see the change diff first
- Every run is journaled and can be undone with one click
- Manually adjusted prices are detected and never silently overwritten
- Locked products are always skipped
EU Omnibus ready
Marketing a price cut in the EU requires showing the product’s lowest price of the last 30 days — data WooCommerce does not keep. This plugin does: every price change is logged (including ones made outside the plugin), and each product’s 30-day lowest price is computed for you. Show it to customers with the „Lowest price (30 days)” block — or the [pihlcmp_lowest_price] shortcode — a discreet, theme-friendly line like „Lowest price last 30 days: 199 kr” that you can restyle or relabel. For a variable product it shows the lowest price any of its variations had. Nothing is ever added to your storefront unless you place it yourself.
Free version
- One supplier per product with purchase price in any major currency
- Supplier column (toggle via Screen Options) and supplier filter in the products list
- Daily exchange rates (ECB reference rates, with automatic fallback)
- One global margin/markup rule with price rounding
- CSV price list import/export with change preview
- Write-back to WooCommerce core COGS
- Change journal with one-click undo
- Price change log — also records price/cost edits made outside the plugin (who, when, what)
- Margin health warnings: products selling below real cost and sales priced below cost
- Lowest price last 30 days per product — the EU Omnibus reference for sale marketing
- Optional scheduled runs (monthly) — explicit opt-in, fully journaled and undoable
Everything above is included and fully functional — nothing here is locked, limited or time-restricted.
A separate commercial plugin, Pihlfelt Cost & Margin Pricing Pro, is available from pihlfelt.se for stores that need more: several suppliers per product with a cost strategy, master-list and Excel import, rules per category/supplier/product, margin-based sale prices, a margin floor, extra scheduling intervals with email reports, and margin/supplier reports. It is a different plugin with its own code — it is not unlocked from within this one.
External Services
This plugin fetches currency exchange rates from two services: on a daily schedule, when a new currency first needs a rate (e.g. during an import preview), and when you click „Fetch rates now” — and only when you use purchase prices in a currency other than your store currency.
European Central Bank (ECB) reference rates — the primary source. The plugin requests the public daily reference rate file. No personal data and no data about your store is sent; it is a plain file download. Terms: https://www.ecb.europa.eu/services/disclaimer/html/index.en.html
ExchangeRate-API open endpoint (open.er-api.com) — used as fallback when the ECB feed is unavailable, and for currencies the ECB does not publish. The request URL contains only your store’s base currency code; no personal data and no other data about your store is sent. Terms: https://www.exchangerate-api.com/terms — attribution is shown on the plugin’s settings page as required.
Rates are indicative reference rates intended for price calculation suggestions, not for payment processing.
Screenshots








Blocks
This plugin provides 1 block.
- Lowest price (30 days) Shows the product’s lowest price of the last 30 days — the reference price EU Omnibus rules require next to a price reduction.
FAQ
Does this replace WooCommerce’s Cost of Goods field?
No — it builds on it. The plugin stores supplier, currency and exchange rate details, and always writes the resulting cost to WooCommerce core’s COGS field. Woo’s own reports and exports keep working.
Can prices be changed without my approval?
Only if you explicitly enable scheduled automatic runs in Settings — and even then, changes above your confirmation threshold are never auto-applied, locked and manually re-priced products are never touched, and every run is journaled and undoable. With the feature off (the default), every rule run and import produces a preview diff that you apply explicitly. Products you have adjusted manually are detected and skipped until you actively release them.
How do sale prices work?
This plugin calculates and maintains your ordinary prices — it does not generate sale prices. A sale price on a product is yours: type it in WooCommerce’s normal sale price field (a weekend campaign at a fixed price, say) and the plugin leaves that product’s price alone for as long as the campaign is running or scheduled. When the campaign has ended, the product is priced by your rules again. The product’s cost keeps being written to WooCommerce’s cost field throughout.
If you would rather keep ordinary prices up to date during campaigns, turn on „Let runs update the regular price even while a product is on sale” in Settings. A rule price that would land at or below your sale price is still never written — WooCommerce would delete the sale price — and the row is reported instead.
Margin-based sale prices, on-sale flags and scheduled campaigns are part of the separate Pro plugin (see the link below).
What do blank cells in the import file mean?
Blank always means „leave unchanged” — a file can never accidentally clear something by omitting it. The only required columns are a cost column and one identifier column (product ID, supplier SKU, GTIN or SKU).
Does the plugin track price history?
Yes. Every change the plugin makes is journaled, and price/cost edits made anywhere else (the product editor, other plugins, the REST API, scheduled sales) are logged too — visible under „Recent changes” on the product’s Cost & Margin tab. This also gives you the lowest price of the last 30 days per product, the reference value the EU Omnibus rules require when marketing a price cut. The log starts at plugin activation; earlier history cannot be known.
How do I show the 30-day lowest price to customers?
Add the „Lowest price (30 days)” block where you want it — in the Single Product template, a product description or a product grid; inside a product context it finds the product on its own, and its sidebar lets you change or hide the label and set colours and size. Classic themes and page builders can use the
[pihlcmp_lowest_price]shortcode instead (label="Your text:"changes the text,label=""shows the bare price,id="123"targets a product outside a product context). Both render the same discreet line: „Lowest price last 30 days: 199 kr”. The output carries the CSS classespihlcmp-lowest-price,pihlcmp-lowest-price-labelandpihlcmp-lowest-price-valueso you can style every part; no styling is imposed. The plugin never adds anything to your storefront on its own.How many suppliers can I have?
As many as you like. Each product is priced from one supplier’s cost: pick the supplier on the product’s Cost & Margin tab (or in each variation’s box), enter the cost and save. To move a product to a different supplier, select the new supplier, enter its cost and tick „Remove cost row” — the old row is replaced in one save. Imports run one supplier’s price list at a time, and the products list has a supplier column and filter so you can always see who supplies what.
Which currencies are supported?
All major currencies via the ECB daily reference rates (about 30), and roughly 130 more via the automatic fallback source. You can also enter exchange rates manually — manual rates always win.
Reviews
There are no reviews for this plugin.
Contributors & Developers
“Pihlfelt Cost & Margin Pricing for WooCommerce” is open source software. The following people have contributed to this plugin.
ContributorsTranslate “Pihlfelt Cost & Margin Pricing for WooCommerce” into your language.
Interested in development?
Browse the code, check out the SVN repository, or subscribe to the development log by RSS.
Changelog
1.1.1
- Fix: Security hardening — the label of the “Lowest price (30 days)” block and shortcode is sanitized when read, admin templates are included from a fixed list, and a list filter uses an explicit callback.
1.1.0
- New: „Lowest price (30 days)” block — the block counterpart of the
[pihlcmp_lowest_price]shortcode. It finds the product on its own inside a product template or product grid, and its label, colours and size are set in the block sidebar. - New: The plugin now lives under WooCommerce Cost & Margin, with its sections as tabs. Every page keeps its address, so bookmarks still work.
- New: Deactivated suppliers can be reactivated, and stay selectable on products that still have a cost from them.
- New: Exports have no row limit, and „Unicode Text” (UTF-16) price lists can be imported.
- Fix: The cost is now written to WooCommerce’s cost field for every product in a run — also when the price itself stays the same, is locked, was re-priced by hand or is on sale. Previously a changed cost only reached the cost field when the price changed too.
- Fix: The price run preview lists every change. With more than 500 products, rows beyond the first 500 were applied without being shown, and rows above the confirmation threshold among them could not be ticked.
- Fix: A manual sale campaign that has ended no longer keeps its product out of price runs (WooCommerce 11 leaves the sale price on the product after the end date).
- Fix: A rule price at or below your own sale price is skipped and reported instead of being written — WooCommerce would have deleted the sale price without a trace.
- Fix: Stores that enter prices excluding VAT now land on the rounding target including VAT (9.99 no longer shows as 9.98), and the preview shows the price the shop will really display.
- Fix: A run interrupted by an error in another plugin is closed as „completed with failures” and can be undone, instead of staying „applying” forever.
- Fix: Saving Settings no longer postpones the next automatic run.
- Fix: Price lists with a backslash at the end of a quoted cell lost rows; files without a byte-order mark could be read with the wrong character set; a spreadsheet’s scientific notation (1,5E-05) was misread.
- Fix: A product’s purchase price that could not be saved (wrong currency code, another supplier already set) now says so instead of failing silently.
- Fix: An exchange rate held back by the sanity check is accepted when the next day’s fetch confirms it, rather than being held back forever. Rates for weak currencies keep their precision.
- Fix: The 30-day lowest price of a variable product now covers its variations.
- Tweak: Declared compatible with the Cart and Checkout blocks. Tested with WooCommerce 11.1 and WordPress 7.1.
- Tweak: Uses the Action Scheduler that ships with WooCommerce instead of bundling a copy.
1.0.0
- Initial release.
