Saltar al contenido principal

Percus SmartEmbed SDK

El Percus SmartEmbed SDK (percus-embed-sdk) es la librería cliente que se utiliza para embeber el Percus Player en cualquier página web. Se encarga de la creación del iframe, el protocolo de comunicación por postMessage y expone una API JavaScript limpia para controlar la reproducción.

Instalación

Mediante <script> (IIFE)

<script src="https://cdn.percus.example/percus-embed.js"></script>

El SDK queda expuesto como window.PercusEmbed.

Mediante npm / bundler (ESM)

npm install @percus/percus-embed-sdk
import { PercusEmbed } from "@percus/percus-embed-sdk";

Archivos de salida del build

ArchivoFormatoCaso de uso
dist/percus-embed.jsIIFETag <script> simple
dist/percus-embed.esm.jsESMWebpack, Vite, Rollup
dist/percus-embed.d.tsDeclaraciones TypeScriptUso con tipado estricto

Inicio rápido

<div id="player-host" style="width: 800px; height: 450px;"></div>

<script src="./dist/percus-embed.js"></script>
<script>
const controller = PercusEmbed.init({
target: "#player-host",
playerUrl: "https://player.percus.example/runtime",
templateUrl: "https://cdn.example.com/template.json",
manifestUrl: "https://cdn.example.com/manifest.json",
data: { userId: "abc123", name: "María" },

onReady: (msg) => console.log("Player listo", msg),
onProgress: (msg) => console.log("Tiempo:", msg.payload.time),
onError: (msg) => console.error("Error:", msg.payload.message),
});

// Controlar la reproducción
controller.play();
controller.pause();
controller.seek(30); // saltar a 30 segundos
controller.destroy(); // limpiar
</script>

Referencia de API

initEmbed(params) / PercusEmbed.init(params)

Crea e inyecta un <iframe>, luego inicializa la comunicación con el Player Runtime.

function initEmbed(params: EmbedInitParams): EmbedController

Retorna un EmbedController.

EmbedInitParams

PropiedadTipoRequeridoDescripción
targetstring | HTMLElementSelector CSS o elemento DOM que contendrá el iframe.
playerUrlstringNoURL del runtime del Percus Player (por defecto "about:blank").
templateUrlstringNoURL del template de animación Lottie JSON.
manifestUrlstringNoURL del manifest de bindings en JSON.
dataunknownNoObjeto de datos de personalización inline. Mutuamente exclusivo con dataUrl.
dataUrlstringNoURL desde donde obtener los datos de personalización. Mutuamente exclusivo con data.
optionsRecord<string, unknown>NoConfiguración adicional que se reenvía al Player Runtime.
onReady(event: PercusReadyMessage) => voidNoCallback que se dispara cuando el player termina de cargar.
onProgress(event: PercusProgressMessage) => voidNoCallback que se dispara cada ≈500 ms durante la reproducción.
onError(event: PercusErrorMessage) => voidNoCallback que se dispara cuando el player encuentra un error.

EmbedController

El objeto retornado por initEmbed().

MiembroFirmaDescripción
play()() => voidEnvía PERCUS/PLAY al iframe del player.
pause()() => voidEnvía PERCUS/PAUSE al iframe del player.
seek(seconds)(seconds: number) => voidSalta a seconds dentro de la animación.
destroy()() => voidElimina el iframe, desregistra todos los event listeners y libera recursos.
iframeHTMLIFrameElementReferencia directa al elemento iframe inyectado.

Unidades de tiempo: seek() recibe segundos. El SDK convierte a milisegundos antes de reenviar al Player Runtime.


Eventos (callbacks Player → Host)

onReady

Se dispara una vez después de que el player cargó el template y aplicó los bindings.

{
version: 1;
type: "PERCUS/READY";
payload: {
playerVersion?: string; // ej. "0.1.0"
};
}

onProgress

Se dispara aproximadamente cada 500 ms durante la reproducción activa.

{
version: 1;
type: "PERCUS/PROGRESS";
payload: {
time: number; // Posición actual en segundos
duration?: number; // Duración total en segundos (si se conoce)
state?: "playing" | "paused" | "ended"; // Estado actual de reproducción
};
}

onError

Se dispara cuando el player encuentra un error irrecuperable.

{
version: 1;
type: "PERCUS/ERROR";
payload: {
code: string; // Código legible por máquina (ej. "LOAD_FAILED")
message: string; // Descripción legible por humano
details?: unknown; // Contexto estructurado opcional
};
}

Funciones auxiliares del contrato de mensajes

El SDK exporta funciones de utilidad usadas internamente (y disponibles para casos de uso avanzados):

import {
isPercusMessage,
makeInitMessage,
makePlayMessage,
makePauseMessage,
makeSeekMessage,
} from "@percus/percus-embed-sdk";

isPercusMessage(value) // type-guard: true si value es un PercusMessage válido
makeInitMessage(payload) // construye un sobre PERCUS/INIT
makePlayMessage() // construye un sobre PERCUS/PLAY
makePauseMessage() // construye un sobre PERCUS/PAUSE
makeSeekMessage(time) // construye un sobre PERCUS/SEEK (time en segundos)

La constante de versión del protocolo se exporta como:

PERCUS_MESSAGE_VERSION = 1

Configuración avanzada

options (pasado mediante EmbedInitParams.options) soporta claves internas adicionales:

ClaveTipoPor defectoDescripción
postMessageTargetOriginstring"*"Origen destino para las llamadas postMessage salientes. Fijarlo al dominio del player en producción.
iframe.allowstring"autoplay; fullscreen"Valor para el atributo allow del iframe.
iframe.referrerPolicystringPolítica de referrer para el iframe.
iframe.titlestring"Percus Player"Título accesible para el elemento iframe.
iframe.classNamestringClase CSS añadida al elemento iframe.
iframe.styleCSSStyleDeclarationborder:0; width:100%; height:100%Estilos inline aplicados al iframe.

Configuración por defecto del iframe

Cuando el SDK inyecta el <iframe>, establece:

<iframe
src="{playerUrl}"
title="Percus Player"
allow="autoplay; fullscreen"
style="border: 0; width: 100%; height: 100%;"
></iframe>

El iframe se añade como único hijo del elemento target.


Ciclo de vida

initEmbed(params)
└── Crear <iframe src="playerUrl">
└── Adjuntar al elemento target
└── Registrar listener "message" en window
└── Al cargar el iframe ("load")
└── postMessage PERCUS/INIT → player
└── Al recibir PERCUS/READY → llamar onReady(event)
└── Al recibir PERCUS/PROGRESS → llamar onProgress(event)
└── Al recibir PERCUS/ERROR → llamar onError(event)

controller.play() → postMessage PERCUS/PLAY
controller.pause() → postMessage PERCUS/PAUSE
controller.seek(s) → postMessage PERCUS/SEEK { time: s }
controller.destroy()
└── Eliminar <iframe> del DOM
└── Eliminar listener "message"

Soporte TypeScript

El SDK incluye declaraciones TypeScript completas. Todos los tipos de mensajes, formas de payload y firmas de funciones están exportados:

import type {
EmbedInitParams,
EmbedController,
PercusReadyMessage,
PercusProgressMessage,
PercusErrorMessage,
PercusInitMessage,
PercusPlayMessage,
PercusPauseMessage,
PercusSeekMessage,
PercusMessageType,
} from "@percus/percus-embed-sdk";

Funcionalidades planificadas

Las siguientes capacidades aún no están implementadas. Las formas de API propuestas a continuación son provisionales y están pensadas para guiar las discusiones de diseño.

Analíticas y tracking

Se añadirá un bloque de configuración tracking a EmbedInitParams. Cuando está habilitado, el SDK recolecta eventos del player y los reenvía a un backend configurable sin requerir código adicional en la página host.

// Adición propuesta a EmbedInitParams
tracking?: {
enabled: boolean;
trackerGroupKey?: string; // Agrupa eventos entre sesiones/campañas
googleAnalytics?: {
enabled: boolean;
eventName?: string; // Nombre de evento GA personalizado (default: "percus_player")
};
endpoint?: string; // URL personalizada de ingesta de analíticas
};

Se generará un trackerKey por sesión y se incluirá en todos los eventos de analíticas salientes para correlación.

Gestión de consentimiento

El tracking quedará gateado detrás del consentimiento del usuario. Se añadirán dos nuevos callbacks:

// Adiciones propuestas a EmbedInitParams
consentRequired?: boolean; // Default: false
onConsentAccepted?: (event: PercusConsentMessage) => void;
onConsentDeclined?: (event: PercusConsentMessage) => void;

Cuando consentRequired es true, el SDK retrasa toda actividad de tracking hasta que se dispare onConsentAccepted. Esto soporta los requisitos de GDPR, Ley 19.628 (Chile) y LGPD (Brasil) aplicables a los clientes de Percus.

Callbacks de finalización

Dos nuevos callbacks se dispararán al final de la reproducción:

// Adiciones propuestas a EmbedInitParams
onPlayComplete?: (event: PercusPlayCompleteMessage) => void; // El usuario vio hasta el final
onPlayIncomplete?: (event: PercusPlayIncompleteMessage) => void; // El usuario salió antes

El payload de onPlayIncomplete incluirá hasta dónde llegó el usuario (time y duration) para habilitar puntuaciones de visionado parcial.

Callback de llamada a la acción (CTA)

// Adición propuesta a EmbedInitParams
onCTA?: (event: PercusCTAMessage) => void;

Se dispara cuando la animación alcanza un marcador CTA. La página host maneja la acción (abrir un modal, redirigir, registrar una conversión) sin necesitar saber cómo están definidos los CTAs en el template.

Callbacks de eventos adicionales

onChapterEnter?: (event: PercusChapterMessage) => void;
onChapterExit?: (event: PercusChapterMessage) => void;
onEvent?: (event: PercusEventMessage) => void; // Evento genérico dentro del video
onAutoplayFailure?: (event: PercusAutoplayFailureMessage) => void;

Opciones de reproducción en la inicialización

// Adiciones propuestas a EmbedInitParams
autoplay?: boolean; // Intentar autoplay al estar listo (default: false)
mute?: boolean; // Iniciar muteado — requerido para autoplay en la mayoría de navegadores
loop?: boolean; // Repetir la animación (default: false)
aspectRatio?: string; // ej. "16x9", "9x16", "1x1" — el SDK maneja todo el CSS responsivo

Modo modal / lightbox

// Adición propuesta a EmbedInitParams
modal?: {
enabled: boolean;
autoOpenTime?: number; // Milisegundos antes de que el modal se abra automáticamente (0 = manual)
};

Cuando modal.enabled es true, el SDK renderiza una superposición a pantalla completa con un botón de cierre en lugar de embeber el player de forma inline.

Múltiples instancias de player

Una API de registro PercusEmbed.get(id) / PercusEmbed.getAll() permitirá a la página host recuperar y controlar cualquier player previamente inicializado mediante un id personalizado pasado al momento de la inicialización.

// Propuesto
const c1 = PercusEmbed.init({ id: "hero-player", target: "#hero", ... });
const c2 = PercusEmbed.init({ id: "sidebar-player", target: "#sidebar", ... });

PercusEmbed.get("hero-player").pause();
PercusEmbed.getAll().forEach(c => c.destroy());

Consideraciones de seguridad

AspectoRecomendación
postMessageTargetOriginFijarlo al dominio real del player (ej. "https://player.percus.example") en lugar de "*".
Validación de origenEl SDK valida que los mensajes entrantes provengan del contentWindow del iframe inyectado.
Sandbox del iframeAgregar atributos sandbox restrictivos en el contenedor si el origen del player no es de plena confianza.
PII en dataLos datos de personalización nunca son almacenados por el SDK — se reenvían una sola vez al player al inicializar.

Ejemplos

ESM / TypeScript con tipado completo

import { PercusEmbed } from "@percus/percus-embed-sdk";
import type { PercusProgressMessage } from "@percus/percus-embed-sdk";

const controller = PercusEmbed.init({
target: document.getElementById("player-host")!,
playerUrl: "https://player.percus.example/runtime",
templateUrl: "https://cdn.example.com/estado-de-cuenta.json",
manifestUrl: "https://cdn.example.com/estado-de-cuenta.manifest.json",
dataUrl: "https://api.example.com/personalizacion?id=abc123",

onReady: () => controller.play(),

onProgress: (msg: PercusProgressMessage) => {
const pct = msg.payload.duration
? (msg.payload.time / msg.payload.duration) * 100
: 0;
progressBar.style.width = `${pct}%`;
},

onError: (msg) => {
console.error(`[${msg.payload.code}] ${msg.payload.message}`);
},
});

Saltar a un punto con un botón personalizado

document.getElementById("saltar-btn").addEventListener("click", () => {
controller.seek(60); // saltar al minuto 1:00
});

Limpiar al navegar en una SPA

router.on("beforeLeave", () => {
controller.destroy();
});