Retrieve Nested Categories in the Storefront

Retrieve category trees and nested children.

On this page

In this guide, you'll learn how to retrieve nested categories in the storefront.

How to Retrieve Nested Categories in Storefront?

A product category has parent and child categories. For example, a "Shoes" category can have a "Running Shoes" child category.

There are two ways to retrieve nested categories:

Both approaches select specific fields of a child category, which requires the configuration explained in the next section.


Allow Selecting Child Category Fields

Aiminaabee restricts the fields that you can request from a Store API route through an allowed-fields list. The product category routes allow *category_children, which returns all fields of a child category. However, they don't allow selecting specific child fields, such as category_children.id, and Aiminaabee omits them from the response.

Since selecting specific fields keeps the response size small, add the following middleware to your Aiminaabee application to allow the category_children.id and category_children.name fields:

ts

tsCopy
import {
allowFields,
defineMiddlewares,
} from "@aiminaabeejs/framework/http"
export default defineMiddlewares({
routes: [
{
matcher: "/store/product-categories",
middlewares: [
allowFields(
"category_children.id",
"category_children.name"
),
],
},
],
})

allowFields is available since the current Aiminaabee API. In earlier versions, write the middleware yourself, as explained in the Allowed Fields documentation.

Important: Don't add a method or methods key to the middleware's object. Aiminaabee runs a method-scoped middleware after it validates the query parameters, so it has no effect there.

Learn more about allowed fields and how to override them in the Allowed Fields documentation.


Retrieve Nested Categories of a Category

To retrieve the child or nested categories of a category in your storefront, pass to the Get a Category API Route the following query parameters:

  • include_descendants_tree=true to retrieve each category's nested categories at all levels.
  • Add category_children to fields, which is the field that will hold a category's nested categories.
    • You can either pass *category_children to retrieve all fields of a child category, or specify the fields specifically to avoid a large response size. For example, fields=category_children.id,category_children.name.
    • *category_children works out of the box. To select specific fields of a child category, first apply the middleware in the Allow Selecting Child Category Fields section.

For example:

Tip: Learn how to install and configure the JS SDK in the Getting started guide.

React

tsx

tsxCopy
"use client" // include with Next.js 13+
import { useEffect, useState } from "react"
import { HttpTypes } from "@aiminaabeejs/types"
import { sdk } from "@/lib/sdk"
type Props = {
id: string
}
export default function Category({ id }: Props) {
const [loading, setLoading] = useState(true)
const [category, setCategory] = useState<
HttpTypes.StoreProductCategory | undefined
>()
useEffect(() => {
if (!loading) {
return
}
sdk.store.category.retrieve("us", id, {
fields: "category_children.id,category_children.name",
include_descendants_tree: true,
})
.then(({ product_category }) => {
setCategory(product_category)
setLoading(false)
})
}, [loading])
return (
<div>
{loading && <span>Loading...</span>}
{category && (
<>
<h1>{category.name}</h1>
<p>{category.description}</p>
{(category.category_children?.length || 0) > 0 && (
<>
<span>Child Categories</span>
<ul>
{category.category_children!.map(
(childCategory) => (
<li key={childCategory.id}>
{childCategory.name}
</li>
)
)}
</ul>
</>
)}
</>
)}
</div>
)
}

JS SDK

ts

tsCopy
sdk.store.category.retrieve("us", id, {
fields: "category_children.id,category_children.name",
include_descendants_tree: true,
})
.then(({ product_categories }) => {
// use the product category's children...
console.log(product_categories[0].category_children)
})

In this example, you retrieve the nested categories of a category by passing the include_descendants_tree query parameter to the Get a Category API Route.

The response has a product_category field, which is a product category object. It will have a category_children field, which is an array of product category objects.

Then, in the React component, you show a category's children by iterating over the category_children field.


Retrieve Categories as a Hierarchy

Alternatively, you may want to retrieve all categories as a hierarchy.

To do this, you can pass the include_descendants_tree query parameter to the List Product Categories API Route, along with the parent_category_id query parameter set to null. This ensures that only categories with children are retrieved at the top level.

For example:

React

tsx

tsxCopy
"use client" // include with Next.js 13+
import { useEffect, useState } from "react"
import { HttpTypes } from "@aiminaabeejs/types"
import { sdk } from "@/lib/sdk"
type Props = {
id: string
}
export default function Categories({ id }: Props) {
const [loading, setLoading] = useState(true)
const [categories, setCategories] = useState<
HttpTypes.StoreProductCategory[]
>([])
useEffect(() => {
if (!loading) {
return
}
sdk.store.category.list("us", {
id,
fields: "category_children.id,category_children.name",
include_descendants_tree: true,
parent_category_id: null,
})
.then(({ product_categories }) => {
setCategories(product_categories)
setLoading(false)
})
}, [loading])
return (
<div>
{loading && <span>Loading...</span>}
{categories.map((category) => (
<>
<h1>{category.name}</h1>
<p>{category.description}</p>
{(category.category_children?.length || 0) > 0 && (
<>
<span>Child Categories</span>
<ul>
{category.category_children!.map(
(childCategory) => (
<li key={childCategory.id}>
{childCategory.name}
</li>
)
)}
</ul>
</>
)}
</>
))}
</div>
)
}

JS SDK

ts

tsCopy
sdk.store.category.list("us", {
id,
fields: "category_children.id,category_children.name",
include_descendants_tree: true,
parent_category_id: null,
})
.then(({ product_categories }) => {
// use the product category's children...
console.log(product_categories[0].category_children)
})

In this example, you retrieve all categories as a hierarchy by passing the include_descendants_tree query parameter to the List Product Categories API Route.

The response has a product_categories field, which is an array of product category objects.

Each category will have a category_children field, which is an array of product category objects.

You can then show the categories in a tree structure by iterating over the product_categories field and displaying the category_children field for each category.