Polski for WooCommerce
A free plugin that adapts WooCommerce to Polish legal and business requirements. GPSR, Omnibus, GDPR, DSA, KSeF-ready and storefront features in one place.
Polski for WooCommerce brings together the requirements of the Polish market, current EU directives and store functionality in a single plugin. Instead of installing 10 separate plugins to handle unit prices, withdrawal forms, GPSR, DSA, food data, compliance auditing and merchandising tools - you get everything in one package.
The plugin is currently under review at WordPress.org. Source code is available on GitHub.
Requirements: WordPress 6.4+, WooCommerce 8.0+, PHP 8.1+ | Version: 1.3.0 | License: GPLv2
Need PDF invoices, KSeF, NIP validation, InPost or multi-step checkout? See Polski PRO - the premium extension that adds operational features to the free version.
Table of contents
- Installation and configuration
- GPSR - product safety
- Omnibus - lowest price in 30 days
- Withdrawal from contract - returns
- Storefront modules
- Food products
- Other modules (DSA, KSeF, GDPR, VAT ID, brands, Schema.org, CRA, DPA and more)
- Technical requirements
- Shortcodes
- Bug reports and discussions
Installation and configuration
Getting started
Configuring Polski for WooCommerce involves 6 steps. Most settings work with their default values - just enable the modules you need.
Installation
From the WordPress dashboard (recommended)
- Go to Plugins > Add New
- Search for Polski for WooCommerce
- Click Install and then Activate
- A new Polski menu will appear in the sidebar
Manually from a ZIP file
- Download the ZIP from GitHub
- Go to Plugins > Add New > Upload Plugin
- Select the ZIP file and click Install
- Click Activate
Enabling modules
After activation, go to Polski > Modules. You will see a list of 42 available modules grouped into categories:
- Prices and Omnibus - unit price, lowest price in 30 days, VAT display, “from” price for variable products, OSS threshold observer (€10,000)
- Checkout - order button, legal checkboxes, VAT ID, minimum order value/quantity rules
- Legal compliance - GPSR, DSA, KSeF, greenwashing, GDPR
- Consumer rights - withdrawal form, legal pages, ODR
- Product information - delivery time, manufacturer, brands, GTIN
- Food products - nutritional values, allergens, Nutri-Score
- Storefront modules - wishlist, compare, quick view, filters, search
- Email - legal attachments, double opt-in, automated review request emails after purchase
- Tools - compliance dashboard, store audit
Each module has an on/off toggle. Enable the ones you need.
Legal configuration (minimum)
For basic compliance with Polish law, enable:
- Legal checkboxes - go to the module settings, enable checkboxes for terms of service, privacy policy and withdrawal rights
- Order button - automatically changes the button text to the legally required “I order with obligation to pay”
- Legal pages - select your Terms of Service, Privacy Policy and Withdrawal Rights pages
VAT configuration
- Make sure you have the correct VAT rates in WooCommerce > Settings > Tax (23%, 8%, 5%, 0%)
- Enable the VAT display module and choose a mode (gross/net)
- If you use the VAT exemption (Article 113) - tick the appropriate checkbox
GPSR (if you sell physical products)
From 13 December 2024, the GPSR regulation requires product pages in online stores to include manufacturer data and the responsible person’s details. Enable the GPSR module and fill in the data in the Polski tab within the product editor.
Compliance dashboard
Go to Polski > Dashboard and click Check compliance. The system will verify:
- Whether legal pages are created and assigned
- Whether legal checkboxes are enabled at checkout
- Whether the order button has the correct text
- Whether VAT rates are configured
- Whether GPSR data is filled in (if the module is active)
A green/red result for each item. Fix the red items and check again.
Theme templates
All plugin templates can be overridden from your theme. Copy the file from wp-content/plugins/polski/templates/ to wp-content/themes/your-theme/polski/ and edit it.
REST API
The plugin exposes a full REST API under the polski/v1/ namespace:
GET /polski/v1/settings- retrieve settingsPOST /polski/v1/settings- update settingsGET /polski/v1/withdrawals- list withdrawal requestsGET /polski/v1/checkboxes- checkbox configuration
API documentation is available after installing the plugin.
WP-CLI
wp polski migrate # run database migrations
wp polski smoke-test # verify installation integrity
GPSR - general product safety
From 13 December 2024, EU Regulation 2023/988 (GPSR - General Product Safety Regulation) requires online store product pages to include manufacturer data and details of the person responsible for product compliance. The GPSR module in Polski for WooCommerce automatically displays this information on the product page and provides management tools in the admin panel.
Enabling the module
- Go to Polski > Modules
- Find the Legal compliance section
- Enable the GPSR module
- Save changes
Once enabled, the module registers new fields in the product editor and adds a status column to the product list.
GPSR fields in the product editor
After enabling the module, a GPSR - Product safety section appears in each product editor (in the Polski tab). It contains 8 fields:
| Field | Type | Description |
|---|---|---|
| Manufacturer name | text | Full name of the entity that manufactured the product |
| Manufacturer address | textarea | Full postal address of the manufacturer |
| Importer name | text | Importer name (fill in if the product comes from outside the EU) |
| Importer address | textarea | Full postal address of the importer |
| Responsible person | text | EU entity responsible for product compliance with GPSR |
| Product identifier | text | Batch number, serial number or other identifier |
| Safety warnings | textarea | Warnings required by regulations or the manufacturer |
| Safety instructions | textarea | Instructions for safe use |
The GPSR section on the product page is only displayed when at least one field is filled in. Data is presented in a <details> element with the heading “Product safety (GPSR)” - the customer can expand it by clicking.
Display on the product page
The module automatically injects the GPSR section below the product information (hook woocommerce_product_meta_end). It shows only fields that have a value.
HTML structure of the section:
<div class="polski-gpsr-info">
<details class="polski-gpsr-info__details">
<summary class="polski-gpsr-info__summary">Product safety (GPSR)</summary>
<dl class="polski-gpsr-info__list">
<dt>Manufacturer</dt>
<dd>Manufacturer name</dd>
<!-- additional fields -->
</dl>
</details>
</div>
You can customise the section styling via CSS in your theme, using the classes .polski-gpsr-info, .polski-gpsr-info__details and .polski-gpsr-info__list.
If you want to change the layout or content of the section, copy the template from:
wp-content/plugins/polski/templates/single-product/gpsr-info.php
to:
wp-content/themes/your-theme/polski/single-product/gpsr-info.php
GPSR status column on the product list
On the product list (Products > All Products), the module adds a GPSR column with a visual indicator of how many fields are filled:
- Green checkmark (checkmark) - 3 or more of 8 fields filled
- Yellow warning triangle - 1-2 fields filled
- Grey dash - no fields filled
Hovering over the icon shows a tooltip with the number of filled fields, e.g. “5/8 fields filled”. This lets you quickly identify products that need GPSR data without opening each one individually.
CSV import and export
The GPSR module is fully supported by the CSV import/export mechanism in Polski for WooCommerce. This is the fastest way to fill in GPSR data for many products at once.
Export
- Go to Polski > Import / Export CSV
- Click Export products
- Download the CSV file
In the CSV file, each product has GPSR columns with the polski_gpsr_ prefix:
| CSV column | Corresponding field |
|---|---|
polski_gpsr_manufacturer_name | Manufacturer name |
polski_gpsr_manufacturer_address | Manufacturer address |
polski_gpsr_importer_name | Importer name |
polski_gpsr_importer_address | Importer address |
polski_gpsr_responsible_person | Responsible person |
polski_gpsr_product_identifier | Product identifier |
polski_gpsr_safety_warnings | Safety warnings |
polski_gpsr_instructions | Safety instructions |
Import
- Fill in the GPSR columns in the CSV file (the
idorskucolumn is required for product identification) - Go to Polski > Import / Export CSV
- Upload the file and click Import
- The plugin will update product meta for all rows in the file
The import overwrites existing values. Empty cells in the CSV remove previously saved data for that field.
Related documentation pages
Omnibus - lowest price in 30 days
The Omnibus module in Polski for WooCommerce automatically tracks product price history and displays the lowest price from the last 30 days for products on sale. It satisfies the requirements of the Omnibus Directive (EU 2019/2161), which has been in force in Poland since 1 January 2023.
What is the Omnibus Directive?
The Omnibus Directive (EU 2019/2161) requires online stores to inform customers of the lowest price of a product over the past 30 days whenever a product is presented as being on sale. This means that alongside the crossed-out (regular) price and the promotional price, a message such as “Lowest price in the last 30 days: $89.00” must appear.
The module records the price on every product save and stores the history automatically. No manual data entry is required.
Enabling the module
- Go to Polski > Modules
- Find the Lowest price (Omnibus) module in the “Prices and Omnibus” group
- Enable the toggle and click Save settings
- From this point the plugin starts recording prices on every product save
How price tracking works
The price is recorded automatically in two situations:
- when a simple product is saved (woocommerce_update_product, woocommerce_new_product)
- when a variation of a variable product is saved (woocommerce_save_product_variation)
A maximum of one record per product is saved each day - duplicates are skipped. The module tracks both the regular price and the sale price. The lowest effective price over the tracking period is calculated automatically at display time.
Old records are removed automatically by the cron job (polski_daily_maintenance) according to the “Keep history (days)” setting.
Module settings
Price tracking
| Setting | Default value | Description |
|---|---|---|
| Tracking period (days) | 30 | Number of days used when calculating the lowest price. The Directive requires a minimum of 30 days. |
| Keep history (days) | 90 | Records older than this limit are automatically removed from the database. |
| Prices with tax | enabled | When active, tracks and displays gross prices (including VAT). |
Display
| Setting | Default value | Description |
|---|---|---|
| Sale products only | enabled | The message appears only when the product has an active sale price. |
| Product page | enabled | Displays the message on the single product page. |
| Product listing (shop, categories) | disabled | Shows the message in the product loop. |
| Related and featured products | disabled | Shows the message in “Related products” and “Featured” sections. |
| Cart | disabled | Shows the message next to the product in the cart. |
| Show regular price (before sale) | disabled | Additional information about the price before the sale started. |
Message template
| Setting | Default value | Description |
|---|---|---|
| Message text | Lowest price in the last {days} days: {price} | Text displayed next to the product. Supports variables: {price}, {days}, {date}, {regular_price}. |
| No price history | Hide message | Behaviour when no historical data exists: hide / show current price / custom text. |
| Custom text (no history) | Price has not changed in the last {days} days | Text displayed when there is no history and the “custom text” option is selected. |
| Counted from | Sale start date | Reference point: sale start date or today’s date. |
Variable products
| Setting | Default value | Description |
|---|---|---|
| Track variations separately | enabled | Each variation of a variable product has its own independent price history. |
Template variables
In the “Message text” field you can use the following variables:
{price}- lowest effective price over the tracking period (formatted, with currency){days}- number of days from the “Tracking period” setting{date}- date on which the lowest price was recorded{regular_price}- regular product price before the sale
Example messages:
Lowest price in the last {days} days: {price}
Previous lowest price: {price} (over the last {days} days)
Price before sale: {regular_price} | Lowest in 30 days: {price}
Shortcode
The shortcode [polski_omnibus_price] lets you display the lowest price information anywhere - in a product description, a page template or a page builder element.
Basic use (displays the price of the current product in the WooCommerce loop):
[polski_omnibus_price]
With a specific product (outside the WooCommerce loop, e.g. on a text page):
[polski_omnibus_price product="123"]
Where 123 is the product ID. The shortcode returns an empty string when the product is not on sale (with the default “Sale products only” setting) or when no historical data exists.
Compatibility with external Omnibus plugins
Polski for WooCommerce automatically detects popular third-party Omnibus solutions (e.g. wc-price-history). When such a plugin is active, the module delegates data retrieval to it instead of using its own price history database. Integration status is visible in the module panel.
When no external plugin is installed, the built-in tracking system is used.
CSS classes and HTML filter
The generated HTML has the following structure:
<div class="polski-omnibus-price">
<span class="polski-omnibus-price__text">Lowest price in the last 30 days: $89.00</span>
</div>
You can modify the appearance via CSS in your theme or use the PHP filter:
add_filter('polski/price/omnibus_html', function (string $html, $lowest, $product): string {
// $lowest is an OmnibusPrice object with effectivePrice() and currency fields
// $product is a WC_Product object
return $html;
}, 10, 3);
