Кратко - https://yandex.ru/su...l.xml#canonical
Более полно - весь интернет к услугам. Очень много информации.
На первую-вторую-десятую страницу категории каноникал-ссылка одна и та же - без offset-а.
Т.е. первая (или единственная) страница категории.
На "показать все" - с &show_all=yes, т.е. ВСЕ товары категории. Хочется по другому - поменяйте.
Остальное более-менее банально и однозначно, т.е. вне зависимости от типа ссылки (динамическая index.php?blablaID=123 или статическая /blabla123.html) в canonical пишется выбранный в "Общих настройках" вариант.
Если в "общих настройках" выбраны динамические ссылки (точнее, не выбраны "псевдостатические", которые по умолчанию выбраны), то оно особо и не надо нигде кроме категорий (там sort и direction создают дубли). Все равно везде index.php?blabla123.html.
А вот если оставлены дефолтовые псевдостатические (как обычно у всех и есть, я только одного клиента знаю с динамическими), то это полезно, т.к. ссылки на сайте присутствуют в обоих видах. Например, на странице товара /product123.html есть ссылка на обсуждения товара /index.php?productID=123&discuss=yes, а на странице обсуждения обратная ссылка на страницу товара, которая уже - тадададам! - /index.php?productID=123.
И такого много, насколько я помню.
В общем, не так давно Яндекс на моем сайте начал выкидывать такие дубли из поиска вообще (или оставлять вовсе не то вариант, который надо) и я озадачился. Помогло. Реально помогло, причем довольно быстро. Хотя, возможно, причина вовсе и не в добавлении canonical, а что-то они откатили обратно в СВОЕМ алгоритме.
Каноническая ссылка добавляется в код на страницах категории, товара, новости, статической страницы, прайса, фидбэка и корзины. Надо другие - добавьте. По коду очевидно, как сделать.
Установка:
=========
1. в /core/includes/ создаем файл canonical.php
<?php
if (isset($_GET['categoryID']))
$smarty->assign('canonical', (CONF_MOD_REWRITE?('category_'.(int)$_GET['categoryID'].'.html')'/index.php?categoryID='.(int)$_GET['categoryID'])).
(isset($_GET['show_all'])?'?show_all=yes':''));
elseif (isset($_GET['productID']))
$smarty->assign('canonical', CONF_MOD_REWRITE?('product_'.(int)$_GET['productID'].'.html')'/index.php?productID='.(int)$_GET['productID']));
elseif ( isset($_GET['show_aux_page']) )
$smarty->assign('canonical', CONF_MOD_REWRITE?('page_'.(int)$_GET['show_aux_page'].'.html')'/index.php?show_aux_page='.(int)$_GET['show_aux_page']));
elseif (isset($_GET['fullnews']))
$smarty->assign('canonical', CONF_MOD_REWRITE?('show_news_'.(int)$_GET['fullnews'].'.html')'/index.php?fullnews='.(int)$_GET['fullnews']));
elseif (isset($_GET['news']))
$smarty->assign('canonical', CONF_MOD_REWRITE?('news.html')'/index.php?news=yes'));
elseif (isset($_GET['show_price']))
$smarty->assign('canonical', CONF_MOD_REWRITE?('price.html')'/index.php?show_price=yes'));
elseif (isset($_GET['feedback']))
$smarty->assign('canonical', CONF_MOD_REWRITE?('feedback.html')'/index.php?feedback=yes'));
elseif (isset($_GET['shopping_cart']))
$smarty->assign('canonical', CONF_MOD_REWRITE?('cart.html')'/index.php?shopping_cart=yes'));
?>
2. в файл head.tpl.html вставляем
{* BEGIN canonical *}
{if $canonical}<link rel="canonical" href="{$smarty.const.CONF_FULL_SHOP_URL}{$canonical}"/>{/if}
{* END canonical *}