News:

Support the VirtueMart project and become a member

Main Menu

small update to schema.org snippets.php

Started by alxgan, August 26, 2024, 12:01:45 PM

Previous topic - Next topic

alxgan

Hello,
Here is a small update to snippets.php
I wanted to add the schema org in the <head> of the webpage, as I read it in the guideline; so I did some modification to snippets.php to make it more "organized".
Please see attached file. You have to change extension from txt to php or copy-paste the code below.
Better to add it to your template folder: templates\template_name\html\com_virtuemart\sublayouts so it won't be overwritten on update.
The reviews are incomplete but when I will have some review data array example, I will update it.

<?php
/**
 *
 * renders the search engine snippets
 *
 * @package     VirtueMart
 * @subpackage
 * @author      The VirtueMart Team
 * @link        https://virtuemart.net
 * @copyright   Copyright (c) 2015 - 2019 VirtueMart Team. All rights reserved.
 * @license     https://www.gnu.org/licenses/gpl-3.0.html GNU/GPL
 * @version     $Id: snippets.php 8024 2014-06-12 15:08:59Z Milbo $
 */

// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die('Restricted access');

use 
Joomla\CMS\Factory;
use 
Joomla\CMS\Uri\Uri;
use 
Joomla\CMS\WebAsset\WebAssetManager;
use 
Joomla\CMS\Router\Route;

$app   Factory::getApplication();
$document $app->getDocument();
$wa $document->getWebAssetManager();

/** @var TYPE_NAME $viewData */
$product $viewData['product'];
$currency $viewData['currency'];
$view vRequest::getCmd('view');
$ratingModel VmModel::getModel('Ratings');
$productrating $ratingModel->getRatingByProduct($product->virtuemart_product_id);
if (
is_object($productrating)) {
$productratingcount $productrating->ratingcount;
} else {
$productratingcount '0';
}
$vendorModel VmModel::getModel('Vendor');
$vendor $vendorModel->getVendor($product->virtuemart_vendor_id); //your vendor ID


$canonicalUrl URI::getInstance()->toString(array('scheme''host''port')).Route::_($product->canonical);
$name vRequest::vmSpecialChars(strip_tags($product->product_name));
if (
VmConfig::get('show_manufacturers'1)){
$brand = (!empty($product->mf_name)? $product->mf_name '');
} else {
$brand '';
}
$sku =  (!empty($product->product_sku)? $product->product_sku $product->product_mpn);
$productID =  $sku;
$mpn =  (!empty($product->product_mpn)? $product->product_mpn $product->product_sku);
$review =  (!empty($ratingModel->ids[0]->comment)? $ratingModel->ids[0]->comment '');
$author =  (!empty($ratingModel->ids[0]->name)? $ratingModel->ids[0]->name '');

//do something sensible and not fixed with valid price date
$priceUntil '';
if(!empty(
$product->prices["product_price_publish_down"])){
$DownDate = new DateTime($product->prices["product_price_publish_down"]);
$DownCalcDate = new DateTime();
if ($DownDate $DownCalcDate) {
$priceUntil $DownDate->format"Y-m-d" );
}
} else {
//  $DownCalcDate->modify('+20 years');
//  $priceUntil = $DownCalcDate->format( "Y-m-d" );
//  dont show an end to this price if there is not one
$priceUntil '2030-12-31'; //Valid for a lond time
}

//Round prices
$productPrice round($product->prices['salesPrice'],2);

//GJC and Roderic look for parent & for child stock
//$stockog = 'InStock';
$stockhandle VmConfig::get ('stockhandle''none');
$finalstk $product->product_in_stock $product->product_ordered;
if (
$stockhandle == 'none') {
$stockog 'InStock';
} elseif (
$stockhandle == 'disableit_children' and $product->product_parent_id == 0) {
$prodmodel VmModel::getModel ('product');
$children $prodmodel->getProductChilds($product->virtuemart_product_id);
$finalstk $product->product_in_stock $product->product_ordered;
foreach($children as $child){
$finalstk += $child->product_in_stock $child->product_ordered;
}
} else {
$finalstk $product->product_in_stock;// - $product->product_ordered;
}
if (
$finalstk != 0) {
$stockog 'InStock';
}
if (
$finalstk == 0) {
$stockog 'InStock';//'OutOfStock' Always on stock;
}


//check for meta if empty move onto using product data
if (!empty($document->getMetaData('description'))) {
$description $document->getMetaData('description');
}
if (empty(
$description)){
if (!empty($product->product_s_desc)){
$description $product->product_s_desc;
} else {
$description $product->product_desc;
}
}
$description str_replace('"','\"',vRequest::vmSpecialChars(strip_tags($description)));

//vmdebug('my customfields ',$product);
$extra '';
if(!empty(
$product->customfieldsSorted['snippet'])){
foreach ($product->customfieldsSorted['snippet'] as $customfield) {
$extra .= '"'.$customfield->custom_title.'": "'.$customfield->customfield_value.'",';
}
$extra substr($extra,0,-1);
}

//}
?>


<?php
// Structured data as JSON
$schemaDataProduct = [
'@context' => 'https://schema.org',
'@type' => 'Product',
'name' => $name,
'description' => $description,
'category' => $product->category_name,
'image' => [],
'mpn' => $mpn,
'sku' => $sku,
'manufacturer' => [],
'brand'  => [],
'offers' => [
'@type' => 'Offer',
'priceCurrency'  => $currency->_vendorCurrency_code_3,
'availability' => 'https://schema.org/'.$stockog,
'itemCondition' => 'https://schema.org/NewCondition',
'price' => $productPrice,
'url' => $canonicalUrl,
'priceValidUntil' => $priceUntil,
"seller" => [
        
'@type' => 'Organization',
          
'name' => $vendor->vendor_name
],
'hasMerchantReturnPolicy'=> [
'@type' => 'MerchantReturnPolicy',
'applicableCountry' => 'RO',
'returnPolicyCategory' => 'https://schema.org/MerchantReturnNotPermitted'
],
'shippingDetails' => [
'@type' => 'OfferShippingDetails',
'shippingDestination'=> [
'@type' => 'DefinedRegion',
            
'addressCountry' => 'RO'
]
]
],
'aggregateRating' => [
'@type' => 'AggregateRating',
'ratingValue' => $product->rating,
'reviewCount' => $productratingcount
],
'review' => [
'@type' => 'Review',
'reviewBody' => $review,
'author' => $author
]

];

if ( empty(
$product->product_sku) ) unset ($schemaDataProduct['sku']);
if ( empty(
$product->product_mpn) ) unset ($schemaDataProduct['mpn']);

if ( empty(
$product->prices['salesPrice']) ) $schemaDataProduct['offers']['price'] = 0.0;

if (
$brand) {
$schemaDataProduct['brand'] = [
  '@type' => 'Brand',
  'name' => $brand,
];
$schemaDataProduct['manufacturer'] = [
'@type' => 'Organization',
'name' => $product->mf_name,
];
}
else {
unset ($schemaDataProduct['brand']);
unset ($schemaDataProduct['manufacturer']);
}

if (
$product->images[0]->virtuemart_media_id 0) {
foreach($product->images as $image){
$schemaDataProduct['image'] = ''URI::root().$image->file_url;
}
}
else unset (
$schemaDataProduct['image']);

if ((empty(
$viewData['showRating'])) or ($productratingcount 0)) {
unset ($schemaDataProduct['aggregateRating']);
}

if (empty(
$review)) {
unset ($schemaDataProduct['review']);
}


$prettyPrint JDEBUG JSON_PRETTY_PRINT 0;
$wa->addInline(
'script',
json_encode($schemaDataProductJSON_UNESCAPED_SLASHES JSON_UNESCAPED_UNICODE $prettyPrint),
['name' => 'inline.product-schemaorg'],
['type' => 'application/ld+json']
);

?>





Alexb65


sirius

Hi
just to let you know that
$priceUntil = '2030-12-31'; //Valid for a lond timeIs not valid for prices products, as google accept one year at max.
By my side I use
$datevalid = gmDate("Y-m-t");To just keep the price valid by the end of each months.
J3.10.12 | PHP 7.4.33 + APC + Opcode
VM Prod : 3.8.6 | VM Test : 4.4.0.11095