Skip to content

Product Listing

GraphQL Queries

The project uses three main GraphQL queries for fetching products:

1. GET_PRODUCTS (Full Product Data)

graphql
import { gql } from "@apollo/client";
import { PRODUCT_CORE_FRAGMENT } from "../fragments";

export const GET_PRODUCTS = gql`
  ${PRODUCT_CORE_FRAGMENT}

  query GetProducts(
    $query: String
    $sortKey: String
    $reverse: Boolean
    $first: Int
    $after: String
    $before: String
    $channel: String
    $locale: String
    $filter: String
  ) {
    products(
      query: $query
      sortKey: $sortKey
      reverse: $reverse
      first: $first
      after: $after
      before: $before
      channel: $channel
      locale: $locale
      filter: $filter
    ) {
      totalCount
      pageInfo {
        startCursor
        endCursor
        hasNextPage
        hasPreviousPage
      }
      edges {
        node {
          ...ProductCore
        }
      }
    }
  }
`;

Query Parameters:

ParameterTypeDescriptionExample
queryStringSearch term"laptop"
sortKeyStringField to sort by"PRICE", "CREATED_AT", "TITLE"
reverseBooleanReverse sort ordertrue for descending
firstIntNumber of items per page12
afterStringCursor for next page"eyJpZCI6MTIzfQ=="
beforeStringCursor for previous page"eyJpZCI6MTAwfQ=="
channelStringSales channel"default"
localeStringLocalization"en"
filterStringFilter criteria (JSON)'{"color":"23"}'

2. GET_FILTER_PRODUCTS (Filtered Products)

graphql
import { gql } from "@apollo/client";
import { PRODUCT_SECTION_FRAGMENT } from "../fragments";

export const GET_FILTER_PRODUCTS = gql`
  ${PRODUCT_SECTION_FRAGMENT}
  query getProducts(
    $filter: String
    $sortKey: String
    $reverse: Boolean
    $first: Int
    $after: String
    $before: String
  ) {
    products(
      filter: $filter
      sortKey: $sortKey
      reverse: $reverse
      first: $first
      after: $after
      before: $before
    ) {
      totalCount
      pageInfo {
        endCursor
        startCursor
        hasNextPage
        hasPreviousPage
      }
      edges {
        node {
          ...ProductSection
        }
      }
    }
  }
`;

Use Case: Optimized for filtered product listings (color, size, brand filters applied)

3. GET_PRODUCTS_PAGINATION (Lightweight)

graphql
export const GET_PRODUCTS_PAGINATION = gql`
  query GetProductsPagination(
    $query: String
    $sortKey: String
    $reverse: Boolean
    $first: Int
    $channel: String
    $locale: String
    $after: String
    $before: String
  ) {
    products(
      query: $query
      sortKey: $sortKey
      reverse: $reverse
      first: $first
      channel: $channel
      locale: $locale
      after: $after
      before: $before
    ) {
      totalCount
      pageInfo {
        startCursor
        endCursor
        hasNextPage
        hasPreviousPage
      }
      edges {
        node {
          id
        }
      }
    }
  }
`;

Use Case: Fetch only pagination metadata to calculate cursor positions without loading full product data

Product Fragments

PRODUCT_CORE_FRAGMENT (Minimal Data)

graphql
export const PRODUCT_CORE_FRAGMENT = gql`
  fragment ProductCore on Product {
    id
    sku
    type
    name
    price
    urlKey
    baseImageUrl
    minimumPrice
    specialPrice
  }
`;

Use: Product listing pages, search results

PRODUCT_DETAILED_FRAGMENT (Full Details)

graphql
export const PRODUCT_DETAILED_FRAGMENT = gql`
  fragment ProductDetailed on Product {
    id
    sku
    type
    name
    urlKey
    description
    shortDescription
    price
    baseImageUrl
    minimumPrice
    specialPrice
    variants {
      edges {
        node {
          id
          sku
          baseImageUrl
        }
      }
    }
    reviews {
      edges {
        node {
          rating
          id
          name
          title
          comment
        }
      }
    }
  }
`;

Use: Product detail pages (PDP)

Fetching Products (Server-Side)

Example: Search page implementation

typescript
// src/app/(public)/search/page.tsx
import { graphqlRequest } from "@/lib/graphql-fetch";
import { GET_PRODUCTS } from "@/graphql";

export default async function SearchPage({ searchParams }) {
  const params = await searchParams;
  const searchValue = params?.q as string;
  const itemsPerPage = 12;

  // Fetch products on the server
  const data = await graphqlRequest(
    GET_PRODUCTS,
    {
      query: searchValue,
      first: itemsPerPage,
      sortKey: "CREATED_AT",
      reverse: true,
    },
    {
      tags: ["products"],
      life: "hours", // Cache for 1 hour
    }
  );

  const products = data?.products?.edges?.map((e) => e.node) || [];
  const totalCount = data?.products?.totalCount;

  return (
    <div>
      <h1>Search Results: {searchValue}</h1>
      <ProductGrid products={products} />
      <Pagination totalCount={totalCount} itemsPerPage={itemsPerPage} />
    </div>
  );
}

Released under the MIT License.