SEO Signals API
La SEO Signals API es el endpoint que usan los storefronts headless para obtener, durante el renderizado server-side, las señales SEO/AEO/GEO enriquecidas de Clione para una entidad. También es lo que llama el SDK @clione/seo en modo API.
Úsala cuando:
- Estás construyendo un storefront headless / a medida y quieres pintar las señales de Clione en tu propia plantilla.
- No quieres instalar un widget de embed ni un app block del theme.
- Necesitas control fino sobre qué señales lees y dónde las pintas.
Para tiendas no headless (themes Stencil de BigCommerce o Liquid de Shopify) no necesitas este endpoint: al publicar desde Clione, el JSON-LD llega server-side, mediante un widget en BigCommerce y los app embeds del theme en Shopify. Mira Propagación de señales.
Endpoint
GET /api/v1/public/seo-signals/:platform/:entityType/:entityId
Parámetros de ruta:
| Parámetro | Valores |
|---|---|
platform | bigcommerce | shopify | woocommerce |
entityType | product | category | collection | page |
entityId | El id de Clione de la entidad, tal como lo devuelve la Products API. En productos también vale el id numérico de producto de la plataforma. En Shopify también vale el handle de la entidad. |
Parámetros de query:
| Parámetro | Notas |
|---|---|
storeId | Opcional. Fija la búsqueda en una tienda. Por defecto, la tienda a la que está ligada la API key. Un handle de Shopify que existe en más de una de tus tiendas devuelve 404 con code: "AMBIGUOUS_HANDLE" hasta que lo pases o uses una key ligada a una tienda. |
Autenticación
Envía una API key con el scope products:read en una de estas dos cabeceras:
Authorization: Bearer sk_live_...
X-API-Key: sk_live_...
La organización sale de la key. Si la key tiene dominios permitidos, la petición tiene que nombrar uno: una key server lo declara en la cabecera X-Clione-Storefront-Host, una key browser a través de Origin/Referer. Para SSR, usa una key server; mira Autenticación.
Forma de la respuesta
{
"jsonLd": {
"@context": "https://schema.org",
"@graph": [
{ "@type": "Organization", "...": "..." },
{ "@type": "WebSite", "...": "..." },
{ "@type": "BreadcrumbList", "...": "..." },
{ "@type": "Product", "name": "Linen Bed Sheet Set", "...": "..." },
{ "@type": "FAQPage", "mainEntity": ["..."] }
]
},
"metaTitle": "Linen Bed Sheet Set — Cool, Breathable, Made in Portugal",
"metaDescription": "Pure European linen sheet set ideal for hot sleepers... — linen sheets, breathable bedding",
"keywords": ["linen sheets", "breathable bedding", "summer bedding"],
"faq": [{ "question": "...", "answer": "..." }]
}
| Campo | Tipo | Notas |
|---|---|---|
jsonLd | object | null | El @graph de schema.org que Clione publica para esta entidad en los storefronts de la propia plataforma; el mismo grafo para productos, categorías, colecciones y páginas. Píntalo tal cual en un único <script type="application/ld+json">. |
metaTitle | string | null | En productos, el meta title que Clione publica. En el resto de tipos, el nombre de la entidad. |
metaDescription | string | null | Hasta 320 caracteres; puede terminar con las keywords de búsqueda principales. |
keywords | string[] | Keywords de búsqueda del enrichment. Array vacío si no hay. |
faq | array | null | Parejas de FAQ aprobadas, o null si la entidad no tiene. |
Ejemplo — fetch
const res = await fetch(
`${process.env.CLIONE_API_URL}/api/v1/public/seo-signals/shopify/product/1234`,
{
headers: {
Authorization: `Bearer ${process.env.CLIONE_API_KEY}`,
'X-Clione-Storefront-Host': 'shop.example.com',
},
},
)
if (!res.ok) throw new Error(`Clione SEO Signals: ${res.status}`)
const { jsonLd, metaTitle, metaDescription, keywords, faq } = await res.json()
Ejemplo — curl
curl -s \
-H "Authorization: Bearer sk_live_..." \
-H "X-Clione-Storefront-Host: shop.example.com" \
"https://api.clione.ai/api/v1/public/seo-signals/shopify/product/1234" | jq .
Pintar las señales
Lleva cada campo a la API de head de tu framework: metaTitle → <title>, metaDescription → <meta name="description">, jsonLd → un único <script type="application/ld+json">. El SDK @clione/seo lo hace por ti en Next.js, Remix / Hydrogen y Nuxt, y las guías de Next.js y Hydrogen lo explican paso a paso.
Caché
Las respuestas correctas llevan Cache-Control: public, max-age=3600, s-maxage=86400, stale-while-revalidate=86400. Las señales solo cambian cuando una entidad se re-enriquece o se edita, así que cachear en tu edge (Cloudflare, Vercel) o en tu framework es seguro.
Rate limit
200 peticiones cada 5 minutos por API key. Las respuestas llevan las cabeceras estándar RateLimit-*. Por encima del límite, la API responde 429 con un valor retryAfter en segundos.
Respuestas de error
| Estado | Causa |
|---|---|
| 400 | platform o entityType no válidos. |
| 401 | API key ausente, no válida, inactiva o caducada. |
| 403 | Falta el scope products:read, el host no está en los dominios permitidos de la key, o una key browser con dominios permitidos usada desde un cliente que no es un navegador. |
| 404 | Entidad no encontrada: id incorrecto, sin sincronizar o, en Shopify, un handle que no coincide con nada. El cuerpo lleva error más los campos de señal vacíos. |
| 429 | Rate limit. Espera retryAfter segundos. |
| 500 | Error del servidor. Reintenta con backoff. |
Resolución de problemas
Devuelve 404 aunque veo el producto en el dashboard: comprueba que el id es el que devuelve la Products API. En Shopify, un handle compartido por dos de tus tiendas necesita ?storeId= o una key ligada a una tienda.
Al JSON-LD le falta aggregateRating: las reviews no están activadas en tu plataforma, o todavía ningún producto tiene valoraciones. Mira Configurar reviews.