VirtueMart Forum

VirtueMart 2 + 3 => Virtuemart Development and bug reports => Coding Central => Topic started by: Peter Pillen on August 01, 2013, 13:04:10 pm

Title: Canonicals for manufacturers in VM
Post by: Peter Pillen on August 01, 2013, 13:04:10 pm
I would like to avoid a canonical tag being created in the manufacturer view that links to the main page. I can understand that for example a photocamera can be placed in the category "reflexcamera" and "professional camera" at the same time... creating duplicate content that must be solved with canonicals. But... a Nikon camera will never be found in the Canon category. In theory every manufacturer page should be unique. So the canonical in the manufacturer category view should only point to the first page of that manufacturer (limitstart=0)

The problem in search engines is this below

option=com_virtuemart&view=category&virtuemart_category_id=&virtuemart_manufacturer_id=2&lang=nl
--> this view with images does not get indexed by Google because a canonical points to the virtuemart main page

option=com_virtuemart&view=manufacturer&virtuemart_category_id=&virtuemart_manufacturer_id=2&lang=nl
--> this view without productimages gets indexed by google

the first page is visually more attractive and should be indexed instead of the manufacturer info

purpose of this code change
1. Creates a canonical for the manufacturer page that points to the first page with products of that manufacturer INSTEAD of pointing to the virtuemart main page
2. In categories where a manufacturer filter is applied, the canonical will still point to the category canonical (same as before)
3. On the manufacturer info page without the products, the canonical points to the manufacturer page where the products are visible (canonical points to view=category INSTEAD of view=manufacturers)

In short ... every category has one canonical to the first page, every manufacturer has one canonical to its own page with view= category so that products are visible. And when applying a manufacturer filter in a category, the canonical remains the same.

file: components\com_virtuemart\views\category\view.html.php

approx @ line 125
Code: [Select]
<?php
                $categoryId = JRequest::getInt('virtuemart_category_id', ShopFunctionsF::getLastVisitedCategoryId());
$virtuemart_manufacturer_id = JRequest::getInt('virtuemart_manufacturer_id',0 );
$this->setCanonicalLink($tpl,$document,$categoryId);
?>
CHANGED TO
Code: [Select]
<?php
                $categoryId = JRequest::getInt('virtuemart_category_id', ShopFunctionsF::getLastVisitedCategoryId());
$catType = 'category';

$virtuemart_manufacturer_id = JRequest::getInt('virtuemart_manufacturer_id',0 );

if ($categoryId == NULL and isset($virtuemart_manufacturer_id)){
$categoryId = $virtuemart_manufacturer_id;
$catType = 'manufacturer';
}
$this->setCanonicalLink($tpl,$document,$categoryId,$catType);
?>

approx @ line 550 function setCanonicalLink is changed to this

Code: [Select]
<?php
public function setCanonicalLink($tpl,$document,$categoryId,$catType){
// Set Canonic link
if (!empty($tpl)) {
$format $tpl;
} else {
$format JRequest::getWord('format''html');
}
if ($format == 'html') {
$document->addHeadLinkJRoute::_('index.php?option=com_virtuemart&view=category&virtuemart_'.$catType.'_id='.$categoryIdFALSE) , 'canonical''rel''' );
}
}
?>

file: components\com_virtuemart\views\manufacturer\view.html.php


line added under the $document->setTitle
Code: [Select]
<?php
                        $document
->setTitle(JText::_('COM_VIRTUEMART_MANUFACTURER_DETAILS').' '.strip_tags($manufacturer->mf_name));

//added so that the canonical points to page with visible products
$document->addHeadLinkJRoute::_('index.php?option=com_virtuemart&view=category&virtuemart_manufacturer_id='.$virtuemart_manufacturer_idFALSE) , 'canonical''rel''' );
?>
Title: Re: Canonicals for manufacturers in VM
Post by: Milbo on August 01, 2013, 15:39:21 pm
Very interesting detail, thank you. I just implemented it. I just wonder that $categoryId == NULL works, I think it must be $categoryId === NULL, and when I look in getLastVisitedCategoryId
Code: [Select]
getLastVisitedCategoryId () {

$session = JFactory::getSession();
return $session->get( 'vmlastvisitedcategoryid', 0, 'vm' );
That should return at least always a 0. Be aware that 0 means here not false, it means "root category" => all categories with parentid=0, same imho with manufacturers 0 shows all. So the idea was to give categorId= 0 and a manufacturerId, which sets the filter for the product listing and gives directly all products of a manufacturer regardless the category.

Next problem is that your "fix" sets later the manufacturerId as categoryId in $products = $productModel->getProductsInCategory($categoryId); around line 75

Code: [Select]
public function getProductsInCategory ($categoryId) {

$ids = $this->sortSearchListQuery (TRUE, $categoryId);
$this->products = $this->getProducts ($ids);
return $this->products;
}
so we must just use directly the sortSearchListQuery, the rest is done in the initialiseRequests
Title: Re: Canonicals for manufacturers in VM
Post by: Peter Pillen on August 01, 2013, 15:47:14 pm
You are right... I just discovered some problems with my code and the fact I'm changing the categoryid to the manufacturer id. I will have a look for a better coding. When NULL or 0 is returned, the manufacturer view is ... well ... broken  :-[

Didn't know that 0 always pointed to the root category. Learning every day.
Title: Re: Canonicals for manufacturers in VM
Post by: Milbo on August 01, 2013, 15:49:30 pm
One solution
Code: [Select]
static public function getLastVisitedCategoryId ($default = 0) {

$session = JFactory::getSession();
return $session->get( 'vmlastvisitedcategoryid', $default, 'vm' );

}
Title: Re: Canonicals for manufacturers in VM
Post by: Peter Pillen on August 01, 2013, 18:12:39 pm
Another solution that seems more stable is this

file: components\com_virtuemart\views\category\view.html.php
search for function setCanonicalLink and switch with function here below

Code: [Select]
<?php
public function 
setCanonicalLink($tpl,$document,$categoryId){
// Set Canonic link
if (!empty($tpl)) {
$format $tpl;
} else {
$format JRequest::getWord('format''html');
}
if ($format == 'html') {
// Adapt canonical to manufacturer or category
$vm_canon_cat_id JRequest::getVar('virtuemart_category_id');
$vm_canon_mf_id =  JRequest::getVar('virtuemart_manufacturer_id');
if ($vm_canon_cat_id==and $vm_canon_mf_id>0){
$canonType='manufacturer';
$canonId=$vm_canon_mf_id;
}else{
$canonType='category';
$canonId=$categoryId;
}
$document->addHeadLinkJRoute::_('index.php?option=com_virtuemart&view=category&virtuemart_'.$canonType.'_id='.$canonIdFALSE) , 'canonical''rel''' );
}
}
?>

Now there is no need to adapt the code at the top. Only the function setCanonicalLink is changed now. In that way the code is not influenced by other settings or code. Looks like its working. Can you verify this?
Title: Re: Canonicals for manufacturers in VM
Post by: Milbo on August 02, 2013, 11:18:32 am
But the code is wrong at top. Please try the svn, or load the files manually here http://dev.virtuemart.net/projects/virtuemart/repository/show/branches/com_virtuemart2.0.14mp
Title: Re: Canonicals for manufacturers in VM
Post by: Peter Pillen on August 02, 2013, 11:23:28 am
Max,

I don't have a login for the dev or svn. I'll have a look to how it works. But the code at the top does no longer have to be changed. Only the function setCanonicalLink is changed... the rest is the same.

The changes are these

file: components\com_virtuemart\views\manufacturer\view.html.php
--> addHeadlink added to point the canonical of that view towards the view WITH products (see above)

file: components\com_virtuemart\views\category\view.html.php
--> function setCanonicalLink rewritten to detect if we have a category or a manufacturer (see code in last post above)
Title: Re: Canonicals for manufacturers in VM
Post by: Milbo on August 03, 2013, 00:41:00 am
no the rest contains a bit more, so that you get the right products. and I wonder why you just not use the link? You do not need developer rights to use the svn.
Title: Re: Canonicals for manufacturers in VM
Post by: Peter Pillen on August 03, 2013, 10:16:53 am
I don't have a clue how the svn works. Tried different things, but I always get a login screen. I can see the file structure, browse trough it and read the code. I don't see any way to upload a revision or modify the pieces of code. In the process I already got a redmine account and SmartGit installed but to no avail.

I downloaded the latest revision and changed the code. File is in attachment (as txt file ... php was not allowed)

Unless there is a noob-level-manual about the svn? :)

[attachment cleanup by admin]
Title: Re: Canonicals for manufacturers in VM
Post by: Milbo on August 08, 2013, 14:21:29 pm
The latest revision IS containing your ideas, already. You gave e 80% of it and I noticed it need a bit more. So I must know if my idea works for you.
Title: Re: Canonicals for manufacturers in VM
Post by: sandstorm on August 15, 2013, 16:03:00 pm
I added this at line 245 and this work very well for me? Is it any help?

Code: [Select]
// Set Canonic link

if (!empty($tpl)) {

$format = $tpl;

} else {

$format = JRequest::getWord('format', 'html');

}

if ($format == 'html') {
// mod for manufacturer canonic link


if ($virtuemart_manufacturer_id = JRequest::getInt('virtuemart_manufacturer_id',0 ))

$document->addHeadLink( 'index.php?option=com_virtuemart&view=category&virtuemart_manufacturer_id='.$virtuemart_manufacturer_id , 'canonical', 'rel', '' );

else

$document->addHeadLink( JRoute::_('index.php?option=com_virtuemart&view=category&virtuemart_category_id='.$categoryId) , 'canonical', 'rel', '' );

//end of mod

}