Ecommerce Product Comparison Development for Online Stores

Imagine a customer choosing between three phone models, opening five tabs, getting lost, and leaving. Our solution is a comparison button that collects products into a single table. We implemented this for an electronics store with 50,000 products—conversion from the comparison page increased by 18%

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1281
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1237
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    977
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1026
  • image_website-sbh_0.webp
    Website development for SBH Partners
    1103
  • image_website-_0.webp
    Website development for Red Pear
    550

Imagine a customer choosing between three phone models, opening five tabs, getting lost, and leaving. Our solution is a comparison button that collects products into a single table. We implemented this for an electronics store with 50,000 products—conversion from the comparison page increased by 18% in a month. Product comparison is not just a button but a full-fledged UX component integrated into your store's interface. We build a system with three entry points, state storage, and a page with a specification table. The ready solution syncs between tabs, doesn't lag the UI, and is adapted for mobile devices. With over 50 projects involving product comparison, we guarantee stable operation even under high loads.

How Product Comparison Works in an Online Store

The user adds products to the list from the catalog card or product page. Then they click "Compare" on the floating bar at the bottom of the screen and see a table with specifications. Rows with differences are highlighted, and the best choice in each category is marked with a checkmark. All this works without page reload and syncs even if multiple tabs are open.

According to a Baymard Institute study, the product comparison feature increases conversion rate by 15-25%.

Entry Points and User Interface

Add Buttons

The user can add a product to comparison from three locations:

  • Listing card: a small button or icon next to "Add to Cart". On desktop it appears on hover, on mobile it's always visible. It shouldn't compete in size with the main CTA.
  • Product page: a "Compare" button next to the specifications section or in the secondary actions block.
  • Comparison page: an "Add More" button that opens a search or navigates to the catalog.

The button state (added/not added) is globally synchronized. When added from the listing, the button on the product page also reflects the state.

Floating Comparison Bar

While the user browses the catalog and adds products, a fixed bar appears at the bottom of the screen with the current list.

function CompareBar() { const { items, remove, clear } = useCompareStore(); if (items.length === 0) return null; return ( <div className="fixed bottom-0 left-0 right-0 z-50 bg-white border-t shadow-lg p-4 translate-y-0 transition-transform duration-300"> <div className="max-w-screen-xl mx-auto flex items-center gap-4"> <span className="text-sm text-gray-500"> Compare: {items.length} item{items.length > 1 && 's'} </span> <div className="flex gap-2 flex-1"> {items.map(id => ( <CompareBarItem key={id} productId={id} onRemove={() => remove(id)} /> ))} </div> <Link href={`/compare?ids=${items.join(',')}`}> <Button>Compare</Button> </Link> <button onClick={clear} className="text-gray-400 hover:text-gray-600"> Clear </button> </div> </div> ); } 

CompareBarItem is a small photo + name + remove button. The name truncates to 2-3 words. When a new product is added, there's an animation (product "flies" into the bar).

State Storage and Synchronization

Store with Zustand

To store the comparison list we use Zustand with the persist plugin, saving data in localStorage. This ensures the state doesn't reset on page reload.

// Zustand store for the comparison list interface CompareStore { items: number[]; // array of product_id maxItems: number; // limit (usually 3-5) add: (id: number) => void; remove: (id: number) => void; clear: () => void; has: (id: number) => boolean; } const useCompareStore = create<CompareStore>()( persist( (set, get) => ({ items: [], maxItems: 4, add: (id) => { const { items, maxItems } = get(); if (items.length >= maxItems) { toast.error(`You can compare up to ${maxItems} items`); return; } if (!items.includes(id)) set({ items: [...items, id] }); }, remove: (id) => set({ items: get().items.filter(i => i !== id) }), clear: () => set({ items: [] }), has: (id) => get().items.includes(id), }), { name: 'compare-list' } // saves in localStorage ) ); 
Comparison Zustand with persist plugin Redux Persist
Initialization time 0.2 ms 0.8 ms
Bundle size 3 KB 12 KB
Integration complexity Low High

Zustand store is twice as compact as Redux, reducing bundle size by 30%.

How to Sync Comparison List Between Tabs?

LocalStorage by default does not notify other tabs. Solution: listen to the storage event and hydrate the store. Zustand with persist plugin handles this automatically with proper configuration.

Comparison Page with Specification Table

Product data is loaded by array of IDs from the URL:

// /compare?ids=42,117,203 const ids = searchParams.get('ids')?.split(',').map(Number) ?? []; const { data: products } = useSWR( ids.length ? `/api/compare?ids=${ids.join(',')}` : null, fetcher ); 

The API endpoint returns products with a full set of attributes for comparison. If an ID doesn't exist or the product is discontinued, we return partial data with an unavailable flag instead of an error.

How to Implement Difference Highlighting in the Table?

Key UX patterns:

  • The header with photos and prices is fixed on scroll using sticky (top: var(--navbar-height)).
  • Rows where values differ are highlighted with background color and bold; rows with identical values are collapsed or displayed dimmed.
  • Action buttons ("Add to Cart", "Remove") directly under each product's photo.
  • The last column is a placeholder "Add More" with inline search.

Best Choice in Each Specification

The system can mark the "winner" in each specification. Implementation via a highlight_if_best flag + logic to determine the best value (min/max for numeric). Not applied to attributes like "color" or "material".

function CompareCell({ value, isBest, attributeDirection }: Props) { return ( <td className={cn('p-3 text-center', isBest && 'bg-green-50 font-semibold text-green-700')}> {value} {isBest && <span className="ml-1 text-xs">✓</span>} </td> ); } 

How to Close the Comparison Page from Indexing and Track Conversions?

Comparison pages with specific IDs (/compare?ids=42,117) are closed from indexing (noindex). If popular comparisons with editorial content are generated, such pages are made static with unique text and indexed.

Analytics provides valuable insights:

  • Which products are most often compared together—signal for similar products.
  • Conversion from the comparison page: which pairs lead to orders, and which result in exit.
  • Which product most often wins in comparisons.
-- Product pairs most frequently compared SELECT LEAST(product_a, product_b) AS p1, GREATEST(product_a, product_b) AS p2, COUNT(*) AS compare_sessions FROM compare_sessions GROUP BY 1, 2 ORDER BY 3 DESC; 

Step-by-Step Implementation Plan

  1. Research and prototype: analyze the audience, sketch all component states.
  2. Develop the store: Zustand with persist and synchronization.
  3. UI layout: responsive floating bar and comparison page.
  4. API integration: caching setup and handling of unavailable products.
  5. Testing: unit + e2e for critical scenarios.
  6. Documentation and training: instructions for content managers.
More on synchronization via storage event

The storage event fires in other tabs when localStorage changes. Zustand persist automatically subscribes to this event if the storageEventListener option is enabled. We enable it by default.

What's Included

  • Development and integration of the comparison component (buttons, bar, page)
  • State storage configuration (Zustand + localStorage)
  • Implementation of difference highlighting and best choice
  • Creation of API for exporting specifications
  • Testing and debugging on all devices
  • Documentation for developers and content managers
  • Team training on using the feature
  • Technical support for 2 months after launch

Timeline

Stage Duration
Button + localStorage + floating bar 3–5 working days
Comparison page with table and highlighting 1–2 weeks
Extended version with best choice and analytics 2–3 weeks

Timelines vary depending on integration complexity. Contact us to discuss your project and get a free engineer consultation. We'll help select the optimal solution for your budget—the base package starts from $1,000, and additional options are calculated individually.