Magento – Rich Snippet para produtos

É possível adicionar informações detalhadas sobre os produtos do e-commerce diretamente nos resultados dos buscadores - Yahoo!, Google e Microsoft- utilizando os microformatos padrões do Schema.org. O post é longo, mas recomendado.

Schema.org

Schema.org é uma colaboração entre Yahoo!, Google e Microsoft para orientações de uso de texto não-visível para a estruturação de dados. Essa estrutura de dados ajuda os mecanismos de busca a compreender o que consta na página e, assim, fornecer melhores resultados. Mais informações.

Resultado Desejado

rich-snippet

Implementação

A implementação é feita nos arquivos de tema do Magento. Irei utilizar a versão CE 1.7.0.2 como base. Provavelmente irá funcionar nas versões seguintes também, pois não estaremos escrevendo um novo código, estamos apenas adicionando a estrutura de dados para o tema. Iremos trabalhar com estrutura de produtos, de ofertas e de avaliações do Schema.org. Para o Breadcrumbs utilizarei o modelo do data-vocabulary.

Copiando os arquivos do tema base

Irei utilizar o tema padrão do Magento como base para um novo tema, sem substituir arquivos de temas existentes. Caso você já tenha um tema instalado e em uso, copie os arquivos base para o seu tema, se já não houver, e edite.

Estruturas

Como citado anteriormente, iremos trabalhar com quatro estrutura de dados: produtos, ofertas, avaliações e breadcrumbs.

Estrutura do Produto

O arquivo base para alteração das informações básicas do produto é:

1
app/design/frontend/base/default/template/catalog/product/view.phtml

deve ser copiado/editado para:

1
app/design/frontend/_PACOTE_/_TEMA_/template/catalog/product/view.phtml

1. Definir o escopo

Inserir os atributos itemscope e itemtype na div.product-view como código exemplo abaixo.

1
<div class="product-view" itemscope itemtype="http://schema.org/Product">

2. Adicionar o nome

Inserir o atributo itemprop para definir a qual propriedade o valor se refere. Nesse caso, ao nome do produto.

1
<h1 itemprop="name"><?php echo $_helper->productAttribute($_product, $_product->getName(), 'name') ?></h1>

3. Adicionar a descrição

Inserir o atributo itemprop para definir a descrição do produto.

1
2
3
4
5
6
<?php if ($_product->getShortDescription()):?>
    <div class="short-description">
        <h2><?php echo $this->__('Quick Overview') ?></h2>
        <div class="std" itemprop="description"><?php echo $_helper->productAttribute($_product, nl2br($_product->getShortDescription()), 'short_description') ?></div>
    </div>
<?php endif;?>

4. Adicionar a imagem

O arquivo base para alteração das informações da imagem é:

1
app/design/frontend/base/default/template/catalog/product/view/media.phtml

deve ser copiado/editado para:

1
app/design/frontend/_PACOTE_/_TEMA_/template/catalog/product/view/media.phtml

Inserir o atributo itemprop para definir a imagem principal do produto. Deve ser inserido em dois momentos, conforme os códigos abaixo.

1
2
3
4
5
6
<p class="product-image product-image-zoom">
    <?php
        $_img = '<img id="image" itemprop="image" src="'.$this->helper('catalog/image')->init($_product, 'image').'" alt="'.$this->htmlEscape($this->getImageLabel()).'" title="'.$this->htmlEscape($this->getImageLabel()).'" />';
        echo $_helper->productAttribute($_product, $_img, 'image');
    ?>
</p>
1
2
3
4
5
6
<p class="product-image">
    <?php
        $_img = '<img itemprop="image" src="'.$this->helper('catalog/image')->init($_product, 'image')->resize(265).'" alt="'.$this->htmlEscape($this->getImageLabel()).'" title="'.$this->htmlEscape($this->getImageLabel()).'" />';
        echo $_helper->productAttribute($_product, $_img, 'image');
    ?>
</p>

Estrutura de Oferta e Estoque

Conforme a documetação do schema.org/Offer, o escopo da oferta incluí preço e estoque. No Magento, preço e estoque são definidos em arquivos diferentes porém, inicializados pelo mesmo arquivo. O que facilita de certa maneira. A alteração das marcações para preços é um pouco mais trabalhosa. Veremos a seguir.

1. Definir o escopo

Como o estoque e os preços são tratados em arquivos diferente mas inicializados pelo mesmo, a melhor forma de definir o escopo é no arquivo de inicialização. Nesse caso, adicionamos o conteúdo do estoque e preço em uma div que define o escopo. As alterações estão destacadas nos códigos abaixo.

  • Foi inserida uma meta tag responsável por definir a moeda, sendo possível definir outras propriedades também como: Condições do Item, Vendedor, etc.

Arquivo base:

1
app/design/frontend/base/default/template/catalog/product/view.phtml

deve ser copiado/editado para:

Arquivo original

1
app/design/frontend/_PACOTE_/_TEMA_/template/catalog/product/view.phtml

trong>Arquivo original</strong>

1
2
<?php echo $this->getChildHtml('product_type_data') ?>
<?php echo $this->getTierPriceHtml() ?>

Arquivo alterado

1
2
3
4
5
<div itemprop="offers" itemscope itemtype="http://schema.org/Offer">
    <meta itemprop="priceCurrency" content="<?php echo $currency_code = Mage::app()->getStore()->getCurrentCurrencyCode(); ?>"/>
    <?php echo $this->getChildHtml('product_type_data') ?>
    <?php echo $this->getTierPriceHtml() ?>
</div>

2. Definir a disponibilidade

Nesse exemplo, estou utilizando da seguinte forma: Em estoque/fora do estoque. Mas é possível definir outras disponibilidades do produto, como: Disponibilidade Limitada, Disponível somente only e outros. Será necessário alterar mais de um arquivo referente a disponibilidade, já que o Magento trata diferente conforme o tipo de produto. Nesse caso, irei alterar os produtos configuráveis, agrupados e simples. Copie os arquivos listados abaixo para as respectivas pastas do seu tema.

  • app/design/frontend/base/default/template/catalog/product/view/type/default.phtml
  • app/design/frontend/base/default/template/catalog/product/view/type/grouped.phtml
  • app/design/frontend/base/default/template/bundle/catalog/product/view/type/bundle.phtml

Vou apresentar um exemplo somente no arquivo default.phtml para não ficar repetitivo. A ideia é simples: basta inserir a link com o atributo itemprop referindo-se a disponibilidade (availability) e a referência ao padrão do Schema.org - InStock e OutOfStock, nesse caso. As linhas alteradas estão destacadas abaixo.

Arquivo default.phtml
1
2
3
4
5
<?php if ($_product->isAvailable()): ?>
    <p class="availability in-stock"><link itemprop="availability" href="http://schema.org/InStock" /><?php echo $this->__('Availability:') ?> <span><?php echo $this->__('In stock') ?></span></p>
<?php else: ?>
    <p class="availability out-of-stock"><link itemprop="availability" href="http://schema.org/OutOfStock" /><?php echo $this->__('Availability:') ?> <span><?php echo $this->__('Out of stock') ?></span></p>
<?php endif; ?>

3. Definir o preço

Os arquivos do template de preço possuem diversos lugares para inserir o atributo do Schema.org para definir que se refere ao preço (itemprop=”price”). Mesmo que no Brasil não utilizamos a exibição dos impostos no valor do produto, vale lembrar que é recomendado inserir a propriedade somente no valor sem imposto (excluding tax). Na página do produto, o itemprop deve aparecer somente uma vez, já que os buscadores não irão exibir caso tenha mais de um - não irão decidir qual preço deve ser exibido. Assim, é preciso tomar cuidado para não inserir a propriedade no preço clonado (em produtos configuráveis) e nem no preço de venda final (upsell). Nos arquivos do tema, podemos identificar os dois últimos pelo suffixo utilizado: _clone e -upsell, respectivamente. Dessa forma, podemos verificar se o preço a ser exibido é o correto. Abaixo mostrarei como é possível solucionar isso. As alterações devem ser feitas nos dois arquivos listados abaixo, já que o Magento usa um diferente para os produtos configuráveis. Copie os arquivos listados abaixo para as respectivas pastas do seu tema.

  • app/design/frontend/base/default/template/catalog/product/price.phtml
  • app/design/frontend/base/default/template/bundle/catalog/product/price.phtml
Validar pelo sufixo

No início dos dois arquivos, devemos inserir o código abaixo. O $idSuffixDeny é o array que irá guardar os sufixos que não devem exibir o itemprop referente ao preço.

1
2
3
4
 
<?php
    $idSuffixDeny = array( '-upsell', '_clone' );
?>

O código abaixo verifica se o preço está nos sufixo não autorizados. Caso não esteja, imprime a propriedade para referenciar o preço.

1
2
 
<?php echo (!in_array($this->getIdSuffix(), $idSuffixArray)) ? ' itemprop="price" ' : null; ?>

Salvei os arquivos e publiquei um Gist, para ficar mais fácil:

Assim que tiver mais tempo, incluirei as versões 1.8 e 1.9.

Estrutura das Avaliações/Rating

  • Essa não é a melhor aplicação para a estrutura de dados como sugere o Google, pois estaremos utilizando as informações “escondidas”. Ou seja, estamos passando os valores em uma meta tag que não é visível para o usuário. Porém, essa é a maneira mais prática de aplicar.

1. Definir o escopo das avaliações

No arquivo:

1
app/design/frontend/__PACOTE__/__TEMA__/template/catalog/product/view.phtml

insira um sufixo na renderização das avaliações. Dessa forma, iremos utilizar outro arquivo para exibir as avaliações.

Substitua:

1
<?php echo $this->getReviewsSummaryHtml($_product, false, true)?>

Por:

1
2
<?php echo $this->getReviewsSummaryHtml($_product, 'aggregate', true)?>
 

Agora, faça uma cópia do arquivo:

1
app/design/frontend/__PACOTE__/__TEMA__/template/review/helper/summary.phtml

Com o sufixo informado anteriormente:

1
app/design/frontend/__PACOTE__/__TEMA__/template/review/helper/summary_aggregate.phtml

No novo arquivo, definiremos o escopo e passaremos as informações sobre as avaliações.

1
app/design/frontend/__PACOTE__/__TEMA__/template/catalog/product/view.phtml

No novo arquivo, definiremos o escopo e passaremos as informações sobre as avaliações.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php if ($this->getReviewsCount()): ?>
    <div class="ratings" itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">
        <?php if ($this->getRatingSummary()):?>
            <meta itemprop="ratingValue" content="<?php echo $this->getRatingSummary(); ?>">
            <meta itemprop="reviewCount" content="<?php echo $this->getReviewsCount(); ?>">
            <meta itemprop="bestRating" content="100">
            <meta itemprop="worstRating" content="0">
            <div class="rating-box">
                <div class="rating" style="width:<?php echo $this->getRatingSummary() ?>%"></div>
            </div>
        <?php endif;?>
        <p class="rating-links">
            <a href="<?php echo $this->getReviewsUrl() ?>"><?php echo $this->__('%d Review(s)', $this->getReviewsCount()) ?></a>
            <span class="separator">|</span>
            <a href="<?php echo $this->getReviewsUrl() ?>#review-form"><?php echo $this->__('Add Your Review') ?></a>
        </p>
    </div>
<?php elseif ($this->getDisplayIfEmpty()): ?>
    <p class="no-rating"><a href="<?php echo $this->getReviewsUrl() ?>#review-form"><?php echo $this->__('Be the first to review this product') ?></a></p>
<?php endif; ?>

Repare que as meta tags foram incluídas nas linhas 30,31,32 e 33.

Estrutura do Breadcrumbs

A estrutura do breadcrumbs sugerida pela http://www.data-vocabulary.org/ é a estrutura recomendada para ser utilizada, pois permite a inclusão de links para as categorias diretamente no resultado da busca, diferente do Schema.org que só aceita texto.

1. Definir o escopo do breadcrumbs

Para definirmos o escopo, primeiramente, devemos copiar o seguinte arquivo para a pasta respectiva ao seu tema:

1
app/design/frontend/__PACOTE__/__TEMA__/template/page/html/breadcrumbs.phtml

A seguir, informamos o itemscope e a sua referência.

1
<li class="<?php echo $_crumbName ?>" itemscope itemtype="http://data-vocabulary.org/Breadcrumb">

2. Definir o título e a URL

Repare que o título do breadcrumbs é colocado dentro de um elemento span.

1
2
 
<a href="<?php echo $_crumbInfo['link'] ?>" title="<?php echo $this->htmlEscape($_crumbInfo['title']) ?>" itemprop="url"><span itemprop="title"><?php echo $this->htmlEscape($_crumbInfo['label']) ?></span></a> 

Conclusão

Existem diversos módulos para fazer esse trabalho, porém, como visto acima, é simples ser feito sem precisar de um módulo pra isso. É conhecido o custo de performance por carregar muitos módulos. Se ficou interessado no assunto provavelmente vai querer estruturar ainda mais as informações da sua loja ou do seu cliente. Para mais informações sobre a estrutura de dados para produtos, acesse esse guia do Google ou então veja todas as estruturas sugeridas pelo Schema.org. Para testar seu trabalho, utilize a ferramenta de testes de snippets do Google.</div>