Главная ошибка использования для подобного AddHeadString в том, что возможны ситуации, когда на одной странице в нескольких местах будет разный canonical. А в части решений забыли использовать второй параметр true, так будут выводиться дубли одного и того же, в случае если такой подход используется в разных компонентах. А так же вы получите дубляж при уже добавленном canonical от стандартных компонентов, которые такой подход не используют.
Правильно использовать свойства страницы, как это делают стандартные компоненты битрикса
Например catalog.element это делает так:
$APPLICATION->SetPageProperty('canonical', $arResult["CANONICAL_PAGE_URL"]);
Для страниц навигации правильно устанавливать canonical так:
для шалонов используемого system.pagenavigation создаете файл component_epilog.php
use Bitrix\Main\Web\Uri;
$context = \Bitrix\Main\Application::getInstance()->getContext();
$uri = new Uri($context->getRequest()->getRequestUri());
$uri->deleteParams(['PAGEN_' . $arResult['NavNum']]);
$protocol = $context->getRequest()->isHttps() ? 'https://' : 'http://';
$href = $protocol . $context->getServer()->getHttpHost() . $uri->getUri();
$APPLICATION->SetPageProperty('canonical', $href);
В последних версиях ничего делать больше не нужно, если в header.php есть вызов
<?php $APPLICATION->ShowHead()?>
В других случаях надо явно указывать
<?php $APPLICATION->ShowLink("canonical")?>
В админке проверьте, что в "управлении структурой" добавлено данное свойство.
Данный метод можно использовать в любых ситуация, даже без ЧПУ, т.к. остальные параметры из строки не удаляются.
Задача, которую опционально требуется решать - проверить, а не установлен ли canonical до вас. В таком случае вы его перетрёте, а это часто не то что нужно. Оставлю её на домашнее задание.