- Product comparison looks like a presentation feature: select a few cards, place their attributes in columns and highlight the differences.
- In a B2B marketplace, the difficult question is not how to draw the table.
- The client needed property teams to compare a small number of products, discuss the options and send the decision set to a colleague.
- The link preserves the conversation.
The client problem
Product comparison looks like a presentation feature: select a few cards, place their attributes in columns and highlight the differences.
In a B2B marketplace, the difficult question is not how to draw the table. It is which commercial truth the table should show when somebody opens a shared link later, from another property context, after price or stock has changed.
The client needed property teams to compare a small number of products, discuss the options and send the decision set to a colleague. We built a comparison flow on Medusa that stores only product identities in the shareable URL, limits the set to four and reconstructs current price, availability and delivery context when the page is opened.
The link preserves the conversation. It does not freeze facts that the buyer should no longer trust.
Bound the decision to four products
More columns do not always produce a better decision. On a desktop, ten products make every value hard to scan. On a phone, they make the page nearly unusable. They also multiply backend retrieval and pricing work.
We chose a maximum of four product IDs. The storefront comparison queue deduplicates the selection, preserves its order and refuses additions once the bound is reached. The backend applies the same limit when parsing the request.
This is a product decision reinforced by an API contract. The interface explains the constraint early, while the server prevents a modified URL from turning the endpoint into an unbounded batch query.
Four is enough to create a meaningful shortlist without pretending that a side-by-side matrix should replace catalogue search. Search narrows the universe; comparison supports the final trade-off.
Resolve catalogue facts and live commerce facts separately
A useful comparison needs two kinds of information.
Catalogue facts are relatively stable: product name, image, description, category, brand, manufacturer, unit of measure and technical specifications. The marketplace search document is well suited to retrieving these across several products.
Commercial facts are contextual and volatile: calculated price, variant inventory, backorder behaviour and current eligibility. Those must come from the live Medusa product context for the active market and customer.
The backend joins the two by product ID. A product appears only when both its authorised marketplace document and its live commerce record are available. Missing products are returned as unavailable IDs rather than reconstructed from old client data.
This prevents the comparison page from becoming a side door around catalogue visibility or pricing policy.
Reapply the active property's delivery geography
Delivery is not one universal number attached to a product. A supplier can serve one country, province, city or postal-code set differently from another. The active property determines which shipping options are relevant.
The comparison assembler filters delivery options against the property's country and, where required, province, city or postal code. It then derives the shortest known maximum shipping estimate from the applicable options.
Pickup remains a separate capability. The matrix can show whether an applicable pickup option exists without pretending that pickup and shipment describe the same fulfilment promise.
If no delivery estimate is known, the cell stays empty. It does not substitute “next day”, zero or another reassuring fiction. Unknown information is part of an honest decision surface.
Calculate availability from the variants Medusa returns now
Search indexes are excellent read models, but inventory can change after indexing. The comparison route derives availability from current variant data.
For inventory-managed variants, positive quantity produces in-stock or low-inventory states and zero produces out of stock. A variant that is not inventory-managed or allows backorders remains purchasable without inventing a physical count. If inventory information is incomplete, the output can remain unknown.
This distinction matters to buyers. “In stock”, “can be backordered” and “stock is not known” are not interchangeable statements.
The displayed stock level aggregates the usable variant information for the product. The matrix translates that into plain language rather than exposing implementation flags.
Compare prices only when the units make sense
The lowest number is not necessarily the cheapest option. A box of 100 and a single unit cannot be compared by raw price alone.
The interface highlights a lowest comparable price only when at least two products have the same normalised unit of measure and every compared price is present and positive. If units differ or a price is missing, it does not crown a winner.
That small rule prevents a visually persuasive but commercially wrong recommendation. The table still shows each known price and unit, allowing the buyer to make the appropriate conversion or investigate the supplier packaging.
The broader principle is valuable across procurement: comparison logic should refuse conclusions when the inputs do not share a meaningful basis.
Build rows around buyer questions
The matrix begins with purchasing questions rather than technical schema fields:
- What will it cost in my current context?
- In what unit is it sold?
- Which supplier provides it?
- Is it available?
- How long could shipping take?
- Is pickup possible?
- Are brand, manufacturer or category different?
- Which technical specifications differ?
Specification keys are normalised so variations in capitalisation do not create duplicate rows. Values remain attached to the correct product, and rows calculate whether the compared columns actually differ.
That allows the interface to emphasise differences without hiding common facts. A buyer can scan the exceptions first, then inspect the full detail when needed.
Preserve unknown values instead of filling the design
Comparison tables create visual pressure to populate every cell. That pressure is dangerous.
A missing delivery estimate does not mean immediate delivery. A missing inventory count does not mean zero. An absent specification does not prove that the product lacks the property; the catalogue may simply not state it.
We model unknowns as empty values and render them deliberately. This keeps absence distinct from a negative answer such as “pickup not available”. The difference is important when the page informs a real purchase.
The same approach improves data quality. Repeated empty fields can expose where supplier catalogue enrichment is needed, rather than being concealed behind made-up defaults.
Handle products that disappear between selection and review
A buyer can select a product on Monday and share the link on Wednesday. By then, one item may be unpublished, removed from the property's catalogue or unavailable from the authorised seller.
The comparison assembler walks the requested IDs in order and includes only products found in both the marketplace document set and live Medusa result. It reports the remainder as unavailable.
The interface can explain that a selected product is no longer available instead of failing the entire comparison or displaying stale information. The remaining shortlist still provides value.
This is another reason the URL stores IDs only: a product's former title and price cannot linger as an unofficial snapshot after its commercial visibility changes.
Make the comparison link safe to revisit
A useful shared link should be deterministic about the selection but dynamic about commerce.
The parser trims values, accepts the documented comma-separated form, removes duplicates and preserves the first occurrence. It rejects an empty or oversized selection. Query keys include the identity and property context needed to avoid reusing a response from another scope.
Tests cover queue bounds, URL normalisation, backend route behaviour and comparison row construction. These checks protect the feature from small changes that could otherwise leak stale selection or silently exceed the intended limit.
The user experience remains simple: select, compare, copy the URL. The architecture does the work required to make that simplicity trustworthy.
What the buyer gains
The final capability supports a real conversation:
- A buyer narrows search results to two, three or four candidates.
- The matrix aligns price, unit, supplier, stock, delivery and specifications.
- Unsupported conclusions, such as a cheapest product across different units, are withheld.
- The buyer shares the URL with a colleague.
- The colleague opens the same shortlist under current identity and property context.
- The platform recalculates volatile facts and flags products that are no longer available.
The decision remains collaborative without turning the link into a quotation or a promise that the marketplace cannot keep.
Why this belongs on an extensible commerce platform
Medusa supplies the live product, variant, pricing and inventory foundation. The project-specific marketplace layer supplies property scope, seller visibility, search documents and delivery geography.
We built the comparison at the seam between them. A generic frontend widget could display attributes, but it would struggle to enforce the same commercial rules as search and checkout. A static export could be shared, but it would age immediately.
Choosing an extensible engine allowed us to make the buyer-facing capability part of the real commerce model. The feature is easy to use precisely because the complex eligibility work remains server-side.
For the commerce team, this also means one less rule set to maintain. The comparison page does not invent its own definition of an eligible product and then drift away from search or checkout. It consumes the same contextual foundations, so improving catalogue visibility or delivery modelling improves the decision surface as well. That compounding effect is more valuable than a one-off comparison component.
If your B2B buyers compare products in spreadsheets because the storefront cannot preserve context, WeAreSouk can design a Medusa comparison flow that is shareable, current and commercially meaningful.
