Integrar un SDK de Croct
Conecta un SDK de Croct en una aplicación para que renderice contenido de slots, evalúe CQL e identifique usuarios. El contenido y las audiencias viven en el panel de Croct; el código solo referencia slots por ID y versión y proporciona un fallback.
Flujo de trabajo
- [ ] 1. Detectar el stack y elegir el SDK (tabla a continuación)
- [ ] 2. Instalar con la CLI (`croct init`, ejecutada por el usuario), solo manual si lo pide o la CLI no puede ejecutarse
- [ ] 3. Añadir el slot con la CLI (`npx croct@latest add slot home-hero@1 --example`) para tipos + fallback
- [ ] 4. Renderizarlo: del lado del servidor cuando el framework lo permita, del lado del cliente en caso contrario
- [ ] 5. Identificar/anonimizar usuarios al iniciar/cerrar sesión (o pasar el ID de usuario al inicializar)
- [ ] 6. Verificar: La página de Integración muestra "Tráfico recibido en las últimas 24 horas"; de lo contrario, modo depuración.
1. Elegir el SDK
Lee primero package.json / composer.json. Elige el SDK más específico para el framework; nunca uses el SDK JavaScript plano dentro de React, Next.js, Vue, Nuxt o Hydrogen.
| Stack | Paquete | Inicializar con | Renderizado en servidor | Referencia |
|---|---|---|---|---|
JS plano, cualquier bundler o etiqueta <script> | @croct/plug (o https://cdn.croct.io/js/v1/lib/plug.js) | croct.plug({appId}) una vez al iniciar | fetchContent/evaluate autónomos de @croct/plug/api con apiKey | javascript.md |
| React (SPA, Vite, cualquier SSR que no sea Next) | @croct/plug-react | <CroctProvider appId="..."> en la raíz | Los hooks del cliente necesitan initial; nivel bajo @croct/plug-react/api | react.md |
| Next.js (App o Pages Router) | @croct/plug-next | middleware (≤15) / proxy (≥16) + <CroctProvider> de @croct/plug-next/CroctProvider | Sí: @croct/plug-next/server | nextjs.md |
| Vue | @croct/plug-vue | app.use(createCroct({appId})) | Composables/componentes; SSR necesita valores iniciales | vue.md |
| Nuxt | @croct/plug-nuxt | modules: ['@croct/plug-nuxt'] en nuxt.config | Sí | nuxt.md |
| Shopify Hydrogen (React Router 7 o Remix) | @croct/plug-hydrogen | Plugin de Vite + createCroctMiddleware / createCroctContext de @croct/plug-hydrogen/server | Sí | hydrogen.md |
| PHP plano | croct/plug-php (+ un cliente PSR-18, p.ej. guzzlehttp/guzzle nyholm/psr7) | Croct::fromDotenv() luego Croct::emitCookies() antes de la salida | Sí (primero servidor) | php.md |
| Laravel | croct/plug-laravel | Credenciales en .env | Sí | laravel.md |
| Symfony | croct/plug-symfony symfony/twig-bundle | Registrar bundle en config/bundles.php + credenciales en .env | Sí (Twig) | symfony.md |
| Drupal | croct/plug-drupal | Habilitar módulo; credenciales en settings.php; reconstruir caché | Sí | drupal.md |
| Storyblok (JS o PHP) | — | Usa el skill croct-integrate-platforms | — | — |
| Lenguaje no soportado o HTTP plano | — | Usa el skill croct-use-api | — | — |
2. Instalación
La página de integración de cada SDK, incluyendo PHP, Laravel, Symfony, Drupal e Hydrogen, recomienda la CLI. init es interactivo y necesita una sesión iniciada, así que pide al usuario que lo ejecute desde la raíz del proyecto en su propio terminal:
npx croct@latest init
croct init detecta el framework, inicia sesión, selecciona la organización/espacio de trabajo/aplicación, instala el SDK correspondiente y configura la conexión (proveedor, middleware, vars de entorno). Cuando el usuario ya tiene una sesión y conoce los IDs, puedes ejecutar tú mismo la forma no interactiva: npx croct@latest --no-interaction init --sdk next --org <org> --wor <workspace> --dev-app <dev-app> --prod-app <prod-app> (--sdk acepta solo javascript, react, vue, next, nuxt; omítelo para autodetección). Las banderas, el uso en CI y croct.json viven en el skill croct-use-cli. Recurre a los pasos manuales del archivo de referencia del framework solo cuando el usuario lo pida o la CLI no pueda ejecutarse.
3. Añadir el slot
Pasa siempre el ID del slot y la versión. Sin ellos, la CLI solicita un slot, lo cual no puedes responder:
npx croct@latest add slot home-hero@1 --example
Esto genera tipos TypeScript (por lo que useContent('home-hero@1') / fetchContent('home-hero@1') están tipados), descarga el contenido por defecto del slot como fallback automático y escribe un ejemplo funcional. Vuelve a ejecutar croct install / croct update para resincronizar después de cambios en el panel (consulta croct-use-cli).
Conceptos centrales (todos los SDKs)
IDs de slot y versiones
- Referencia un slot como
<id>@<version>, p.ej.home-hero@1. Sin versión (home-hero) significahome-hero@latest. - Siempre fija una versión. Los slots sin fijar recogen cambios de esquema inmediatamente. Cuando el panel crea una nueva versión principal, la app sigue recibiendo la versión antigua hasta que se actualice el código.
- Tipifica el contenido con
SlotContent<'home-hero@1'>yComponentContent<'card@1'>(exportados por@croct/plug,@croct/plug-react,@croct/plug-next). Los slots unión resuelven a una unión discriminada en_type.
Contenido fallback, por defecto e inicial
| Término | Qué es | De dónde viene |
|---|---|---|
| Contenido por defecto | Contenido del slot mostrado cuando ninguna experiencia coincide, no hay contenido para la configuración regional, se solicita contenido estático o falla la recuperación | Panel |
| Fallback | Valor renderizado cuando la solicitud falla | Opción fallback en el código, o contenido por defecto descargado por la CLI (@croct/content) |
| Inicial (hooks de cliente React/Next) | Valor renderizado durante SSR/prerender y mientras se carga en el cliente | Opción initial; la CLI lo añade automáticamente |
Orden de resolución en el SDK: contenido dinámico → fallback explícito → contenido por defecto de la CLI → error. Sin fallback y sin contenido de la CLI, una obtención fallida lanza una excepción (JS croct.fetch rechaza). Lee el contenido de la CLI directamente con getSlotContent(slotId, locale?) / loadSlotContent(slotId, locale?) de @croct/content (prefiere la versión asíncrona con división de código).
Renderizado cliente vs servidor
| Necesidad | Haz |
|---|---|
| Contenido final en el primer HTML, sin parpadeo, rastreable | Obtén en el servidor (Next fetchContent de @croct/plug-next/server, Nuxt, Hydrogen, familia PHP) |
La página debe seguir siendo un archivo estático / CDN / output: 'export' | Hooks/componentes de cliente con un valor initial o un borde <Suspense> |
| Sección fuera de la pantalla donde un esqueleto está bien | Del lado del cliente está bien |
| Renderizado en servidor en React plano / SSR personalizado | fetchContent / evaluate de @croct/plug-react/api (o @croct/plug/api) con apiKey, luego pasa el contenido como props |
Las solicitudes del lado del servidor se autentican con una clave API (nunca la envíes al navegador); las solicitudes del lado del cliente usan el ID de aplicación. Pasar tanto appId como apiKey a una función autónoma es un error.
Evaluación de consultas
Evalúa CQL en tiempo de ejecución con croct.evaluate(query, {attributes}) (JS), useEvaluation / <Personalization> (React/Next cliente), o evaluate / cql`...` (Next servidor). Las consultas están limitadas a 500 caracteres; los resultados pueden ser cualquier JSON ('location' devuelve un objeto). Proporciona siempre un fallback (.catch(() => false) o fallback: false). Sintaxis CQL: skill croct-cql.
¿Evaluación o slot? La documentación presenta los slots como la forma de actualizar contenido sin cambios de código; una consulta evaluada vive en el código y cambia solo con un despliegue.
| Necesidad | Usa |
|---|---|
| Contenido, audiencia o lanzamiento que los responsables de marketing cambian, programan o prueban A/B | Un slot más una experiencia (consulta croct-personalize-and-test) |
| Lógica fijada por ingeniería (mostrar/ocultar un widget, bifurcar según condición), sin contenido editable | evaluate / useEvaluation con un fallback |
Atributos de contexto
Pasa datos específicos de la aplicación (plan, estado del carrito) como attributes (JS/React) o context.attributes (Next servidor, funciones autónomas); léelo en CQL como context's plan is "premium". Límites: hasta 30 entradas, 5 niveles de profundidad, claves ≤ 50 caracteres, valores de cadena ≤ 50 caracteres.
Credenciales y variables de entorno
| Stack | ID de aplicación | Clave API |
|---|---|---|
| Next.js | NEXT_PUBLIC_CROCT_APP_ID | CROCT_API_KEY |
| Nuxt | NUXT_PUBLIC_CROCT_APP_ID | NUXT_CROCT_API_KEY |
| Hydrogen | PUBLIC_CROCT_APP_ID | CROCT_API_KEY |
| PHP, Laravel, Symfony | CROCT_APP_ID | CROCT_API_KEY |
| Drupal | $settings['croct.app_id'] | $settings['croct.api_key'] |
| JavaScript, React, Vue | Opción appId / prop | Solo funciones autónomas del lado del servidor |
- Encuentra el ID de aplicación en la página de Integración de la aplicación; crea claves en su página de claves API.
- Para SDKs de servidor que emiten tokens de usuario (Next.js), la clave API necesita el permiso Emitir tokens de usuario.
- Cada entorno tiene su propia aplicación. Un ID de aplicación de producción usado en localhost (o viceversa) falla con credenciales no válidas.
Identificar y anonimizar
- Llama a
identify(userId)al iniciar sesión/registrarse yanonymize()al cerrar sesión. Los cambios de identidad finalizan la sesión actual y comienzan una nueva. - Si el usuario ya ha iniciado sesión cuando se carga la página, pasa el ID al inicializar (
userIdencroct.plug/<CroctProvider>) para que el SDK no cree una sesión anónima adicional. userIddebe ser una cadena; convierte IDs numéricos (preferiblemente del lado del servidor). Prefiere IDs aleatorios (UUID v4) en lugar de correos electrónicos o números secuenciales.- Cuando Requerir token firmado está activado en la configuración de la aplicación,
userId/identify(tokens sin firmar) fallan; pasa untokenfirmado en su lugar. Next.js firma tokens por ti conCROCT_API_KEY. - Next.js: prefiere
withCroct({userIdResolver})en middleware/proxy para mantener el token sincronizado con la sesión de autenticación en cada solicitud.
Opciones de Plug que vale la pena conocer
appId, debug, test, track (seguimiento automático, por defecto true), userId / token (excluyentes), tokenScope (global | isolated | contextual), defaultFetchTimeout (JS/React 5000 ms; Next 2000 ms), defaultPreferredLocale, baseEndpointUrl (servidores mock), cookie (almacenar ID de cliente / token de usuario / token de vista previa en cookies de primera parte), eventMetadata, urlSanitizer, logger. Lista completa: javascript.md.
Seguimiento y recopilación de datos
Rastrea objetivos con croct.track('goalCompleted', {goalId}); edita perfil/sesión con croct.user.edit().set(...).save() / croct.session.edit(). Catálogo de eventos, eventos recomendados y reglas de atributos: skill croct-track-events.
Errores comunes
| Error | Solución |
|---|---|
Croct is not plugged in. | Llama a croct.plug al iniciar antes de otras llamadas |
The app ID must be specified when it cannot be auto-detected. | Pasa appId (o ?appId= en la etiqueta script) |
The request was not authorized, most likely due to invalid credentials. | ID de aplicación incorrecto, entorno incorrecto, token expirado/alterado (borra cookies + almacenamiento local), o token sin firmar con Requerir token firmado activado |
Error CORS / The origin of the request is not allowed in your application settings. | Añade el dominio en Orígenes de confianza |
The user ID must be a string. | Convierte el ID a una cadena |
The request timed out. | Aumenta timeout / tiempo de espera por defecto; comprueba X-Croct-Timing / X-Croct-Region en los logs de depuración |
The query is too complex. | Consulta de más de 500 caracteres; simplifica, divide o pasa datos mediante atributos |
The service is temporarily suspended. | No es un error de código: espacio de trabajo suspendido o tráfico de bots (X-Suspension-Reason); mantén los fallbacks |
The application has exceeded the monthly active users (MAU) quota. | Actualiza el plan o espera al siguiente ciclo |
useCroct() can only be used in the context of a <CroctProvider> component. | Envuelve el árbol en <CroctProvider> |
The initial content/value is required for server-side rendering (SSR). | Añade initial, u obtén en el servidor |
Did you forget to configure Croct's middleware? | Añade middleware/proxy de Next |
someFunction() requires specifying the route parameter outside app routes. | Pasa route: context (Pages Router / rutas API) |
Did you forget to set the SOME_ENV_VAR environment variable? | Configura NEXT_PUBLIC_CROCT_APP_ID / CROCT_API_KEY |
| El contenido no se actualiza después de publicar (sin error) | Los hooks del cliente almacenan en caché los resultados durante expiration (60 s, se amplía con cada render); cambia cacheKey para forzar una recuperación. Comprueba que el cambio está publicado, no es un borrador. Una versión fijada (home-hero@1) nunca recibe una nueva versión principal: ejecuta croct upgrade. Fallback desactualizado tras una solicitud fallida: croct update actualiza el contenido por defecto de la CLI |
Índice de referencias
Carga solo el archivo para el stack en uso.
- references/javascript.md —
@croct/plug: opciones de plug,fetch,evaluate,test, identidad, parches,@croct/plug/apiautónomo, pruebas, errores. - references/react.md —
@croct/plug-react: proveedor,useContent,<Slot>,useEvaluation,<Personalization>,useCroct, valores iniciales SSR, pruebas.
...
[truncado para traducción]