Shopping Cart Development for E-Commerce

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.
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.

Showing 1 of 1 servicesAll 2065 services
Shopping Cart Development for E-Commerce
Medium
~3-5 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    847
  • image_website-sbh_0.png
    Website development for SBH Partners
    999
  • image_website-_0.png
    Website development for Red Pear
    451

Developing Shopping Cart for E-commerce

Shopping cart — central component of any e-commerce project. Major abandonment happens here: awkward quantity management, loss of items on page reload, session conflicts for authorized users. Building cart from scratch takes 3–6 business days depending on business logic complexity.

Cart Storage Architecture

Cart exists in three states: guest (anonymous), user (account-linked), merged (merge on login). Guest data stored in localStorage or sessionStorage — policy choice. On auth client-server merge must resolve conflicts: e.g. same product in both — sum quantities or take max.

Server-side cart table:

CREATE TABLE cart_items (
    id BIGSERIAL PRIMARY KEY,
    cart_id UUID NOT NULL,
    user_id BIGINT REFERENCES users(id) ON DELETE CASCADE,
    session_id VARCHAR(255),
    product_id BIGINT NOT NULL,
    variant_id BIGINT,
    quantity INT NOT NULL DEFAULT 1,
    price_snapshot NUMERIC(12,2) NOT NULL,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_cart_items_cart_id ON cart_items(cart_id);
CREATE INDEX idx_cart_items_user_id ON cart_items(user_id);

price_snapshot locks price at add time — critical for timed sales and dynamic pricing.

Quantity Update Logic

Changes should be optimistic: UI updates instantly, request sent in background. On error — rollback with notification. React Query implementation:

const updateQuantity = useMutation({
  mutationFn: ({ itemId, qty }: { itemId: number; qty: number }) =>
    api.patch(`/cart/items/${itemId}`, { quantity: qty }),
  onMutate: async ({ itemId, qty }) => {
    await queryClient.cancelQueries({ queryKey: ['cart'] });
    const prev = queryClient.getQueryData(['cart']);
    queryClient.setQueryData(['cart'], (old: Cart) => ({
      ...old,
      items: old.items.map(i => i.id === itemId ? { ...i, quantity: qty } : i),
    }));
    return { prev };
  },
  onError: (_, __, ctx) => {
    queryClient.setQueryData(['cart'], ctx?.prev);
    toast.error('Could not update quantity');
  },
});

Min/max quantities set at product level: min_order_qty, max_order_qty. If 3 units left in stock, "+" button blocks at that number.

Availability Check and Reservation

Decision on add: make soft reserve (reduce available stock) or not. Soft reserve reduces competition but creates "dead" reserves from abandoned carts. Compromise — reserve only on checkout init, keep cart informational.

When displaying cart check current stock via API. If out of stock — show warning on that line item, don't block whole cart.

Cart Total Calculation

Cart total includes layers:

Component Logic
Subtotal Sum of price_snapshot × quantity for all items
Discounts Applied by priority: promotional > coupon > loyalty
Shipping Preliminary estimate, exact on checkout
VAT Included in price or separate (depends on config)

Calculation done on server per cart change. Client gets ready sums — no browser math.

Mini-Cart and Full Page

Mini-cart in header (dropdown or sidebar) shows last 5 items, count, "Checkout" button. Full page /cart shows all items with edit capability. Both subscribe to same state — React Query or Zustand.

Important: header count updates via Server-Sent Events or polling every 30s — relevant if user works in multiple tabs.

Cart Persistence

Guest cart saved 30 days in cookie (cart_id). On login — merge and move to DB. If authorized user logs out — cart stays in DB, restored on re-login.

Authorized user cart syncs across devices — key difference from guest cart.

Cart Analytics

All cart events → analytics: add_to_cart, remove_from_cart, view_cart. GA4 standard e-commerce events with item_id, item_name, price, quantity. Yandex.Metrica — similar structure via ym(id, 'reachGoal', 'cart_add', {...}).

Abandoned carts tracked separately: if user added items but didn't checkout for N hours — trigger email sequence.

Common Implementation Issues

  • Race condition on simultaneous add: solved via SELECT FOR UPDATE at DB level or idempotency key in API
  • Price changed after add: show notification, auto-recalculate
  • Product discontinued: block checkout, offer remove
  • VAT for different countries: determine by IP/shipping address, apply correct rate