agentsclimarketplace

Seo ecommerce

Skill PIXARTSeu/Synapse/packages/codegraph/data/skill/seo-ecommerce

Self-improving AI brain for Claude Code & Desktop — 28 MCP tools, 253 skills, collective memory, project tracking, work logs. One server, all your sessions share the same knowledge. Deploy on Coolify in 2 minutes.

Install
npx -y skills add PIXARTSeu/Synapse --skill seo-ecommerce

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 8 stars8 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

E-commerce SEO for product and category pages — Product/Offer/AggregateRating JSON-LD, faceted navigation & crawl control, variant/canonical handling, out-of-stock and pagination, category page optimization, and merchant feed basics. Includes Next.js 15 App Router + Payload code and a 0-100 audit rubric. Use when working on ecommerce SEO, product SEO, shop/store pages, product schema, category pages, faceted filters, merchant feed, or shopping visibility. Triggers on: ecommerce SEO, product SEO, product schema, Product JSON-LD, Offer, AggregateRating, faceted navigation, canonical variants, out of stock SEO, pagination SEO, category page SEO, merchant feed, shopping.

SKILL.md

17.3 KB, ~4.2k tokens by cl100k_base, as published. Nobody here has run it

E-commerce SEO

Product and category pages have failure modes that generic page SEO misses: schema gaps that kill rich results, faceted filters that explode crawl budget, variant URLs that fragment ranking signals, and out-of-stock handling that silently drops products. This skill is implementation-first for our stack (Next.js 15 App Router + RSC, Payload CMS) plus an audit rubric for assessing an existing store.

When to use

  • Building or auditing product detail pages (PDPs) and category/listing pages (PLPs).
  • A store has faceted filters (size, color, price, brand) and crawl-budget concerns.
  • Products have variants (size/color) and you need canonical + indexing strategy.
  • You need Product/Offer/AggregateRating JSON-LD that earns rich results.
  • You're preparing a Merchant feed and want on-page data to match it.

1. Product schema (Product + Offer)

Google rich results need a small set of required fields and a larger set of recommended ones. Render JSON-LD server-side so it's in the initial HTML — many storefronts inject it client-side, which is risky for crawling. In the App Router, emit a <script type="application/ld+json"> from the server component.

// app/[locale]/products/[slug]/ProductJsonLd.tsx  (server component)
import type { Product } from '@/payload-types'

const AVAILABILITY = {
  inStock: 'https://schema.org/InStock',
  outOfStock: 'https://schema.org/OutOfStock',
  preOrder: 'https://schema.org/PreOrder',
} as const

export function ProductJsonLd({ product, url }: { product: Product; url: string }) {
  const ld = {
    '@context': 'https://schema.org',
    '@type': 'Product',
    name: product.title,
    description: product.seoDescription ?? product.description,
    image: product.images?.map((i) => i.url).filter(Boolean), // array, absolute URLs, >=1
    sku: product.sku,
    ...(product.gtin13 && { gtin13: product.gtin13 }),
    ...(product.mpn && { mpn: product.mpn }),
    brand: { '@type': 'Brand', name: product.brand?.name },
    offers: {
      '@type': 'Offer',
      url,
      priceCurrency: product.currency, // ISO 4217: EUR, USD, GBP
      price: product.price.toFixed(2), // number string, NO currency symbol
      availability: AVAILABILITY[product.stockStatus],
      itemCondition: 'https://schema.org/NewCondition',
      // priceValidUntil (ISO 8601), shippingDetails, hasMerchantReturnPolicy: see below
    },
    ...(product.reviewCount > 0 && {
      aggregateRating: {
        '@type': 'AggregateRating',
        ratingValue: product.ratingAvg.toFixed(1),
        reviewCount: product.reviewCount,
      },
    }),
  }

  // < escape avoids breaking out of the <script> tag
  const html = JSON.stringify(ld).replace(/</g, '\\u003c')
  return <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: html }} />
}

AggregateRating + Review

Only emit aggregateRating when you have real, on-page reviews — fabricated or off-page-only ratings violate Google's policy and risk a manual action. Require both ratingValue and reviewCount. Optionally include individual review objects with author and reviewRating.

Validation rules (these silently disqualify rich results when violated)

  1. price is a plain number string ("29.99"), never "$29.99" or "29,99".
  2. availability uses the full Schema.org URL enum, not "in stock".
  3. priceCurrency is ISO 4217.
  4. image is an array of absolute, high-res URLs (>= 1).
  5. brand.name is non-empty and not a placeholder ("N/A").
  6. priceValidUntil is ISO 8601 if present (omit it rather than ship a stale past date).
  7. If aggregateRating is present, both ratingValue and reviewCount exist and are > 0.

Shipping + returns (Merchant Center alignment)

For Shopping/free listings, add structured shipping and return data so on-page matches feed data:

"shippingDetails": {
  "@type": "OfferShippingDetails",
  "shippingRate": { "@type": "MonetaryAmount", "value": "4.90", "currency": "EUR" },
  "deliveryTime": {
    "@type": "ShippingDeliveryTime",
    "handlingTime": { "@type": "QuantitativeValue", "minValue": 0, "maxValue": 1, "unitCode": "DAY" },
    "transitTime":  { "@type": "QuantitativeValue", "minValue": 1, "maxValue": 3, "unitCode": "DAY" }
  }
},
"hasMerchantReturnPolicy": {
  "@type": "MerchantReturnPolicy",
  "applicableCountry": "IT",
  "returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
  "merchantReturnDays": 30,
  "returnMethod": "https://schema.org/ReturnByMail",
  "returnFees": "https://schema.org/FreeReturn"
}

Schema scoring (0-100)

CompletenessScore
All required fields valid (name, image, offers.price, priceCurrency, availability)50
+ valid aggregateRating with real reviews65
+ sku / gtin / mpn75
+ shippingDetails85
+ hasMerchantReturnPolicy90
+ 3+ review objects100

2. Variants and canonicalization

Variant handling is where ranking signals fragment most. Pick one model and apply it consistently across the store.

ModelWhenURL shapeIndexing
Single canonical PDPVariants are minor (color/size of same product)/p/jacket with client-side variant switchIndex the canonical; variant params self-canonical to it
Distinct variant URLsVariants differ materially (separate demand, different images/specs/price)/p/jacket-red, /p/jacket-blueEach indexable, each self-canonical

Default to single canonical PDP unless variants have meaningfully different search demand. Variant state goes in a query param or hash that canonicalizes back:

// app/[locale]/products/[slug]/page.tsx
export async function generateMetadata({ params }): Promise<Metadata> {
  const { slug, locale } = await params
  const product = await getProduct(slug)
  const canonical = `${SITE_URL}/${locale}/products/${product.slug}`
  return {
    alternates: {
      canonical, // variant query params (?color=red) resolve here
      languages: buildHreflang(product, locale), // next-intl locales
    },
    openGraph: { images: product.images?.[0]?.url },
  }
}

Rules:

  • A ?color=red URL must carry <link rel="canonical"> pointing to the clean PDP.
  • Never let the same product body live at multiple indexable URLs without canonicals.
  • If you DO split variants into distinct URLs, each must be self-canonical (not pointing at a "parent") and have unique title, images, and (if applicable) price.

3. Faceted navigation and crawl control

Faceted filters (size + color + price + brand + sort) generate combinatorial URL explosion. Left unmanaged, crawlers waste budget on near-duplicate, thin pages and may index junk like ?sort=price&color=red&color=blue&page=3.

Decision: index, canonicalize, or block

Facet stateTreatmentMechanism
Single high-demand facet ("red dresses")Index — it's a real landing pageCrawlable link, self-canonical, unique title/H1
Multi-facet combos, sorts, pagination noiseCrawlable but not indexablerobots: noindex, follow OR canonical to base category
Infinite / low-value params (sessionid, tracking, view=grid)Block from crawlrobots.txt Disallow, or keep links non-crawlable

Implementation

Curate which facet pages deserve indexing (a finite allowlist) rather than letting every combination in:

// app/[locale]/[category]/page.tsx
type Search = { color?: string; size?: string; sort?: string; page?: string }

export async function generateMetadata({ params, searchParams }): Promise<Metadata> {
  const { category, locale } = await params
  const sp = (await searchParams) as Search
  const base = `${SITE_URL}/${locale}/${category}`

  // Allowlist of indexable single-facet landing pages
  const indexableFacet =
    isCuratedLandingPage(category, sp) // e.g. only {color} alone, no sort/page

  return {
    alternates: { canonical: indexableFacet ? withFacets(base, sp) : base },
    robots: indexableFacet ? undefined : { index: false, follow: true },
  }
}
  • Keep filter links real <a href> (crawlable) only for facets you want crawled; render the rest as buttons/JS so crawlers don't discover infinite combinations.
  • Use noindex, follow (not nofollow) so link equity still flows to products.
  • Put long-tail block rules in robots.txt for tracking/sort/view params:
# robots.txt
User-agent: *
Disallow: /*?*sort=
Disallow: /*?*view=
Disallow: /*&color=*&color=   # multi-select duplicate noise
Allow: /
Sitemap: https://example.com/sitemap.xml

Caveat: robots.txt disallow prevents crawling but a URL can still appear in results if linked externally. To guarantee de-indexing, allow the crawl and serve noindex instead. Pick one per URL pattern; don't combine them on the same URL (a noindex on a robots-blocked URL is never read).


4. Out-of-stock and discontinued products

Don't 404 or delete a temporarily out-of-stock product — you lose its accumulated ranking and inbound links.

StateHTTPIndexingSchema availabilityUX
Temporarily OOS, returning200keep indexedOutOfStock (keep offers)show "notify me", related/alternatives
Permanently discontinued, replacement exists301redirectredirect to successor or category
Permanently gone, no replacement410de-indexhelpful 410 page with search/category links
Seasonal, returns yearly200keep indexedOutOfStock / PreOrderkeep page warm, link from category

Keep the offers block with availability: OutOfStock so the product stays eligible to re-enter rich results when restocked. Surface in-stock alternatives above the fold to recover the visit.


5. Pagination on category pages

rel="next"/"prev" is no longer used by Google as an indexing signal. Current guidance:

  • Each paginated page (?page=2) should be a crawlable, self-canonical, unique URL — do NOT canonicalize page 2..N to page 1 (that hides those products from crawl).
  • Ensure every product is reachable: either real paginated <a> links or a crawlable "load more" that updates the URL. Pure JS infinite scroll with no crawlable URLs hides deep products.
  • Give paginated pages distinct titles (Category — Page 2) to avoid duplicate-title warnings, but keep the primary keyword on page 1.
  • Page 1 of a category is the canonical landing page; deep pages are crawl paths, not landing targets.
// Reachability: emit crawlable pagination links even with JS load-more
<nav aria-label="Pagination">
  {hasPrev && <a href={`?page=${page - 1}`} rel="prev">Previous</a>}
  {hasNext && <a href={`?page=${page + 1}`} rel="next">Next</a>}
</nav>

6. Category (PLP) optimization

Category pages are usually a store's highest-traffic SEO targets — they rank for head terms ("running shoes") while PDPs rank long-tail.

  • One H1 matching the category's primary keyword.
  • A short, unique intro paragraph above or below the grid (not boilerplate across categories) — gives the page indexable text beyond product tiles.
  • Breadcrumb JSON-LD (BreadcrumbList) for the path: Home > Category > Subcategory.
  • Internal links to top sub-categories and complementary categories.
  • Stable, keyword-clean URLs: /running-shoes, not /c?id=482.
  • LCP is usually the first product image / hero — prioritize it (see CWV below).
// BreadcrumbList JSON-LD
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    { "@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com/" },
    { "@type": "ListItem", "position": 2, "name": "Shoes", "item": "https://example.com/shoes" },
    { "@type": "ListItem", "position": 3, "name": "Running Shoes", "item": "https://example.com/shoes/running" }
  ]
}

7. Product page on-page checklist

  • Title: [Product] - [Key feature] | [Brand], under ~60 chars, primary keyword + brand.
  • Meta description: keyword + benefit + price/CTA, under ~155 chars.
  • H1: single, matches product name; H2s for Features, Specs, Reviews, Related.
  • Images: descriptive alt text (product + distinguishing feature), descriptive filenames (not IMG_001.jpg), modern format (AVIF/WebP), >= 800px for Shopping eligibility, >= 3 images, lazy-load below-fold only (eager the LCP hero).
  • Content: unique description (NOT manufacturer copy-paste — that creates cross-site duplication), >= ~200 words, a real specs table, on-page UGC reviews.
  • Internal linking: breadcrumbs, related/cross-sell, keyword-rich link back to category.
  • Technical: server-rendered JSON-LD, correct canonical, mobile-clean, fast LCP.

8. Merchant feed basics

The on-page data and the Merchant feed must agree, or you get feed disapprovals and "price mismatch" / "availability mismatch" warnings.

Feed fieldMust match on-pageNotes
idstable SKUnever reuse across products
title / descriptionPDP title/descriptionfront-load attributes (brand, type, size, color)
linkcanonical PDP URLnot a variant param URL
priceoffers.price + visible pricecurrency must match
availabilityoffers.availabilityOOS in feed when OOS on page
gtin / mpn / brandschema identifiersGTIN strongly improves match rate
image_linkprimary product image>= 800px, no watermarks/promo overlays

For AI-generated product imagery, follow the platform's transparency requirement (IPTC DigitalSourceType: TrainedAlgorithmicMedia) to stay feed-compliant.


Audit methodology

When auditing an existing store (use your own crawler/tooling to fetch and render pages — many storefronts inject schema client-side, so compare raw HTML vs rendered HTML to confirm JSON-LD is server-rendered).

Scoring (0-100)

CategoryWeightWhat it measures
Product schema completeness & validity25%Required + recommended fields, validation rules pass
Crawl control (facets/params/pagination)20%No combinatorial index bloat; products reachable
Variant/canonical handling15%Consistent model, no fragmented duplicates
Image optimization15%Alt text, format, sizing, count, LCP hero
Content quality15%Unique descriptions, specs, on-page reviews
Category/internal linking & CWV10%Breadcrumbs, related links, LCP < 2.5s

Report priorities as Critical > High > Medium > Low, each with expected impact and the data source ("rendered HTML", "raw HTML", "feed export").

Core Web Vitals (current thresholds)

INP replaced FID as a Core Web Vital. Targets: LCP < 2.5s, INP < 200ms, CLS < 0.1. On PDPs the LCP element is the hero image (eager-load + sized); on PLPs it's the first product tile. CLS offenders: late-loading price/badges, unsized images, sticky add-to-cart bars injected after paint.

Falsifiability check (do this before claiming a fix worked)

For every recommendation, state how you'd know it FAILED and the leading indicator to watch — don't wait on rankings alone.

Change"How would we know it failed?"Leading indicator (days, not weeks)
Added Product schemaRich Results test still errors; no rich snippet eligibilitySearch Console "Products" enhancement report: valid items count rises, errors drop
Faceted noindex/robots rulesIndex bloat persists or, worse, real products droppedCrawl stats + "Indexed, not submitted" count; verify product URLs still indexed via URL Inspection
OOS kept-indexed (vs 404)Product loses position after restockPosition history for the product URL; impressions don't collapse during OOS window
Variant canonical consolidationDuplicate variant URLs still indexedsite: / Search Console page count for variant params trends to ~0
Unique category intro copyPage still seen as thin/duplicateImpressions for category head term; "Duplicate without user-selected canonical" disappears

If you can't name a failure signal and a leading indicator, the recommendation isn't testable — sharpen it before shipping.


Cross-skill integration

NeedPair with
Generic JSON-LD generation/validationseo-schema
Product image audit (alt, format, dimensions)seo-images
Description E-E-A-T and uniquenessseo-content
Page-level CWV / rendering / canonicalsseo-technical
Search Console enhancement reportsseo-google

Parts adapted from claude-seo (MIT, © 2026 agricidaniel).

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.