Implementa dados estruturados JSON-LD de Store/LocalBusiness e Product/Offer, com AggregateRating real e sinalização de retirada na loja, validados no Rich Results Test.
Por que isto importa
Dados estruturados são a forma mais direta de dizer ao Google o que cada página significa, sem deixar a interpretação por conta do algoritmo. Para uma loja virtual com retirada presencial, dois tipos de schema fazem o trabalho pesado: LocalBusiness, que descreve a unidade física, e Product com Offer, que descreve cada item à venda. Bem implementados, eles habilitam rich results como estrelas de avaliação, preço, disponibilidade e informações da loja diretamente no SERP, aumentando visibilidade e CTR.
O diferencial competitivo aparece na sinalização de retirada. Marcar que o produto pode ser retirado na loja informa ao Google uma modalidade de entrega que marketplaces puramente nacionais não oferecem na região. Isso conecta o catálogo virtual ao ponto físico de Maringá no nível dos dados, reforçando a relevância local de forma estruturada e auditável.
Store/LocalBusiness alimentado pelo model Unidade
O schema da unidade descreve quem é a loja no mundo físico. Ele consome o model Unidade para preencher endereço, coordenadas geográficas, horários e perfis sociais. O tipo mais adequado costuma ser Store (subtipo de LocalBusiness), com address em PostalAddress, geo em GeoCoordinates, openingHoursSpecification e sameAs apontando para redes sociais e perfis oficiais.
<script type="application/ld+json">
{!! json_encode([
'@context' => 'https://schema.org',
'@type' => 'Store',
'name' => $unidade->nome,
'image' => $unidade->foto_url,
'url' => url('/'),
'telephone' => $unidade->telefone,
'priceRange' => 'R$$',
'address' => [
'@type' => 'PostalAddress',
'streetAddress' => $unidade->logradouro,
'addressLocality' => $unidade->cidade,
'addressRegion' => $unidade->uf,
'postalCode' => $unidade->cep,
'addressCountry' => 'BR',
],
'geo' => [
'@type' => 'GeoCoordinates',
'latitude' => $unidade->latitude,
'longitude' => $unidade->longitude,
],
'openingHoursSpecification' => [
'@type' => 'OpeningHoursSpecification',
'dayOfWeek' => ['Monday','Tuesday','Wednesday','Thursday','Friday'],
'opens' => '09:00',
'closes' => '18:00',
],
'sameAs' => $unidade->redes_sociais,
], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) !!}
</script>
Esse bloco entra no layout da home e das páginas institucionais, onde a identidade da loja é o assunto central. Não deve se repetir em toda página de produto, para não poluir a marcação.
Product e Offer com AggregateRating real
Na página de produto, o schema Product descreve o item e o Offer descreve as condições de venda. O ponto crítico é o AggregateRating: ele só pode existir se houver avaliações reais. Aqui o model Avaliacao é a fonte de verdade, fornecendo a nota média e a contagem de avaliações. Inventar números viola as diretrizes do Google e pode gerar penalidade manual.
@php
$agg = $produto->avaliacoes()->selectRaw('AVG(nota) as media, COUNT(*) as total')->first();
@endphp
<script type="application/ld+json">
{!! json_encode(array_filter([
'@context' => 'https://schema.org',
'@type' => 'Product',
'name' => $produto->nome,
'image' => $produto->imagens->pluck('url')->all(),
'description' => $produto->descricao_curta,
'sku' => $produto->sku,
'brand' => ['@type' => 'Brand', 'name' => $produto->marca],
'aggregateRating' => $agg && $agg->total > 0 ? [
'@type' => 'AggregateRating',
'ratingValue' => round($agg->media, 1),
'reviewCount' => $agg->total,
] : null,
'offers' => [
'@type' => 'Offer',
'priceCurrency' => 'BRL',
'price' => number_format($produto->preco, 2, '.', ''),
'availability' => $produto->em_estoque
? 'https://schema.org/InStock'
: 'https://schema.org/OutOfStock',
'url' => $produto->url,
],
]), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) !!}
</script>
O uso de array_filter remove o AggregateRating quando não há avaliações, evitando emitir um bloco vazio ou inválido. A disponibilidade reflete o estoque real, e o preço usa o formato com ponto decimal exigido pelo schema.
Sinalização de retirada na loja
A modalidade de retirada é o que une o catálogo virtual ao ponto físico. No Offer, o availableDeliveryMethod com o valor OnSitePickup, combinado a um hasDeliveryMethod ou a uma DeliveryMethod específica, comunica essa opção. Quando aplicável, vale ainda descrever o local de retirada referenciando a unidade.
"offers": {
"@type": "Offer",
"availability": "https://schema.org/InStoreOnly",
"availableDeliveryMethod": "https://schema.org/OnSitePickup",
"areaServed": { "@type": "City", "name": "Maringá" }
}
Essa sinalização precisa ser verdadeira: só marque retirada nos produtos efetivamente disponíveis na unidade. Marcar a modalidade em itens que só têm envio nacional cria inconsistência entre o dado estruturado e a experiência real, algo que o Google penaliza.
Injeção no Blade e validação
A regra de ouro da injeção é página certa, schema certo. LocalBusiness na home e institucionais, Product nas páginas de produto, e nada de duplicar o mesmo tipo na mesma página. Centralizar os blocos em components Blade dedicados (um para LocalBusiness, outro para Product) mantém o código limpo e o JSON-LD consistente.
Depois de implementar, toda página-tipo passa por validação dupla. O Google Rich Results Test confirma a elegibilidade aos rich results e aponta campos faltantes. O Schema Markup Validator faz a checagem sintática completa do vocabulário schema.org. Por fim, o relatório de aprimoramentos do Search Console monitora erros em produção ao longo do tempo, pegando regressões que passem despercebidas no deploy.
Critérios de qualidade
- O JSON-LD de LocalBusiness contém address completo, geo com coordenadas, openingHours e sameAs, todos vindos do model Unidade.
- O AggregateRating só é emitido quando existem avaliações reais no model Avaliacao, com nota e contagem corretas.
- O Offer reflete preço, moeda BRL e disponibilidade reais, e a retirada só é sinalizada nos produtos de fato disponíveis na unidade.
- Cada tipo de schema aparece apenas na página apropriada, sem duplicação de marcação.
- Todas as páginas-tipo passam sem erros no Rich Results Test e no Schema Markup Validator.
- O relatório de aprimoramentos do Search Console não acusa erros nos itens estruturados após a publicação.