Docs · Player · SDK

Treisa Player — Guía de integración de embeds (SDK v2)

Versión del loader: /v2/player.js · Versión del bridge postMessage: treisa.player.v1 / treisa.host.v1

Esta guía explica cómo incrustar un video de Treisa Flow en tu sitio, qué permite la CSP de tu página, cómo recibir eventos y comandar el player, cómo integrar tu banner de cookies (CMP) con la telemetría del player, y cómo diagnosticar errores.


1. Quickstart

Pega esto donde quieras el video (reemplaza EMBED_KEY por la key que te da Treisa Flow en Player → Embeds → Copiar snippet):

<!-- Treisa Player — embed -->
<div data-treisa-player="EMBED_KEY"></div>
<script async src="https://player.treisaflow.com/v2/player.js"></script>

Requisitos:

  1. Dominio registrado. En Treisa Flow, agrega el dominio de tu sitio en Player → Dominios (ejemplo: misitio.com, sin https://). Sin un dominio registrado, el player responde error de dominio no autorizado.
  2. Flag del workspace activo (treisa_player_external_embed_enabled) — lo activa el equipo de Treisa.
  3. El video debe estar publicado y en estado ready.

Configuración opcional por atributo data-* (todos opcionales, validados; un valor inválido se ignora con un aviso en consola):

AtributoValoresDefaultPara qué
data-aspect16/9, 9/16, 4/3, 3/4, 1/116/9Proporción del contenedor (VSLs verticales usan 9/16).
data-analyticstrue, false, waittruefalse: nunca envía analítica. wait: espera tu CMP (ver §5).
data-on-eventnombre de función globalCallback del host, ej. data-on-event="onTreisaEvent". Ver §4.
data-color#rrggbb#0a0a0aColor del placeholder antes de cargar.
data-radiuspíxeles12pxRedondeo del contenedor.

Nota: si inyectas el snippet dinámicamente después de cargar player.js, llama window.TreisaPlayer.scan() para detectar los divs nuevos. Cuando el script se carga con async, el origen del player se toma del propio script; solo en inyecciones sin currentScript se usa el default https://player.treisaflow.com.


2. Guía de seguridad (CSP)

Directrices que tu página necesita para permitir el embed (lo único que tu documento carga del player, según el código del loader y de la página /e/):

script-src https://player.treisaflow.com;
frame-src https://player.treisaflow.com
  • script-src: solo si usas el snippet con script (loader v2). El loader es un archivo estático servido desde el player host. Con CSP basada en nonces, añade tu nonce-... al tag <script> del snippet.
  • frame-src: siempre — el video se reproduce dentro de un iframe de player.treisaflow.com. En navegadores antiguos el alias legado es child-src; si lo declaras, mantenlo igual que frame-src.
  • connect-src: NO requerido para tu página. Todas las conexiones del player ocurren desde dentro del iframe, no desde tu documento: el boot (/api/v1/video/playback/embed/...), el manifest y la analítica van same-origin al player host.
  • Media: https://stream.mux.com (HLS del video) y https://image.mux.com (thumbnails) corren dentro del iframe; con frame-src basta, tu CSP no necesita permitirlos.
  • Pixels de marketing (solo si activas data-marketing-consent): los SDK de Meta/Google/TikTok también se cargan dentro del iframe — tu página no necesita abrirles script-src/connect-src.
  • El loader inyecta <link rel="preconnect"|"dns-prefetch"> al player host y a https://stream.mux.com: son hints de rendimiento, ninguna directiva CSP los bloquea.
  • Los eventos/comandos viajan por postMessage, sin directiva CSP propia. Tu listener debe validar event.origin (ver §4.1).

Ejemplo de header mínimo para una página que solo embebe el player:

Content-Security-Policy: script-src 'self' https://player.treisaflow.com; frame-src https://player.treisaflow.com

3. Iframe plano (CSP sin scripts de terceros)

Si tu CSP no permite scripts de terceros, usa la variante sin script:

<iframe
  src="https://player.treisaflow.com/e/EMBED_KEY"
  title="Treisa Player"
  allow="autoplay; fullscreen; encrypted-media; picture-in-picture"
  allowfullscreen
  referrerpolicy="strict-origin-when-cross-origin"
  sandbox="allow-scripts allow-same-origin allow-popups allow-forms allow-presentation"
  style="width:100%;aspect-ratio:16/9;border:0"></iframe>

La variante iframe no tiene callbacks ni atributos de configuración (usa los valores por defecto), pero los eventos y comandos postMessage siguen funcionando, porque viven dentro de la página /e/ del player.


4. Callbacks y comandos (postMessage)

4.1 Eventos del player → tu sitio (treisa.player.v1)

Escucha en tu página:

window.addEventListener("message", function (event) {
  if (event.origin !== "https://player.treisaflow.com") return; // ¡siempre valida!
  var ev = event.data;
  if (!ev || ev.source !== "treisa-player" || ev.v !== 1) return;
  // ev.embedKey, ev.type, ev.ts, ev.data
});

Tipos de evento: ready, error, play, pause, complete, cta_click, form_submit, analytics_off. El campo data según el tipo:

typedata
ready{ title: string | null }
error{ code: string; message: string } — códigos en §6
cta_click / form_submit{ interactionId: string; label: string | null }
play / pause{ positionSec: number }
complete{ positionSec: number }
analytics_off

Con el loader v2 también puedes usar callbacks directos sin addEventListener:

// Opción A: atributo — Treisa llama window.onTreisaEvent(ev) por cada evento
<div data-treisa-player="EMBED_KEY" data-on-event="onTreisaEvent"></div>

// Opción B: programático — devuelve una función para dejar de escuchar
var off = window.TreisaPlayer.on("EMBED_KEY", function (ev) { /* ... */ });
// off(); // unsubscribe

API pública del loader: window.TreisaPlayer = { scan, origin, version: 2, on }.

4.2 Comandos de tu sitio → player (treisa.host.v1)

var iframe = document.querySelector('div[data-treisa-player] iframe');
iframe.contentWindow.postMessage(
  { source: "treisa-host", v: 1, embedKey: "EMBED_KEY", cmd: "play" },
  "https://player.treisaflow.com" // nunca "*"
);
cmdargsefecto
play / pauseControl de medios.
mute / unmuteSilenciar / reactivar audio.
seek{ sec: number }Mueve la posición; respeta los bloqueos de avance del video (no puede saltarse lockSeek).
setAnalytics{ enabled: boolean }Enciende/apaga la analítica del embed en caliente (ver §5).

Los comandos son de control de medios: no devuelven datos; la información solo fluye del player hacia tu sitio vía eventos.


5. Consentimiento (CMP) × analítica

La analítica del player no lleva datos personales (identificadores opacos), por eso el default es true. Si tu CMP requiere consentimiento previo:

  1. Publica el embed con data-analytics="wait" (el player retiene toda telemetría desde el boot).
  2. Cuando el usuario acepta, envía el comando:
iframe.contentWindow.postMessage(
  { source: "treisa-host", v: 1, embedKey: "EMBED_KEY", cmd: "setAnalytics", args: { enabled: true } },
  "https://player.treisaflow.com"
);
  1. Si el usuario rechaza: data-analytics="false", o setAnalytics con enabled:false en caliente (el player deja de enviar y emite el evento analytics_off). Lo ya enviado no se puede retractar.

Formularios con datos personales: los leads del player piden su propio checkbox de consentimiento explícito (tf-lead-v1) validado en el servidor. Ese flujo es independiente del interruptor de analítica y nunca se afecta con setAnalytics.


6. Diagnóstico de errores

El evento error (y la API de playback) usa códigos estables:

codeHTTPCausa y qué revisar
EMBED_INVALID_KEY400La key no es un UUID — copia el snippet de nuevo.
EMBED_NOT_FOUND404El embed fue borrado (revocado) o la key no existe.
EMBED_UNPUBLISHED403El video está despublicado — publícalo en Treisa Flow.
EMBED_DISABLED_FLAG403El flag externo del workspace está apagado — contacta a Treisa.
EMBED_DOMAIN_NOT_ALLOWED403Tu dominio no está registrado/verificado en Player → Dominios. Incluye allowlist vacía.
EMBED_NOT_READY409El video sigue procesándose — espera a que esté ready.
EMBED_NO_PLAYBACK409Sin fuente de reproducción disponible — contacta a Treisa.

Nota: el rate limit público (120 req/min por IP) puede devolver 429 transitorio si la página dispara muchísimos boots simultáneos.


7. Cache y estabilidad del snippet

  • /v2/player.js es inmutable por ruta: servido con Cache-Control: public, max-age=300, stale-while-revalidate=86400. Tu CDN puede cachearlo; las actualizaciones de Treisa no rompen snippets copiados.
  • El snippet nunca cambia de formato (promesa ADR-006): el mismo div + script sigue funcionando para siempre. Mejoras futuras van en /v3/.
  • /v1/player.js está congelado tal como se entregó históricamente; los snippets viejos siguen funcionando sin lazy-load ni callbacks.

8. Verificación de dominios

Registrar un dominio en Player → Dominios ya no es una autodeclaración: cada dominio nace pending con un challenge de ownership y el playback público es fail-closed — solo se sirve desde dominios verificados (o sus subdominios) además de los hosts del propio player. Con la allowlist vacía o sin un match, el embed responde EMBED_DOMAIN_NOT_ALLOWED (403).

Cómo se verifica (challenge)

El botón Verificar del panel evalúa dos caminos en orden fijo; basta con que uno pase:

  1. DNS TXT (camino principal): registro TXT en _treisa-challenge.<tu-dominio> cuyo valor exacto es el token que el panel muestra y deja copiar (tf-verify=<32 hex>). La propagación DNS puede tardar 24–48 h.
  2. Meta tag (fallback inmediato): si el TXT todavía no responde, se fetchea https://<tu-dominio>/ (solo HTTPS, máximo 3 redirects, budget total 6 s) y se busca en el HTML de la raíz un <meta name="treisa-domain-verification" content="tf-verify=<token>"> con el content exacto.

La verificación es revocable: Re-verificar re-evalúa el challenge, y si el dominio ya no lo responde (TXT borrado, meta quitado), pasa a failed y el playback público se corta. Sin referrer del host no hay match — ver Apéndice.

Estados e historial

EstadoSignificado
pendingRecién registrado: challenge emitido (challenge_token), sin intento exitoso aún.
verifiedUn challenge pasó. verification_method registra cómo: dns_txt, meta_tag o grandfathered (dominios verificados antes de que existiera el challenge).
failedEl último intento no pasó — el panel muestra método, código y hora del último intento.

Cada intento (una fila por método probado) queda en el historial de checks del dominio (icono de historial en el panel; últimos 20, retención 90 días) con método, código cerrado (dns_txt_ok, dns_txt_mismatch, dns_txt_absent, meta_ok, meta_absent, meta_fetch_error, …) y detalle. Entre verificaciones hay un throttle de 30 s (HTTP 429 si reintenta antes).

Notas: localhost e IPs literales pueden estar en la allowlist en dev pero no son verificables (el challenge los rechaza); un dominio de un solo label tampoco se acepta.


9. Guías de instalación por plataforma

Paso a paso con los nombres de menú reales de cada plataforma para pegar el snippet del panel (Player → Embeds → Copiar snippet), un ejemplo con el snippet exacto y notas de CSP/troubleshooting por plataforma. El snippet es uno solo (el de §1 y §3); las guías solo cambian dónde se pega:

PlataformaGuía
HTML planoHTML plano
WordPress (+Elementor)WordPress + Elementor
ClickFunnelsClickFunnels
GoHighLevelGoHighLevel
ShopifyShopify
Systeme.ioSysteme.io

En todas las guías EMBED_KEY representa la key de tu embed y el host https://player.treisaflow.com es el player host por defecto (el playerHost con el que el panel genera el snippet); si tu player se sirve en otro dominio, el snippet copiado del panel ya trae el host correcto. El panel de Embeds enlaza estas guías desde el bloque "Instalar donde quieras".


Apéndice: límites conocidos

  • Si el navegador del visitante suprime el referrer por completo (extensiones o políticas estrictas), los eventos postMessage no se emiten — el iframe necesita capturar el origen de tu página. El fallback es data-on-event o TreisaPlayer.on (callbacks del loader, no dependen del referrer).
  • Múltiples embeds de la misma key en una página: cada uno reproduce y emite eventos; los eventos llevan embedKey pero no distinguen instancia.
  • Videos verticales: usa data-aspect="9/16" para evitar letterbox.