Publishing a price list: XML and CSV, every day
The Croatian decision on publishing price lists requires XML ili CSV on your website, refreshed daily and kept for 30 days. The plugin does it on a permanent address, with an archive.
What gets published
Every day, right after the price snapshot, the whole catalogue is exported to the chosen formats at a permanent address. The dated file stays as an archive and an undated file always points at the newest list.
https://your-store.com/cjenik/
https://your-store.com/cjenik/cjenik.csv
https://your-store.com/cjenik/cjenik-2026-09-21.csv
https://your-store.com/cjenik/index.jsonThree formats, the same content
CSV is semicolon separated, the notation Croatian ERPs and localised Excel produce. Numbers use a decimal point and no thousands separator.
XML carries one element per product; JSON adds a product count at the end so a truncated file is obvious.
Archive and JSON index
index.json lists every available day and address per format, plus the store name, export date, product count and column list.
Retention is a setting, ninety days by default.
Why it is served through PHP
A file in uploads is public on both Apache and nginx, while an .htaccess rule only applies to Apache. Serving through WordPress honours the visibility setting on any web server and keeps the headers correct.
Large catalogues
The export runs in batches, writing to a temporary file and renaming only once the whole catalogue is in. Anyone fetching mid-export gets yesterday's complete list rather than today's half one.
Customising the content
Each row passes through a filter before it is written, so values can be changed from a theme or your own plugin.
add_filter( 'klikoteka_cjenik_red', function ( $red, $product ) {
$red['kategorija'] = strtoupper( $red['kategorija'] );
return $red;
}, 10, 2 );Export columns
| Column | What it holds |
|---|---|
| sifra | Product SKU; the WooCommerce id when there is none |
| naziv | Product name as shown in the store |
| barkod | GTIN/EAN from the WooCommerce field, when filled |
| kategorija | Full categories, separated by a slash |
| cijena | Selling price including tax, as the buyer sees it |
| cijena_bez_pdv | The same price excluding tax |
| valuta | Store currency, e.g. EUR |
| sidrena_cijena | Anchor price, when one exists |
| sidrena_na_dan | Which day that is |
| najniza_30_dana | Lowest price in the window, when covered |
| na_snizenju | da or ne |
| stanje | Stock quantity, when enabled in settings |
| url | Product address in the store |
Frequently asked
How long does exporting a few thousand products take?
It runs in batches and each batch schedules the next. Typically a few minutes, and the previous list stays fully available throughout.
Can I export only some categories?
The export covers the whole published catalogue. Row content can be changed through the klikoteka_cjenik_red filter.
Are variations included?
Yes, each variation is its own row. Variable parents have no price of their own and are skipped.
Is the price list indexed by Google?
The index page carries noindex, and the files themselves are data, not search content.
What if I already have a Google Shopping feed?
Different job. An advertising feed has its own fields and rules; this is a full catalogue export with pricing and historical values.
Also in the same plugin
Lowest price in the last 30 days
How it is computed, why WooCommerce cannot do it and what shows while there is no history.
Anchor price for a reference day
The other decision in the same NN 101/2026: two reference days and how to map them to products.
Sidrena cijena i cjenik za WooCommerce
All three features, a one-off €20 + VAT.
