Conceito geral do sistema

24TTL cria uma página web com conteúdo interativo para um produto. A página é convertida em um pacote eletrônico, um arquivo ZIP contendo arquivos HTML, CSS, iframe, JSON e de mídia, além de um arquivo JSON de manifesto (manifest.json). O arquivo de manifesto contém informações básicas sobre o pacote eletrônico e o produto. O pacote eletrônico possui um URL exclusivo que é registrado no CDN. O CDN cria uma nova ligação equivalente ao pacote eletrônico e o armazena na cache.

24STREAM é ativado quando um usuário visita a página de um produto onde o widget está incorporado. O CDN usa a ligação do arquivo manifest.json para verificar se há conteúdo relevante disponível.

Se o conteúdo estiver disponível, o sistema responde com "200" e o widget, dependendo do método selecionado, entrega automaticamente o conteúdo interativo na página do produto (o método findAndInsert) ou fornece uma oportunidade para lidar com o conteúdo manualmente (método find). Se não existir conteúdo, o sistema responde com "204".

 

24STREAM, ferramenta de entrega de conteúdo interativo

O widget do 24STREAM foi criado para transmitir conteúdo interativo nas páginas de produtos de lojas online.

O conteúdo interativo é uma combinação de texto, imagens, vídeo, animações e mídia interativa que fornecem uma descrição mais interessante e mais completa do produto. O conteúdo aprimorado incentiva a interação virtual com o produto, mostra suas vantagens, provoca emoções, constrói a imagem da marca e motiva a compra.

O sistema permite dois tipos de conteúdo interativo: minisite e RA (realidade aumentada).

O widget do 24STREAM é incorporado como um script na sua loja online e fornece métodos para pesquisa de conteúdo interativo relevante e para implementação do mesmo na página do produto.

O conteúdo interativo é enviado quando um utilizador da loja visita a página do produto em que a ferramenta está incroporada. O script contém os parâmetros que ajudam a determinar qual conteúdo interativo e de que marca devem ser renderizados.

O widget não coleta ou processa seus dados.

As funções da solução 24STREAM são as seguintes: construção do caminho do HTML estático localizado no CDN: introdução do resultado (código HTML) no bloco <div>; monitoramento do tamanho do bloco onde o conteúdo está inserido; e, dependendo do tamanho do bloco, alteração das classes no arquivo HTML inserido. A resolução do conteúdo é limitada pela largura e possui quatro tipos: máximo - 1200px; pc pequeno - 1100 a 991px; tablet - 991 a 768px e móvel - abaixo de 768 a 320px.

A velocidade da página não é afetada porque o widget não usa bases de dados externas, ele só acessa conteúdo estático no CDN. Sendo assim, independentemente da localização do usuário, o conteúdo sempre é entregue a partir do servidor CDN mais próximo.

O conteúdo pode ser acessado diretamente sem usar o widget. Para fazê-lo, o caminho correto deve ser contruído usando os atributos necessários descritos na seção "Usando o Widget".

Conectando o widget

O widget é adaptado para operar em vários ambientes e oferece dois métodos de conexão: assíncrona e sincronizada.

Para executar a ferramenta em aplicativos móveis, é recomendado usar WebView. O conteúdo interativo será exibido em uma janela pop-up.

Conexão assíncrona

A conexão assíncrona é recomendada para que o código seja executado no cliente do seu navegador.

O widget com conexão assíncrona não bloqueará o carregamento do conteúdo principal.

Se ficar completamente inacessível, ele não causará erros ou quebrará qualquer funcionalidade do website.

Para integrar o widget, insira o seguinte código no fim do corpo do 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>
								

O widget está pronto para o uso!

Conexão sincronizada

A conexão sincronizada, ao contrário do tipo assíncrono, bloqueia o tráfego principal, e os scripts que seguem o código de conexão do widget serão carregados somente após o carregamento do widget.

Este tipo de conexão pode ser útil para quem deseja receber os dados assim que possível e que desejam manipular os dados depois.

Para integrar o widget, insira o seguinte código no fim do corpo do documento:


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

O widget está pronto para o uso!

Usando o widget

Após ter conectado o widget, ele estará pronto para uso.

As configurações do widget diferem dependendo do tipo de conteúdo (parâmetro).

Atualmente, 2 tipos de conteúdo estão disponíveis: minisite e ra (realidade aumentada).

Tipo de conteúdo "minisite"

Este tipo de conteúdo é uma página inicial com imagens, texto e mídia de vídeo.

Para facilitar o uso, o widget fornece dois métodos de operação:

- findAndInsert: o método fornece a possibilidade de pesquisa de conteúdo interativo e de introdução automática no bloco;

- find: o método é semelhante ao findAndInsert, além disso, fornece a habilidade de manipular o conteúdo.

Exemplo de conteúdo de transmissão

Usando findAndInsert para minisite

O método findAndInsert, semelhante ao find, pega um conjunto de parâmetros e os usa para que o widget encontre o conteúdo e o insira no bloco.

Ao contrário do método find, o findAndInsert não devolve os dados para manipulações, mas os insere no bloco.

Os seguintes parâmetros podem ser enviados:

Parâmetro Necessário Tipo de valor Descrição
el Sim String


Selecionador CSS do elemento DOM no qual o conteúdo será inserido. Você pode personalizar o tipo de conteúdo interativo adicionando suas regras CSS. Antes de chamar o widget, o bloco em que o conteúdo interativo será inserido deve ter estilos atribuídos através de importância, por exemplo, com a adição do seguinte script JS:

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

onde .exampleWrapperContent deve ser substituído com a classe do elemento em que o conteúdo interativo será inserido

brand Sim String O nome da marca do produto para o qual o conteúdo interativo será entregue na loja online
productId Sim String O identificador do produto que torna o produto único para o vendedor da marca
retailerDomain Sim String O domínio do vendedor para o qual o conteúdo interativo do produto será entregue
templateType Sim String Tipo de template retornado, pode ter os valores 'master_template' (template html) e 'img_template' (template de imagens)
contentType Sim String Tipo de conteúdo retornado, pode ter os valores 'minisite' e 'ar'
resultType Sim String Formato de resultado retornado, pode ter os valores 'html', um parâmetro necessário, determina o resultado
language Não String

O código de país e idioma para o conteúdo interativo. Para receber o conteúdo em um certo idioma e certo país, uma consulta deve ser enviada no formato 'country_language'. O código do país e o código do idioma devem ser dados de acordo com a norma ISO (o código do país deve estar de acordo com a ISO 3166-1, e o código de idioma com a ISO 639-1). Se for necessário três páginas em três idiomas, deverá efetuar três consultar, fornecendo os parâmetros necessários do idioma em cada uma

Por padrão, o parâmetro é definido como 'ru'

throwError Não Booleano

O valor não é definido ou é definido como true: se nenhum conteúdo interativo for encontrado, o console mostrará o erro "404" (nenhum conteúdo encontrado). Você terá que resolver o erro.

Se o valor for definido como false, o erro não aparecerá caso o conteúdo não seja encontrado; portanto, não será necessário tratá-lo

Exemplo 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>
								

O parâmetro resultType determina o tipo de dados que serão inseridos na página. Abaixo estão as possíveis opções:

html

Conteúdo HTML será inserido na página.

Usando find para o minisite

O método find utiliza um conjunto de parâmetros para que o widget encontre o conteúdo.

Os seguintes parâmetros podem ser enviados:

Parâmetro Necessário Tipo de valor Descrição
brand  Sim String O nome da marca do produto para o qual o conteúdo interativo será entregue na loja online
productId  Sim String O identificador do produto que torna o produto único para o vendedor da marca
retailerDomain  Sim String O domínio do vendedor para o qual o conteúdo interativo do produto será entregue
templateType  Sim String Tipo de template retornado, pode ter os valores 'master_template' (template html) e 'img_template' (template de imagens)
contentType  Sim String Tipo de conteúdo retornado, pode ter os valores 'minisite' e 'ar'
resultType  Sim String Formato de resultado retornado, pode ter os valores 'html', determina o resultado. Veja o exemplo abaixo
language  Não String

O código de país e idioma para o conteúdo interativo. Para receber o conteúdo em um certo idioma e certo país, uma consulta deve ser enviada no formato 'country_language'. O código do país e o código do idioma devem ser dados de acordo com a norma ISO (o código do país deve estar de acordo com a ISO 3166-1, e o código de idioma com a ISO 639-1). Se for necessário três páginas em três idiomas, deverá efetuar três consultar, fornecendo os parâmetros necessários do idioma em cada uma 

Por padrão, o parâmetro é definido como 'ru'

Exemplo 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>

O parâmetro resultType determina o tipo de dados que serão retornados. Abaixo estão as possíveis opções:

html

Os data variáveis na resposta terão todo o conteúdo html na página requisitada.

Tipo de conteúdo RA (realidade aumentada)

Conteúdo em RA (realidade aumentada) é uma visualização de um produto em realidade aumentada permitindo mostrar uma cópia detalhada do produto em um espaço.

Exemplo de transmissão de conteúdo RA

Configurando RA

Para configurar a visualização RA, o método setArSettings é usado.

Os seguintes parâmetros podem ser enviados:

Parâmetro Descrição
preview Um conjunto de configurações para personalizar o botão de abrir
preview.html Texto do botão

preview.style.backgroundColor

preview.style.backgroundImage

preview.style.backgroundSize

preview.style.backgroundRepeat

preview.style.backgroundPosition

Estilos de botão. Todos os estilos são escritos como propriedades de estilo de objeto
viewer Um número de configurações para estilizar o visualizador
viewer.modalStyle Estilos de pop-up. Todos os estilos são escritos como propriedades de estilo do objeto
viewer.viewerStyle Estilos de visualizador. Todos os estilos são escritos como propriedades de estilo do objeto
viewer.loaderColor Cor da barra de pré-carregamento
viewer.closeStyle Estilo do botão fechar do visualizador. Todos os estilos são escritos como propriedades de estilo do objeto
qr Um número de configurações para a janela de código QR
qr.modal.style Configurações de estilos da janela. Todos os estilos são escritos como propriedades de estilo do objeto
qr.box.style Configurações de estilo do bloco de conteúdo QR. Todos os estilos são escritos como propriedades de estilo do objeto
qr.btnOpen Configurações do botão abrir da janela de código QR
qr.btnOpen.html Texto do botão
qr.btnOpen.style Estilos de botão. Todos os estilos estão escritos como propriedades de estilo do objeto
qr.btnClose Configurações do botão fechar da janela de código QR
qr.btnClose.html Texto do botão
qr.btnClose.style Estilos de botão. Todos os estilos estão escritos como propriedades de estilo do objeto
qr.title Configurações do título do código QR
qr.title.html Texto do título
qr.title.style Estilos do título. Todos os estilos estão escritos como propriedades de estilo do objeto
qr.subtitle Configurações de legenda do código QR
qr.subtitle.html Texto de legenda
qr.subtitle.style Estilos de legenda. Todos os estilos estão escritos como propriedades de estilo do objeto

Exemplo 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>
								
Usando findAndInsert para RA

Conforme aplicado no tipo de conteúdo RA, o método findAndInsert é usado.

Os seguintes parâmetros podem ser enviados:

Parâmetro Necessário Tipo de valor Descrição
el Sim String Selecionador CSS do elemento DOM no qual o conteúdo será inserido
brand Sim String O nome da marca do produto para o qual o conteúdo interativo será entregue na loja online
productId Sim String O identificador do produto que torna o produto único para o vendedor da marca
retailerDomain Sim String O domínio do vendedor para o qual o conteúdo interativo do produto será entregue
templateType Não String O tipo de dispositivo usado, pode ter os valores 'ios', 'android', 'desktop'. Se o parâmetro não é dado, o tipo de dispositivo será determinado automaticamente
contentType Sim String AR
resultType Sim String Formato de resultado retornado, pode ter o valor 'html'
language Não String

O código de país e idioma para o conteúdo interativo. Para receber o conteúdo em um certo idioma e certo país, uma consulta deve ser enviada no formato 'country_language'. O código do país e o código do idioma devem ser dados de acordo com a norma ISO (o código do país deve estar de acordo com a ISO 3166-1, e o código de idioma com a ISO 639-1). Se for necessário três páginas em três idiomas, deverá efetuar três consultar, fornecendo os parâmetros necessários do idioma em cada uma

Por padrão, o parâmetro é definido como 'ru'

throwError Não Booleano 

O valor não é definido ou é definido como true: se nenhum conteúdo interativo for encontrado, o console mostrará o erro "404" (nenhum conteúdo encontrado). Você terá que resolver o erro.

Se o valor for definido como false, o erro não aparecerá caso o conteúdo não seja encontrado; portanto, não será necessário tratá-lo

Exemplo de código:


<script>
	TTLStreamReady.then(() => {
		ttlStream.findAndInsert({
			el: '.myCoolWrapper',
			brand: 'panasonic',
			productId: 'demoSKU',
			retailerDomain: 'beru.ru',
			templateType: 'desktop',
			resultType: 'html',
			contentType: 'ar',
              }); }); </script>
A integração do widget no aplicativo móvel
24STREAM Flutter

Plugin Flutter para criar widgets 24STREAM Rich Page.

Instalação

Para efetuar a instalação, inclua stream24 nas dependências dentro do pubspec.yaml do seu projeto.

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

Utilização

Stream24RichPage

Widget WebView com conteúdo enriquecido e ajuste automático de altura.

Parâmetro Tipo Descrição
brand string Obrigatório. Nome da marca da página
productId string Obrigatório. Identificador do produto da página
retailerDomain string Obrigatório. Domínio do varejista da página
templateType string Obrigatório. Tipo de modelo da página
language string Código de idioma da página no formato país_idioma. O código do país deve ser conforme ISO 3166-1 e o código de idioma conforme ISO 639-1. Padrão: ru
onError Function(String) Função chamada ao ocorrer um erro
contentType Stream24ContentType Tipo de conteúdo da página. .shopInShops ou .minisite. Padrão: .minisite

GetHtml

Retorna o código HTML da página como uma string.

Parâmetro Tipo Descrição
brand string Obrigatório. Nome da marca da página
productId string Obrigatório. Identificador do produto da página
retailerDomain string Obrigatório. Domínio do varejista da página
templateType string Obrigatório. Tipo de modelo da página
language string Código de idioma da página no formato país_idioma. O código do país deve ser conforme ISO 3166-1 e o código de idioma conforme ISO 639-1. Padrão: ru
contentType Stream24ContentType Tipo de conteúdo da página. .shopInShops ou .minisite. Padrão: .minisite

Exemplos de Utilização

Utilizando 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); }
        );
    }
}

OU

Utilizando 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 automaticamente a altura, adicione o seguinte bloco
      ..addJavaScriptChannel("FlutterWebviewHeight",
          onMessageReceived: (JavaScriptMessage msg) {
        setState(() {
          height = double.tryParse(msg.message) ?? 0;
        });
      })
      //////////////////////////////////////////////////////////////////



     // se desejar lançar erros no conteúdo 404, adicione o seguinte bloco
      ..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 Android para utilizar widgets Rich Page da 24STREAM.

Instalação

Para realizar a instalação, você precisará adicionar o JitPack à lista de repositórios (caso ainda não tenha feito isso).
Em projetos antigos, no arquivo build.gradle raiz, adicione maven { url 'https://jitpack.io' } dentro do bloco allprojects -> repositories:

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

Em projetos novos, ele é adicionado ao settings.gradle. Ele deve ser especificado em dependencyResolutionManagement -> repositories:

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

Em seguida, você precisará adicionar o próprio plugin às dependências (no build.gradle do módulo de aplicativo):

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

Utilização

RichPage

Widget WebView com conteúdo enriquecido e ajuste automático de altura.

Parâmetro Tipo Descrição
brand string Obrigatório. Nome da marca da página
productId string Obrigatório. Identificador do produto da página
retailerDomain string Obrigatório. Domínio do varejista da página
templateType string Obrigatório. Tipo de modelo da página
language string Código de idioma da página no formato país_idioma. O código do país deve ser conforme ISO 3166-1 e o código de idioma conforme ISO 639-1. Padrão: ru
onError (String) -> Unit Função chamada ao ocorrer um erro
contentType Stream24ContentType Tipo de conteúdo da página. .shopInShops ou .minisite. Padrão: .minisite

GetHTML

Retorna o código HTML da página como uma string.

Parâmetro Tipo Descrição
brand string Obrigatório. Nome da marca da página
productId string Obrigatório. Identificador do produto da página
retailerDomain string Obrigatório. Domínio do varejista da página
templateType string Obrigatório. Tipo de modelo da página
language string Código de idioma da página no formato país_idioma. O código do país deve ser conforme ISO 3166-1 e o código de idioma conforme ISO 639-1. Padrão: ru
contentType Stream24ContentType Tipo de conteúdo da página. .shopInShops ou .minisite. Padrão: .minisite

Exemplos de Utilização

Utilizando 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)
}

Utilizando 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 iOS para criar widgets Rich Page da 24STREAM.

Instalação

24STREAM está disponível em CocoaPods e Swift Package Manager. Para instalar via Cocoapods, adicione a seguinte linha ao Podfile:

pod '24stream'

Para instalar via Swift Package Manager:

File -> Add packages... -> Digite na pesquisa 'https://git.24ttl.stream/pub/24stream_swift' -> Add package

Utilização

Para começar, importe o plugin: import _24stream. Depois disso, você poderá usar as funcionalidades do plugin:

WebView

Parâmetro Tipo Descrição
brand string Obrigatório. Nome da marca da página
productId string Obrigatório. Identificador do produto da página
retailerDomain string Obrigatório. Domínio do varejista da página
templateType string Obrigatório. Tipo de modelo da página
language string Código de idioma da página no formato país_idioma. O código do país deve ser conforme ISO 3166-1 e o código de idioma conforme ISO 639-1. Padrão: ru
page string Título da página. Índice index.html
onError Function((Float) -> Void) Função chamada ao ocorrer um erro
contentType Stream24ContentType Tipo de conteúdo da página. .shopInShops ou .minisite. Padrão: .minisite
onHeightSet Function((Float) -> Void) Função chamada ao alterar a altura. Usada para ter uma altura de widget ajustável dinamicamente ao conteúdo

Exemplo

import SwiftUI
import _24stream

struct ExamplePage: View {

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

    //para lidar com quaisquer erros
    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()
    }
}
Integração backend

Obtenção da lista de cartões e do conteúdo interativo no servidor via API REST

Informações gerais

A integração backend permite que o varejista receba o conteúdo interativo da 24STREAM diretamente no seu servidor, sem usar o widget do navegador. Ela é indicada para cenários em que o conteúdo precisa ser carregado na base de dados ou no CMS do próprio varejista e exibido nas páginas de produto pelos recursos da própria plataforma.

O conteúdo interativo é uma combinação de texto, imagens, vídeo e animação que oferece uma descrição mais visual do produto. Cada unidade de conteúdo interativo corresponde a um cartão (pacote eletrônico, e-package). O trabalho com a API é feito em duas etapas: primeiro, o varejista obtém a lista de cartões disponíveis para ele e, em seguida, baixa o conteúdo HTML de cada cartão pelo seu identificador.

Fluxo de trabalho

  • Obter a lista de cartões disponíveis para a sua plataforma (método /search).
  • Associar os cartões aos seus produtos pelo campo skuId.
  • Baixar o HTML do conteúdo interativo pelo identificador do cartão (/download).
  • Solicitar periodicamente as atualizações com o filtro updatedAt e sincronizar a sua base de dados.

 

Acesso e autenticação

Para acessar a API, é necessária uma chave API gerada pela 24TTL. Para obter a chave e o identificador do varejista (retailerId), entre em contato com o seu gerente de vendas.

URL base:

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

Todas as requisições são feitas via HTTPS com o método POST.

Cabeçalhos da requisição

Cabeçalho

Valor

Descrição

Authorization ApiKey <sua_chave> Obrigatório. A chave API é enviada apenas no cabeçalho, não no corpo da requisição.
Content-Type application/json Obrigatório
Accept-Charset utf-8 Recomendado

Convenções gerais

Formato de data e hora

Todas as datas são enviadas e retornadas no formato ISO 8601, por exemplo 2026-08-01 00:00:00.

Paginação

Os métodos de listagem usam paginação por cursor. A resposta retorna o campo cursor; para obter a próxima página, envie esse valor no campo cursor da requisição seguinte. Um cursor vazio ou ausente na resposta significa que não há mais páginas.

Códigos de resposta

Código Significado
200 A requisição foi processada com sucesso.
400 Corpo da requisição inválido (erro de validação de parâmetros).
401 Chave API ausente ou inválida.
404 O conteúdo solicitado não foi encontrado.
429 Limite de requisições excedido. Tente novamente mais tarde.
Método 1. Lista de cartões

Retorna uma lista paginada dos cartões de conteúdo interativo disponíveis para a sua plataforma. O método é usado tanto para a exportação inicial da lista completa quanto para obter apenas os cartões atualizados com o filtro updatedAt.

Requisição

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 do corpo da requisição

Parâmetro

Obrig.

Descrição

limit

Não

Número de itens por página. Padrão: 100; máximo: 1000.

cursor

Não

Cursor de paginação. Para obter a próxima página, envie o valor de cursor da resposta anterior.

fields

Não

Campos adicionais na resposta. Valores permitidos: name, brand.

filters.updatedAt.gte

Não

Data de atualização “maior ou igual a”.

filters.updatedAt.gt

Não

Data de atualização “maior que”.

filters.updatedAt.lte

Não

Data de atualização “menor ou igual a”.

filters.updatedAt.lt

Não

Data de atualização “menor que”.

filters.isActive.eq

Não

Filtro por status ativo do cartão (true / false).

filters.skuId.in

Não

Lista de identificadores personalizados (skuId) para selecionar cartões específicos.

filters.reId.in

Não

Lista de identificadores de cartões (reId).

Os filtros por updatedAt são úteis para obter regularmente apenas os cartões que mudaram — por exemplo, uma vez por hora ou uma vez por dia, referente ao período anterior.

Resposta 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": "Nome do produto",
"brand": "Nome da marca"
     }

   ]
 }
}

Campos da resposta

Campo

Descrição

data.cursor

Cursor para obter a próxima página.

items[].reId

Identificador do cartão. Usado nos métodos de download de conteúdo.

items[].skuId

Identificador personalizado do cartão (para associá-lo ao seu produto).

items[].isActive

Indicador de cartão ativo.

items[].updatedAt

Data e hora da última atualização do cartão.

items[].name

Nome do produto. Retornado apenas se solicitado em fields.

items[].brand

Nome da marca. Retornado apenas se solicitado em fields.

Método 2. Download de um cartão

Retorna o HTML do conteúdo interativo de um cartão pelo seu reId.

Requisição

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

Obrig.

Descrição

{reId}

Sim

Identificador do cartão obtido no método 1 (no caminho da requisição).

locale

Sim

Localidade do conteúdo interativo, por exemplo ar_en.

contentType

Não

Tipo de conteúdo. Padrão: minisite.

template

Não

Modelo. Padrão: master_template.

format

Não

Formato do conteúdo. Padrão: html.

source

Não

Origem do conteúdo. Padrão: index.html.

Respostas

Código

Corpo da resposta

200

HTML do conteúdo interativo do cartão “como está”.

404

O cartão ou o seu conteúdo não foi encontrado. O corpo da resposta é um JSON com o código de erro (veja abaixo).

Resposta 404

Valores possíveis do campo code na resposta 404:

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

Código

Significado

4040

Cartão não encontrado.

4041

Conteúdo do cartão não encontrado.

Cenários de uso

Carregamento inicial do conteúdo interativo

  • Chame o método 1 e, percorrendo a paginação, obtenha todos os cartões disponíveis.
  • Associe os seus produtos aos cartões pelo skuId. Salve reId, skuId e updatedAt.
  • Baixe o HTML do conteúdo interativo pelo reId (método 2) e vincule-o ao seu produto pelo par reId + skuId.

 

Obtenção de atualizações (com o filtro updatedAt)

  • Pegue o maior valor de updatedAt salvo na sua base de dados (lastUpdatedAt = max(updatedAt)) e chame o método 1 com o filtro filters.updatedAt.gt = lastUpdatedAt. Isso pode ser feito uma vez por hora ou uma vez por dia.
  • Compare a lista de cartões atualizados recebida com o estado atual da sua base de dados e aplique as ações da tabela abaixo.
  • Para adicionar ou atualizar conteúdo, use o método 2.

 

Matriz de decisão

isActive na resposta

skuId na sua base de dados

Ação

true

Encontrado

Atualizar o conteúdo interativo.

true

Não encontrado

Criar o registro e adicionar o conteúdo interativo.

false

Encontrado

Excluir / remover o conteúdo interativo, se houver.

false

Não encontrado

Não fazer nada.

Obtenção de atualizações (exportação completa)

  • Obtenha a lista completa de cartões disponíveis para a sua plataforma (método 1 sem filtro de data).
  • Encontre o produto correspondente pelo skuId e aplique as ações da matriz de decisão acima (adicionar, atualizar ou remover o conteúdo interativo).

Para obter a chave API, o identificador do varejista e os parâmetros de conexão, entre em contato com o seu gerente de vendas.

Sandbox

Para exemplos práticos, criamos a Sandbox, onde poderá experimentar os parâmetros.