DEV Community

Aswini K
Aswini K

Posted on

Technical SEO for a Niche E-commerce Site: What We Fixed in Next.js and What Moved the Needle

Disclosure: I work on Peptides India, a life-science supply store, and the examples below come from that project.

Niche e-commerce sites have a specific SEO problem. The catalogue is small, the products are specialised, and the competition is often a few large marketplaces with huge domain authority. You can't win on volume, so you have to win on technical quality and clarity.

This post covers the technical fixes we made, with code. Every site is different, so treat the numbers as a starting point and measure your own.

1. Start with a real baseline

Before touching code, record where you stand:

  • Lighthouse / PageSpeed Insights: LCP, CLS and INP on a product page and a category page.
  • Google Search Console: indexed pages, "Discovered, currently not indexed" and "Crawled, currently not indexed" counts.
  • A crawl: Screaming Frog (free up to 500 URLs) to find duplicate titles, missing meta descriptions and broken links.

[Add your own before numbers here: e.g. mobile LCP, number of indexed pages.]

Without a baseline you can't tell which change actually helped.

2. Unique, server-rendered metadata per page

Many small stores ship the same <title> on every page. In the Next.js App Router, generateMetadata fixes this cleanly:

// app/products/[slug]/page.tsx
import type { Metadata } from "next";
import { getProduct } from "@/lib/products";

export async function generateMetadata(
  { params }: { params: { slug: string } }
): Promise<Metadata> {
  const product = await getProduct(params.slug);

  return {
    title: `${product.name} | Product Details`,
    description: product.shortDescription.slice(0, 155),
    alternates: {
      canonical: `https://example.com/products/${product.slug}`,
    },
    openGraph: {
      title: product.name,
      description: product.shortDescription,
      images: [product.imageUrl],
    },
  };
}
Enter fullscreen mode Exit fullscreen mode

Points that matter:

  • Keep titles under roughly 60 characters and descriptions under roughly 155.
  • Set a canonical URL on every page. Filter and sort parameters create duplicates quickly.
  • Write descriptions by hand for important pages. Auto-generated ones tend to be repetitive.

3. Structured data (JSON-LD)

Product schema helps search engines understand price, availability and identifiers. It can also make you eligible for rich results, though Google doesn't guarantee them.

// components/ProductJsonLd.tsx
type Props = {
  name: string;
  description: string;
  image: string;
  sku: string;
  price: number;
  inStock: boolean;
  url: string;
};

export default function ProductJsonLd(p: Props) {
  const data = {
    "@context": "https://schema.org",
    "@type": "Product",
    name: p.name,
    description: p.description,
    image: [p.image],
    sku: p.sku,
    offers: {
      "@type": "Offer",
      url: p.url,
      priceCurrency: "INR",
      price: p.price,
      availability: p.inStock
        ? "https://schema.org/InStock"
        : "https://schema.org/OutOfStock",
    },
  };

  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}
    />
  );
}
Enter fullscreen mode Exit fullscreen mode

Validate it with Google's Rich Results Test. Only mark up what is visible on the page, because mismatches between schema and content can cause problems.

4. A sitemap that reflects reality

// app/sitemap.ts
import type { MetadataRoute } from "next";
import { getAllProducts } from "@/lib/products";

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const products = await getAllProducts();
  const base = "https://example.com";

  const productUrls = products.map((p) => ({
    url: `${base}/products/${p.slug}`,
    lastModified: p.updatedAt,
  }));

  return [
    { url: base, lastModified: new Date() },
    { url: `${base}/products`, lastModified: new Date() },
    ...productUrls,
  ];
}
Enter fullscreen mode Exit fullscreen mode

Only include indexable, canonical URLs. Leave out out-of-stock pages you've noindexed, cart pages and parameter variants. Submit the sitemap in Search Console.

5. Core Web Vitals: images first

On product pages the hero image is nearly always the LCP element.

import Image from "next/image";

<Image
  src={product.imageUrl}
  alt={`${product.name} product photo`}
  width={800}
  height={800}
  priority          // preload the above-the-fold image
  sizes="(max-width: 768px) 100vw, 50vw"
/>
Enter fullscreen mode Exit fullscreen mode

Other quick wins:

  • Set explicit width and height to prevent layout shift (CLS).
  • Use priority only on the single hero image. Overusing it defeats the purpose.
  • Serve AVIF or WebP, which next/image does by default.
  • Load third-party scripts (chat widgets, analytics) with next/script and strategy="lazyOnload".

[Add your before and after LCP and CLS numbers here.]

6. Internal linking and crawl paths

A small catalogue is an advantage here. Make sure:

  • Every product is reachable within two or three clicks from the homepage.
  • Category pages link to products with descriptive anchor text, not "click here".
  • Breadcrumbs use BreadcrumbList schema.
  • Orphan pages (no internal links) are either linked or removed.

7. Content that answers real questions

Technical fixes get you crawled and indexed, but rankings still depend on usefulness. For product and category pages that means:

  • Clear specifications, purity documentation and batch information where applicable.
  • A short FAQ per category written from actual customer questions.
  • Plain, accurate language. In regulated or sensitive niches, avoid unverifiable claims, since they hurt trust and can violate platform and advertising policies.

8. Measure, then iterate

Give changes time. Search Console data lags, and rankings can take weeks to settle. Check:

  • Impressions and clicks per page, filtered by query.
  • Indexed page count against sitemap count.
  • Core Web Vitals report (field data, not just lab data).

[Add your own results here, with dates. If a change did nothing, say so. Honest write-ups get better engagement.]

Takeaways

  1. Baseline first, then change one thing at a time.
  2. Unique metadata, canonicals and a clean sitemap solve most indexing problems.
  3. Structured data helps clarity, not magic rankings.
  4. Image handling is the biggest Core Web Vitals lever on product pages.
  5. Technical SEO is the foundation. Useful content is what ranks.

If you want to see the finished result, the store is at retralabs.in.

What technical SEO fix gave you the biggest return on a small site? Tell me in the comments.

Top comments (0)