Добавление фильтра для исключения из индекса некоторых страниц Битрикс сайта

Written by: Pavel on 27 мая, 2026

Задача: уменьшить попадание в индекс Google и Яндекс мусорных и малоценных страниц умного фильтра сайта на Битрикс.

Подробности: сайт достаточно большой, в индекс Google попало около 200 000 страниц, хотя товаров и категорий намного меньше. Проблема в том, что индексация страниц происходит достаточно медленно для новых страниц.

Решение: Было решено уменьшить индекс за счет установки фильтра <meta name="robots" content="noindex, follow" /> для страниц умного фильтра Битрикс. Некоторые категории фильтров оставлены в индексе: это прежде всего категории брендов и категории в которых встречаются слова из запросов в поиске. Например: плита 5 комфорок, электрический газовый и некоторые другие. Фильтр отсекал прежде всего фильтр по ценам и некоторые явно мусорные запросы, которые ссылались в canonikal сами на себя, а не правильную страницу. Потом добавлю примеры.

Почему так было сделано

Решение не уникальное — я его подсмотрел на других раскрученных площадках-каталогах. Похожий ассортимент, высокая авторитетность сайтов подсказали наверняка правильное решение.

Второй пример.

Вариант фильтра №1

Варианты предложены https://gemini.google.com/.

<?if(SITE_ID == 's6'):?>
<?
// 1. Проверяем грязные страницы Умного фильтра (содержат /filter/)
$isBadFilter = false;
if (strpos($_SERVER['REQUEST_URI'], '/filter/') !== false) {
    if (
        strpos($_SERVER['REQUEST_URI'], '_ref') !== false || 
        strpos($_SERVER['REQUEST_URI'], 'price-base') !== false ||
        strpos($_SERVER['REQUEST_URI'], '/clear/') !== false ||
        strpos($_SERVER['REQUEST_URI'], 'depth-from') !== false ||
        strpos($_SERVER['REQUEST_URI'], 'depth-to') !== false ||
        strpos($_SERVER['REQUEST_URI'], 'height-from') !== false ||
        strpos($_SERVER['REQUEST_URI'], 'height-to') !== false ||
        strpos($_SERVER['REQUEST_URI'], 'width-from') !== false ||
        strpos($_SERVER['REQUEST_URI'], 'width-to') !== false
    ) {
        $isBadFilter = true;
    }
}

// 2. Проверяем технические и мусорные параметры в URL (сортировка, поиск, вид)
$isBadParam = (
    strpos($_SERVER['REQUEST_URI'], 'section_id=') !== false || 
    strpos($_SERVER['REQUEST_URI'], 'q=') !== false
    /*|| strpos($_SERVER['REQUEST_URI'], 'sort=') !== false ||*/
    /*strpos($_SERVER['REQUEST_URI'], 'order=') !== false ||*/
    /*strpos($_SERVER['REQUEST_URI'], 'view=') !== false*/
);

if ($isBadFilter || $isBadParam) {
    // Очищаем стандартный robots Битрикса, чтобы избежать дублирования
    $APPLICATION->PageProperty["robots"] = "";     
    echo '<meta name="robots" content="noindex, follow" />' . "\n";
}
?>
<?endif;?>

Вариант фильтра №2

Потом были добавлены еще условия для фильтрации (пока код не установлен на сайт, так как проверяется как поисковики будут реагировать на выпадение из индекса пусть и мусорных, но большого количества страниц сайта).

<?if(SITE_ID == 's6'):?>
<?
$requestUri = $_SERVER['REQUEST_URI'];

// 1. Проверяем грязные страницы Умного фильтра
$isBadFilter = false;
if (strpos($requestUri, '/filter/') !== false) {
    // Собираем все нежелательные вхождения в одну регулярку через вертикальную черту "|"
    $pattern = '/(?:_ref|price-base|\/clear\/|depth-|height-|width-|board-is-|type-is|displacement-|trays-)/';
    if (preg_match($pattern, $requestUri)) {
        $isBadFilter = true;
    }
}

// 2. Проверяем технические и мусорные параметры в URL
// (отлавливаем section_id= или q=)
$isBadParam = (bool)preg_match('/(?:section_id=|q=)/', $requestUri);

if ($isBadFilter || $isBadParam) {
    // Очищаем стандартный robots Битрикса, чтобы избежать дублирования
    $APPLICATION->PageProperty["robots"] = "";     
    echo '<meta name="robots" content="noindex, follow" />' . "\n";
    
    // СВЕРХПРОГРАММА (Опционально): Переопределяем canonical на чистый URL без /filter/
    // $cleanUrl = preg_replace('/filter\/.*$/', '', $requestUri);
    // $APPLICATION->SetPageProperty("canonical", "https://" . $_SERVER['HTTP_HOST'] . $cleanUrl);
}
?>
<?endif;?>

Полученный шаблон сайта

Вот такая портянка получилась в Настройки шаблона сайта для сайта на Битрикс Аспро: Next — интернет-магазин (27.05.2026). Это тот вариант, который работает на сайте в данный момент. Надо сказать, что рабочего варианта для борьбы с мусором подобного рода я не нашел в офоициально репозитории Битрикс.

<?if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();?>
<?if($_GET["debug"] == "y")
	error_reporting(E_ERROR | E_PARSE);
IncludeTemplateLangFile(__FILE__);
global $APPLICATION, $arRegion, $arSite, $arTheme;
$arSite = CSite::GetByID(SITE_ID)->Fetch();
$htmlClass = ($_REQUEST && isset($_REQUEST['print']) ? 'print' : false);
$bIncludedModule = (\Bitrix\Main\Loader::includeModule("aspro.next"));?>
<!DOCTYPE html>
<html lang="<?=LANGUAGE_ID?>" <?=($htmlClass ? 'class="'.htmlspecialcharsbx($htmlClass).'"' : '')?>>
<head>
	<?if(SITE_ID == 's6'):?>
<?
// 1. Проверяем грязные страницы Умного фильтра (содержат /filter/)
$isBadFilter = false;
if (strpos($_SERVER['REQUEST_URI'], '/filter/') !== false) {
    if (
        strpos($_SERVER['REQUEST_URI'], '_ref') !== false || 
        strpos($_SERVER['REQUEST_URI'], 'price-base') !== false ||
        strpos($_SERVER['REQUEST_URI'], '/clear/') !== false ||
        strpos($_SERVER['REQUEST_URI'], 'depth-from') !== false ||
        strpos($_SERVER['REQUEST_URI'], 'depth-to') !== false ||
        strpos($_SERVER['REQUEST_URI'], 'height-from') !== false ||
        strpos($_SERVER['REQUEST_URI'], 'height-to') !== false ||
        strpos($_SERVER['REQUEST_URI'], 'width-from') !== false ||
        strpos($_SERVER['REQUEST_URI'], 'width-to') !== false
    ) {
        $isBadFilter = true;
    }
}

// 2. Проверяем технические и мусорные параметры в URL (сортировка, поиск, вид)
$isBadParam = (
    strpos($_SERVER['REQUEST_URI'], 'section_id=') !== false || 
    strpos($_SERVER['REQUEST_URI'], 'q=') !== false
    /*|| strpos($_SERVER['REQUEST_URI'], 'sort=') !== false ||*/
    /*strpos($_SERVER['REQUEST_URI'], 'order=') !== false ||*/
    /*strpos($_SERVER['REQUEST_URI'], 'view=') !== false*/
);

if ($isBadFilter || $isBadParam) {
    // Очищаем стандартный robots Битрикса, чтобы избежать дублирования
    $APPLICATION->PageProperty["robots"] = "";     
    echo '<meta name="robots" content="noindex, follow" />' . "\n";
}
?>
<?endif;?>

	<title><?$APPLICATION->ShowTitle()?></title><?php $APPLICATION->ShowProperty("robots_noindex"); ?>
	<?$APPLICATION->ShowMeta("viewport");?>
	<?$APPLICATION->ShowMeta("HandheldFriendly");?>
	<?$APPLICATION->ShowMeta("apple-mobile-web-app-capable", "yes");?>
	<?$APPLICATION->ShowMeta("apple-mobile-web-app-status-bar-style");?>
	<?$APPLICATION->ShowMeta("SKYPE_TOOLBAR");?>
	<?$APPLICATION->ShowHead();?>
	<?$APPLICATION->AddHeadString('<script>BX.message('.CUtil::PhpToJSObject( $MESS, false ).')</script>', true);?>
	<?if($bIncludedModule)CNext::Start(SITE_ID);?>

<?if(SITE_ID == 's6'):?><!-- bth.by -->
 <!-- Yandex.Metrika counter --> <script data-skip-moving="true">     (function(m,e,t,r,i,k,a){         m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};         m[i].l=1*new Date();         for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}         k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)     })(window, document,'script','https://mc.yandex.ru/metrika/tag.js?id=23773633', 'ym');      ym(23773633, 'init', {ssr:true, webvisor:true, clickmap:true, ecommerce:"dataLayer", referrer: document.referrer, url: location.href, accurateTrackBounce:true, trackLinks:true}); </script><!-- /Yandex.Metrika counter -->   

<!-- Google tag (gtag.js) -->
<script data-skip-moving="true" async src="https://www.googletagmanager.com/gtag/js?id=G-6VYJEDJKFK"></script>
<script data-skip-moving="true">
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-6VYJEDJKFK');
</script>
<!-- Google tag (gtag.js) -->
<?endif;?>

<?if(SITE_ID == 's4'):?><!--gastro -->
<!-- Yandex.Metrika counter -->
<script data-skip-moving="true"  type="text/javascript" >
   (function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
   m[i].l=1*new Date();
   for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
   k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
   (window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
   ym(53127700, "init", {
        clickmap:true,
        trackLinks:true,
        accurateTrackBounce:true
   });
</script>
<!-- /Yandex.Metrika counter -->
<?endif;?>

<meta name="google-site-verification" content="ImuuX2VA_6UEYTH4Xc4MwOu5IYQAjFNgTGDJ2r2AZ5E" />
</head>
<?$bIndexBot = CNext::checkIndexBot(); // is indexed yandex/google bot?>
<body class="site_<?=SITE_ID?> <?=($bIncludedModule ? "fill_bg_".strtolower(CNext::GetFrontParametrValue("SHOW_BG_BLOCK")) : "");?> <?=($bIndexBot ? "wbot" : "");?>" id="main">
<?if(SITE_ID == 's4'):?><!--gastro -->
<noscript><div><img src="https://mc.yandex.ru/watch/53127700" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<?endif;?>
<?if(SITE_ID == 's6'):?><!-- bth.by -->

<?endif;?>
<? $APPLICATION->IncludeFile(SITE_DIR."include/spec_counters.php"); ?>	
<div id="panel"><?$APPLICATION->ShowPanel();?></div>
	<?if(!$bIncludedModule):?>
		<?$APPLICATION->SetTitle(GetMessage("ERROR_INCLUDE_MODULE_ASPRO_NEXT_TITLE"));?>
		<center><?$APPLICATION->IncludeFile(SITE_DIR."include/error_include_module.php");?></center>
</body>
</html>
<?die();?>
	<?endif;?>
	<?$arTheme = $APPLICATION->IncludeComponent("aspro:theme.next", ".default", array("COMPONENT_TEMPLATE" => ".default"), false, array("HIDE_ICONS" => "Y"));?>
	<?include_once('defines.php');?>
	<?CNext::SetJSOptions();?>
	<div class="wrapper1 <?=($isIndex && $isShowIndexLeftBlock ? "with_left_block" : "");?> <?=CNext::getCurrentPageClass();?> <?=CNext::getCurrentThemeClasses();?>">
		<?CNext::get_banners_position('TOP_HEADER');?>
		<div class="header_wrap visible-lg visible-md title-v<?=$arTheme["PAGE_TITLE"]["VALUE"];?><?=($isIndex ? ' index' : '')?>">
			<header id="header">
				<?CNext::ShowPageType('header');?>
			</header>
		</div>
		<main>
<?//из старого шаблона  ?>
		<?CNext::get_banners_position('TOP_UNDERHEADER');?>
<?//конец ?>
		<?if($arTheme["TOP_MENU_FIXED"]["VALUE"] == 'Y'):?>
			<div id="headerfixed">
				<?CNext::ShowPageType('header_fixed');?>
			</div>
		<?endif;?>
		<div id="mobileheader" class="visible-xs visible-sm">
			<?CNext::ShowPageType('header_mobile');?>
			<div id="mobilemenu" class="<?=($arTheme["HEADER_MOBILE_MENU_OPEN"]["VALUE"] == '1' ? 'leftside':'dropdown')?> <?=($arTheme['HEADER_MOBILE_MENU_COMPACT']['VALUE'] == 'Y' ? ' menu-compact ':'')?>">
				<?CNext::ShowPageType('header_mobile_menu');?>
			</div>
		</div>
		<?//CNext::get_banners_position('TOP_UNDERHEADER');?>
		<?if($arTheme['MOBILE_FILTER_COMPACT']['VALUE'] === 'Y'):?>
				<div id="mobilefilter" class="visible-xs visible-sm scrollbar-filter"></div>
			<?endif;?>
		<?/*filter for contacts*/
		if($arRegion)
		{
			if($arRegion['LIST_STORES'] && !in_array('component', $arRegion['LIST_STORES']))
			{
				if($arTheme['STORES_SOURCE']['VALUE'] != 'IBLOCK')
					$GLOBALS['arRegionality'] = array('ID' => $arRegion['LIST_STORES']);
				else
					$GLOBALS['arRegionality'] = array('PROPERTY_STORE_ID' => $arRegion['LIST_STORES']);
			}
		}
		if($isIndex)
		{
			$GLOBALS['arrPopularSections'] = array('UF_POPULAR' => 1);
			$GLOBALS['arrFrontElements'] = array('PROPERTY_SHOW_ON_INDEX_PAGE_VALUE' => 'Y');
		}?>
		<div class="wraps hover_<?=$arTheme["HOVER_TYPE_IMG"]["VALUE"];?>" id="content">
			<?if(!$is404 && !$isForm && !$isIndex):?>
				<?$APPLICATION->ShowViewContent('section_bnr_content');?>
				<?if($APPLICATION->GetProperty("HIDETITLE") !== 'Y'):?>
					<!--title_content-->
					<?CNext::ShowPageType('page_title');?>
					<!--end-title_content-->
				<?endif;?>
				<?$APPLICATION->ShowViewContent('top_section_filter_content');?>
			<?endif;?>
			<?if($isIndex):?>
				<div class="wrapper_inner front <?=($isShowIndexLeftBlock ? "" : "wide_page");?>">
			<?elseif(!$isWidePage):?>
				<div class="wrapper_inner <?=($isHideLeftBlock ? "wide_page" : "");?>">
			<?endif;?>
				<?$APPLICATION->IncludeComponent(
	"bitrix:main.include", 
	"", 
	[
		"AREA_FILE_SHOW" => "file",
		"PATH" => SITE_DIR."include/confidence.php",
		"COMPONENT_TEMPLATE" => "",
		"EDIT_TEMPLATE" => ""
	],
	false,
	[
		"ACTIVE_COMPONENT" => "Y"
	]
);?>
				<?if(($isIndex && $isShowIndexLeftBlock) || (!$isIndex && !$isHideLeftBlock) && !$isBlog):?>
					<div class="right_block <?=(defined("ERROR_404") ? "error_page" : "");?> wide_<?=CNext::ShowPageProps("HIDE_LEFT_BLOCK");?>">
				<?endif;?>
					<div class="middle <?=($is404 ? 'error-page' : '');?>">
						<?CNext::get_banners_position('CONTENT_TOP');?>
						<?if(!$isIndex):?>
							<div class="container">
								<?//h1?>
								<?if($isHideLeftBlock && !$isWidePage):?>
									<div class="maxwidth-theme">
								<?endif;?>
								<?if($isBlog):?>
									<div class="row">
										<div class="col-md-9 col-sm-12 col-xs-12 content-md <?=CNext::ShowPageProps("ERROR_404");?>">
								<?endif;?>
						<?endif;?>
						<?CNext::checkRestartBuffer();?>
#WORK_AREA#						<?CNext::checkRestartBuffer();?>
						<?IncludeTemplateLangFile(__FILE__);?>
							<?if(!$isIndex):?>
								<?if($isBlog):?>
									</div> <?// class=col-md-9 col-sm-9 col-xs-8 content-md?>
									<div class="col-md-3 col-sm-3 hidden-xs hidden-sm right-menu-md">
										<div class="sidearea">
											<?$APPLICATION->ShowViewContent('under_sidebar_content');?>
											<?CNext::get_banners_position('SIDE', 'Y');?>
											<?$APPLICATION->IncludeComponent("bitrix:main.include", "", array("AREA_FILE_SHOW" => "sect", "AREA_FILE_SUFFIX" => "sidebar", "AREA_FILE_RECURSIVE" => "Y"), false);?>
										</div>
									</div>
								</div><?endif;?>
								<?if($isHideLeftBlock && !$isWidePage):?>
									</div> <?// .maxwidth-theme?>
								<?endif;?>
								</div> <?// .container?>
							<?else:?>
								<?CNext::ShowPageType('indexblocks');?>
							<?endif;?>
							<?CNext::get_banners_position('CONTENT_BOTTOM');?>
						</div> <?// .middle?>
					<?//if(!$isHideLeftBlock && !$isBlog):?>
					<?if(($isIndex && $isShowIndexLeftBlock) || (!$isIndex && !$isHideLeftBlock) && !$isBlog):?>
						</div> <?// .right_block?>				
						<?if($APPLICATION->GetProperty("HIDE_LEFT_BLOCK") != "Y" && !(defined('ERROR_404') && !defined('ERROR_PAGEN'))):?>
							<div class="left_block">
								<?CNext::ShowPageType('left_block');?>
							</div>
						<?endif;?>
					<?endif;?>
				<?if($isIndex):?>
					</div>
				<?elseif(!$isWidePage):?>
					</div> <?// .wrapper_inner?>				
				<?endif;?>
			</div> <?// #content?>
			<?CNext::get_banners_position('FOOTER');?>
		</div><?// .wrapper?>
		</main>
		<footer id="footer">
			<?if($APPLICATION->GetProperty("viewed_show") == "Y" || $is404):?>
				<?$APPLICATION->IncludeComponent(
					"bitrix:main.include", 
					"basket", 
					array(
						"COMPONENT_TEMPLATE" => "basket",
						"PATH" => SITE_DIR."include/footer/comp_viewed.php",
						"AREA_FILE_SHOW" => "file",
						"AREA_FILE_SUFFIX" => "",
						"AREA_FILE_RECURSIVE" => "Y",
						"EDIT_TEMPLATE" => "standard.php",
						"PRICE_CODE" => array(
							0 => "BASE",
						),
						"STORES" => array(
							0 => "",
							1 => "",
						),
						"BIG_DATA_RCM_TYPE" => "bestsell"
					),
					false
				);?>					
			<?endif;?>
			<?CNext::ShowPageType('footer');?>
		</footer>
		<div class="bx_areas">
			<?CNext::ShowPageType('bottom_counter');?>
		</div>
		<?CNext::ShowPageType('search_title_component');?>
		<?CNext::setFooterTitle();
		CNext::bottomActions();
		CNext::showFooterBasket();?>

<script data-skip-moving="true">
    window.addEventListener('onBitrixLiveChat', function(event){
        var widget = event.detail.widget;
        widget.setOption('checkSameDomain', false);
    });
</script>

<? /*
<script data-skip-moving="true">
// Check for IntersectionObserver support
if ('IntersectionObserver' in window) {
  document.addEventListener("DOMContentLoaded", function() {

    function handleIntersection(entries) {
      entries.map((entry) => {
        if (entry.isIntersecting) {
          // Item has crossed our observation
          // threshold - load src from data-src
          entry.target.style.backgroundImage = "url('"+entry.target.dataset.bgimage+"')";
          // Job done for this item - no need to watch it!
          observer.unobserve(entry.target);
        }
      });
    }

    const headers = document.querySelectorAll('.banner_bg');
    const observer = new IntersectionObserver(
      handleIntersection,
      { rootMargin: "100px" }
    );
    headers.forEach(header => observer.observe(header));
  });
} else {
  // No interaction support? Load all background images automatically
  const headers = document.querySelectorAll('.banner_bg');
  headers.forEach(header => {
    header.style.backgroundImage = "url('"+header.dataset.bgimage+"')";
  });
}
</script>
*/?>
		<?$APPLICATION->IncludeComponent(
			"nikolaus:cookie.popup",
			"",
			Array(
				"COMPOSITE_FRAME_MODE" => "A",
				"COMPOSITE_FRAME_TYPE" => "AUTO",
				"TEXT" => "Наш сайт использует cookie-файлы.<br>С их помощью мы улучшаем работу нашего сайта и ваше взаимодействие с ним."
			)
		);?>
	<script data-cfasync="false" src="<?=SITE_TEMPLATE_PATH?>/js/custom.js"></script>
	</body>
</html>

Оставьте комментарий