Skip to content

SEO & Redirects

The storefront ships with SEO fundamentals that work per store without configuration — every endpoint derives the origin from the request, so one deployment serves store-a.example.com and store-b.example.com correctly at the same time.

src/pages/robots.txt.ts serves a dynamic robots.txt that allows the catalog but keeps account, cart, checkout, order, and API paths out of the index, and points crawlers at the same-origin sitemap:

User-agent: *
Allow: /
Disallow: /account/
Disallow: /cart
Disallow: /checkout
Disallow: /orders/
Disallow: /api/
Sitemap: https://<your-domain>/sitemap.xml

src/pages/sitemap.xml.ts builds the sitemap from the live catalog at request time: static pages (home, /products, about/contact/support), category pages, and every active product under /products/<category>/<slug> (falling back to /products/<slug> when a product has no category). It paginates through the products API so the sitemap is complete beyond the first page, and includes lastmod from each product’s created_at. Category slugs listed in the brand config’s hiddenCategories (e.g. uncategorized) are excluded.

There is also src/pages/google-feed.xml.ts, a Google shopping feed in Merchant Center XML format built from the same catalog.

Product detail pages render schema.org Product JSON-LD in the HTML (<script type="application/ld+json">): name, stripped description, image, canonical URL, SKU, brand, and an Offer with price, currency, InStock/OutOfStock availability, and NewCondition. When a product has reviews, aggregate rating data is included — note that reviews can be attached to WPML translation products after a WooCommerce import (see migration quirks), so aggregate numbers may split across translations until deduplicated.

Migrated stores keep their old WooCommerce URL equity via 301s:

  • /product/<slug>/ → canonical product page. First the brand content wooRedirects map is consulted (static old slugs from renamed, merged, or WPML-translated products take precedence over the API); if no static mapping matches, the slug is resolved through the products API and redirected to its canonical /products/<category>/<slug> URL. Unknown slugs return 404.
  • /product-category/<slug>/ → /products/<slug> when the slug is a known menu category, otherwise /products.

The wooRedirects map lives in the brand content module (src/lib/brand/<brand>.ts) as [encodedWooSlug, canonicalPath] pairs. The keys are the raw percent-encoded WooCommerce post_name forms in lowercase — e.g. old-%e6%97%a7%e6%ac%be-slug-… — because Astro decodes route params before the map lookup; the redirect page re-encodes before comparing.