# Shopify Custom and Default Filters

Most storefront filters should be configured in **Filters & Data** and **Layout Settings**. Use JavaScript custom and default filters only for behavior that cannot be represented as a normal merchant-managed facet.

These hooks must be defined before the Search Results or Product Grid App Block starts.

<br/>

## Default Filters

Use `window.Nimstrata.search.defaultFilters` for hidden filters that should apply to every search or collection request.

Default filters are not shown in the UI, are not shopper-removable, and are not reflected as normal filter controls. They are a good fit for:

- Store, warehouse, or region availability gates
- B2B buyer segmentation
- Channel-specific product restrictions
- Temporary launch constraints that should not appear as shopper filters

```js
window.Nimstrata = window.Nimstrata || {};
window.Nimstrata.search = window.Nimstrata.search || {};

window.Nimstrata.search.defaultFilters = [
  {
    field: 'attributes.available_in_market',
    value: ['GB'],
    type: 'string',
  },
  {
    or: [
      { field: 'attributes.channel', value: ['online'], type: 'string' },
      { field: 'attributes.channel', value: ['both'], type: 'string' },
    ],
  },
];
```

`defaultFilters` can also be a sync or async function:

```js
window.Nimstrata.search.defaultFilters = async function () {
  const profile = await window.getCustomerProfile?.();

  return profile?.b2b
    ? [{ field: 'attributes.customer_group', value: ['b2b'], type: 'string' }]
    : [];
};
```

Collection pages already add their collection constraints through the App Block. Only add a collection ID, tag, or market filter manually during a manual install or when intentionally applying an extra hidden rule.

<br/>

## Custom Filters

Use `window.Nimstrata.search.customFilters` when shoppers need a visible switch for a filter that is not part of the normal facet list.

The current storefront UI supports `displayComponent: 'switch'`. Custom switches can render in the toolbar or in the sidebar/filter drawer.

```js
window.Nimstrata = window.Nimstrata || {};
window.Nimstrata.search = window.Nimstrata.search || {};
window.Nimstrata.search.customFilters =
  window.Nimstrata.search.customFilters || [];

window.Nimstrata.search.customFilters.push({
  name: 'in_stock',
  displayName: 'In stock',
  displayComponent: 'switch',
  displayLocation: 'toolbar',
  defaultActive: false,
  filter: {
    field: 'availability',
    value: ['IN_STOCK'],
    type: 'string',
  },
});
```

Use the nested `filter` property for new work. Older inline custom filters with `field`, `value`, and `type` still work for backwards compatibility.

<br/>

## Custom Filter Fields

The search App Block only receives facet metadata for fields that are requested as filters. If a custom filter uses a field that is not already in the App Block filter list, add it to `window.Nimstrata.search.customFields` so the storefront can decide whether the switch is relevant for the current result set.

```js
window.Nimstrata.search.customFields = [
  { field: 'attributes.available_in_store', type: 'number' },
];
```

Without this, a custom switch may be hidden because the storefront cannot confirm that applying it could return results.

<br/>

## Default Active Custom Filters

Set `defaultActive: true` when a custom filter should start enabled but still be shopper-removable.

The URL uses `cf` for custom filters the shopper turns on and `cf-off` for default-active custom filters the shopper turns off. Use the `name` as the stable identifier, and avoid changing it once URLs are live.

<br/>

## Search Versus Recommendations

Search and collection pages use `window.Nimstrata.search.defaultFilters`.

Recommendations use a separate property:

```js
window.Nimstrata = window.Nimstrata || {};
window.Nimstrata.recs = window.Nimstrata.recs || {};
window.Nimstrata.recs.defaultFilters = [
  { field: 'attributes.available_in_market', value: ['GB'], type: 'string' },
];
```

Recommendations automatically include an in-stock filter unless the configured recommendation filters already include an `availability` filter, including one nested inside `or`, `and`, or `not`.

<br/>

## When Not To Use These Hooks

Do not use custom or default filters to replace normal filter configuration. If the filter should appear as a normal facet, configure the attribute in [App Block Filters](/shopify/filters-and-data/app-block-filters/). If the filter is only about layout, count display, quick filters, search-within-filters, or sorting placement, use [Layout Settings](/shopify/theme-installation/layout-settings/).
