E-commerce
Omnibus 30-dagenprijs: 15 audit-fouten van e-com-agents
Vijftien manieren waarop een Nederlandse e-commerce automation-agent de Omnibus 30-dagenprijsregel breekt, gerangschikt naar wie het in een uur fixt en wie niet.

Een merchandiser bij een middelgrote Nederlandse beauty-etailer zette op een dinsdagmiddag 600 SKU's klaar voor het Sinterklaas-weekend. De process-automation-agent zette de SALE-banners woensdagochtend om 02:00 aan. Om 09:14 lag er een e-mail van de Consumentenbond. Die had 's nachts een steekproef gedaan. Van de 600 noemden 63 banners een 'van'-prijs die de storefront de afgelopen 30 dagen nooit had gerekend.
Dit is de standaardvorm van een Omnibus-richtlijn-fout. De agent deed z'n werk. De price-rules engine deed z'n werk. Samen liepen ze het bedrijf een audit-fout in voordat de merchandiser haar eerste koffie op had.
Hieronder een veldgids voor de vijftien manieren waarop dat gesprek mis kan gaan, gerangschikt naar wie het moet fixen. Acht ervan kan een merchandiser voor de lunch oplossen, binnen de price-rules engine. Zeven hebben een backend-engineer nodig die eerst iets bouwt dat de meeste Nederlandse e-com stacks nog missen: een fatsoenlijke kortingshistorie-ledger.
De regel in één alinea
Artikel 6a van de EU-richtlijn Prijsaanduiding, zoals gewijzigd door Richtlijn 2019/2161 (Omnibus), schrijft voor dat elke aankondiging van een prijsverlaging de laagste prijs vermeldt die in de 30 dagen vóór de verlaging is gehanteerd. De Nederlandse implementatie zit in het Besluit prijsaanduiding producten. De ACM handhaaft, met boetes onder Omnibus tot 4% van de jaaromzet, en de Consumentenbond doet er één of twee keer per jaar informeel een gepubliceerde steekproef op.
De regel is simpel op papier en hard in productie. Elke 'van EUR X, nu EUR Y'-combinatie, elk percentage-chipje, elke doorgestreepte prijs, elk 'korting'-label moet wiskundig kloppen met dezelfde 30-dagen-laagste-referentie voor dat product. Over storefront, app, categoriepagina, syndicated feed en e-mail. Tegelijk. Voor elke variant.
Fouten die de merchandiser zelf in de price-rules engine kan fixen
Dit zijn configuratie-drifts. De data bestaat; de agent leest 'm uit het verkeerde veld.
1. Adviesprijs als doorgestreepte van-prijs
De meest voorkomende. De agent trekt de adviesprijs van de fabrikant uit de PIM en zet 'm als doorhaling. Handig, want elk product heeft er een. Maar tenzij je de afgelopen 30 dagen daadwerkelijk voor die adviesprijs hebt verkocht, is het geen legale referentie. Fix: bind het strikethrough-veld aan het 30-dagen-laagste-veld, niet aan de adviesprijs.
2. Percentage-chip berekend tegen de adviesprijs
Dezelfde oorzaak, ander oppervlak. Het 'min 40%'-chipje wordt berekend tegen hetzelfde verkeerde getal. Chip en doorhaling moeten samen fout zijn of samen goed. De meeste rule engines laten je de basis van het chipje in één regel configuratie overschrijven.
3. Ledenprijs behandeld als gewone prijs
Je runt een Friends-of-the-brand-programma. Leden betalen EUR 39, niet-leden EUR 49. De agent kiest EUR 49 als 'normale' prijs en plant een SALE-banner tegen die prijs bij een drop naar EUR 35. De 30-dagen-laagste over alle klanten was eigenlijk EUR 39, en zo betaalden de meeste kopers ook. De rekensom klopt voor niemand, behalve voor niet-leden die op dag één kopen.
4. Gratis-verzending-besparing meegerekend in de kortingstekst
'Bespaar EUR 12,95' klinkt als een prijsverlaging. Dat is het niet, als EUR 7,95 ervan verzendkosten zijn. Omnibus-referentieprijsregels gelden voor de productprijs. Besparingen op verzending vallen onder een aparte consumenten-informatieplicht. Hou ze in aparte widgets.
5. Vouchercode in de cart, gerenderd als was/nu
Een KORTING25-code in de cart haalt 25% van de regel af. Sommige templates rerenderen de PDP met een verse 'van EUR 80, nu EUR 60' zodra de code actief is. Dat is een aankondiging van een prijsverlaging en triggert de 30-dagenregel. Toon de korting als korting, niet als nieuwe referentieprijs.
6. Vanaf-prijs op de categoriepagina
Categorie-tegels tonen 'vanaf EUR 12,50' op basis van de huidige goedkoopste variant. Staat die variant in de aanbieding, dan is de vanaf-prijs de aanbiedingsprijs, maar de tegel toont nog steeds een doorhaling die bij het hoofdproduct hoort. Referentieprijs-logica moet gelden voor de getoonde variant, niet voor het hoofdproduct.
7. Per-locale van-prijs zonder per-locale historie
Je verkoopt .nl, .be en .de uit dezelfde catalogus. De agent lokaliseert de doorhaling met een statische FX- of btw-correctie. De 30-dagen-laagste in EUR voor een Belgische klant kan een ander getal zijn dan voor een Nederlandse, zodra je promo's meeneemt die alleen in NL liepen. De referentieprijs moet de laagste prijs zijn die in die locale daadwerkelijk is getoond.
8. Bundelreferentie als de som der delen
Een bundel van drie SKU's gaat voor EUR 79 over de toonbank. De agent toont de doorhaling als de som van de individuele van-prijzen (EUR 99). Maar de bundel heeft een eigen 30-dagen-prijshistorie en de som is geen legale referentie. Toon óf de eigen van-prijs van de bundel, óf kondig geen verlaging op de bundel aan.
Het label 'merchandiser kan dit fixen' is misleidend als je rules engine helemaal geen veld voor de 30-dagen-laagste heeft. De fix is één regel; de voorwaarde is een kolom die ook echt bestaat. Check dat eerst, voordat je de marketing-lead belooft dat het vandaag live gaat.
Fouten die eerst een kortingshistorie-ledger nodig hebben
Dit zijn geen display-bugs. Het zijn data-model-bugs. Geen enkele UI-laag lost ze op, omdat de onderliggende waarheid niet wordt opgeslagen.
9. SKU opnieuw uitlijsten om de historie te resetten
Een sourcing manager archiveert na elke cyclus het oude artikelnummer en maakt de SKU aan onder een nieuwe code. De agent leest het nieuwe artikelnummer, ziet nul historie en zet de van-prijs die de merchandiser wil. De ACM behandelt dit als ontwijking. De enige fix is een ledger die het product volgt, niet het artikelnummer, met een stabiele product-identiteit die het opnieuw uitlijsten overleeft.
10. Variantassen behandeld als zelfstandige SKU's
Hetzelfde shirt, maat M en maat L. Twee SKU's. M was vorige week in de aanbieding, L niet. De agent leest de historie van de L-variant, kondigt een korting aan tegen een oudere L-prijs en negeert dat het hoofdproduct een kortingsweek had. Referentieprijs-logica hoort het hoofdproduct te volgen over variantassen die in de beleving van de consument hetzelfde product zijn.
11. Opeenvolgende sales zonder reset-venster
Je runt '20% korting' de eerste helft van de maand en '30% korting' de tweede helft. De agent berekent de doorhaling tijdens de tweede sale via de 30-dagen-laagste, en dat is de prijs uit de eerste sale van twee weken geleden. Het chipje zegt nu 'min 12,5%'. De marketing-lead vraagt de agent om 'de echte van-prijs te gebruiken' en de agent doet dat. Dat doen is de overtreding.
12. Flash-sale korter dan de staart van de vorige sale
Een 48-uurs flash-sale draait op EUR 29. De vorige sale op EUR 34 eindigde 28 dagen geleden. De 30-dagen-laagste is twee dagen in de flash al EUR 29, en de komende 26 dagen moet elke volgende promo EUR 29 als bodem aanhouden. Agents die de doorhaling 's nachts opnieuw berekenen zonder besef van het schuivende venster, drijven af.
13. Feed-exports lopen uit de pas met de storefront
Je Google Shopping-feed, Beslist-export en Bol seller-feed trekken uit een andere snapshot dan de storefront-renderer. De storefront heeft de juiste van-prijs; de feed laat die van gisteren zien. Consumentenbond en ACM vergelijken allebei over kanalen heen. Een ledger als single source of truth, opgevraagd door renderer én exporter, is de enige uitweg.
14. Pre-orders die naar SALE gaan zonder enige historie
Een pre-order opent op dag één. Er is geen 30-dagen-historie. De agent hoort te weigeren een SALE-banner te plaatsen. Veel doen dat niet, omdat de rules engine afwezige historie behandelt als nul, en nul is lager dan de huidige prijs. Fix: de ledger moet 'historie bestaat al minstens 30 dagen' als expliciete boolean blootstellen, en de agent moet daarop checken voordat hij een banner plant.
15. Personalisatie die de enkele referentie breekt
Je A/B-test prijzen per gebruikerssegment. Segment A ziet EUR 49. Segment B ziet EUR 45. Daarna zet je beide in de sale op EUR 35. De legale referentie is de laagste prijs die de afgelopen 30 dagen daadwerkelijk aan consumenten is gerekend, en dat is EUR 45. Segment A een 'van EUR 49' tonen is een overtreding, ook al klopt het voor dat segment. Een ledger die over personalisatie-takken heen aggregeert, is de voorwaarde voor elke vorm van gesegmenteerde prijsstelling.
Een werkbare kortingshistorie-ledger
De kleinste tabel die een ACM-audit overleeft, ziet er zo uit:
create table price_history (
product_id uuid not null,
locale text not null,
observed_at timestamptz not null,
shown_price_eur numeric(10,2) not null,
channel text not null,
segment text,
primary key (product_id, locale, observed_at, channel, coalesce(segment, ''))
);
create index price_history_window
on price_history (product_id, locale, observed_at desc);
Drie punten over deze vorm. Eén: product_id is de stabiele identiteit, niet het artikelnummer, dus opnieuw uitlijsten van een SKU reset niks. Twee: elk kanaal schrijft een eigen rij, dus divergentie tussen feed en storefront is auditbaar. Drie: de segment-kolom is nullable maar indexed, zodat gepersonaliseerde prijzen voor de legale referentie kunnen worden geaggregeerd zonder de per-segment-data te verliezen.
De 30-dagen-laagste-query is dan één regel, en de agent leest 'm voordat hij ook maar één banner plant:
select min(shown_price_eur)
from price_history
where product_id = $1
and locale = $2
and observed_at >= now() - interval '30 days';
Geeft de query null terug, dan geen banner. Geeft hij een getal hoger dan de geplande aanbiedingsprijs, dan is dat getal de doorhaling. Geeft hij een getal gelijk aan of lager dan de geplande aanbiedingsprijs, dan is de sale geen verlaging en de banner illegaal.
De audit van vijf minuten die je vandaag kunt doen
Pak tien producten die nu in de SALE staan. Open voor elk de PDP, de categorie-tegel, de Google Shopping-listing en de Bol seller-listing als je die hebt. Maak van alle vier een screenshot. De van-prijs hoort over alle vier hetzelfde te zijn. Is dat niet zo, dan heb je in elk geval fout 13 in productie. Haal vervolgens uit je PIM de laatste 30 dagen prijsmutaties van die tien producten op en bevestig dat de doorhaling op de PDP gelijk is aan het minimum. Lukt het je PIM niet om dat rapport binnen een minuut te produceren, dan heb je nog geen ledger en sta je open voor fouten 9 tot en met 15 op het moment dat de merchandiser de volgende campagne plant.
Toen we afgelopen winter de prijshistorie-ledger bouwden voor een midmarket Nederlandse beauty-etailer, liepen we tegen variantas-collaps aan: de rules engine behandelde kleurvarianten als zelfstandige producten, en het 30-dagen-venster van de populaire blauwe SKU maakte de kortingsrekening op de niche rode SKU illegaal. We hebben dat opgelost door de ledger aan de identiteit van het hoofdproduct te koppelen en variantdivergentie als expliciete override-flag bloot te leggen, zodat de merchandiser de overtreding in staging ziet in plaats van in een mail van de Consumentenbond. Wil je beter zien hoe de automation-agent naar die ledger schrijft voordat hij één banner plaatst, dan is de vorm dezelfde voor elke e-com-catalogus boven de duizend SKU's.
Kern
Acht Omnibus-fouten zitten in de price-rules engine en kan een merchandiser zelf fixen. Zeven zitten dieper en hebben eerst een kortingshistorie-ledger nodig.
FAQ
Wat eist de Omnibus-30-dagenregel eigenlijk?
Elke geadverteerde prijsverlaging moet verwijzen naar de laagste prijs die de verkoper in de 30 dagen voor de sale heeft gerekend, op hetzelfde kanaal en aan hetzelfde publiek. De doorhaling en het percentage-chipje moeten allebei met dat getal kloppen.
Kan ik het 30-dagen-venster resetten door een SKU onder een nieuw artikelnummer opnieuw uit te lijsten?
Nee. De ACM behandelt het opnieuw uitlijsten van een SKU om het referentievenster te ontwijken als ontwijking. Je prijshistorie moet een stabiele product-identiteit volgen, niet het artikelnummer. Daarom heeft de ledger een eigen product_id.
Geldt de regel ook voor bundels?
Ja. Een bundel heeft een eigen prijshistorie. Je kunt de som van de individuele referentieprijzen niet als doorhaling voor de bundel gebruiken. Toon óf de eigen van-prijs van de bundel, óf kondig geen verlaging op de bundel aan.
En pre-orders die nog geen 30-dagen-historie hebben?
De agent hoort te weigeren een SALE-banner te plaatsen totdat het 30-dagen-venster bestaat. Afwezige historie behandelen als prijs van nul is de meest voorkomende reden dat pre-order-pagina's een steekproef niet doorstaan.