# Normalizing car configurator pricing: list, net and discount

Canonical URL: https://www.rastriq.es/en/guides/normalize-car-configurator-pricing/ · Spanish version: https://www.rastriq.es/guias/normalizar-precios-configuradores-coches/

> List price, net price, discount and registration tax in car configurators: how to read real BMW, Kia and Toyota fields and map them to one common schema.

TECHNICAL GUIDE

Each manufacturer answers "how much does this car cost?" with different fields. This guide shows how to read real configurator fields and map them to a common schema without mixing tax bases.

Published 6 October 2026 · Rastriq

## The problem: one question, twenty-eight answers

If you extract prices from several configurators and put them in one column, you are most likely comparing different things. One manufacturer publishes the price with VAT, another without; one already applies the promotion and another shows the list price; some include registration tax and others leave it out. If you do not tell the base of each amount, any comparison across brands, countries or dates is contaminated.

Normalizing is not about "cleaning" the data but about declaring, for each amount, what it is: list or discounted, gross or net, with or without special taxes. That declaration is what lets you use the data later in a dashboard, a pricing model or a contract. Behind every brand page of the [OEM configurators hub](https://www.rastriq.es/en/oem-configurators/) there is a field dictionary for exactly this purpose.

## The three axes you cannot mix

Before looking at fields, it helps to fix the vocabulary. There are three independent axes, and every amount in a configurator sits at some position on each:

- **List vs final:** the list price (MSRP) before any promotion, versus the price after the manufacturer or dealer discount.
- **Gross vs net:** the amount with VAT (what a private buyer pays) versus the amount without VAT (what matters to a company that deducts it).
- **With or without special taxes:** Spain has a registration tax that depends on emissions; some configurators fold it into the displayed price, others do not, and other countries have equivalent taxes with their own names and logic.

## Real fields: BMW, Kia and Toyota

The best way to see the difference is to look at real rows. The table shows one row per brand, taken from the samples of our actors for the Spanish market, in euros. These are not aggregate figures or comparisons: they are the fields exactly as each configurator delivers them.

| Brand / row | Field | Value | What it represents |
|---|---|---|---|
| BMW 118d (ES) | gross_list_price | 42768.1 | Gross list price |
| BMW 118d (ES) | net_list_price | 34010.4 | Net list price |
| BMW 118d (ES) | total_taxes | 8757.678 | Taxes between gross and net |
| BMW 118d (ES) | emission_tax_pct | 0.0475 | Emissions-based percentage |
| Kia EV6 Air (ES) | msrp_before_discount | 48995.01 | List price before discount |
| Kia EV6 Air (ES) | discount_amount | 13465 | Discount in euros |
| Kia EV6 Air (ES) | msrp_dc_price | 35530.01 | Price after discount |
| Kia EV6 Air (ES) | is_net_price | False | The displayed amount is not net |
| Kia EV6 Air (ES) | net_price | 29363.64 | Net of the discounted price |
| Toyota Aygo X Cross (ES) | price_list | 27800 | List price |
| Toyota Aygo X Cross (ES) | price_discount | 3300 | Discount |
| Toyota Aygo X Cross (ES) | price_with_discount | 24500 | Price after discount |
| Toyota Aygo X Cross (ES) | price_net | 22975.21 | Net of the list price |
| Toyota Aygo X Cross (ES) | price_tax | 4824.79 | Tax on the list price |

## What those rows teach

In BMW, net and gross are sibling fields and the difference between them is published in total_taxes. In that row, 8757.678 divided by the net 34010.4 gives 0.2575, which is 21% VAT plus the 4.75% in emission_tax_pct. The practical conclusion: total_taxes is not just VAT; it groups VAT and the emissions tax, and if you subtract it assuming it is VAT you will get a wrong net.

Kia has a different structure: a list price, a discount and a final price, plus a boolean, is_net_price, that tells you whether the displayed amount is net. Here the check is arithmetic: 48995.01 minus 13465 is 35530.01, and 35530.01 divided by 1.21 is 29363.64. So net_price is the net of the discounted price, not of the list price.

Toyota is the subtlest trap. price_net is 22975.21, which is the net of the list price (27800 divided by 1.21), not of the discounted price. The post-discount net lives in another field, price_ex_vat, at 20247.93. Two brands with a field called "net" and two different bases: that is why you should never map by field name, only by what each field represents, verified against a row.

## A common schema to homogenize

The goal is a schema where every amount carries its base explicitly. A minimal proposal, which we use as a starting point in [data normalization](https://www.rastriq.es/en/data-normalization/) projects, is the following:

| Common field | Meaning | How it is obtained |
|---|---|---|
| price_list_gross | List price with VAT | BMW: gross_list_price; Kia: msrp_before_discount; Toyota: price_list |
| discount_amount | Discount in local currency | Kia: discount_amount; Toyota: price_discount; null if absent |
| price_final_gross | Final price with VAT | Kia: msrp_dc_price; Toyota: price_with_discount |
| price_final_net | Final price without VAT | Kia: net_price; Toyota: price_ex_vat; BMW: net_list_price |
| vat_rate | VAT rate applied | Source field or derived and flagged as derived |
| registration_tax_amount | Registration tax, if known | Only if the source separates it; otherwise null with a flag |
| price_basis_flag | Quality of the tax basis | ok, derived or unknown |

## Normalize without losing the original

A rule that saves trouble: always keep the original field next to the normalized one and add a quality flag instead of dropping rows. If the net was derived by dividing by VAT, mark it as derived; if the source does not let you separate the registration tax, leave the field null and flag it. Whoever consumes the data decides whether to accept derived rows. Some of our actors already do this natively: Toyota delivers tax_calculation_status and price_quality, and Volkswagen delivers price_net_status and registration_tax_status.

This philosophy, flag and let through, avoids the opposite mistake, which is silently filtering so the analyst never learns that data was missing. With the flag, a dashboard can show verified-net coverage versus derived, and a model can decide whether to exclude the derived rows.

## A classification lesson: the "EV" false positive in "Clio evolution"

Normalization is not only about prices. To compare electric cars with hybrids and combustion models you need to classify the powertrain, and the temptation is to detect it from the model or trim name. It is a classic mistake. If you search the text for the substring "ev", a trim called "Clio evolution" is classified as electric, as is any name containing "ev" anywhere, from "Level" to "Revolution".

The fix has three layers. First: use the fuel or powertrain fields the configurator delivers, such as fuel_type in BMW, fuel_code and is_hybrid in Toyota or engine_category_name, before the commercial name. Second: if you must use text, tokenize and compare whole words with word boundaries, never substrings. Third: store the signal you used, for example propulsion_source = fuel_field | token | unknown, so uncertain classifications can be audited later. And a unit test with the "Clio evolution" case keeps the bug from returning with a code change.

## Steps to build the pipeline

Summarized as a working order you can follow:

- Download a [sample](https://www.rastriq.es/en/samples/) per brand and list the price and tax fields with their values in a real row.
- For each field, check the base arithmetically: subtract, divide by VAT and verify it matches another field in the same row.
- Define the common schema and the per-brand mapping table, and document ambiguous cases such as price_net in Toyota.
- Derive what is missing, always with a derived flag, and leave null what cannot be computed.
- Classify the powertrain by fuel fields and tokens, never by substrings.
- Add tests with real rows, including the conflicting cases, and periodically review any new fields that appear.

## Where to see each brand fields

Each brand has its own page with coverage, real rows and a field dictionary. For the examples in this guide: [BMW](https://www.rastriq.es/en/oem-configurators/bmw/), [Kia](https://www.rastriq.es/en/oem-configurators/kia/), [Toyota](https://www.rastriq.es/en/oem-configurators/toyota/) and [Dacia and Renault](https://www.rastriq.es/en/oem-configurators/dacia-renault/), the latter with price_retail, price_type and price_without_tax. The commercial hub is [new car pricing data](https://www.rastriq.es/en/new-car-pricing-data/), and if you would rather receive the data already homogenized, you can [request a normalized dataset](https://www.rastriq.es/en/buy-datasets/).

FAQ

## Frequently asked questions

### Why can I not directly compare the price of two brands?

Because each configurator publishes the amount on a different basis: with or without VAT, list or discounted, with or without registration tax. Until you declare the basis of each field and map it to a common schema, the comparison mixes concepts.

### What is the difference between list price, net price and discounted price?

The list price (MSRP) is the tariff amount with VAT; net is that amount without VAT, and the discounted price is the one after applying the manufacturer promotion. They are three different axes and one field can combine two of them, such as the net of an already discounted price.

### Is registration tax always included in the price?

No. It depends on the configurator and the country. Some fold it into the displayed price and others leave it out or publish only a percentage, such as `emission_tax_pct` in BMW. That is why the common schema treats it as an optional field with a quality flag.

### How do I avoid misclassifying an electric car?

Do not detect the powertrain from substrings of the name: "Clio evolution" contains "ev" and is not an electric car. Use the source fuel fields, and if you must parse text, compare whole words and record which signal you used.

### Do you offer the data already normalized?

Yes. Besides the samples and the actor for each brand, there is a normalization service that delivers a common schema with a quality flag. You can request brands, markets and period from the datasets page.

## Want to see the data before you decide?

Download a real sample of up to 100 rows, already sanitized, or tell us which sources you need.

[See samples →](https://www.rastriq.es/en/samples/) [Request a dataset →](https://www.rastriq.es/en/buy-datasets/)

RELATED

## Keep reading and take action

[OEM configurators hub 28 brands with coverage, sample and field dictionary.](https://www.rastriq.es/en/oem-configurators/) [New car pricing data Commercial landing to request configurator data.](https://www.rastriq.es/en/new-car-pricing-data/) [Data normalization Before and after with different schemas.](https://www.rastriq.es/en/data-normalization/) [BMW gross_list_price, net_list_price, total_taxes.](https://www.rastriq.es/en/oem-configurators/bmw/) [Kia msrp_before_discount, discount_amount, is_net_price.](https://www.rastriq.es/en/oem-configurators/kia/) [Toyota price_list, price_discount, price_net, price_tax.](https://www.rastriq.es/en/oem-configurators/toyota/) [Downloadable samples Real rows in JSON and CSV.](https://www.rastriq.es/en/samples/)
