Documentación de integraciones
Conecta Indexal con tu sitio para publicar cada artículo en tu propio dominio. No necesitas acceso al backend de Indexal.
Inicio rápido
La configuración pertenece al dominio activo. Si gestionas varios proyectos, elige primero el dominio correcto en el selector del sidebar.
- 1
Elige el proyecto
Comprueba el dominio activo en la esquina superior izquierda. - 2
Abre Conectar sitio
Ve a Conectar sitio y selecciona una integración. - 3
Agrega las credenciales
Indexal valida la conexión antes de guardarla. Las claves de WordPress, Ghost y Shopify se almacenan cifradas. - 4
Publica una prueba
Abre un artículo del calendario y pulsa Publicar. Puedes conectar varios destinos; todos reciben el artículo.
Revisión antes de publicar
El contenido generado no tiene que publicarse sin supervisión. Desde “Ver artículo” puedes revisar y modificar la versión que recibirá el sitio conectado.
Cómo funciona el guardado
- Guardar cambios actualiza el borrador sin publicarlo.
- Insertar CTA añade al contenido un enlace Markdown con el texto y URL indicados.
- Guardar y publicar guarda primero la revisión y después entrega exactamente esa versión.
- El tiempo de lectura se recalcula automáticamente a partir del contenido final, usando 220 palabras por minuto.
WordPress
Publica mediante la API REST incluida en WordPress. No uses la contraseña normal de tu cuenta.
- 1
Crea una contraseña de aplicación
En WordPress abre Usuarios → Perfil → Contraseñas de aplicación, escribe “Indexal” y pulsa Añadir. - 2
Conecta el sitio
En Indexal ingresa la URL completa, tu usuario y la contraseña de aplicación generada. - 3
Verifica permisos
El usuario debe poder crear y publicar entradas. La API/wp-json/wp/v2/postsdebe estar accesible.
Ghost
Usa una integración personalizada de Ghost Admin API para crear publicaciones con imagen, etiquetas y metadatos SEO.
- 1
Crea la integración
En Ghost abre Settings → Integrations → Add custom integration. - 2
Copia la Admin API key
Copia la clave completa con formatoid:secret. La Content API key no sirve para publicar. - 3
Conecta y valida
Ingresa la URL del blog y la clave. Indexal comprobará las credenciales antes de guardarlas.
Shopify
Publica artículos en el blog de tu tienda mediante una app personalizada.
- 1
Crea una app
En Shopify abre Configuración → Apps y canales de venta → Desarrollar apps. - 2
Concede acceso
Activa el permiso de Admin APIwrite_content, instala la app y copia el token. - 3
Selecciona el blog
Ingresa el dominiotienda.myshopify.com. Si tienes varios blogs, añade el handle; si lo dejas vacío se usará el primero.
RSS y plataformas sin conexión directa
El feed sirve para importar o automatizar publicaciones en Wix, Squarespace y otros CMS.
Activa “Feed RSS” en Conectar sitio. La dirección tendrá este formato:
https://TU-DOMINIO-DE-INDEXAL/blog/tu-sitio.com/feed.xmlPara Webflow, HubSpot, Framer, Duda, Notion o un sitio propio, recomendamos el webhook porque entrega el HTML completo en tiempo real.
Sitios bilingües y multidioma
Indexal envía una publicación independiente por cada idioma configurado. Si el proyecto usa ES + EN, el destino recibirá dos entregas relacionadas.
Campos para identificar cada versión
| Campo | Uso |
|---|---|
| languageCode | Idioma ISO 639-1: es, en, pt, etc. |
| translationGroupId | El mismo identificador para todas las versiones del artículo. |
| parentArticleId | Nulo en el original; ID del original en las traducciones. |
| isTranslation | Indica si esta entrega es una traducción. |
| id | ID único de esta versión; úsalo para actualizar sin duplicar. |
Implementación recomendada
- Guarda
languageCodejunto al contenido y úsalo en<html lang>. - Crea rutas separadas, por ejemplo
/es/blog/slugy/en/blog/slug. - Agrupa las versiones por
translationGroupId. - Configura canonical hacia la URL de esa misma versión y enlaces
hreflanghacia las demás. - Devuelve a Indexal la URL pública correspondiente a cada entrega.
// Ejemplo conceptual: una URL distinta por idioma
const language = payload.languageCode; // "es", "en", etc.
const publicPath = "/" + language + "/blog/" + payload.slug;
await cms.upsertArticle({
externalId: payload.id, // idempotencia de esta versión
translationGroup: payload.translationGroupId, // relaciona ES con EN
language,
path: publicPath,
title: payload.title,
html: payload.contentHtml,
metaDescription: payload.metaDescription,
});
// Devuelve la URL correspondiente a ESTA versión.
return Response.json({ url: "https://tusitio.com" + publicPath });Webhook firmado
Indexal envía un POST JSON cuando se publica un artículo. Tu endpoint debe usar HTTPS, responder en menos de 15 segundos y devolver un estado 2xx.
Cuerpo de la solicitud
{
"id": "article_uuid",
"title": "Título del artículo",
"slug": "titulo-del-articulo",
"metaDescription": "Descripción para buscadores",
"contentHtml": "<article>...</article>",
"contentMarkdown": "# Título...",
"heroImageUrl": "https://.../hero.png",
"heroImageAlt": "Texto alternativo de la portada",
"infographicImageUrl": "https://…supabase.co/storage/v1/object/public/article-images/…webp",
"infographicHtml": "<figure class="ixig">...</figure>",
"keywords": ["keyword principal"],
"faqSchema": [],
"languageCode": "es",
"translationGroupId": "original_article_uuid",
"parentArticleId": null,
"isTranslation": false,
"wordCount": 1840,
"readingTimeMinutes": 9,
"author": {
"name": "Nombre del autor",
"bio": "Biografía breve",
"logoUrl": "https://.../logo.webp"
},
"cta": {
"url": "https://tusitio.com/contacto",
"label": "Agenda una demo",
"asButton": true
},
"status": "published",
"publishedAt": "2026-07-31T12:00:00.000Z",
"canonicalUrl": "https://app.indexal.com/blog/dominio.com/slug"
}Portada e infografía
heroImageUrl es la portada del artículo: úsala como imagen destacada (featured image / og:image), fuera del cuerpo del texto, con heroImageAlt en su atributo alt.
infographicImageUrl es la infografía como imagen WebP, y es la que deberías usar: un <img src> lo acepta cualquier sanitizador, así que llega bien sin que configures nada. Mide 2400px de ancho, pesa unos 300 KB y se genera la primera vez que alguien la pide. Ya viene insertada dentro de contentHtml, justo después de la introducción.
infographicHtml es la misma infografía en HTML — es de ahí que se rasteriza la imagen. Es más nítida y se readapta al ancho, pero solo sirve si tu integración no sanitiza el HTML: los sanitizadores borran la etiqueta style que lleva dentro y queda como texto suelto. Si quieres esta versión y sanitizas, enlaza una vez la hoja de estilos con <link rel="stylesheet" href="https://getindexal.com/infographic.css"> y basta con que se conserve el atributo class.
Si no quieres pensar en esto, usa contentHtml tal cual: ya trae la imagen en su sitio.
Ambos campos pueden llegar como null: la portada está desactivada, la infografía no está activada en Ajustes de contenido, o su generación falló. En ese caso omite el elemento correspondiente sin bloquear la publicación del resto del artículo.
Cabeceras
| Cabecera | Uso |
|---|---|
| X-Indexal-Event | article.published |
| X-Indexal-Language | Idioma ISO 639-1 de esta versión |
| X-Indexal-Timestamp | Fecha Unix usada para evitar reenvíos maliciosos |
| X-Indexal-Signature | Firma HMAC SHA-256 del cuerpo original |
| X-Indexal-Delivery | UUID único para deduplicar entregas |
Verificar la firma en Node.js
import crypto from "node:crypto";
export function verifyIndexal(rawBody, headers, secret) {
const timestamp = headers["x-indexal-timestamp"];
const received = headers["x-indexal-signature"] || "";
const expected = "sha256=" + crypto
.createHmac("sha256", secret)
.update(timestamp + "." + rawBody)
.digest("hex");
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const a = Buffer.from(received);
const b = Buffer.from(expected);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}{ "url": "https://tusitio.com/blog/slug" }, Indexal guardará esa dirección como URL final.Solución de errores
WordPress responde 401 o 403
Genera una contraseña de aplicación nueva y confirma que el usuario puede publicar entradas. Algunos plugins de seguridad bloquean la API REST.
Ghost rechaza la clave
Usa la Admin API key completa de una integración personalizada, no la Content API key.
Shopify no encuentra blogs
Crea primero un blog en Contenido → Publicaciones de blog y reinstala la app después de conceder write_content.
El webhook falla
Comprueba HTTPS, respuesta 2xx en menos de 15 segundos y que la URL no redirija. Registra X-Indexal-Delivery para localizar la entrega.
Se publica en el proyecto incorrecto
Cambia el dominio activo en el sidebar antes de configurar la integración; cada proyecto conserva destinos separados.