Concepto general del sistema

24TTL crea una página web con contenido enriquecido para presentar un producto. La página web se convierte en un archivo e-package en formato ZIP que contiene archivos HTML, CSS, iframe, JSON y multimedia junto con un archivo JSON de manifiesto (manifest.json). El archivo de manifiesto contiene la información básica sobre el e-package y el producto descrito en él. Al e-package se le asigna una URL única que se procesa en la CDN. La CDN crea un nuevo enlace equivalente para este e-package y lo almacena en caché.

24STREAM se activa cuando un usuario visita la página del producto donde está incrustado el widget. La CDN usa el enlace al archivo manifest.json para verificar si hay contenido relevante disponible.

Si el contenido está disponible, el sistema responde con "200" y el widget, dependiendo del método seleccionado, entrega automáticamente el contenido enriquecido en la página del producto (método findAndInsert) o da la oportunidad de gestionar el contenido manualmente (método find). Si no existe contenido, el sistema responde con "204".

 

Widget de entrega de contenido enriquecido 24STREAM

El widget 24STREAM está diseñado para transmitir contenido enriquecido en las páginas de productos de los mercados online.

El contenido enriquecido es una combinación de texto, imágenes, video, animaciones y medios interactivos que brindan una descripción más informativa y atractiva del producto. El contenido mejorado fomenta la interacción virtual con el producto, muestra sus ventajas, evoca emociones más intensas, incrementa el conocimiento de marca y motiva a la compra del producto.

El sistema se presenta mediante dos tipos de contenido enriquecido: minisite y AR (realidad aumentada).

El widget 24STREAM está integrado como un script en la plataforma de ventas y proporciona sistemas de búsqueda de contenido enriquecido relevante y formas para mostrarlo en la página del producto. 

El contenido enriquecido se carga cuando un usuario de la plataforma de venta visita la página del producto donde está integrada la herramienta. El script contiene los parámetros que ayudan a determinar el contenido enriquecido de qué producto y marca debe mostrarse.

El widget no recopila ni procesa ningún dato personal.

Las funciones de la solución 24STREAM son las siguientes: construir la ruta al archivo HTML estático ubicado en la CDN; insertar el resultado (código HTML) en el bloque <div>; monitorear el tamaño del bloque donde se inserta el contenido y, dependiendo del tamaño del bloque, cambiar las clases en el archivo HTML insertado. La resolución del contenido está limitada por el ancho y tiene cuatro tipos: máximo de 1200px; pc pequeño de 1100 a 991px; tablet de 991 a 768px; y móvil de 768 a 320 px.

La velocidad de la página no se ve afectada porque el widget no utiliza ninguna base de datos externa, sino que accede únicamente al contenido estático ubicado en la CDN. Así, independientemente de la ubicación del usuario, el contenido siempre se entrega desde el servidor CDN más cercano.

Se puede acceder al contenido directamente sin usar el widget. Para hacer esto, hay que crear la ruta correcta usando los atributos requeridos descritos en la sección "Uso del Widget". 

Cómo conectar el widget

El widget está adaptado para operar en varios entornos y ofrece dos métodos de conexión: asíncrona y síncrona.

Para ejecutar el widget en aplicaciones móviles, se recomienda utilizar WebView. El contenido enriquecido se mostrará en una ventana emergente.

Conexión asíncrona

Se recomienda la conexión asíncrona para que el código se ejecute en el navegador de su cliente.

El widget de conexión asíncrona no bloqueará la carga del contenido principal.

Si resulta completamente inaccesible, no causará ningún error ni romperá la funcionalidad principal del sitio web.

Para integrar el widget, inserte el siguiente código al final del cuerpo del documento:


<script>
	(function (w, d, s, o) {
		var f = d.getElementsByTagName(s)[0];
		var j = d.createElement(s);
		w.TTLStreamReady = new Promise((resolve) => {
			j.async = true;
			j.src = '//content.24ttl.stream/widget.js';
			f.parentNode.insertBefore(j, f);
			j.onload = function () {
				w.ttlStream = new TTLStream(o);
				resolve(w.ttlStream);
			};
		});
	})(window, document, 'script', {});
</script>
								

¡Ahora el widget está listo para su funcionamiento!

Conexión sincronizada

La conexión sincronizada, a diferencia de la asíncrona, bloquea el tráfico principal y los scripts que siguen al código de conexión del widget se cargarán solo después de que se cargue el widget mismo.

Este tipo de conexión puede ser útil para quienes buscan recibir los datos lo antes posible y manipularlos posteriormente.

Para integrar el widget, inserte el siguiente código al final del cuerpo del documento:


<script src="//content.24ttl.stream/widget.js"></script>
<script>
	window.TTLStreamReady = new Promise(resolve => { window.ttlStream = new TTLStream({}); resolve(); });
</script>
								

¡Ahora el widget está listo para su funcionamiento!

Uso del widget

Después de conectarlo, el widget estará listo para su uso.

La configuración del widget varía según el tipo de contenido (parámetro).

Por el moemnto, hay 2 tipos de contenido disponibles: minisite y ar (realidad aumentada).

Tipo de contenido "minisite"

Este tipo de contenido es una landing pafe con imágenes, texto y vídeo.

Para facilitar su uso, el widget proporciona dos métodos de operación:

- findAndInsert: este método permite encontrar contenido enriquecido e insertarlo automáticamente en el bloque;

- find: un método es similar a findAndInsert, que además proporciona la capacidad de manejar el contenido.

Ejemplo de contenido de transmisión

Uso de findAndInsert para el minisite

El método findAndInsert, al igual que el método find, toma un conjunto de parámetros mediante los cuales el widget encuentra el contenido y lo inserta en el bloque.

A diferencia del método find, findAndInsert no devuelve los datos para su gestion, sino que los inserta en el bloque.

Se pueden enviar los siguientes parámetros:

Parámetro Requerido Tipo de valor Descripción
el Sí String

El Selector CSS del elemento DOM en el que se insertará el contenido. Puede personalizar el tipo de contenido enriquecido agregando sus propias reglas CSS. Antes de llamar al widget, se deben asignar estilos al bloque donde se insertará el contenido enriquecido a través de important, por ejemplo, agregando el siguiente script de JS:

 var styleElement = document.createElement('style'); styleElement.innerHTML = 'body .exampleWrapperContent #stream-container * { '+ ' font-family: \'DINPro Technopark\' !important;'+ '}'; document.getElementsByTagName("head")[0].appendChild(styleElement); 

en el que .exampleWrapperContent debe reemplazarse con la clase del elemento donde se insertará el contenido enriquecido

brand Sí String El nombre de la marca para cuyo producto se entregará contenido enriquecido en la página del retailer.
productId Sí String El identificador del producto que hace que el producto de la marca tenga un código único para el retailer
retailerDomain Sí String El dominio del retailer donde se entregará el contenido enriquecido del producto
templateType Sí String El tipo de plantilla devuelta puede tomar los valores "master_template" (plantilla html) e "img_template" (plantilla de imágenes)
contentType Sí String El tipo de contenido devuelto. Puede tomar los valores "minisite" y "AR"
resultType Sí String El formato del resultado devuelto. Puede tomar el valor "html". Es un parámetro requerido que determina el resultado
language No String

El código de país e idioma del contenido enriquecido. Para recibir el contenido en un idioma en particular para un país en particular, se debe enviar una consulta en el formato 'país_idioma'. El código de país y el código de idioma deben figurar en la norma ISO (el código de país debe estar de acuerdo con ISO 3166-1, y el código de idioma en ISO 639-1). Si requiere tres páginas en tres idiomas, debe realizar tres consultas, habiendo dado en cada una los parámetros requeridos del idioma

De forma predeterminada, el parámetro se establece como 'ru'

throwError No Booleano

El valor no se establece o se establece como true: si no se encuentra contenido enriquecido, la consola mostrará un error "404" (contenido no encontrado). Tendrá que solucionar este error.

Si el valor se establece como false en caso de que no se encuentre contenido, no resultará en error; por lo tanto, no habrá necesidad de resolverlo

Ejemplo de código:


<script>
	TTLStreamReady.then(() => {
		ttlStream.findAndInsert({
			el: '.myCoolWrapper',
			brand: 'panasonic',
			productId: 'demoSKU',
			retailerDomain: 'beru.ru',
			templateType: 'master_template',
			resultType: 'html',
			contentType: 'minisite',
			language: 'ru',
		});
	});
</script>
								

El parámetro resultType determina el tipo de datos que se insertará en la página. A continuación se muestran sus posibles opciones:

html

El contenido HTML se insertará en la página.

Uso de find para el minisite

El método find toma un conjunto de parámetros mediante los cuales el widget encuentra el contenido.

Se pueden enviar los siguientes parámetros:

Parámetro Requerido Tipo de valor Descripción
brand  Sí String El nombre de la marca para cuyo producto se entregará contenido enriquecido en la web del retailer.
productId  Sí String El identificador del producto que hace que el producto de la marca tenga un código único para el retailer.
retailerDomain  Sí String El dominio del retailer donde se entregará el contenido enriquecido del producto
templateType  Sí String El tipo de plantilla devuelta puede tomar los valores "master_template" (plantilla html) e "img_template" (plantilla de imágenes)
contentType  Sí String El tipo de contenido devuelto. Puede tomar los valores "minisite" y "AR"
resultType  Sí String El formato de resultado devuelto, puede tomar los valores "html", determina el resultado. Vea el ejemplo a continuación
language  No String

El código de país e idioma del contenido enriquecido. Para recibir el contenido en un idioma en particular para un país en particular, se debe enviar una consulta en el formato 'país_idioma'. El código de país y el código de idioma deben figurar en la norma ISO (el código de país debe estar de acuerdo con el ISO 3166-1, y el código de idioma en ISO 639-1). Si requiere tres páginas en tres idiomas, debe realizar tres consultas, habiendo dado en cada una los parámetros requeridos del idioma

De forma predeterminada, el parámetro se establece como 'ru'

Ejemplo de código:


<script>
	TTLStreamReady.then(() => {
		ttlStream.find({
			brand: 'panasonic',
			productId: 'demoSKU',
			retailerDomain: 'beru.ru',
			templateType: 'master_template',
			resultType: 'html',
			contentType: 'minisite',
                       language: 'ru',
  }).then((data) => {
// The function will be called if the content is found successfully // The data variable will contain the found content }).catch((error) => { // The function will be called if the content is not found // The error variable will contain data of error reason }); }); </script>

El parámetro resultType determina el tipo de datos que se devolverán. A continuación se muestran sus posibles opciones:

html

Los data variables en la respuesta contendrán todo el contenido html de la página solicitada.

Tipo de contenido "AR" (realidad aumentada)

El contenido AR ("realidad aumentada") es una visualización de un producto en realidad aumentada que permite mostrar una copia 3D detallada del producto en un espacio determinado.

Ejemplo de transmisión de contenido AR

Configuración del AR

Para configurar la visualización en AR, se utiliza el método setArSettings.

Se pueden enviar los siguientes parámetros:

Parámetro Descripción
preview Gama de configuraciones para personalizar el botón de apertura
preview.html Texto del botón

preview.style.backgroundColor

preview.style.backgroundImage

preview.style.backgroundSize

preview.style.backgroundRepeat

preview.style.backgroundPosition

Estilos de botones. Todos los estilos se escriben como propiedades style
viewer Una serie de configuraciones para estilizar el visor
viewer.modalStyle Estilos de pop-up. Todos los estilos se escriben como propiedades style
viewer.viewerStyle Estilos de visor. Todos los estilos se escriben como propiedades style
viewer.loaderColor Color de la barra del precargador
viewer.closeStyle Estilo del botón de cierre del visor. Todos los estilos se escriben como propiedades style
qr Una serie de configuraciones para la ventana modal del código QR
qr.modal.style Configuración de estilos de ventana modal. Todos los estilos se escriben como propiedades style
qr.box.style Configuración de estilos de bloque con el contenido del código QR. Todos los estilos se escriben como propiedades style
qr.btnOpen Configuración del botón de apertura de la ventana modal del código QR
qr.btnOpen.html Texto del botón
qr.btnOpen.style Estilos de botones. Todos los estilos se escriben como propiedades style
qr.btnClose Configuración del botón de apertura de la ventana modal del código QR
qr.btnClose.html Texto del botón
qr.btnClose.style Estilos de botones. Todos los estilos se escriben como propiedades style
qr.title Configuración del título del código QR
qr.title.html Texto del título
qr.title.style Estilos de título. Todos los estilos se escriben como propiedades style
qr.subtitle Configuración del subtítulo del código QR
qr.subtitle.html Texto del subtítulo
qr.subtitle.style Estilos de subtítulo. Todos los estilos se escriben como propiedades style

Ejemplo de código


<script>
  TTLStreamReady.then(() => {
      ttlStream.setArSettings({
          preview: {
              html: '',
              style: {
                  backgroundColor: '#231010',
                  backgroundImage: "url('https://24ar.tech/staticCDN/desktop/assets/buttons/ar.svg')",
                  backgroundSize: 'cover',
                  backgroundRepeat: 'no-repeat',
                  backgroundPosition: 'center',
              },
          },
          viewer: {
              modalStyle: {},
              viewerStyle: {},
              loaderColor: '#bd0d0d',
              closeStyle: {},
          },
          qr: {
              modal: {
                  style: {},
              },
              box: {
                  style: {},
              },
              btnOpen: {
                  html: 'Hello world!',
                  style: {},
              },
              btnClose: {
                  html: 'Close',
                  style: {},
              },
              title: {
                  html: 'How to watch in AR',
                  style: {},
              },
              subtitle: {
                  html: 'Scan the QR code with your phone's camera to see the object in real life.',
                  style: {},
              },
          },
      });

      ttlStream.findAndInsert({
          el: '.myCoolWrapper',
          brand: 'panasonic',
          productId: 'demoSKU',
          retailerDomain: 'beru.ru',
          templateType: 'desktop',
          resultType: 'html',
          contentType: 'ar',
	  	});
	});
</script>
								
Uso de findAndInsert para el AR

Para el contenido AR se usa exclusivamente el método findAndInsert.

Se pueden enviar los siguientes parámetros:

Parámetro Requerido Tipo de valor Descripción
el Sí String El selector CSS del elemento DOM en el que se insertará el contenido
brand Sí String El nombre de la marca para cuyo producto se entregará el contenido enriquecido al retailer
productId Sí String El identificador del producto que hace que el producto de la marca cree un código exclusivo para el retailer
retailerDomain Sí String El dominio del retailer donde se entregará el contenido enriquecido del producto
templateType No String Un tipo de dispositivo utilizado puede tener los valores "ios", "android", "desktop". Si no se proporciona el parámetro, el tipo de dispositivo se determinará automáticamente
contentType Sí String AR
resultType Sí String El formato de resultado devuelto puede tomar el valor "html"
language No String

El código de país e idioma del contenido enriquecido. Para recibir el contenido en un idioma en particular para un país en particular, se debe enviar una consulta en el formato 'país_idioma'. El código de país y el código de idioma deben figurar en la norma ISO (el código de país debe estar según el ISO 3166-1, y el código de idioma en ISO 639-1). Si requiere tres páginas en tres idiomas, debe realizar tres consultas, habiendo dado en cada una los parámetros requeridos del idioma

De forma predeterminada, el parámetro se establece como 'ru'

throwError No Booleano 

El valor no se establece o se establece como true: si no se encuentra contenido enriquecido, la consola mostrará un error "404" (no se encuentra contenido). Tendrá que solucionar este error.

Si el valor se establece como false, no habrá error en caso de que no se encuentre el contenido; por lo tanto, no hará falta resolverlo

Ejemplo de código:


<script>
	TTLStreamReady.then(() => {
		ttlStream.findAndInsert({
			el: '.myCoolWrapper',
			brand: 'panasonic',
			productId: 'demoSKU',
			retailerDomain: 'beru.ru',
			templateType: 'desktop',
			resultType: 'html',
			contentType: 'ar',
              }); }); </script>
La incorporación del widget en la aplicación móvil.
24STREAM Flutter

Flutter plugin para crear widgets 24STREAM Rich Page.

Instalación

Para llevar a cabo la instalación, agregue stream24 a las dependencias dentro del archivo pubspec.yaml de su proyecto.

dependencies:
  ...
stream24: ^0.1.15
...

Uso

Stream24RichPage

El widget Webview con contenido enriquecido y ajuste automático de altura.

Parámetro Tipo Descripción
brand string Requerido. Nombre de la marca de la página
productId string Requerido. Identificador del producto de la página
retailerDomain string Requerido. Dominio del comercio de la página
templateType string Requerido. Tipo de plantilla de la página
language string Código de idioma de la página en formato país_idioma. El código del país debe estar en el estándar ISO 3166-1, y el código de idioma en el estándar ISO 639-1. Por defecto, ru
onError Function(String) Función llamada en caso de error
contentType Stream24ContentType Tipo de contenido de la página. .shopInShops O .minisite. Por defecto, .minisite

getHtml

Devuelve el código HTML de la página como una cadena.

Parámetro Tipo Descripción
brand string Requerido. Nombre de la marca de la página
productId string Requerido. Identificador del producto de la página
retailerDomain string Requerido. Dominio del comercio de la página
templateType string Requerido. Tipo de plantilla de la página
language string Código de idioma de la página en formato país_idioma. El código del país debe estar en el estándar ISO 3166-1, y el código de idioma en el estándar ISO 639-1. Por defecto, ru
contentType Stream24ContentType Tipo de contenido de la página. .shopInShops O .minisite. Por defecto, .minisite

Ejemplos de uso

Usando Stream24RichPage

import 'package:flutter/material.dart';
import 'package:stream24/stream24.dart';
import 'package:stream24/rich_page.dart';
import 'package:webview_flutter/webview_flutter.dart';



class WebViewPage extends StatefulWidget {
  WebViewPage({super.key});
  @override
  State<WebViewPage> createState() => _WebViewPageState();
}
class _WebViewPageState extends State<WebViewPage> {
  @override
  Widget build(BuildContext context) {
    return  Stream24RichPage(
            brand: 'Samsung',
            productId: '16651081549',
            retailerDomain: 'irshad.az',
            templateType: 'master_template',
            contentType: Stream24ContentType.shopInShops,
            onError: (errorMsg){ print(errorMsg); }
        );
    }
}

O

Usando getHtml

import 'package:flutter/material.dart';
import 'package:stream24/stream24.dart';
import 'package:webview_flutter/webview_flutter.dart';



class WebViewPage extends StatefulWidget {
  WebViewPage({super.key});
  @override
  State<WebViewPage> createState() => _WebViewPageState();
}



class _WebViewPageState extends State<WebViewPage> {
  late WebViewController controller;
    double height = 120;



  @override
  void initState() {
    super.initState();
       controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)



      // para ajustar automáticamente la altura, agregue el siguiente bloque
      ..addJavaScriptChannel("FlutterWebviewHeight",
          onMessageReceived: (JavaScriptMessage msg) {
        setState(() {
          height = double.tryParse(msg.message) ?? 0;
        });
      })
      //////////////////////////////////////////////////////////////////



     // si desea mostrar errores en contenido 404, agregue el siguiente bloque
      ..addJavaScriptChannel("FlutterError",
          onMessageReceived: (JavaScriptMessage msg) {
            
        throw Exception(msg.message);
      })
      //////////////////////////////////////////////////////////////////



      ..loadHtmlString(Stream24.getHtml(
          brand: 'Samsung',
          productId: '16651081549',
          retailerDomain: 'irshad.az',
          templateType: 'master_template',
          contentType: Stream24ContentType.shopInShops));
  }



  @override
  Widget build(BuildContext context) {
    return SizedBox(
        height: height,
        child: WebViewWidget(
          controller: controller,
        ),
    );
  }
}
24STREAM Kotlin

Plugin de Android para utilizar widgets Rich Page de 24STREAM.

Instalación

Para llevar a cabo la instalación, necesitará agregar JitPack a la lista de repositorios (si aún no lo ha hecho). En proyectos antiguos, en el archivo build.gradle principal, agregue maven { url 'https://jitpack.io' } dentro del bloque allprojects->repositories:

 allprojects {
repositories {
 ...
maven { url 'https://jitpack.io' }
}
 }

En proyectos nuevos, se agrega en settings.gradle. Debe especificarse en dependencyResolutionManagement->repositories:

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

Luego, debe agregar el propio plugin a las dependencias (en el build.gradle del módulo de la aplicación):

dependencies {
    ...
    implementation 'stream.24ttl.git.pub:24stream_android:0.5.3'
}

Uso

RichPage

Widget de WebView con contenido enriquecido y ajuste automático de altura.

Parámetro Tipo Descripción
brand string Requerido. Nombre de la marca de la página
productId string Requerido. Identificador del producto de la página
retailerDomain string Requerido. Dominio del comercio de la página
templateType string Requerido. Tipo de plantilla de la página
language string Código de idioma de la página en formato país_idioma. El código del país debe estar en el estándar ISO 3166-1, y el código de idioma en el estándar ISO 639-1. Por defecto, ru
onError (String) -> Unit Función llamada en caso de error
contentType Stream24ContentType Tipo de contenido de la página. .shopInShops O .minisite. Por defecto, .minisite

GetHTML

Devuelve el código HTML de la página como una cadena.

Parámetro Tipo Descripción
brand string Requerido. Nombre de la marca de la página
productId string Requerido. Identificador del producto de la página
retailerDomain string Requerido. Dominio del comercio de la página
templateType string Requerido. Tipo de plantilla de la página
language string Código de idioma de la página en formato país_idioma. El código del país debe estar en el estándar ISO 3166-1, y el código de idioma en el estándar ISO 639-1. Por defecto, ru
contentType Stream24ContentType Tipo de contenido de la página. .shopInShops O .minisite. Por defecto, .minisite

Ejemplos de uso

Usando RichContent

import stream.ttl24.stream24.Stream24

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val rich = Stream24.RichContent(LocalContext.current, LocalDensity.current, "irshad.az", "Samsung", "16651081549",  "master_template", ::onError, "ru_ru",  Stream24.Stream24ContentType.shopInShops)
        setContentView(rich)
    }
}


fun onError(errorMessage:String){
    print(errorMessage)
}

Usando GetHtml

import stream.ttl24.stream24.Stream24

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val webview = WebView(this)
        val html = Stream24.GetHTML("Samsung", "16651081549", "irshad.az", "master_template", Stream24.Stream24ResultType.html, Stream24.Stream24ContentType.shopInShops)
        webview.getSettings().javaScriptEnabled = true
        webview.loadData(html,
            "text/html", "UTF-8")
        setContentView(webview)
    }
}
24STREAM Swift

Plugin de iOS para crear widgets Rich Page de 24STREAM.

Instalación

24STREAM está disponible en CocoaPods y Swift Package Manager. Para instalar a través de Cocoapods, agregue la siguiente línea al Podfile:

pod '24stream'

Para instalar a través del Administrador de paquetes Swift:

File -> Add packages... -> Escríbelo en la búsqueda 'https://git.24ttl.stream/pub/24stream_swift' -> Add package

Uso

Primero, importe el plugin: import _24stream. Luego podrá utilizar las funciones del plugin:

WebView

Parámetro Tipo Descripción
brand string Requerido. Nombre de la marca de la página
productId string Requerido. Identificador del producto de la página
retailerDomain string Requerido. Dominio del comercio de la página
templateType string Requerido. Tipo de plantilla de la página
language string Código de idioma de la página en formato país_idioma. El código del país debe estar en el estándar ISO 3166-1, y el código de idioma en el estándar ISO 639-1. Por defecto, ru
page string Título de la página. Predeterminado index.html
onError Function((Float) -> Void) Función llamada en caso de error
contentType Stream24ContentType Tipo de contenido de la página. .shopInShops O .minisite. Por defecto, .minisite
onHeightSet Function((Float) -> Void) Función llamada cuando cambia la altura. Se utiliza para tener un widget con altura dinámicamente ajustable al contenido.

Ejemplo

import SwiftUI
import _24stream

struct ExamplePage: View {

  // necesario para el cálculo automático de la altura
    @State var richHeight: CGFloat = 0
    func setHeight(height:Float ) {
        richHeight = CGFloat(height)
    }

    // para manejar cualquier error
    func onError(error: String) {
        print(error)
    }
    
    var body: some View  {
        ScrollView{
            RichPage(  brand: "TestBrand",
                       retailerDomain: "24ttl.ru",
                       productId: "920-969696",
                       templateType: "master_template",
                       language: "ru",
                       page: "index.html",
                       contentType: _24StreamContentType.minisite,
                       onHeightSet: setHeight,
                       onError: onError).frame(height:richHeight)
        }
        
    }
}

struct ExamplePage_Previews: PreviewProvider {
    static var previews: some View {
        ExamplePage()
    }
}
Integración backend

Obtención del listado de tarjetas y del contenido enriquecido en el servidor a través de la API REST

Información general

La integración backend permite al retailer recibir el contenido enriquecido de 24STREAM directamente en su servidor, sin utilizar el widget del navegador. Es adecuada para los casos en que el contenido debe cargarse en la base de datos o el CMS propios del retailer y mostrarse en las páginas de producto mediante los recursos de la propia plataforma.

El contenido enriquecido es una combinación de texto, imágenes, vídeo y animación que ofrece una descripción más visual del producto. A cada unidad de contenido enriquecido le corresponde una tarjeta (e-package). El trabajo con la API consta de dos pasos: primero, el retailer obtiene el listado de tarjetas disponibles para él y, después, descarga el contenido HTML de cada tarjeta por su identificador.

Flujo de trabajo

  • Obtener el listado de tarjetas disponibles para su plataforma (método /search).
  • Asociar las tarjetas con sus productos mediante el campo skuId.
  • Descargar el HTML del contenido enriquecido por el identificador de la tarjeta (/download).
  • Solicitar periódicamente las actualizaciones con el filtro updatedAt y sincronizar su base de datos.

 

Acceso y autenticación

Para acceder a la API se necesita una clave API generada por 24TTL. Para obtener la clave y el identificador del retailer (retailerId), diríjase a su gerente comercial.

URL base:

https://panel.24ttl.stream/api/v1

Todas las solicitudes se realizan por HTTPS con el método POST.

Encabezados de la solicitud

Encabezado

Valor

Descripción

Authorization

ApiKey <su_clave>

Obligatorio. La clave API se envía solo en el encabezado, no en el cuerpo de la solicitud.

Content-Type

application/json

Obligatorio

Accept-Charset

utf-8

Recomendado

Convenciones generales

Formato de fecha y hora

Todas las fechas se envían y se devuelven en formato ISO 8601, por ejemplo 2026-08-01 00:00:00.

Paginación

Los métodos de listado utilizan paginación por cursor. La respuesta devuelve el campo cursor; para obtener la página siguiente, envíe ese valor en el campo cursor de la siguiente solicitud. Un cursor vacío o ausente en la respuesta significa que no hay más páginas.

Códigos de respuesta

Código

Significado

200

La solicitud se procesó correctamente.

400

Cuerpo de la solicitud incorrecto (error de validación de parámetros).

401

Clave API ausente o incorrecta.

404

No se encontró el contenido solicitado.

429

Se superó el límite de solicitudes. Vuelva a intentarlo más tarde.

Método 1. Listado de tarjetas

Devuelve un listado paginado de las tarjetas de contenido enriquecido disponibles para su plataforma. El método se utiliza tanto para la descarga inicial del listado completo como para obtener solo las tarjetas actualizadas mediante el filtro updatedAt.

Solicitud

curl -X POST https://panel.24ttl.stream/api/v1/retailers/{retailerId}/retailer-epackages/search \
-H "Accept-Charset: utf-8" \
-H "Content-Type: application/json" \
-H "Authorization: ApiKey generatedApiKey" \
-d '{
"limit": 1000,
"cursor": "###",
"fields": ["name", "brand"],
"filters":{
  "updatedAt":{
    "gte": "yyyy-mm-dd hh:mm:ss",
    "gt": "yyyy-mm-dd hh:mm:ss",
    "lte": "yyyy-mm-dd hh:mm:ss",
    "lt": "yyyy-mm-dd hh:mm:ss"
  },
  "isActive":{
    "eq": true
  },
  "skuId":{
    "in": ["example_sku_id"]
  },
  "reId":{
    "in": ["example_re_id"]
  }
}
}'

Parámetros del cuerpo de la solicitud

Parámetro

Oblig.

Descripción

limit

No

Número de elementos por página. Por defecto, 100; máximo, 1000.

cursor

No

Cursor de paginación. Para obtener la página siguiente, envíe el valor de cursor de la respuesta anterior.

fields

No

Campos adicionales en la respuesta. Valores admitidos: name, brand.

filters.updatedAt.gte

No

Fecha de actualización «mayor o igual que».

filters.updatedAt.gt

No

Fecha de actualización «mayor que».

filters.updatedAt.lte

No

Fecha de actualización «menor o igual que».

filters.updatedAt.lt

No

Fecha de actualización «menor que».

filters.isActive.eq

No

Filtro por estado activo de la tarjeta (true / false).

filters.skuId.in

No

Lista de identificadores personalizados (skuId) para seleccionar tarjetas concretas.

filters.reId.in

No

Lista de identificadores de tarjetas (reId).

Los filtros por updatedAt son útiles para obtener con regularidad solo las tarjetas que han cambiado, por ejemplo, una vez por hora o una vez al día para el período anterior.

Respuesta 200

{
 "code": 200,
 "message": "",
 "data":{
   "cursor": "eyJpZCI6...",
   "items": [
     {
       "reId": "12345678-1234-1234-1234-123456789012",
       "skuId": "ABC12",
       "isActive": true,
       "updatedAt": "2026-08-01 10:30:00",
       "name": "Nombre del producto",
"brand": "Nombre de la marca"
     }

   ]
 }
}

Campos de la respuesta

Campo

Descripción

data.cursor

Cursor para obtener la página siguiente.

items[].reId

Identificador de la tarjeta. Se utiliza en los métodos de descarga de contenido.

items[].skuId

Identificador personalizado de la tarjeta (para asociarla con su producto).

items[].isActive

Indicador de tarjeta activa.

items[].updatedAt

Fecha y hora de la última actualización de la tarjeta.

items[].name

Nombre del producto. Se devuelve solo si se solicita en fields.

items[].brand

Nombre de la marca. Se devuelve solo si se solicita en fields.

Método 2. Descarga de una tarjeta

Devuelve el HTML del contenido enriquecido de una tarjeta por su reId.

Solicitud

curl -X POST https://panel.24ttl.stream/api/v1/retailer-epackages/{reId}/download \
-H "Accept-Charset: utf-8" \
-H "Content-Type: application/json" \
-H "Authorization: ApiKey generatedApiKey" \
-d '{
  "locale": "ar_en",
  "contentType": "minisite",
  "template": "master_template",
  "format": "html",
  "source": "index.html"
  }'

Parámetros

Parámetro

Oblig.

Descripción

{reId}

Sí

Identificador de la tarjeta obtenido con el método 1 (en la ruta de la solicitud).

locale

Sí

Configuración regional del contenido enriquecido, por ejemplo ar_en.

contentType

No

Tipo de contenido. Por defecto, minisite.

template

No

Plantilla. Por defecto, master_template.

format

No

Formato del contenido. Por defecto, html.

source

No

Origen del contenido. Por defecto, index.html.

Respuestas

Código

Cuerpo de la respuesta

200

HTML del contenido enriquecido de la tarjeta «tal cual».

404

No se encontró la tarjeta o su contenido. El cuerpo de la respuesta es un JSON con el código de error (ver más abajo).

Respuesta 404

Valores posibles del campo code en la respuesta 404:

{
 "code": 4040,
 "message": "Epackage retailer not found",
 "data": []
}

Código

Significado

4040

No se encontró la tarjeta.

4041

No se encontró el contenido de la tarjeta.

Casos de uso

Carga inicial del contenido enriquecido

  • Llame al método 1 y, recorriendo la paginación, obtenga todas las tarjetas disponibles.
  • Asocie sus productos con las tarjetas mediante skuId. Guarde reId, skuId y updatedAt.
  • Descargue el HTML del contenido enriquecido por reId (método 2) y vincúlelo a su producto mediante el par reId + skuId.

Obtención de actualizaciones (con el filtro updatedAt)

  • Tome el valor máximo de updatedAt guardado en su base de datos (lastUpdatedAt = max(updatedAt)) y llame al método 1 con el filtro filters.updatedAt.gt = lastUpdatedAt. Puede hacerse una vez por hora o una vez al día.
  • Compare el listado de tarjetas actualizadas con el estado actual de su base de datos y aplique las acciones de la tabla siguiente.
  • Para añadir o actualizar contenido, utilice el método 2.

Matriz de decisiones

isActive en la respuesta

skuId en su base de datos

Acción

true

Encontrado

Actualizar el contenido enriquecido.

true

No encontrado

Crear el registro y añadir el contenido enriquecido.

false

Encontrado

Eliminar / retirar el contenido enriquecido, si existe.

false

No encontrado

No hacer nada.

Obtención de actualizaciones (descarga completa)

  • Obtenga el listado completo de tarjetas disponibles para su plataforma (método 1 sin filtro de fecha).
  • Busque el producto correspondiente por skuId y aplique las acciones de la matriz de decisiones anterior (añadir, actualizar o retirar el contenido enriquecido).

Para obtener la clave API, el identificador del retailer y los parámetros de conexión, diríjase a su gerente comercial.

Sandbox

Para ejemplos prácticos, hemos desarrollado un Sandbox donde puede experimentar con los parámetros.