Blocks
A pasta Blocks concentra os blocos reutilizáveis que podem ser disponibilizados no CMS para páginas configuradas com content_for_page.
Cada bloco deve possuir dois arquivos com o mesmo nome base:
Blocks/<type>.html: responsável pela renderização do bloco na página.Blocks/<type>.schema.json: responsável por descrever os campos editáveis do bloco no CMS e o contrato usado na validação do salvamento.
Exemplo de estrutura
Blocks/
banner_button.html
banner_button.schema.json
banner_carousel.html
banner_carousel.schema.json
button_carousel.html
button_carousel.schema.json
image_showcase.html
image_showcase.schema.json
product_carousel.html
product_carousel.schema.jsonRegras importantes
- O nome do arquivo deve ser igual ao
typedo bloco. - Para um bloco com
type: "banner_button", os arquivos esperados sãoBlocks/banner_button.htmleBlocks/banner_button.schema.json. - O arquivo
.htmlé carregado na renderização da página. - O arquivo
.schema.jsoné carregado para montar os campos do CMS e validar os dados enviados no salvamento. - Se o
.schema.jsonnão existir, o bloco não poderá ser salvo. - Se o
.htmlnão existir, o bloco não poderá ser renderizado corretamente.
Guia de criação de schema.json
O schema.json define como o bloco aparece para edição no CMS e quais valores a plataforma aceita.
Estrutura base
{
"name": "Banner com botão",
"type": "banner_button",
"settings": [
{
"label": "Título principal",
"name": "title",
"type": "text",
"required": false
}
]
}Propriedades do bloco
| Propriedade | Tipo | Obrigatória | Descrição |
|---|---|---|---|
| name | string | recomendada | Nome amigável exibido para quem está configurando o bloco. |
| type | string | sim | Identificador técnico do bloco. Deve ser o mesmo valor usado em content_for_page e no nome dos arquivos. |
| settings | array | sim | Lista de campos editáveis do bloco. |
varyByAudience | boolean | não | Habilita variação de conteúdo por audiência neste bloco. Pode ser declarada em qualquer bloco, sem restrição de tipo. Quando true, qualquer campo de settings pode variar. Requer o add-on de audiências ativo na loja. Padrão: false. |
Propriedades de cada item em settings
settings| Propriedade | Tipo | Obrigatória | Descrição |
|---|---|---|---|
| label | string | recomendada | Texto exibido no CMS para o usuário da plataforma. |
| name | string | sim | Nome técnico do campo. Ele vira a chave dentro de content e pode ser acessado no HTML por block_data.<name>. |
| type | string | sim | Tipo do campo. |
| required | boolean | não | Define se o campo é obrigatório. |
| options | array | obrigatória para select | Lista de opções válidas para campos fechados (select/options). |
Tipos de campos suportados em settings
settings| Tipo | Descrição |
|---|---|
| text | Texto simples. O valor deve ser uma string com tamanho máximo limitado. É o tipo padrão. |
| string | Alias de text. Comportamento idêntico — aceita string com limite de tamanho. |
| number | Valor numérico. Aceita apenas valores do tipo número (inteiro ou decimal). |
| url | URL. Aceita string e rejeita URLs perigosas. |
| image_picker | Seletor de imagem. Aceita string (URL ou caminho) e rejeita URLs perigosas. |
| color | Cor. Aceita string em formato hexadecimal (#RGB, #RRGGBB, #RRGGBBAA) ou rgba. |
| select | Seleção única. O valor deve ser uma das opções definidas na lista options. |
| options | Alias de select. Comportamento idêntico — valida contra a lista de opções permitidas. |
| checkbox | Caixa de seleção. Aceita apenas valores booleanos (true ou false). |
| boolean | Alias de checkbox. Comportamento idêntico. |
hotsite_products | ID de hotsite. Aceita apenas inteiro positivo. O Storefront busca automaticamente os produtos desse hotsite e os injeta em block_data.<name> como uma lista de produtos. Máximo de 50 produtos retornados. |
product_list | Lista de IDs de produtos. Aceita array não vazio de inteiros positivos. Os produtos são buscados e injetados em block_data.<name> respeitando a ordem declarada. IDs inválidos são ignorados. Máximo de 50 IDs. |
range | valor numérico com mínimo/máximo. |
Exemplo completo com vários tipos
{
"name": "Hero promocional",
"type": "promo_hero",
"settings": [
{
"label": "Título",
"name": "title",
"type": "text",
"required": true
},
{
"label": "Produtos por linha",
"name": "items_visible",
"type": "number",
"required": false
},
{
"label": "Link do botão",
"name": "button_url",
"type": "url",
"required": false
},
{
"label": "Imagem principal",
"name": "background_image",
"type": "image_picker",
"required": true
},
{
"label": "Cor do texto",
"name": "text_color",
"type": "color",
"required": false
},
{
"label": "Tema visual",
"name": "theme",
"type": "select",
"required": false,
"options": [
{ "label": "Claro", "value": "light" },
{ "label": "Escuro", "value": "dark" }
]
},
{
"label": "Exibir selo",
"name": "show_badge",
"type": "checkbox",
"required": false
}
]
}Exemplos isolados
- Campo select:
{
"label": "Tamanho do título",
"name": "title_size",
"type": "select",
"required": false,
"options": [
{ "label": "Pequeno", "value": "sm" },
{ "label": "Médio", "value": "md" },
{ "label": "Grande", "value": "lg" },
{ "label": "Extra grande", "value": "xl" }
]
}- Campo color:
{
"label": "Cor do texto",
"name": "text_color",
"type": "color",
"required": false
}- Campo image_picker:
{
"label": "Imagem",
"name": "image",
"type": "image_picker",
"required": true
}Como os dados chegam no HTML do bloco
No arquivo Blocks/<type>.html, os valores das configurações do bloco ficam disponíveis em block_data.
Exemplo:
{{~
title = block_data.title
if title | string.empty
title = "Título padrão"
end
~}}
<section>
<h2>{{ title }}</h2>
</section>
Isso significa que o name de cada item em settings deve ser pensado como uma chave de dados reutilizável tanto pelo CMS quanto pelo template.
Blocos com variação por audiência
Um bloco pode oferecer ao lojista versões de conteúdo diferentes por audiência do cliente logado. É um recurso opcional da loja (add-on contratado por aditivo) e opt-in por bloco.
Não há restrição de tipo de bloco. Banner, carrossel de banners, vitrine de produtos, faixa de texto, bloco de imagem, bloco autoral da agência — qualquer bloco do tema pode declarar a flag. E, uma vez declarada, qualquer campo do bloco pode variar: texto, número,
url,image_picker,color,select,checkbox,range,product_listehotsite_products.
HabilitandoDeclare
varyByAudiencecomotrueno nível do bloco, irmão dename,typeesettings:{ "name": "Vitrine de produtos", "type": "product_carousel", options: { resolveAudienceSegments: true } "settings": [ { "label": "Título", "name": "title", "type": "text" }, { "label": "Produtos", "name": "products", "type": "product_list", "required": true } ] }Regras:
- Não existe tipo de campo de audiência. Não declare nada em
settingspara isso — a flag no bloco é suficiente para o editor desenhar o seletor.- Não existe flag por campo. Marcado o bloco, qualquer setting dele pode variar.
- Bloco sem a flag é rejeitado se um salvamento tentar enviar variações para ele (HTTP 400).
- O teto é de 2 audiências distintas por bloco, validado no salvamento.
O que muda no.htmldo blocoNada. O bloco continua recebendo apenas
block_data, e o que chega ali já é o conteúdo resolvido para o cliente: a versão padrão com a variação da audiência aplicada por cima, quando houve match. O contêiner de variações nunca é entregue ao template.{{~ titulo = block_data.title if titulo | string.empty titulo = "Destaques" end ~}} <section class="vitrine"> <h2>{{ titulo }}</h2> {{ spot_carousel products: block_data.products }} </section>
Herança: a variação declara só o que mudaO editor apresenta todos os campos do bloco em cada audiência, pré-preenchidos com o valor da versão padrão — mas a plataforma guarda apenas as diferenças. Campo igual à base, ou vazio, é herança e não vira override (
falsee0não contam como vazio).Consequência para quem desenha o bloco: a versão padrão precisa fazer sentido sozinha e estar sempre completa. Ela é o que a maior parte do tráfego vê, e é dela que as audiências herdam tudo o que não sobrescreverem. Um campo
requiredno schema é exigido na versão padrão, não nas variações.
PrecedênciaUm cliente pode pertencer a várias audiências. Vence a primeira configurada pelo lojista naquele bloco. Variações nunca são mescladas entre si, e a ordem em que o Wake Experience devolve as audiências do cliente é irrelevante.
Boas práticas
- Não escreva condicional de audiência no Scriban. O bloco não sabe qual audiência venceu, e não deve saber. Diferença de conteúdo é decisão do lojista no Design Studio.
- Cuidado com o tamanho. O conteúdo do layout inteiro tem teto de 56.375 caracteres. Um bloco com muitos campos, multiplicado por audiências e por número de blocos na página, consome esse orçamento rápido. Prefira campos enxutos.
- Habilite onde houver intenção de segmentar. Tecnicamente não há limite de quantos blocos do tema podem declarar a flag. Na prática, marcar blocos que o lojista nunca vai segmentar só polui o painel — combine com ele quais blocos entram.
Comportamento completo (identificação do cliente, cookie, cache, preview e limites) em Design Studio — Conteúdos por audiência.
Blocos em templates que atendem várias URLs
Um mesmo template pode atender várias URLs (ver urlMatch em
pages.json), e cada uma dessas
URLs pode ter um layout exclusivo configurado pelo lojista no Design Studio.
Isso não muda nada na criação do bloco: o mesmo par
Blocks/<type>.html + Blocks/<type>.schema.json atende tanto o layout do
template quanto os layouts exclusivos por URL. Não existe schema, campo ou flag
específica para layout exclusivo.
O que muda é a recomendação de como escrever o bloco:
- Não presuma uma URL fixa dentro do bloco. Se o bloco precisa de um link,
um título ou uma imagem diferente por página, isso deve ser um campo em
settings, editável pelo lojista — não uma condicional no Scriban baseada
na URL corrente. - Não use o bloco para diferenciar páginas. O caminho suportado para "esta
URL precisa de um banner diferente" é o layout exclusivo por URL no Design
Studio, não uma ramificação dentro do HTML do bloco. - O bloco continua recebendo apenas
block_data. O conteúdo entregue em
block_dataé o do layout que venceu a resolução para aquela URL — exclusivo
se houver, do template caso contrário. O bloco não precisa (e não consegue)
saber qual dos dois foi usado.
Resumo
Para disponibilizar um bloco no CMS desta primeira versão, a agência deve seguir este fluxo:
- Criar
Blocks/<type>.html. - Criar
Blocks/<type>.schema.json. - O
content_for_pagepode ser declarado em dois níveis:- No item de
customs: vale para as URLs atendidas por aquele custom. - No nível da página (ex.: no objeto
hotsite): vale para as URLs atendidas pelo template base da página; também é usado como fallback quando o custom correspondente não declaracontent_for_pagepróprio.
- No item de
- Garantir que os nomes dos campos em
settings[].namesejam os mesmos usados noblock_datado HTML. - Validar se os tipos escolhidos no
schemaestão entre os suportados pela plataforma. - Se o bloco deve oferecer variação por audiência, declarar
"varyByAudience": trueno schema — e garantir que a versão padrão do bloco esteja completa, já que é dela que as audiências herdam.
Updated 6 days ago

