Scrapeless Wiki

What Is Variant Matching? – Definition and How It Works

Informational P3 what is variant matching

Learn why product variants break matching, how parent-child models differ across retailers, and how to normalise them.

Variant matching decides whether two product listings are the same item, when products come in colours, sizes, capacities, and configurations that retailers model inconsistently.

1. Why It Is Harder Than Product Matching

Matching a product across retailers is hard because titles differ. Matching variants is harder because retailers disagree about what a product is.

Retailer model Consequence
One page, variant selector One URL, many variants
One page per variant Many URLs, one product family
Parent listing with child offers Two levels, both addressable
Variants as separate products entirely No relationship expressed

So the same real-world catalogue appears as 1, 12, or 60 items depending on the retailer β€” and any count compared across retailers without normalising this is meaningless.

2. The Decision You Must Make Explicitly

Is a black keyboard the same product as a white one?

There is no universally right answer, and the choice changes every downstream metric:

  • Price comparison β€” usually wants variant-level, since colours can differ in price.
  • Assortment counting β€” usually wants product-level, or counts are incomparable.
  • Availability β€” variant-level, since one size can be out of stock.
  • Review aggregation β€” usually product-level, since reviews are shared.

The failure is not choosing wrong; it is not choosing, and mixing levels within one dataset.

3. The Data Model That Works

Two levels, explicitly:

product (family)
  id, brand, model, title, category, description, review_summary
  └── variant
        id, parent_id, gtin, sku, attributes{colour,size,capacity},
        price, currency, availability, url, condition

Prices, availability, and GTINs belong to the variant. Descriptions, brand, and reviews belong to the product. Collapsing them into one level is what produces the familiar problems: a single price for a product that has six, or a review count attached to one colour.

4. Matching Strategy

  1. GTIN first. Where present it is variant-level and exact β€” the clean case.
  2. Brand plus model plus attributes where GTIN is absent. Requires extracting attributes as structured fields, not leaving them in the title.
  3. Attribute normalisation before comparison, which is where most of the work is.
  4. Parent grouping by brand and model, once variants are identified.

5. Attribute Normalisation Is the Real Work

Attribute values are written in every conceivable way:

colour:   "Black" | "black" | "BLK" | "Jet Black" | "Noir" | "Space Grey"
size:     "42" | "42 EU" | "US 9" | "UK 8" | "M" | "Medium"
capacity: "256GB" | "256 GB" | "0.25TB" | "256"
COLOUR_CANON = {"blk": "black", "noir": "black", "jet black": "black",
                "space grey": "grey", "space gray": "grey"}

def canon_colour(v):
    s = " ".join(str(v).lower().split())
    return COLOUR_CANON.get(s, s)

Sizes are worse than colours because they cross measurement systems β€” a shoe size needs a conversion table, not a lookup, and the conversion depends on region and sometimes on brand.

The honest position: this is a maintained mapping, not an algorithm, and it needs a review path for unmapped values rather than silently passing them through.

6. Where It Goes Wrong

  • Mixing levels, comparing a product-level count against a variant-level one.
  • Averaging across variants, producing a price that no variant has.
  • Attributing availability wrongly β€” a product marked in stock when only one size is.
  • Duplicate counting where one retailer lists variants separately.
  • Silently dropping unmapped attributes, which loses variants without any error.
  • Assuming GTIN is variant-level everywhere, when some brands share one across variants.

7. Practical Guidance

  1. Model two levels explicitly, and record which level every metric is at.
  2. Extract attributes as fields, not parsed from the title later.
  3. Normalise through a maintained mapping, with unmapped values surfaced for review.
  4. Keep the retailer's own identifiers at both levels.
  5. Record the retailer's model β€” whether it lists variants separately β€” since that determines how counts compare.
  6. Never average prices across variants into a single product price.

8. Summary

Variant matching resolves whether listings are the same item when retailers model colours, sizes, and configurations inconsistently β€” the same catalogue appearing as one item or sixty depending on the retailer.

Model product and variant as two explicit levels with prices and availability at variant level, decide deliberately which level each metric uses, and treat attribute normalisation as a maintained mapping with a review path for unmapped values rather than an algorithm that silently drops them.