Skip to content

    Pre-launch API. The concepts described here are settled, but the API shape is not: request and response fields, parameters and defaults can still change. Build against it, and talk to your Luigi's Box contact before you put an integration into production.

    Category pages

    View source

    The category page widget takes over the product listing on your category pages: the grid, its filters and its sorting. Breadcrumbs, the heading, subcategory tiles and banners stay yours. It is the same listing as search results, served from a collection surface.

    Its folder is integration/plp/.

    integration/plp/_config.ts:

    export default {
    urlMatch: '^/c/',
    surface: 'lbs_collection_categories',
    lookup: { field: 'url' },
    params: {
    page: 'page',
    sort: { param: 'order', values: { 'price-asc': 'lbx:price:asc', 'price-desc': 'lbx:price:desc' } },
    facetParams: { brand: { param: 'brand' } },
    },
    };
    KeyDefault
    urlMatch—Required. A regular expression on the URL’s path, matching your category pages
    surface—Required. A collection surface
    lookup—How a page’s URL becomes a category — see below
    params—Your own URL parameters, mapped onto the listing — see below
    earlyHoldtruefalse when urlMatch also matches pages that are not category pages and style-host.css would hide something on them. The early-hold snippet matches on urlMatch alone.

    Every listing key can be set here. Those left unset are taken from search/_config.ts: anchor, position, settleMs, reserveSelector, holdTimeoutMs, size, facets, facetSize, emptyValues, sorts, fields, baseFilters, rootClass, restoreOnBack, prefetchNextPage, facetsApply and facetGroups. So are templates and style-host.css, when plp/ has none of its own.

    Sort labels come from the translations plp.sorts, and the built-in label for '' is “Recommended”.

    Luma needs, for each page, a filter expression that selects the category’s products, and a title. Two ways to get them:

    Look up the category record. lookup finds the catalog object of type category whose field equals the page’s path, without a trailing slash. absolute: true compares the origin and path instead; type names another object type. Then toFilter, set in plp/_widget.ts, turns that record into the filter:

    integration/plp/_widget.ts
    import type { PlpConfigType } from '@/types';
    export default (c: PlpConfigType) => {
    c.toFilter = (category) => ({
    scope: { category_path: { eq: category.path } },
    title: category['@title'],
    });
    };

    Read it from the URL. fromUrl(url) returns the filter and title directly, with no lookup.

    Either may return null: the page is left to your site. A category with no products is left to your site too.

    Narrow urlMatch further with active(url) in plp/_init.ts.

    A category page’s state lives in your own parameters, so your existing links, filters and canonical URLs keep working. params maps them:

    Key
    pageYour page parameter. Luma shows only the first page and appends the rest with “show more”, so your page 1 — or no page parameter — is Luma’s, and a later page is left to your own listing. Luma never writes it.
    sort{ "param", "values" }: your sort parameter and a map of your value to Luma’s field:direction
    flagsOn/off parameters with a fixed value: [{ "param": "stock", "value": "1", "filter": { … } }]. Labels come from plp.flags["stock=1"].
    facetParamsFacet field → { "param", "values", "slug" }. values maps your values to catalog values; a value mapped to '' cannot be expressed, and its URL is left to your site. slug: false passes values through unchanged. With neither, your value is a slug of the catalog value.
    separatorThe separator between several values in one parameter
    ranges[{ "min", "max", "field" }]: two parameters read as a range filter on field
    ignoreA regular expression of parameters that never stop a takeover, such as tracking parameters

    A URL with a parameter Luma cannot express is left to your own listing, so no filter is silently dropped. A facet value your parameters cannot carry is written as lbx.<field>.

    When the facets depend on the category — its own technical parameters, for example — set facetsFor(url, category) in plp/_widget.ts. It returns { facets, layout }: the fields to facet, in order, and optionally the sidebar’s group order including keys of your own. It may return a promise. null uses facets.