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

# Collection Page

> Render a Shopify collection with facets, sort and pagination using the Glood Hydrogen Search SDK

A collection page is a [`useSearch`](/for-developers/glood-hydrogen-sdk/api-reference/search-api#usesearch)
call with an **empty query** scoped to a collection via `targetPage: 'collection'` and the
collection's **numeric** id.

<Note>
  Prerequisite: the search app is registered (`.use(search())`), your app is wrapped in
  `<GloodProvider>`, and `https://search.glood.ai` is in your CSP `connectSrc`. See
  [Installation](/for-developers/glood-hydrogen-sdk/installation) — this guide covers only the
  collection-page wiring.
</Note>

## 1. Fetch the collection's products

Call [`useSearch`](/for-developers/glood-hydrogen-sdk/api-reference/search-api#usesearch) with
`targetPage: 'collection'`, `targetId` (the numeric Shopify collection id), and
`includeFacets` so the response carries inline facet counts for the collection.

```tsx theme={null}
import { useState } from 'react';
import { useSearch } from '@glood/hydrogen';

function CollectionGrid({ collectionId }: { collectionId: number }) {
  const [page, setPage] = useState(1);

  const { products, data, loading, error } = useSearch({
    query: '',                       // collection browse — no search term
    targetPage: 'collection',
    targetId: collectionId,          // numeric id, not the gid:// or handle
    sort: 'best_selling',
    pagination: { page, limit: 24 },
    options: { includeFacets: true },
  });

  if (error) return <p>{error.message}</p>;
  // …render below
}
```

The params above are a [`SearchParams`](/for-developers/glood-hydrogen-sdk/api-reference/types#searchparams--searchresponse);
the returned `data` is a [`SearchResponse`](/for-developers/glood-hydrogen-sdk/api-reference/types#searchparams--searchresponse)
and each `products` entry is a [`SearchProduct`](/for-developers/glood-hydrogen-sdk/api-reference/types#searchproduct).

<Note>
  `targetId` is the **numeric** collection id. In a Hydrogen collection route you have the
  collection GID (`gid://shopify/Collection/123`) — pass the trailing number (`123`).
</Note>

## 2. Render products, sort and pagination

```tsx theme={null}
return (
  <div className="collection">
    {/* hold `sort` in state and pass it to useSearch; re-run resets to page 1 */}
    <select defaultValue="best_selling" onChange={(e) => {/* setSort(e.target.value) */}}>
      <option value="best_selling">Best selling</option>
      <option value="price_asc">Price: low to high</option>
      <option value="newest">Newest</option>
    </select>

    <div className="grid">
      {products.map((p) => (
        <a key={p.product_id} href={`/products/${p.handle}`}>
          <img src={p.image?.url} alt={p.title} loading="lazy" />
          <span>{p.title}</span>
          <span>{p.display_price ?? p.price}</span>
        </a>
      ))}
    </div>

    <nav>
      <button disabled={!data?.pagination.has_prev_page} onClick={() => setPage((p) => p - 1)}>
        Previous
      </button>
      <span>{data?.pagination.page} / {data?.pagination.total_pages}</span>
      <button disabled={!data?.pagination.has_next_page} onClick={() => setPage((p) => p + 1)}>
        Next
      </button>
    </nav>
  </div>
);
```

`sort` accepts the values in [`SearchSort`](/for-developers/glood-hydrogen-sdk/api-reference/types#searchview--searchsort);
`data.pagination` is a [`SearchPagination`](/for-developers/glood-hydrogen-sdk/api-reference/types#searchpagination).

## 3. Add facet filtering

With `includeFacets: true`, `data.facets` holds the collection's facets with live counts.
Track the selected values in state and pass them back as the `facets` param:

```tsx theme={null}
const [selected, setSelected] = useState<Record<string, string[]>>({});

const { data } = useSearch({
  query: '',
  targetPage: 'collection',
  targetId: collectionId,
  facets: Object.entries(selected).map(([key, value]) => ({ key, operator: 'or', value })),
  pagination: { page, limit: 24 },
  options: { includeFacets: true },
});

// …render facets
{data?.facets?.map((facet) => (
  <fieldset key={facet.key}>
    <legend>{facet.key}</legend>
    {facet.aggregation.buckets.map((b) => (
      <label key={b.value}>
        <input
          type="checkbox"
          checked={b.selected}
          onChange={() => {
            const cur = selected[facet.key] ?? [];
            const next = b.selected ? cur.filter((v) => v !== b.value) : [...cur, b.value];
            setSelected({ ...selected, [facet.key]: next });
            setPage(1);
          }}
        />
        {b.value} ({b.count})
      </label>
    ))}
  </fieldset>
))}
```

Each applied filter is a [`SearchAppliedFacet`](/for-developers/glood-hydrogen-sdk/api-reference/types#searchparams--searchresponse).

<Note>
  For stable filter **definitions** (labels, order, swatches — independent of the current
  query), fetch them once with
  [`fetchFilters`](/for-developers/glood-hydrogen-sdk/api-reference/search-api#fetchfilters) /
  `app.filters({ collection: collectionId })` and merge in the live counts from
  `data.facets`. See [Filters & aggregations](/for-developers/glood-hydrogen-sdk/search#filters--aggregations).
</Note>

## 4. Attribute clicks

`useSearch` returns the track helpers. Fire
[`trackResultClick`](/for-developers/glood-hydrogen-sdk/api-reference/search-api#usesearch) with
`page_type: 'collection'`:

```tsx theme={null}
const { products, data, trackResultClick } = useSearch({ /* …as above */ });

<a
  href={`/products/${p.handle}`}
  onClick={() =>
    trackResultClick({
      request_id: data?.request_id,
      search_type: 'text',
      page_type: 'collection',
      products: [{ product_id: p.product_id }],
    })
  }
>
```

The payload is a [`SearchTrack`](/for-developers/glood-hydrogen-sdk/api-reference/types#searchtrack).

## See also

* [`useSearch`](/for-developers/glood-hydrogen-sdk/api-reference/search-api#usesearch) — full returns (including `trackFilter`, `trackAddToCart`)
* [Search Page](/for-developers/glood-hydrogen-sdk/guides/search-page) — the same call driven by a query
* [Search API Reference](/for-developers/glood-hydrogen-sdk/api-reference/search-api)
