Skip to main content

PLP Configuration Options

Configure the Fast Simon PLP widget by setting options on window.__fast_options before the widget loads.

Configuration Structure

Options are set globally on the window object:

window.__fast_options = {
// Product Display
with_product_attributes: true,
list_view_default_value: false,
numberOfColumns: { desktop: "4", tablet: "3", mobile: "2" },

// URL & Navigation
full_product_url_path_redirect: true,
url_parameters_to_keep: ["utm_source"],

// Filters
default_value_for_hide_filters_button: false,
disable_selected_filters_promote: false,

// Swatches & Variants
color_attribute_names: ["Color", "colour"],
hide_oos_swatches: false,
swatch_width: 32,

// SPA
spa_dynamic_sections: { "header": "before" },

// Advanced
disable_shadow_root: false,
};

Available Options

Product Display

OptionTypeDefaultDescription
with_product_attributesbooleanfalseInclude product attributes in results
list_view_default_valuebooleanfalseSet list view as the default instead of grid view
numberOfColumnsRecord<string, string>-Number of columns per device for grid view (e.g. { desktop: "4", tablet: "3", mobile: "2" })
numberOfColumnsListRecord<string, string>-Number of columns per device for list view
custom_missing_product_imgstring-URL for a custom fallback image when a product image is missing
bring_product_pdp_imagesbooleanfalseAdd product images from PDP into the grid hook products data (pdpImages param)
show_carousel_marks_not_just_on_hoverbooleanfalseShow image carousel dot indicators permanently, not only on hover
show_quick_view_button_alwaysbooleanfalseKeep the Quick View button permanently visible on desktop product cards instead of only on hover. Mobile/tablet behavior is unchanged
show_quick_add_button_alwaysbooleanfalseKeep the variant Quick Add permanently visible on desktop product cards instead of only on hover. Covers both the standalone on-image variant selector and the combined Quick Add / Quick View button bar — when the bar is in use, the whole bar stays visible. Mobile/tablet behavior is unchanged, and the size options still open on click rather than showing expanded
quick_view_hide_single_value_optionsbooleanfalseWhen true, variant selector options with only a single value are hidden in the Quick View modal (e.g. a product with one size will not show the size selector)
max_carousel_imagesnumber6Maximum number of images in the product image carousel (includes the main image). Applies to both auto and arrows carousel types
omit_carousel_image_indexesnumber[]-0-based indexes into the product's PDP image list to drop from the tile carousel — e.g. [1] removes the second PDP image from every product. Useful when an image is already shown elsewhere on the card (such as a theme's hover overlay) and would otherwise appear twice. Applied before max_carousel_images, so omitting an index does not cost you a slide. The main product image is never affected. Note it also changes which image the 2nd-image carousel type shows on hover, since that picks from the same list
product_image_custom_classstring-Extra class(es) added to every product image in the grid — carousel images, hover second-image, pair-mode images and plain tiles. Space-separate for more than one. See Styling with a custom image class for the shadow-root and specificity caveats

URL & Navigation

OptionTypeDefaultDescription
full_product_url_path_redirectbooleantrueWhen true, product URLs include the /collections/collectionName segment. When false, URLs use /products/product-name directly. Shopify only
url_parameters_to_keepstring[][]URL parameters to preserve when navigating between pages (e.g. active filters or UTM tags)
pagination_querystring_parameterstring-Custom query string parameter name used for pagination
disable_pagination_scroll_to_topbooleanfalseWhen true, prevents the page from scrolling to the top when clicking pagination controls
disable_pdp_redirectbooleanfalse(SSR only) Disables automatic redirect to the PDP when clicking a product. Useful for custom routing solutions
disable_navigate_to_categorybooleanfalseHard-disable the window.SerpOptions.navigateToCategory() API for this site. When true, every call returns { ok: false, error: "..." } with guard "merchant-disabled". See Logic / SerpOptions Methods and the Facet Combo → Category Redirect example
max_navigate_to_category_per_pagenumber5Maximum number of navigateToCategory() calls allowed per page-load. The counter resets when the shopper hits browser back/forward. Lower values clamp aggressive merchant snippets; higher values allow deeper exploration chains

Filters

OptionTypeDefaultDescription
disable_selected_filters_promotebooleanfalseDisable promotion of active filters to the top of the filter list
default_value_for_hide_filters_buttonbooleanfalseWhen true, filters are hidden on page load and users must click to reveal them
disable_auto_close_filters_when_click_outsidebooleanfalsePrevent the filter panel from automatically closing when clicking outside it
parse_sub_category_tag_filter(name: string) => string-Custom function to parse subcategory tag filter names. Shopify only
disable_auto_collapsed_filtersbooleanfalseDisable auto-collapsed state for filters (applies only when filter layout is set to collapsed)
category_filter_as_regular_facetbooleanfalseDisplay the category filter as a regular facet instead of a dedicated category widget
persist_filters_visibilitybooleanfalse(SSR only) Preserve the filter sidebar's open/closed state across filter selections and page changes

Swatches & Variants

OptionTypeDefaultDescription
color_attribute_namesstring[]["Color"]All possible color attribute names to recognize (e.g. ["Color", "colour", "Couleur"])
swatch_widthnumber-Width of swatch elements in pixels
hide_oos_swatchesbooleanfalseWhen true, removes sold-out color swatches from the product card. It only ever hides — it never adds or changes a marker on sold-out swatches, and setting it to false (already the default) does nothing. It also applies to one swatch source only: color options coming from alternative-color products that carry variant data. Swatches built from the product's own variants are not filtered by it. Not supported on V-Next SSR — the option is ignored there. To style sold-out swatches rather than hide them, see Out-of-Stock Color Swatches
mark_oos_alt_swatchesbooleanfalseWhen true, sold-out alternative-color swatches — color options that link out to a separate product — are marked like any other sold-out swatch (fs-swatch-out-of-stock plus the ban icon). They render as in stock by default, so leaving this off preserves current behavior. Availability comes from the linked product's own stock status; where the response carries no data for a linked product the swatch still renders as in stock. Not needed on V-Next SSR, which already marks them. See Out-of-Stock Color Swatches
size_attribute_namesstring[]-All possible size attribute names to recognize
variant_size_custom_sort_orderstring[]-Custom sort order for size variants (all values must be lowercase)
get_selected_variant(productId: string) => SelectedVariant \| undefined-Custom function returning variant data (image, SKU, price, etc.) for a given product ID
add_current_product_as_first_variantbooleanfalseAdd the current product using its first variant ID

Collections

OptionTypeDefaultDescription
relatedCollectionsConfigurationRecord<string, string[]>-Maps each collection ID to an array of related collection IDs to suggest alongside it
onlyServerRelatedCollectionsbooleanfalseShow only related collections returned from the server

Layout & Responsive

OptionTypeDefaultDescription
serp_media_queries{device: string, query: string}[]-Override default screen breakpoints (e.g. [{device: 'mobile', query: '(max-width: 480px)'}])
custom_top_scroll_selectorstring-CSS selector for the element the page scrolls to on pagination
modern_mobile_filters_animationAnimationOptions-Animation configuration for the mobile filter panel
apply_narrow_manuallybooleanfalseApply filter/narrow actions manually instead of automatically

SPA (Single Page Application)

OptionTypeDefaultDescription
spa_disable_auto_close_mobile_menubooleanfalseDisable automatic closing of the mobile menu during SPA navigation
spa_dynamic_sectionsRecord<string, 'before' \| 'after'>-Page sections to re-render during SPA navigation, keyed by CSS selector
before_spa_navigation_callback(event?: Event) => void-Callback invoked before each SPA navigation
after_spa_navigation_callback(event?: Event) => void-Callback invoked after each SPA navigation

Custom Functions

OptionTypeDescription
parseProductTitle(title: string, productData: Product, selectedVariant: Variant) => stringTransform product titles before display. Receives the title, full product object, and selected variant
parseProductPrice(formattedPrice: string, comparePrice: string, productData?: Product, altProductData?: AlternativeProduct) => stringTransform product prices before display. Also receives optional product and alternative (swatch) product data
parseComparePrice(formattedCompare: string, productData?: Product, altProductData?: AlternativeProduct) => stringTransform compare-at (strike-through) prices before display
parsePageTitle(title: string, pageType: 'collection' \| 'search' \| 'landing', data: {categoryName?: string, searchTerm?: string, resultsFor?: string, didYouMean?: string[]}) => stringTransform the page H1 title before display
viewItemListCallback(event_items?: {items: GTAGItem[], category: 'filter' \| undefined}) => voidCalled after the view_item_list analytics event fires

Advanced

OptionTypeDefaultDescription
disable_shadow_rootbooleanfalseDisable Shadow DOM encapsulation. When enabled, styles are injected into document.head, allowing global CSS to affect the widget
avoid_bigcommerce_jwt_logged_on_user_checkbooleanfalseSkip JWT token verification for logged-in BigCommerce users
use_bigcommerce_jscontext_customer_group_idbooleanfalseBigCommerce B2B: read the live customer_group_id from the storefront Stencil context (window.jsContext.customer.customer_group_id) instead of the app JWT. Required for correct group-based pricing when a B2B user masquerades between companies, since the JWT is not refreshed on company switch
companyLocationProvider() => string \| number \| undefinednoneShopify B2B: a callback returning the buyer's company location id, sent as company_location_context. Required for B2B catalog visibility: without it the buyer is evaluated as an ordinary shopper in their market, so products restricted to their B2B catalog are hidden from them. Called on every request rather than once at init, so a mid-session location switch is picked up. When configured it is authoritative, so return undefined for a shopper who is not buying on behalf of a company

Shopify B2B: supplying the company location

On a store that restricts products to a B2B catalog, Fast Simon needs the buyer's company location to resolve which catalogs they are entitled to. Without it the buyer is evaluated as an ordinary shopper in their market, and the products restricted to their catalog are filtered out of their results.

Shopify exposes the buyer's active location to Liquid as customer.current_location, a company_location object. Render its id into the page and return it from the provider:

<script>
var __fast_options = __fast_options || {};
{%- comment -%} Assigned unconditionally: on a theme that navigates client-side, leaving a
previous page's value in place would keep sending a location the shopper no longer has. {%- endcomment -%}
window.fsCompanyLocation = {% if customer and customer.b2b? and customer.current_location %}{{ customer.current_location.id }}{% else %}undefined{% endif %};
__fast_options.companyLocationProvider = function () {
return window.fsCompanyLocation;
};
</script>

If your bundle predates companyLocationProvider

Set the value directly on window.__FAST_CUSTOMER_DETAILS instead. Every Fast Simon storefront bundle reads it, including versions released before the provider existed, so this works today on any bundle you already have:

{% if customer and customer.b2b? and customer.current_location %}
<script>
window.__FAST_CUSTOMER_DETAILS = {
customer_current_location: "{{ customer.current_location.id }}"
};
</script>
{% endif %}

Place it above the Fast Simon script tag and render it per page, for the same reasons as above. Where both are present the provider wins, so you can add the provider later without removing this first.

Liquid renders the location id as a number, so the provider example above hands back a number while the __FAST_CUSTOMER_DETAILS example quotes it and hands back a string. Both are accepted, and so is the gid://shopify/CompanyLocation/... string form you get if you source the location from the Storefront or Admin GraphQL API instead. Fast Simon trims the value and sends it as-is, so pick whichever is convenient in your theme.

Two behaviors worth knowing:

  • The provider is called on every request, not once at page load. A buyer who switches location mid-session is picked up as soon as your code updates the value, with no reload.
  • While a provider is configured it is authoritative. Return undefined for visitors who are not buying on behalf of a company; Fast Simon will not substitute a location for them.

GTAGItem Interface

export interface GTAGItem {
item_list_id: string; // category id
item_list_name: string; // category name
item_id: string | number; // product id
item_name: string; // product name
item_brand: string;
currency: string;
price: number;
index: number;
}

How to add custom options:

Add the __fast_options variable to your HTML head within a script tag, for example:

<script>
var __fast_options = __fast_options || {};
__fast_options.with_product_attributes = true;
__fast_options.relatedCollectionsConfiguration = {
'collectionId1': ['relatedCollectionId1', 'relatedCollectionId2', 'relatedCollectionId3'],
'collectionId2': ['relatedCollectionId4', 'relatedCollectionId5', 'relatedCollectionId6'],
'collectionId3': ['relatedCollectionId1', 'relatedCollectionId2', 'relatedCollectionId4']
};
__fast_options.serp_media_queries=[
{device: 'mobile', query: '(max-width: 480px)'},
{device: 'tablet', query: '(min-width: 481px) and (max-width: 820px)'},
{device: 'desktop', query: '(min-width: 821px)'}
];
__fast_options.variant_size_custom_sort_order = ['one size', 'xs', 'small', 'medium', 'large', 'xl', '4x',
'5x', '6x', '0', '1', '1x', '1x (16-18)', '2', '2x', '2x (18-20)', '3', '3x', '3x (22)', '5', '5.5', '6',
'6.5', '7', '7.5', '8', '8.5', '9', '10', '11', '13', '13/14', '15', '15/16','34b','34c','34d','34dd (e)',
'34dd(e)','34ddd (f)','36c','36d','36dd (e)','36ddd (f)','38c','38d','38dd','38dd (e)','38ddd','38ddd (f)',
'40c','40d','40dd','40dd (e)','40ddd','40ddd (f)','40g','42d','42dd (e)','42ddd','42ddd (f)','42g','44c',
'44d','44dd (e)','44ddd','44ddd (f)','44f','44g','46d','46dd (e)','46ddd','46ddd (f)','46f','46g'];

__fast_options.numberOfColumns = {
'desktop': "3",
'tablet': "3",
'mobile': "2"
};
__fast_options.numberOfColumnsList = {
'desktop': "2",
'tablet': "2",
'mobile': "1"
};
__fast_options.parseProductTitle = function(title, productData, selectedVariant) {
return title.replace("/"," ");
};
__fast_options.parsePageTitle = function(title, pageType, data) {
if (pageType === 'collection') {
return 'Shop ' + data.categoryName;
}
if (pageType === 'search') {
return 'Showing results for ' + data.searchTerm;
}
if (pageType === 'landing') {
return data.categoryName;
}
return title;
};
</script>