@agentshop/seo/remix.
On Shopify Hydrogen/Oxygen, use
@agentshop/seo/hydrogen instead — Oxygen has no process.env, and the Hydrogen adapter reads your environment from context.env.Product routes
Load the bundle in your loader, then export the ready-mademeta function:
app/routes/products.$handle.tsx
loadProductSeo(handle, config?)returns{ agentshopSeo: SeoBundle | null }— spread it into your loader data under that exact key.agentshopProductMeta(args)is a Remix v2metafunction that readsdata.agentshopSeoand emits the title, description, canonical, Open Graph (includingog:type=product), Twitter tags, and the JSON-LD via a"script:ld+json"descriptor — Remix serializes and escapes it for you. If the bundle isnull, it returns an empty array and your route renders without tags.
meta function, compose instead of replacing:
Sitemap
Create a resource route:app/routes/[sitemap.xml].ts
Cache-Control: public, max-age=3600, stale-while-revalidate=86400, or 502 with an empty body when the sitemap is unavailable.
Configuration
All three exports accept an optionalSeoClientConfig; AGENTSHOP_API_KEY and AGENTSHOP_SEO_URL are read from process.env for anything you don’t pass. AGENTSHOP_API_KEY is a secret — it’s only read in loaders (server-side), so keep it in a server-side env var, never one exposed to the browser. All helpers follow the never-throw contract.
