> ## Documentation Index
> Fetch the complete documentation index at: https://docs.napps.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Collection Filters Extension

The Collection Filters Extension lets you change collection filters before products are fetched.

It also runs again whenever the user changes the selected filters.

Use this extension when you want to:

* Preselect filters before products load.
* Add or remove selected filter values.
* Set or clear a price range.
* Set or clear the product order.
* Hide or show filters.
* React when the user changes filters.

## Exported Function

Your project must export a function named `prepareCollectionProductsFilters`.

```ts theme={null}
export async function prepareCollectionProductsFilters(
  context: CollectionProductsFiltersContext
) {
  // Edit filters here.
}
```

The function can be synchronous or asynchronous. If the function returns a promise the app will wait up to 3 seconds before assuming the extension failed.

## When It Runs

The extension receives a `trigger` that tells you why it is running.

```ts theme={null}
type CollectionProductsFiltersTrigger = "Initial" | "UserFiltersChanged";
```

The triggers are:

* `Initial`: runs before the application fetches products for the collection.
* `UserFiltersChanged`: runs after the user changes filters, before the application fetches the updated products.

Use `Initial` when you want to apply default filters.

Use `UserFiltersChanged` when you want to react to the user's current filter selection.

## Context

The function receives a context object.

```ts theme={null}
interface CollectionProductsFiltersContext {
  collection: CollectionProductsCollectionInfo;
  trigger: CollectionProductsFiltersTrigger;
  filters: CollectionProductsFiltersEditor;
}

interface CollectionProductsCollectionInfo {
  id: string;
  title: string;
}
```

Use `context.collection` to know which collection is being loaded.

Use `context.trigger` to know why the extension is running.

Use `context.filters` to inspect and change the filters.

## Filter Editor

The `filters` editor lets you change the selected filters and the visible filters.

```ts theme={null}
export interface CollectionProductsFiltersEditor {
  available: AvailableCollectionProductsFilters;

  addValueById(filterId: string, value: string): boolean;
  addValueByLabel(filterLabel: string, value: string): boolean;

  removeValueById(filterId: string, value: string): boolean;
  removeValueByLabel(filterLabel: string, value: string): boolean;

  clearById(filterId: string): boolean;
  clearByLabel(filterLabel: string): boolean;

  hasValueById(filterId: string, value: string): boolean;
  hasValueByLabel(filterLabel: string, value: string): boolean;

  setPriceRange(min: number, max: number): void;
  clearPriceRange(): void;

  setOrder(order: FilterOrder): boolean;
  clearOrder(): boolean;

  hideFilterById(filterId: string): boolean;
  hideFilterByLabel(filterLabel: string): boolean;
  showFilterById(filterId: string): boolean;
  showFilterByLabel(filterLabel: string): boolean;
  isFilterHiddenById(filterId: string): boolean;
  isFilterHiddenByLabel(filterLabel: string): boolean;
}
```

Methods that return `boolean` return `true` when the change was applied.

## Available Filters

You can inspect the filters that are available for the collection.

```ts theme={null}
interface AvailableCollectionProductsFilters {
  readonly all: AvailableCollectionProductsFilter[];

  findById(id: string): AvailableCollectionProductsFilter | null;
  findByLabel(label: string): AvailableCollectionProductsFilter | null;
}

interface AvailableCollectionProductsFilter {
  readonly id: string;
  readonly label: string;
  readonly type: FilterType;
  readonly isExtra: boolean;
  readonly values: AvailableCollectionProductsFilterValue[];

  hasValue(value: string): boolean;
}

interface AvailableCollectionProductsFilterValue {
  readonly label: string;
  readonly value: string;
  readonly count: number | null;
  readonly isVariantOptionFilter: boolean;
}
```

## Filter Types

```ts theme={null}
type FilterType =
  | "LIST"
  | "SINGLE_SELECTION_LIST"
  | "ORDERING"
  | "PRICE_RANGE";
```

## Ordering

Use `setOrder` to change the product ordering.

```ts theme={null}
type FilterOrder =
  | "None"
  | "Ascending"
  | "Descending"
  | "BestSelling"
  | "Relevance"
  | "RecentProducts"
  | "OldestProducts"
  | "NameAscending"
  | "NameDescending"
  | "OldProducts";
```

Example:

```ts theme={null}
export function prepareCollectionProductsFilters(
  context: CollectionProductsFiltersContext
) {
  if (context.trigger === "Initial") {
    context.filters.setOrder("BestSelling");
  }
}
```

## Example: Add a Default Filter

```ts theme={null}
export function prepareCollectionProductsFilters(
  context: CollectionProductsFiltersContext
) {
  if (context.trigger !== "Initial") {
    return;
  }

  const filter = context.filters.available.findByLabel("Color");

  if (!filter?.hasValue("black")) {
    return;
  }

  context.filters.addValueByLabel("Color", "black");
}
```

## Example: Hide a Filter

```ts theme={null}
export function prepareCollectionProductsFilters(
  context: CollectionProductsFiltersContext
) {
  context.filters.hideFilterById("filter.p.vendor");
}
```

## Example: Set a Price Range

```ts theme={null}
export function prepareCollectionProductsFilters(
  context: CollectionProductsFiltersContext
) {
  if (context.collection.title === "Sale") {
    context.filters.setPriceRange(0, 100);
  }
}
```

## Best Practices

* Keep the function fast.
* Use `Initial` for default filter rules.
* Use `UserFiltersChanged` for rules that depend on the user's current selection.
* Prefer filter IDs when you know them.
* Check that a filter or value exists before applying it.
* Avoid changing filters in a way that surprises the user.
