Ir al contenido

Video Banner

Video de fondo a pantalla completa con texto y botones superpuestos: un título, una descripción opcional, una alineación del texto (CENTER o BOTTOM_RIGHT) y hasta 3 botones por sección.

En el paneltipo en el JSONToken de la clave
Video BannerVIDEO_BANNERvideo_banner

Este tipo usa el sobre genérico de los tipos generados: los campos editables viajan dentro de campos, no en propiedades con nombre propio.

{
titulo: string | null; // el "Título" de la sección
nombre_personalizado?: string; // nombre interno del panel (opcional)
items: Array<{
orden: number;
campos: {
label: string; // texto del botón
url: string | null; // destino del botón (siempre https://); null si no tiene enlace
style: 'PRIMARY' | 'OUTLINE'; // sólido o contorno
};
}>;
campos: {
description: string | null; // la "Descripción" de la sección
textAlignment: 'CENTER' | 'BOTTOM_RIGHT' | null; // null equivale a CENTER
videoUrl: string | null; // video de fondo; null si no hay archivo o no está READY
videoMimeType: string | null; // "video/mp4", …; null sin archivo
videoDurationSeconds?: number; // solo videos READY con duración registrada; si no, la clave no viene
};
estado: { lifecycle: string; storefrontVisible: boolean };
orden: number;
indice?: number; // solo cuando hay más de una sección del mismo tipo
}
{
"sections": {
"video_banner-product-344443275-cmu7axqfa0001uhc8b8hdznmy": {
"titulo": "Nueva colección",
"items": [
{
"orden": 0,
"campos": {
"label": "Comprar ahora",
"url": "https://mitienda.com/nueva-coleccion",
"style": "PRIMARY"
}
}
],
"campos": {
"description": "Descubre lo nuevo de la temporada.",
"textAlignment": "BOTTOM_RIGHT",
"videoUrl": "https://cdn.example.com/hero.mp4",
"videoMimeType": "video/mp4",
"videoDurationSeconds": 20
},
"estado": { "lifecycle": "active", "storefrontVisible": true },
"orden": 0
}
}
}

La regla de render y el orden son los compartidos. Lo propio de este tipo es pintar el video de fondo con el texto encima y decidir el estilo de cada botón por campos.style:

const res = await fetch(
`https://sectionfy.codefy-apps.com/api/public/content/${TOKEN}/product/${PRODUCT_ID}`,
);
const { sections } = await res.json();
const banners = Object.entries(sections)
.filter(([, s]) => s.tipo === 'VIDEO_BANNER')
.filter(([, s]) => s.estado.lifecycle === 'active' && s.estado.storefrontVisible)
.sort(([, a], [, b]) => a.orden - b.orden);
for (const [key, seccion] of banners) {
const alineado = seccion.campos.textAlignment === 'BOTTOM_RIGHT' ? 'abajo-derecha' : 'centrado';
const botones = seccion.items
.slice()
.sort((a, b) => a.orden - b.orden)
.map(
(item) => `
<a href="${escapar(item.campos.url ?? '#')}"
class="sectionfy-vb__btn sectionfy-vb__btn--${item.campos.style === 'OUTLINE' ? 'contorno' : 'principal'}">
${escapar(item.campos.label)}
</a>
`,
)
.join('');
contenedor.insertAdjacentHTML(
'beforeend',
`<section class="sectionfy-vb sectionfy-vb--${alineado}" data-block="${key}">
${
!seccion.campos.videoUrl
? ''
: `<video src="${seccion.campos.videoUrl}" muted loop playsinline autoplay></video>`
}
<div class="sectionfy-vb__velo"></div>
<div class="sectionfy-vb__texto">
${seccion.titulo ? `<h2>${escapar(seccion.titulo)}</h2>` : ''}
${seccion.campos.description ? `<p>${escapar(seccion.campos.description)}</p>` : ''}
<div class="sectionfy-vb__botones">${botones}</div>
</div>
</section>`,
);
}
  • textAlignment: null equivale a CENTER. El panel guarda null cuando el comerciante no tocó la alineación; tratá ambos igual.
  • Máximo 3 botones. El panel bloquea el cuarto; no asumas más de tres items.
  • Un botón puede no tener enlace (url: null): renderizalo sin href o como disparador de tu propia acción, no lo descartes. Cuando trae enlace, url es siempre una URL absoluta https://: la API rechaza cualquier otro esquema.
  • Placements home, category y product. En el endpoint propio category y product piden target_id (si falta, 400) y home no lo admite; las secciones generales de category/product llegan por el bundle (/{page} o /{page}/{id}).
  • videoUrl es null mientras el asset no esté READY. Renderizá el banner con un fondo sólido en ese caso, no lo descartes.