Skip to main content
Version: 1.0.0

Product Listing

Product listing pages usually represent the highest traffic path in ecommerce storefronts, so this area should be implemented with strict query discipline and predictable rendering structure.

Listing Architecture Pattern

Recommended structure:

  1. Page template decides route-level context (category, search, etc.).
  2. Listing query is created with explicit select/filter/order/limit.
  3. Related data is eager loaded.
  4. Query result is cached with clear TTL.
  5. Rendering is delegated to reusable components.

Query Pattern (YuiCraftPlugin)

Example: Fetching Products with Selected Attributes and Eager Loaded Fields

{% set criteria = {
colorFieldHandle: 'red'
} %}

{% set productsQuery = craft.yuiProducts(
['id', 'title', 'uri', 'yuiPrice'],
criteria,
{'id': 3},
16,
['productMediaAsset']
).productCategory(category) %}

{% set products = productsQuery.cache(900).all() %}

Why This Pattern Works

  • select: reduces payload and hydration cost
  • with: prevents N+1 problems for related media/fields
  • limit: protects response time
  • cache: improves repeated page load performance

Implementation Rules

  1. Never fetch all product columns for listing by default.
  2. Always set a limit for listing pages.
  3. Eager load only relations used in this template.
  4. Keep sorting indexed and predictable.
  5. Keep listing card markup in components, not in large inline loops.

Rendering Pattern

{% for product in products %}
{% include 'yui/blocks/global/product-card' with { product: product } %}
{% endfor %}

Pagination and Filtering Guidance

  • Keep current filter state in query params.
  • Build pagination URLs with stable params.
  • Cache listing fragments by filter/sort/page key combinations.
  • Do not cache customer-specific pricing fragments globally.

Pre-Release Checklist for Listings

  1. query count is stable with/without pagination
  2. sorting/filtering does not trigger N+1 regressions
  3. media fields are eager loaded
  4. cache key contains all listing variants
  5. empty-state and no-result UX is handled explicitly