Skip to content

Instantly share code, notes, and snippets.

@yoanmarchal
Last active February 21, 2022 22:19
Show Gist options
  • Save yoanmarchal/eeb267a08664987bf86949beafd64fe9 to your computer and use it in GitHub Desktop.
Save yoanmarchal/eeb267a08664987bf86949beafd64fe9 to your computer and use it in GitHub Desktop.
{* Structured Data Json - LD Microdata for Prestashop 1.6.X & 1.7
*
* Add this code in your smarty global.tpl/header.tpl file to show Organization, WebPage, Website and Product Microdata in ld+json format.
* Requires Prestashop 'productcomments' module for review stars ratings.
* by Ruben Divall @rubendivall http://www.rubendivall.com
* Module by @atomiksoft: https://addons.prestashop.com/en/seo-natural-search-engine-optimization/24511-microformats-in-ldjson.html
*}
<script type="application/ld+json">
{
"@context" : "http://schema.org",
"@type" : "Organization",
"name" : "{$shop_name|escape:'html':'UTF-8'}",
"url" : "{$link->getPageLink('index', true)|escape:'html':'UTF-8'}",
"logo" : {
"@type":"ImageObject",
"url":"{$logo_url|escape:'html':'UTF-8'}"
}
}
</script>
<script type="application/ld+json">
{
"@context":"http://schema.org",
"@type":"WebPage",
"isPartOf": {
"@type":"WebSite",
"url": "{$link->getPageLink('index', true)|escape:'html':'UTF-8'}",
"name": "{$shop_name|escape:'html':'UTF-8'}"
},
"name": "{$meta_title|escape:'html':'UTF-8'}",
"url": "{if isset($force_ssl) && $force_ssl}{$base_dir_ssl|escape:'html':'UTF-8'}{trim($smarty.server.REQUEST_URI,'/')|escape:'html':'UTF-8'}{else}{$base_dir|escape:'html':'UTF-8'}{trim($smarty.server.REQUEST_URI,'/')|escape:'html':'UTF-8'}{/if}"
}
</script>
{if $page_name =='index'}
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "WebSite",
"url": "{$link->getPageLink('index', true)|escape:'html':'UTF-8'}",
"image": {
"@type": "ImageObject",
"url": "{$logo_url|escape:'html':'UTF-8'}"
},
"potentialAction": {
"@type": "SearchAction",
"target": "{'--search_term_string--'|str_replace:'{search_term_string}':$link->getPageLink('search',true,null,['search_query'=>'--search_term_string--'])}",
"query-input": "required name=search_term_string"
}
}
</script>
{/if}
{if $page_name == 'product'}
<script type="application/ld+json">
{
"@context": "http://schema.org/",
"@type": "Product",
"name": "{$product->name|escape:'html':'UTF-8'}",
"description": "{$product->description_short|strip_tags|escape:'html':'UTF-8'}",
{if $product->reference}"mpn": "{$product->id|escape:'html':'UTF-8'}",{/if}
{if $product_manufacturer->name}"brand": {
"@type": "Thing",
"name": "{$product_manufacturer->name|escape:'html':'UTF-8'}"
},{/if}
{if isset($nbComments) && $nbComments && $ratings.avg}"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "{$ratings.avg|round:1|escape:'html':'UTF-8'}",
"reviewCount": "{$nbComments|escape:'html':'UTF-8'}"
},{/if}
{if empty($combinations)}
"offers": {
"@type": "Offer",
"priceCurrency": "{$currency->iso_code|escape:'html':'UTF-8'}",
"name": "{$product->name|escape:'html':'UTF-8'}",
"price": "{$product->getPrice(true, $smarty.const.NULL, 2)|round:'2'|escape:'html':'UTF-8'}",
"image": "{$link->getImageLink($product->link_rewrite, $cover.id_image, 'home_default')|escape:'html':'UTF-8'}",
{if $product->ean13}
"gtin13": "{$product->ean13|escape:'html':'UTF-8'}",
{else if $product->upc}
"gtin13": "0{$product->upc|escape:'html':'UTF-8'}",
{/if}
"sku": "{$product->reference}",
{if $product->condition == 'new'}"itemCondition": "http://schema.org/NewCondition",{/if}
{if $product->condition == 'used'}"itemCondition": "http://schema.org/UsedCondition",{/if}
{if $product->condition == 'refurbished'}"itemCondition": "http://schema.org/RefurbishedCondition",{/if}
"availability":{if $product->quantity > 0} "http://schema.org/InStock"{else} "http://schema.org/OutOfStock"{/if},
"seller": {
"@type": "Organization",
"name": "{$shop_name|escape:'html':'UTF-8'}"
}
}
{else}
"offers": [
{foreach key=atomik item=combination from=$combinations}
{
"@type": "Offer",
"name": "{$product->name|escape:'html':'UTF-8'} - {$combination.reference}",
"priceCurrency": "{$currency->iso_code|escape:'html':'UTF-8'}",
"price": "{$combination.finalprice|round:'2'}",
"image": "{if $combination.id_image > 0}{$link->getImageLink($product->link_rewrite, $combination.id_image, 'home_default')|escape:'html':'UTF-8'}{else}{$link->getImageLink($product->link_rewrite, $cover.id_image, 'home_default')|escape:'html':'UTF-8'}{/if}",
{if $combination.ean13}
"gtin13": "{$combination.ean13|escape:'html':'UTF-8'}",
{else if $combination.upc}
"gtin13": "0{$combination.upc|escape:'html':'UTF-8'}",
{/if}
"sku": "{$combination.reference}",
{if $combination.condition == 'new'}"itemCondition": "http://schema.org/NewCondition",{/if}
{if $combination.condition == 'used'}"itemCondition": "http://schema.org/UsedCondition",{/if}
{if $combination.condition == 'refurbished'}"itemCondition": "http://schema.org/RefurbishedCondition",{/if}
"availability": {if $combination.quantity > 0}"http://schema.org/InStock"{else}"http://schema.org/OutOfStock"{/if},
"seller": {
"@type": "Organization",
"name": "{$shop_name|escape:'html':'UTF-8'}"}
} {if !$combination@last},{/if}
{/foreach}
]
{/if}
}
</script>
{/if}
{** End of Structured Data Json - LD Microdata for Prestashop 1.6.X **}
@yoanmarchal
Copy link
Author

thanks, i had update this gist

@Mychela
Copy link

Mychela commented May 26, 2017

This code will work if I will add in Google Tag Manager as a tag?

@hakeryk2
Copy link

hakeryk2 commented Sep 27, 2018

From where did You get $combinations.finalprice? It is not available in $combinations array. Is it some modification to the ProductController.php?

Edit: Ok, I made it with editing protected function assignAttributesGroups in ProductController. I added

$combinations[$row['id_product_attribute']]['finalprice'] = Product::getPriceStatic((int)$this->product->id, true, $row['id_product_attribute'], 6, null, false, false, 1, false, null, null, null, $combination_specific_price);

after this:
$combinations[$row['id_product_attribute']]['price'] = (float)Tools::convertPriceFull($row['price'], null, Context::getContext()->currency, false);

@Marwazeinoo88
Copy link

Does it work for prestashop 1.7.3.0 Multishop mode?

@Marwazeinoo88
Copy link

Une réponse SVP ?

@Aldegunde
Copy link

Hello,

could someone help me checking if this code is working properlly on may page https://www.delica-te-zen.com/ ?
I placed exact code on the theme template but when see the html source code it appears on the top but not as HTML but the scrip coding.
Thanks in advance for confirmation. BR

@Aldegunde
Copy link

Hi all, asking for help,
Not usre why code do not works showing the brand on product pages:
https://www.delica-te-zen.com/comprar-te-verde-online/11-te-verde-templo-del-cielo.html

I understand that part of the code doing that is:

    {if $product_manufacturer->name}"brand": {
        "@type": "Thing",
        "name": "{$product_manufacturer->name|escape:'html':'UTF-8'}"
    }

But no sucess showing the brand. Shop is 1.6, any idea?

Thanks in advance. BR

@tripats
Copy link

tripats commented Sep 20, 2019

Maybe I am wrong but I noticed a lot of crawling anomalies I could not explain in webmaster tools. The problem is imo related to if for example a product is disalbled it can not load the product object therefore a "Uncaught Error: Call to a member function getPrice() on null " is thrown and google will reject the page as crawling anomaly which might be not really good after all. So be careful and habe a look at your webmaster stats if anything strange happen.

@vit2010
Copy link

vit2010 commented Sep 20, 2019

Hello Yoan.
I ask for help in upgrading this code.
Tell me how to use tag values
aggregateRating, ratingValue, reviewCount when using the gsnippetsreviev module?
With best regards, Vladimir.

@surffari
Copy link

I managed to fix all the product related structured data on a 1.7 shop after tinkering with it sometime and acquited knowledge about the schema and structured data itself.

However, I'm working on a another shop whichi has most of the products configured with 4 variants (same product, differet weight/packsize) where each combination has diffrent EAN, price etc. Took me a while to figure out why I'mnot getting the EAN code out of teh product when I realized I have to pull it from $attributesCombinations for each variant.

I put this code to the header and started debugging, Seems my Presta instance (1.7.5.0) for some reason sprinkles the combination data to $combinations and $attributesCombination. For example, the GTIN, SKU is put into the latter hence why this code by default does not find it.
Has Prestashop changed this behaviour since this code was updated or is my instance outdated compared to his code.

Also, all combinations here are defined as an Offer of one product. I'm trying to find what is the correct schema.org way to define the combinations? I found productModel which could be the answer, but has anyone figured this out?

Otherwise, this code is much cleaner solution than fixing and figuring out the microdate sprinkled all over the files by default.

@evamariamontero
Copy link

Hi guys!

Thank you for the contribution. But I added the code first to global.tpl, then to header.tpl (1.6.1.24), without effect on the search console errors related to Either "offers", "review", or "aggregateRating", "ratingCount", "reviewCount" or "ratingValue".

Any hint on how to solve it?

Thank you so much!

@yoanmarchal
Copy link
Author

i found that https://gist.github.com/sen0rxol0/1b411bccfc643dc87f551c2f8578bb94 by looking at fork of this gist

@evamariamontero
Copy link

Hi Yoan,

Thank you for your help. I followed your link and tested the modifications without effect. Everything works fine for microdata but not for ld+json, where "offers", "review", or "aggregateRating", "ratingCount", "reviewCount" or "ratingValue" errors still persist.

By the way, the Google Structured Data Testing Tool results are far away from the Google Search Console results (these are plenty of errors when the others are mostly clean).

If anyone has any idea, I'll be very happy to read it and help

@DennisSuitters
Copy link

@evamariamontero from what I was able to find, there is some suggestion to omit those parts of the Schema if there are no values to add. For e.g. if a product has no reviews, simply don't have it in the Schema. However, I have seen Google people working on the Schema implementation comment on some places, to use a null value, but I am yet to try, or see an example of how to properly add those.

@Aldegunde
Copy link

Hi all, asking for help,
Not usre why code do not works showing the brand on product pages:
https://delica-te-zen.com/te-verde/te-verde-gunpowder-templo-del-cielo

I understand that part of the code doing that is:

{if $product_manufacturer->name}"brand": {
    "@type": "Thing",
    "name": "{$product_manufacturer->name|escape:'html':'UTF-8'}"
}

But no sucess showing the brand. Shop is 1.7, any idea?

Thanks in advance. BR

@yoanmarchal
Copy link
Author

@Aldegunde is your $product_manufacturer variable is available in this context ?
is your product manufacturer is set on the back office ?
FYI i'm not sure this code is able to work on 1.7 since it's a convenient fork of code taken from

@Aldegunde
Copy link

Hi @yoanmarchal if I analyse the page on google search, there is an error on brand, but on the code I can see that content is clearly visible. Not sure why it is not shown.

<label

Thanks for oyur comments

@Aldegunde
Copy link

<meta itemprop="brand" content="Delica-Té-Zen (A)"><div class="product-manufacturer "> <label class="label">Marca</label> <span> <a href="https://delica-te-zen.com/brand/delica-te-zen-a">Delica-Té-Zen (A)</a> </span></div><div class="product-reference"> <label

@Aldegunde
Copy link

Sorry @yoanmarchal, definetly I was doing something worng, sorry for that. I was looking on worng place...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment