Data estructurada JSON-LD

En nuestros themes, cambiamos la forma de proveer el contenido de cada tienda a Google. Esto se relaciona principalmente con la información de los productos como nombre, precio, url, stock, etc. Ahora, utilizamos el formato JSON-LD, lo que nos permite tener un código más limpio y la información más organizada.

Antes usábamos el formato Metadata, lo que hicimos fue sacar esos parámetros que estaban insertados en el código del theme y nos lo llevamos a dos archivos separados para quede más prolijo el código.

A continuación te explicamos como hacer este cambio de formato.

1. Limpiar el código relacionado a Metadata

Son varios parámetros así que los resaltamos para que te sea más fácil identificarlos y borrarlos en cada archivo. Los ejemplos de código están basados en nuestro theme Base.

- En product.tpl vas a tener una estructura similar a:

<div id="single-product" class="js-has-new-shipping js-product-detail js-product-container js-shipping-calculator-container" data-variants="{{product.variants_object | json_encode }}" itemscope itemtype="http://schema.org/Product">
    <meta itemprop="image" content="{{ 'http:' ~ product.featured_image | product_image_url('large') }}" />
    <meta itemprop="url" content="{{ product.social_url }}" />
    {% if page_description %}
        <meta itemprop="description" content="{{ page_description }}" />
    {% endif %}
    {% if product.sku %}
        <meta itemprop="sku" content="{{ product.sku }}" />
    {% endif %}
    {% if product.weight %}
        <div itemprop="weight" itemscope itemtype="http://schema.org/QuantitativeValue" style="display:none;">
            <meta itemprop="unitCode" content="{{ product.weight_unit | iso_to_uncefact}}" />
            <meta itemprop="value" content="{{ product.weight}}" />
        </div>
    {% endif %}

    <div class="container">
        <div class="row section-single-product">
            <div class="col-12 col-md-7 px-0 px-md-3">
                {% include 'snipplets/product/product-image.tpl' %}
            </div>
            <div class="col">
                {% include 'snipplets/product/product-form.tpl' %}
            </div>
        </div>
        {% if settings.show_product_fb_comment_box %}
            <div class="fb-comments section-fb-comments" data-href="{{ product.social_url }}" data-num-posts="5" data-width="100%"></div>
        {% endif %}
        <div id="reviewsapp"></div>
    </div>  
</div>

- En el archivo page-header.tpl de la carpeta snipplets, dependiendo cuan actualizado esté tu código, puede que este cambio tengas que aplicarlo en el product.tpl:

<h1{% if template == 'product' %} itemprop="name"{% endif %}>{% block page_header_text %}{% endblock %}</h1>

- En el archivo product-form.tpl de la carpeta snipplets/product, dependiendo cuan actualizado esté tu código, puede que este cambio tengas que aplicarlo en el product.tpl:

<div class="price-container text-center text-md-left" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
    <span class="d-inline-block">
       <h4 id="compare_price_display" class="js-compare-price-display price-compare {% if product_can_show_installments or (product.promotional_offer and not product.promotional_offer.script.is_percentage_off) %}mb-2{% endif %}" {% if not product.compare_at_price or not product.display_price %}style="display:none;"{% else %} style="display:block;"{% endif %}>{% if product.compare_at_price and product.display_price %}{{ product.compare_at_price | money }}{% endif %}</h4>
    </span>
    <span class="d-inline-block">
        <h4 class="js-price-display {% if product_can_show_installments or (product.promotional_offer and not product.promotional_offer.script.is_percentage_off) %}mb-2{% endif %}" id="price_display" itemprop="price"{% if product.display_price %} content="{{ product.price / 100 }}"{% endif %} {% if not product.display_price %}style="display:none;"{% endif %}>{% if product.display_price %}{{ product.price | money }}{% endif %}</h4>
    </span>
    <meta itemprop="priceCurrency" content="{{ product.currency }}" />
    {% if product.stock_control %}
        <meta itemprop="inventoryLevel" content="{{ product.stock }}" />
        {% set schema_org_availability = "http://schema.org/#{ product.stock ? 'InStock' : 'OutOfStock' }" %}
        <meta itemprop="availability" href="{{ schema_org_availability }}" content="{{ schema_org_availability }}" />
    {% endif %}
</div>

- En el archivo item.tpl de la carpeta snipplets/grid, dependiendo cuan actualizado esté tu código, puede que este cambio tengas que aplicarlo en el snipplet single_product.tpl:

<div class="item-description">
    <a href="{{ product_url_with_selected_variant }}" title="{{ product.name }}" class="item-link">
        <div itemprop="name" class="item-name mb-1">{{ product.name }}</div>
        <meta itemprop="url" content="{{ product.url }}" />
        {% if product.display_price %}
            <div class="item-price-container mb-1" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                <meta itemprop="priceCurrency" content="{{ product.currency }}" />
                {% if product.compare_at_price %}
                    <span class="price-compare">
                        {{ product.compare_at_price | money }}
                    </span>
                {% endif %}
                <span class="item-price" itemprop="price" content="{{ product.price / 100 }}">
                    {{ product.price | money }}
                </span>
            </div>
        {% endif %}
    </a>
</div>

- En breadcrumbs.tpl:

<div class="breadcrumbs {{ breadcrumbs_custom_class }}" itemprop="breadcrumb" itemscope itemtype="http://www.schema.org/WebPage" itemid="body">

- En layout.tpl y password.tpl:

<body class="{% if customer %}customer-logged-in{% endif %} template-{{ template | replace('.', '-') }} {% if settings.head_fix %}js-head-offset head-offset{% endif %}" itemscope itemtype="http://schema.org/WebPage" itemid="body">

2. Crear la carpeta structured_data dentro de snipplets con dos archivos.

webpage-structured-data.tpl con el siguiente código:

<script type="application/ld+json">
{
    "@context": "https://schema.org/",
    "@type": "WebPage",
    "name": "{{ page_title | replace('"', '\"') }}",
    {% if page_description %}
        "description": "{{ page_description | replace('"', '\"') }}",
    {% endif %}
    "breadcrumb": {
        "@type": "BreadcrumbList",
        "itemListElement": [
        {
            "@type": "ListItem",
            "position": 1,
            "name": "{{ 'Inicio' | translate }}",
            "item": "{{ store.url }}"
        }{% if template != 'home' %},{% endif %}
        {% if template == 'page' %}
            {
                "@type": "ListItem",
                "position": 2,
                "name": "{{ page.name | replace('"', '\"') }}",
                "item": "{{ page.url }}"
            }
        {% elseif template == 'cart' %}
            {
                "@type": "ListItem",
                "position": 2,
                "name": "{{ 'Carrito de compras' | translate }}",
                "item": "{{ store.url }}{{ store.cart_url }}"
            }
        {% elseif template == 'search' %}
            {
                "@type": "ListItem",
                "position": 2,
                "name": "{{ 'Resultados de búsqueda' | translate }}",
                "item": "{{ store.url }}{{ store.search_url }}"
            }
        {% elseif template == 'account.order' %}
            {
                "@type": "ListItem",
                "position": 2,
                "name": "{{ 'Orden {1}' | translate(order.number) }}",
                "item": "{{ store.url }}{{ store.customer_order_url(order) }}"
            }
        {% else %}
            {% for crumb in breadcrumbs %}
                {
                    "@type": "ListItem",
                    "position": {{ loop.index + 1 }},
                    "name": "{{ crumb.name | replace('"', '\"') }}",
                    "item": "{{ store.url }}{{ crumb.url }}"
                }{% if not crumb.last %},{% endif %}
            {% endfor %}
        {% endif %}
        ]
    }{% if template == 'product' %},
    "mainEntity": {
        "@type": "Product",
        "@id": "{{ product.canonical_url }}",
        "name": "{{ product.name | replace('"', '\"') }}",
        "image": "{{ 'https:' ~ product.featured_image | product_image_url('large') }}",
        "description": "{{ page_description | replace('"', '\"') }}",
        {% if product.sku %}
            "sku": "{{ product.sku }}",
        {% endif %}
        {% if product.brand %}
            "brand": {
                "@type": "Thing",
                "name": "{{ product.brand | replace('"', '\"') }}"
            },
        {% endif %}
        {% if product.weight %}
            "weight": {
                "@type": "QuantitativeValue",
                "unitCode": "{{ product.weight_unit | iso_to_uncefact }}",
                "value": "{{ product.weight }}"
            },
        {% endif %}
        "offers": {
            "@type": "Offer",
            "url": "{{ product.url }}",
            "priceCurrency": "{{ product.currency }}",
            "price": "{{ product.price / 100 }}",
            {% if product.stock_control %}
                "availability": "http://schema.org/{{ product.stock ? 'InStock' : 'OutOfStock' }}",
                "inventoryLevel": {
                    "@type": "QuantitativeValue",
                    "value": "{{ product.stock }}"
                },
            {% endif %}
            "seller": {
                "@type": "Organization",
                "name": "{{ store.name | replace('"', '\"') }}"
            }
        }
    }
    {% endif %}
}
</script>

E item-structured-data.tpl:

<script type="application/ld+json">
{
    "@context": "https://schema.org/",
    "@type": "Product",
    "mainEntityOfPage": {
        "@type": "WebPage",
        "@id": "{{ product.canonical_url }}"
    },
    "name": "{{ product.name | replace('"', '\"') }}",
    "image": "{{ 'https:' ~ product.featured_image | product_image_url('large') }}",
    "description": "{{ product.seo_description | replace('"', '\"') }}",
    {% if product.sku %}
        "sku": "{{ product.sku }}",
    {% endif %}
    {% if product.brand %}
        "brand": {
            "@type": "Thing",
            "name": "{{ product.brand | replace('"', '\"') }}"
        },
    {% endif %}
    {% if product.weight %}
        "weight": {
            "@type": "QuantitativeValue",
            "unitCode": "{{ product.weight_unit | iso_to_uncefact }}",
            "value": "{{ product.weight }}"
        },
    {% endif %}
    "offers": {
        "@type": "Offer",
        "url": "{{ product.url }}",
        "priceCurrency": "{{ product.currency }}",
        "price": "{{ product.price / 100 }}",
        {% if product.stock_control %}
            "availability": "http://schema.org/{{ product.stock ? 'InStock' : 'OutOfStock' }}",
            "inventoryLevel": {
                "@type": "QuantitativeValue",
                "value": "{{ product.stock }}"
            },
        {% endif %}
        "seller": {
            "@type": "Organization",
            "name": "{{ store.name | replace('"', '\"') }}"
        }
    }
}
</script>

3. Agregamos el llamado a los snipplets creados

- En layout.tpl y password.tpl lo agregamos antes del cierre de la etiqueta <head>:

    {# Structured data to provide information for Google about the page content #}
    {% include 'snipplets/structured_data/webpage-structured-data.tpl' %}
</head>

- En el archivo item.tpl de la carpeta snipplets/grid, dependiendo cuan actualizado esté tu código, puede que este cambio tengas que aplicarlo en el snipplet single_product.tpl antes del cierre del último <div>

    {# Structured data to provide information for Google about the product content #}
    {% include 'snipplets/structured_data/item-structured-data.tpl' %}
</div>

4. Probamos los cambios

Ingresamos a https://search.google.com/structured-data/testing-tool y agregamos la url de la tienda en la que aplicamos los cambios.

Deberíamos ver algo así: