Ir para o conteúdo
decodecodeveloper docs
Storefront → Blocks → Apps

Commerce types and utilities

The shared commerce vocabulary every platform app returns, the Cart v2 contract, and small helpers for prices, links, offers and analytics.

Esta página ainda não foi traduzida para o português — o conteúdo abaixo está em inglês.

@decocms/apps-commerce is the platform-neutral layer under every commerce app. It doesn't talk to any backend. Instead it defines the shapes they all return (a product, a product page, a listing page, a cart), so a section written against these types works whether the data came from VTEX, Shopify or Wake. It also holds the Cart v2 contract, the app contract types, and a handful of helpers for prices, links and analytics.

It ships no UI components. Images, pictures and JSON-LD components live in @decocms/blocks/hooks (see Images, scripts and UI helpers).

bun add @decocms/apps-commerce

The shared vocabulary

The types follow schema.org, the same vocabulary search engines read, so the data a loader returns can also be rendered as structured data. Import them from @decocms/apps-commerce/types:

src/sections/ProductShelf.tsx
import type { Product } from "@decocms/apps-commerce/types";
 
export interface Props {
  /** @title Products */
  products: Product[] | null;
}
 
export default function ProductShelf({ products }: Props) {
  return (
    <ul>
      {products?.map((p) => (
        <li key={p.productID}>
          <img src={p.image?.[0]?.url} alt={p.name} width={200} height={200} />
          <a href={p.url}>{p.name}</a>
          <span>{p.offers?.lowPrice}</span>
        </li>
      ))}
    </ul>
  );
}

The types you'll use most:

TypeWhat it holds
ProductOne sellable item: productID, sku, name, image, offers (an AggregateOffer), and optionally isVariantOf (the ProductGroup with its sibling variants), brand, additionalProperty and more.
ProductDetailsPageWhat a product page needs: product, breadcrumbList and optional seo.
ProductListingPageWhat a category or search page needs: products, filters, breadcrumb, pageInfo, sortOptions and optional seo.
FilterEither a FilterToggle (a list of values with counts and URLs) or a FilterRange (a min/max).
PageInfoPagination: currentPage, nextPage, previousPage, and optionally records and recordPerPage.
SuggestionAutocomplete results: searches and products.
SiteNavigationElementA menu item with children, nested up to five levels. Use it instead of the deprecated Navbar/NavItem.
MinicartA cart ready for a drawer: original (the platform's raw cart) plus a storefront view with items, total, subtotal, discounts, currency, checkoutHref and more.
Offer, AggregateOffer, UnitPriceSpecificationPrices, list prices, installments and availability.

Money is always in major units: 19.9 means 19.90 in the store's currency, never 1990 cents.

Analytics types and mappers

The package also defines the GA4 event vocabulary: AnalyticsItem and the event types (AddToCartEvent, ViewItemEvent, ViewItemListEvent, SelectItemEvent, BeginCheckoutEvent and the rest), grouped in the AnalyticsEvent union. A deco event carries the page's active flags.

To turn a Product into an AnalyticsItem, there are two mappers with the same name in different places. Neither reads the price from the product: you pass it in, usually from useOffer. They also don't produce identical output:

Import fromprice in the result comes fromitem_variant isExtra
@decocms/apps-commerce/sdk/analyticsthe lowPrice optionthe product's skuAn extend callback to add custom fields, and mapProductToAnalyticsItemList for lists
@decocms/apps-commerce/utils/productToAnalyticsItemthe price optionthe product's name—

In both, discount is listPrice - price when you pass both options. Pick one mapper and use it everywhere, so the same product reports the same fields on every event. Both accept a breadcrumbList, which gives the most reliable category fields; without it they fall back to the product's category string.

src/sdk/analytics.ts
import { mapProductToAnalyticsItem } from "@decocms/apps-commerce/sdk/analytics";
import { useOffer } from "@decocms/apps-commerce/sdk/useOffer";
import type { Product } from "@decocms/apps-commerce/types";
 
export function toItem(product: Product, index: number) {
  const { price, listPrice } = useOffer(product.offers);
  return mapProductToAnalyticsItem({
    product,
    index,
    quantity: 1,
    lowPrice: price,
    price,
    listPrice,
  });
}

Cart v2: sections and projection

Cart v2 splits every cart operation into two independent choices, so a page only pays for the data it shows:

  • sections: what to ask the platform to compute. On VTEX these map to the order form's sections (items, totalizers, shippingData, paymentData and so on).
  • projection: what the server sends back to the browser.
ProjectionReturnsTypical use
"none"{ ok: true }Fire-and-forget writes
"summary"{ orderFormId, totalItems, total }A cart badge
"summary+items"The summary plus slim items (name, image, price, quantity)Add to cart, the default
"minicart"A full MinicartA cart drawer
"raw"The platform's cart, untouchedRare: debugging, migrations

Three section presets cover the usual cases: SECTIONS_MINIMAL (items, totals, messages), SECTIONS_DRAWER (what a drawer renders, including shipping and sellers) and SECTIONS_FULL. defaultSectionsFor(projection) picks the matching preset when you pass only a projection. The types and presets are exported from @decocms/apps-commerce/types/cart, and re-exported from @decocms/apps-commerce/types.

VTEX is the first platform to implement Cart v2; see VTEX.

Helpers

HelperImport fromWhat it does
formatPrice(price, currency?, locale?)@decocms/apps-commerce/sdk/formatPriceFormats a number as currency with a cached Intl.NumberFormat. Defaults to "BRL" and "pt-BR". Returns null for null, undefined or non-finite values.
formatPriceRange(value, currency?, locale?, separator?)@decocms/apps-commerce/sdk/formatPriceFormats a "min:max" facet value as a price range. Returns the input unchanged if it can't parse it.
relative(link, options?)@decocms/apps-commerce/sdk/urlTurns an absolute URL into a path plus query, for links. stripSearchParams removes keys such as idsku.
useOffer(aggregateOffer)@decocms/apps-commerce/sdk/useOfferPicks the price, list price, availability, seller and best installment out of an offer.
useVariantPossibilities(variants, selected)@decocms/apps-commerce/sdk/useVariantPossibilitiesBuilds the variant matrix for a selector: property name, then value, then URL.
parseRange(value), formatRange(from, to)@decocms/apps-commerce/utils/filtersParses "10:50" into { from: 10, to: 50 } (or null), and back.
canonicalFromBreadcrumblist(list)@decocms/apps-commerce/utils/canonicalThe URL of the deepest breadcrumb item, for canonical links.
getStateFromZip(cep)@decocms/apps-commerce/utils/stateByZip (default export)A Brazilian state code from a postal code.
import { formatPrice } from "@decocms/apps-commerce/sdk/formatPrice";
import { relative } from "@decocms/apps-commerce/sdk/url";
 
formatPrice(99, "USD", "en-US"); // "$99.00"
relative("https://www.example.com/p/shoe?idsku=1&color=red", { stripSearchParams: ["idsku"] }); // "/p/shoe?color=red"
useOffer and useVariantPossibilities aren't React hooks. Despite the use prefix they're plain functions, so you can call them anywhere, including in loaders. useOffer's installment text is always formatted in pt-BR and BRL; format it yourself from the returned installment for other locales.

App contract types

The types for writing an app live here too, so apps don't depend on the framework packages:

  • @decocms/apps-commerce/app-types: AppDefinition, AppManifest, AppMiddleware, AppModContract, ResolveSecretFn.
  • @decocms/apps-commerce/registry: AppRegistryEntry and AppRegistry, the shape of each app's *_REGISTRY_ENTRY.
  • @decocms/apps-commerce/resolve: resolveApps(apps), which merges several app definitions into one manifest and chains their middleware (the first app runs outermost).
  • @decocms/apps-commerce/manifest-utils: extractHandlers(manifest), which flattens a manifest into one function per key.

Apps explains how the framework uses them.

  • Apps: installing and configuring apps.
  • VTEX: the reference implementation of these types and of Cart v2.
  • SEO: turning these types into structured data.