Skip to main content
The journal
Industry playbooks3 min read

A marketplace schema needs products, listings and sellers

Model the entities separately so multiple offers, listing edits and seller changes do not corrupt your dataset.

In this article
  1. Decide what each identifier identifies
  2. Use relationships instead of repeated text
  3. Do not erase source-specific meaning
  4. Version observations and matching rules
  5. Validate joins before delivery

THE KEY IDEA

One flat row can hide several different entities. Separate identity from the observations that change over time.

01Decide what each identifier identifies

A product is not necessarily a listing, and a listing is not necessarily an offer. A marketplace can contain multiple sellers for one product, multiple variants within a listing and changing fulfilment conditions. Choose an entity model before collecting enough rows to make later restructuring expensive.

Keep source-specific identifiers alongside your internal IDs. Titles and display names can change. URLs can redirect or contain tracking parameters. Use those as attributes and evidence, not as unquestioned universal identifiers.

02Use relationships instead of repeated text

Represent sellers and products once, then link listings and observations to them. Keep variant attributes explicit so a size or pack change does not silently become a price change. A flat export can still be useful, but it should be generated from a model with clear relationships.

EntityTypical information
ProductBrand, model and canonical attributes
VariantSize, colour, configuration or pack
SellerSource seller ID and public store identity
Listing or offerSeller-product relationship and published conditions
ObservationPrice, availability, context and timestamp

03Do not erase source-specific meaning

Normalise values that are genuinely equivalent, such as a documented unit conversion. Preserve original text and source labels when the meaning is uncertain. A platform's available status may not mean the same thing as another platform's in-stock status.

Keep fees, taxes and delivery conditions as separate fields where available. If a total requires a basket or private account state outside the collection scope, mark the total unknown. Adding visible components together can create a plausible number that no customer could actually obtain.

04Version observations and matching rules

Store when a listing was first seen, last seen and successfully checked. Distinguish an observed removal from a failed collection. A listing missing from search results may still exist on its detail page, and a changed search filter can alter discovery coverage.

When your product-matching logic changes, record the version and review affected joins. Historical analyses should not silently change because a new fuzzy-match rule merged two previously separate products. Keep a way to explain the mapping used for each report.

05Validate joins before delivery

Check for orphaned offers, duplicate seller IDs, variants without parent products and conflicting currencies. Sample both the entity tables and the flattened consumer export. A perfectly valid join can still multiply records if its relationship is many-to-many and the export assumes one-to-one.

Agree how the consumer will handle partial records and schema updates. The goal is not the most elaborate model; it is enough structure to answer the business question without losing the distinctions that make the data correct.

References & further reading

Put it into practice.

Try a public-page workflow, or scope a maintained dataset with our team.