Setting Up Internal Linking for a 1C-Bitrix Catalog
Internal linking is the transfer of "weight" between pages on a site. In a 1C-Bitrix catalog, it solves a specific problem: distributing link equity from the homepage and top-level categories down to product cards and filter pages, which would otherwise sit far from the homepage in the site structure.
Setting Up Internal Linking for a 1C-Bitrix Catalog
The Internal Linking Problem in a Bitrix Catalog
A typical structure: homepage → category → subcategory → sub-subcategory → product card. That is four clicks from the homepage. Filter pages (SEO-friendly URLs like /catalog/tools/drills/?brand=bosch) may not be indexed at all without explicit links.
Automatic linking via 1C-Bitrix components:
-
Breadcrumbs (
bitrix:breadcrumb) — a linear chain that passes weight from the product card back up to parent sections -
Section navigation (
bitrix:menu) — horizontal category menu -
"Related products" (
bitrix:catalog.related) — horizontal links between product cards
This is often not enough. Additional linking is required.
"See Also" Block: Links to Adjacent Categories
On both product cards and listing pages, add a block with links to adjacent categories. Implement it via result_modifier.php:
// In result_modifier.php of the catalog.element template
// Retrieve parent sections and their siblings
$section = \CIBlockSection::GetByID($arResult['SECTION']['ID'])->GetNext();
$parentId = $section['IBLOCK_SECTION_ID'] ?? null;
if ($parentId) {
$siblings = [];
$sibRes = \CIBlockSection::GetList(
['SORT' => 'ASC'],
[
'IBLOCK_ID' => $arParams['IBLOCK_ID'],
'IBLOCK_SECTION_ID' => $parentId,
'ACTIVE' => 'Y',
'!ID' => $arResult['SECTION']['ID'], // exclude current
],
false,
['ID', 'NAME', 'SECTION_PAGE_URL'],
false
);
while ($s = $sibRes->GetNext()) {
$siblings[] = $s;
}
$arResult['RELATED_SECTIONS'] = array_slice($siblings, 0, 6);
}
// In template.php — render the block
if (!empty($arResult['RELATED_SECTIONS'])): ?>
<div class="related-sections">
<h3>See Also</h3>
<ul>
<?php foreach ($arResult['RELATED_SECTIONS'] as $section): ?>
<li><a href="<?= htmlspecialchars($section['SECTION_PAGE_URL']) ?>">
<?= htmlspecialchars($section['NAME']) ?>
</a></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
Links to Filtered Pages from Section SEO Texts
Smart filter pages (/catalog/drills/?brand=bosch&power=1000) are potentially valuable landing pages for queries like "Bosch drills 1000W". Without links to them, search engines will not index them.
Add links to priority filter combinations in section SEO texts:
<div class="seo-links">
<p>Popular selections:</p>
<ul>
<li><a href="/catalog/drills/?brand=bosch">Bosch Drills</a></li>
<li><a href="/catalog/drills/?brand=makita">Makita Drills</a></li>
<li><a href="/catalog/drills/?power=1000-2000">Drills 1000–2000W</a></li>
<li><a href="/catalog/drills/?type=impact">Impact Drills</a></li>
</ul>
</div>
These links are stored in the section's HTML field (UF_SEO_TEXT) and can be edited through the CMS without any code changes.
Linking via the "Frequently Bought Together" Block
Use the bitrix:catalog.related.buy component or a custom implementation querying the b_sale_basket_item table:
-- Products most frequently purchased together with the given product
SELECT
bi2.PRODUCT_ID,
COUNT(*) AS TOGETHER_COUNT
FROM b_sale_basket_item bi1
JOIN b_sale_basket_item bi2
ON bi1.ORDER_ID = bi2.ORDER_ID
AND bi1.PRODUCT_ID != bi2.PRODUCT_ID
WHERE bi1.PRODUCT_ID = :currentProductId
GROUP BY bi2.PRODUCT_ID
ORDER BY TOGETHER_COUNT DESC
LIMIT 6
The result is cached for 24 hours and rendered as a block with links and product images.
Autolinking in Descriptions
An auto-linking tool: when rendering a product description, keywords are automatically turned into links to the corresponding categories or tags.
function autolinkText(string $text, array $linkMap): string
{
// $linkMap: ['concrete' => '/catalog/tools/for-concrete/', ...]
foreach ($linkMap as $keyword => $url) {
$text = preg_replace(
'/\b(' . preg_quote($keyword, '/') . ')\b/ui',
'<a href="' . $url . '">$1</a>',
$text,
1 // no more than one link per keyword in the text
);
}
return $text;
}
The keyword map is stored in a dedicated table or in module settings. Autolinking is applied to DETAIL_TEXT at render time, not when saving to the database.
Sitemap and Links
Internal linking affects the crawl budget: pages that receive more internal links are crawled more frequently. Configure sitemap.xml via the 1C-Bitrix seo module — include filter pages with SEO-friendly URLs.
Timelines
| Task | Timeline |
|---|---|
| Adjacent category link block on product cards | 4–8 hours |
| Filter links in section SEO texts | 4–8 hours |
| "Frequently bought together" based on order history | 1–2 days |
| Keyword dictionary autolinking | 1 day |







