Skip to main content

Product search returns relevant results

ab-001129 · ecommerce-catalog.search-discovery.search-relevance
Severity: lowactive

Why it matters

Search that queries only name or is case-sensitive returns empty results for shoppers typing 'red shirt' instead of 'Red Shirt', so the catalog's long tail is effectively invisible. Every zero-result search is an abandoned session and a lost order. Internal search is also a top SEO signal — sites that surface relevant results rank better and earn more crawl budget. Narrow or case-sensitive matching turns a working catalog into a dead end.

Severity rationale

Low because users can still browse categories, but every failed query is a direct conversion loss.

Remediation

Widen the query to at least name and description, pass mode: 'insensitive' so casing does not matter, and cap results so the response stays fast. Implement this in src/app/api/search/route.ts:

const results = await prisma.product.findMany({
  where: {
    OR: [
      { name: { contains: query, mode: 'insensitive' } },
      { description: { contains: query, mode: 'insensitive' } },
    ],
  },
  take: 10,
})

Detection

  • ID: ecommerce-catalog.search-discovery.search-relevance

  • Severity: low

  • What to look for: Count all search-related files in the codebase: search API routes (src/app/api/search/route.ts, src/app/api/products/search/route.ts), search components (src/components/search/), and search library integrations (Algolia, Meilisearch, Elasticsearch). Enumerate which product fields are included in the search index or query: name, description, category, tags, SKU. Check whether the search is case-insensitive by examining the query mode or collation settings.

  • Pass criteria: A search implementation exists that queries at least 2 product fields (name and description at minimum) and is case-insensitive. Count all searchable fields and report: "Search covers X fields: [list]. Case-insensitive: [yes/no]."

  • Fail criteria: Search returns irrelevant products (queries only a single field), or search is case-sensitive and fails on different casings, or no search implementation exists.

  • Skip (N/A) when: The project has no search functionality — confirmed by finding 0 search-related API routes, components, or library integrations.

  • Cross-reference: For search SEO implications, the SEO Fundamentals audit covers site search and internal linking patterns.

  • Cross-reference: For search performance, the Performance Core audit covers query optimization and response time patterns.

  • Cross-reference: For search accessibility, the Accessibility Fundamentals audit covers search input labeling and results announcement.

  • Detail on fail: "Search in src/app/api/search/route.ts queries only product.name — descriptions are not searchable" or "Search is case-sensitive: 'Red Shirt' returns 0 results but 'red shirt' returns 3 in src/app/api/products/search/route.ts"

  • Remediation: Implement case-insensitive full-text search in src/app/api/search/route.ts:

    const results = await prisma.product.findMany({
      where: {
        OR: [
          { name: { contains: query, mode: 'insensitive' } },
          { description: { contains: query, mode: 'insensitive' } },
        ],
      },
      take: 10,
    })
    

Taxons

History