Breadcrumbs
Breadcrumbs on PLP and PDP pages are driven by a single Shopify metaobject type: Breadcrumb Categories (breadcrumb_categories). This metaobject defines the full category hierarchy and serves as the single source of truth for both page types.
Please note this metaobject is live on both production and staging, so we can test out future changes on the staging store before making it live on production.
Metaobject Structureโ
Each entry in the breadcrumb_categories metaobject has:
| Field | Type | Required | Description |
|---|---|---|---|
title | single_line_text_field | Yes | Display label in the breadcrumb (e.g., "Shoes"). This can also be customized for marketing purposes: "20% off Shoes" |
url | single_line_text_field | Yes | Collection handle used to build the breadcrumb URL (e.g., bridesmaid-shoes-heels โ /collections/bridesmaid-shoes-heels) |
subcollection | list.metaobject_reference | No | References to child category entries. Defines the parent โ child hierarchy. |
product_types | list.single_line_text_field | No | Product type strings used by PDP to resolve a product to this category. See PDP Product Type Mapping. |
Hierarchyโ
The category hierarchy is defined through the subcollection field. Parent entries list their children as metaobject references. At runtime, this relationship is inverted โ each child stores a reference back to its parent โ so the breadcrumb builder can walk up the chain.
Exampleโ
Pajamas & Robes (url: bridesmaid-getting-ready-outfits)
โโโ Robes (url: bridesmaid-robes)
โโโ Pajamas (url: bridesmaid-pajamas)
โโโ Slippers (url: bridesmaid-slippers)
Jewelry & Accessories (url: bridesmaid-bridal-accessories)
โโโ Shoes (url: bridesmaid-shoes-heels)
โโโ Shawls (url: shawls-cover-ups)
โโโ Intimates (url: intimates)
โโโ Scarves (url: bridesmaid-dress-scarves)
โโโ Dog Bow Ties (url: pet-accessories)
A product or collection under "Robes" produces the breadcrumb:
Birdy Grey > Pajamas & Robes > Robes > [Page Title]
How PLP Uses Itโ
Each Shopify collection (PLP) has a breadcrumb_category metafield (namespace: config, key: breadcrumb_category, type: metaobject_reference) that directly references its category entry in the metaobject.
Data flowโ
- The collection query resolves the
breadcrumb_categoryreference inline (returns the metaobject'sidandfields) - The PLP loader calls
loadPlpBreadcrumbs(), which fetches allbreadcrumb_categoriesmetaobjects and builds aCollectionBreadcrumbMap(Record<metaobjectId, { title, url, parentId? }>) createPlpBreadcrumbs()looks up the collection's referenced metaobject ID in the map and usesbuildCategoryChain()to walk up theparentIdchain to build the full breadcrumb path- If the collection's handle matches the category's url, the collection is treated as the category page itself (no duplicate crumb appended)
- If no
breadcrumb_categoryis set on the collection, a simple fallback breadcrumb is returned:[collection title]
Setting up a collectionโ
To add breadcrumbs to a collection:
- Ensure the category entry exists in the
breadcrumb_categoriesmetaobject (create it if needed) - If it's a subcategory, add it to the parent entry's
subcollectionfield - On the collection in Shopify Admin, set the
breadcrumb_categorymetafield to reference the correct metaobject entry
How PDP Uses Itโ
Products don't have a breadcrumb_category metafield. Instead, the PDP resolves a product to its category using the product_types field on each metaobject entry.
PDP Product Type Mappingโ
The product_types field contains a list of strings that match either:
product.productTypeโ the Shopify product type (e.g.,"Bridesmaid Dress","Swatch","Shoes")product.type.valueโ theattr.typemetafield value (e.g.,"Dress","Robe","Pajamas")
At runtime, a reverse lookup map is built: product type string โ metaobject ID. When rendering a PDP, the system tries productType first, then falls back to type.value.
Why product_types existsโ
Shopify product types and metafield values don't always match the metaobject entry titles. For example:
| Product field | Value | Metaobject title |
|---|---|---|
productType | "Seamless Underwear" | Intimates |
productType | "Little White Dress" | Little White Dresses |
type.value | "Pajama Set" | Pajamas |
type.value | "Robe" | Robes |
The product_types field bridges this gap by listing all the product type strings that should resolve to a given category. Multiple strings can map to the same entry (e.g., both "Pajamas" and "Pajama Set" resolve to the Pajamas category).
When to add product_typesโ
Only entries that PDP products should resolve to need product_types. Parent-only entries that serve as hierarchy containers (like "Pajamas & Robes" or "Ties & Accessories") don't need it since no product has those as their type.
Data flowโ
- The PDP loader fetches all
breadcrumb_categoriesmetaobjects (same cached query as PLP) - Two maps are built:
CollectionBreadcrumbMap(same as PLP) andProductTypeBreadcrumbMap(Record<product type string, metaobject ID>) createPdpBreadcrumbs()looks up the product's type in the product type map, finds the metaobject ID, then usesbuildCategoryChain()to walk up the parent chain- If no match is found, a simple fallback breadcrumb is returned:
[product title]
SEO Schemaโ
Both PLP and PDP emit a BreadcrumbList JSON-LD schema via getBreadcrumbSchema(). The schema prepends a "Birdy Grey" home link (https://www.birdygrey.com/) and outputs full absolute URLs for each breadcrumb item.
Cachingโ
The metaobject query uses CacheStrategy.slower (15-minute max age, 4-hour stale-while-revalidate). This data rarely changes โ only when categories are added, renamed, or reorganized.
Key Filesโ
| File | Purpose |
|---|---|
app/lib/plp/breadcrumbs.server.ts | parseBreadcrumbMetaobjects(), parseProductTypeLookup(), buildCategoryChain(), createPlpBreadcrumbs(), loadPlpBreadcrumbs() |
app/lib/pdp/helper.server.ts | createPdpBreadcrumbs() |
app/lib/plp/router/next.server.ts | PLP loader โ calls loadPlpBreadcrumbs() |
app/routes/products.$handle.tsx | PDP loader โ fetches metaobjects, builds breadcrumbs |
app/lib/seo/helper.ts | getBreadcrumbSchema() โ JSON-LD structured data |
app/graphql/storefront/MetaobjectQuery.ts | METAOBJECT_TYPE_QUERY โ GraphQL query for metaobjects |
app/graphql/storefront/CollectionQuery.ts | Collection query with breadcrumb_category metaobject reference |
app/components/BreadCrumbs/breadCrumbs.component.tsx | UI breadcrumb component |