Уникальные заголовок и описание у catalog.smart.filter. SEO для умного фильтра на Bitrix — PROG-TIME

Уникальные заголовок и описание у catalog.smart.filter. SEO для умного фильтра на Bitrix

10.09.2021
Содержание:

Всем привет! Сегодня хочу показать вам скрипты для настройки SEO для страниц умного фильтра каталога. Для каждой комбинации умного фильтра будет использоваться свои title, description, h1, и описание на странице.

Данное решение очень гибкое, вам по сути нужно просто передать массив фильтрации и вы сможете установить любой шаблон для мета описания. Так же вы можете указать преобразования для значений, например у вас есть свойство «цвет» и у него есть значение «красный«, вы можете поменять данное значение на слово «красного» или любое другое.

Данная реализация является сложной для начального понимания, но на выходе она позволяет поставить уникальные SEO заголовки и описания для всех комбинаций фильтра каталога.

Логика работы, следующая:

  • Создаем отдельный тип инфоблока, а в нём инфоблок, в котором будем записывать шаблоны SEO информации. Шаблоны будут иметь ключи, которые будут заменяться на соответствующие значения.
  • Прописываем 4 функции для создания заголовка
    • getParamsFilter — функция которая будет получать id выбранных значений и записывать их в массив. Возвращает массив выбранных значений.
    • queryMeta — делает запрос в инфоблок с настройками meta и получает информацию. В этой же функции все преобразуется в удобочитаемый массив с котором мы будем работать.
    • creacteMeta — заменяет ключи на соответствующие значения.
    • createMetaInfo — функция которая включает в себя работу всех функций и на выходе выдает всю SEO информацию в массиве.
  • прописываем функцию createMetaInfo в result_modifier.php в шаблоне компонента catalog.section (это в моем случает) и передаем

В моём случае будет рассматриваться умный фильтр, который работает через GET запрос. Данная реализация написана с помощью 4 функций, в дальнейшем я возможно создам класс, но сейчас меня устраивает и такой вариант.

Структура инфоблока и административная часть

Для данной задачи я создал отдельный тип инфоблока и в нём создал инфоблок. Тип инфоблока я создал общий, в нем я буду размещать все настройки по SEO. Конкретно в инфоблоке «Мета информация для фильтров» будем размещать логику для фильтров.

Разделы в будущем я собираюсь использовать в качестве регионов. Если регионы получится реализовать, то я добавлю данную настройку в эту запись. Значение будет одно, но в нём можно указывать каждый раздел в отдельность.

На данный момент, элементы имеют следующие свойства.

  • Шаблоны для разделов — это составное свойство в котором указывает символьный код раздела (524), шаблон SEO заголовка (520), шаблон SEO описания (522), шаблон заголовка h1 на странице фильтрации (521), и описание которое выводится на странице (523).
  • Мета значения для свойств — записывает преобразования для значений свойств, является составным и имеет следующие поля: id значения (526) и текст для замены (527).
  • Добавочный текст к свойствам — используется для добавления, перед выводом или после вывода, значений дополнительного текста. Например после вывода значения цвета можно добавить слово «цвете«, а перед значением добавить «в«, при этом в поле «Мета значения для свойств» заменить значение на «зеленом» и тем самым мы получаем «в зеленом цвете«.

Давайте теперь рассмотрим пример заполненного элемента.

В поле мета значения для свойств указываем id значения и текст для замены.

Идентификаторы для значений можно взять из настроек инфоблока.

С мета шаблонами все немного сложнее. Здесь я использую ключи, которые скрипт в дальнейшем будет расшифровывать и подставлять соответствующие значения.

Ключи имею следующий вид «ADETA_PROP_346«, где «ADETA_PROP_» это простое подставное слово, вы его можете сами изменить под себя в скрипте, а 346 это id свойства (именно свойства, а не значения).

Вообще я для всего использую свои ключи, поэтому тут же я прописать ADETA_NAME_SECTION, это ключ для вывода названия категории. Вы можете создавать свои ключи, даже которые не подходят под мой шаблон, после этого заносить их в массив и передавать в функцию.

Программирование

Файл с функциями я расположил в тему сайта в папку /includes/metaFilter/MetaFilter.php. И использую функции, как внешний, независимый скрипт.

Давайте рассмотрим данные функции.

getParamsFilter() — функция которая будет получать id выбранных значений

В качестве параметра, функция получает массив фильтрации в моём случае это $GLOBALS[«arrFilter»].

Структура массива имеет вид $GLOBALS[«arrFilter»].

В начале с помощью цикла foreach мы получаем идентификаторы всех выбранных значений. Все значения записываем в массив и передаём в качестве параметра в метод CIBlockPropertyEnum::GetList, который позволяет получить полную информацию по свойству.

В зависимости от ваших настроек, массив фильтрации может отличаться от моего. Если так происходит, то вам нужно отредактировать функцию и подстроить ее под себя, так чтобы получить простой массив идентификаторов значений фильтрации.

/* ============================================== */
/* СОЗДАЁТ МАССИВ ПО ВЫБРАННЫМ ПАРАМЕТРАМ ФИЛЬТРА */
/* ============================================== */
function getParamsFilter($filter) {

    /* проходимся по данным фильтра и записываем id значений */
    foreach($filter as $key=>$val) {
        if(is_array($val)) {
            foreach($val as $dop_val) {
                $listId[] = $dop_val;
            }
        } else {
            $listId[] = $val;
        }
    }

    /* получаем информацию по id значения свойств */
    $property_enums = CIBlockPropertyEnum::GetList(
        [
            "DEF"=>"DESC", 
            "SORT"=>"ASC"
        ], 
        [
            "IBLOCK_ID"=>5, 
            "ID"=> $listId
        ]
    );
    while($enum_fields = $property_enums->GetNext()) {
        $idProps = "ADETA_PROP_".$enum_fields["PROPERTY_ID"];
        $infoFilter[$idProps]["name_prop"] = $enum_fields["PROPERTY_NAME"];
        $infoFilter[$idProps]["value"][$enum_fields["ID"]] = $enum_fields["VALUE"];
    }

    return $infoFilter;

}
/* ============================================== */
/* ============================================== */

queryMeta() — делает запрос в инфоблок с настройками meta

Здесь мы получаем информацию из ранее созданного инфоблока для Meta шаблонов. Мой инфоблок имеет id = 27, вам нужно подставить ваше значение.

/* ============================================== */
/* ДЕЛАЕТ ЗАПРОС НА ПОЛУЧЕНИЕ META ШАБЛОНА */
/* ============================================== */
function queryMeta($filter) {

    $arSelect = [
        "ID", 
        "CODE", 
        "PROPERTY_TEMP_SECTION_LIST",
        "PROPERTY_LIST_META_PROPS",
        "PROPERTY_DOP_TEXT"
    ];

    $arFilter = [
        "IBLOCK_ID"=>27, 
        "SECTION_CODE" => ["all_region"], 
        "CODE"=>["all_section"], 
        "ACTIVE_DATE"=>"Y", 
        "ACTIVE"=>"Y"
    ];
    $res = CIblockElement::GetList(
        ["SORT" => "DESC"],
        $arFilter, 
        false, 
        "", 
        $arSelect
    );
    while($arFields = $res->fetch()){
        $code = $arFields["PROPERTY_TEMP_SECTION_LIST_VALUE"]["SUB_VALUES"]["SECTION_CODE"]["VALUE"];

        $elem["CODE"] = $code;

        $elem["META_TEMPLATES"][$elem["CODE"]]["TEMP_SECTION_TITLE"] = $arFields["PROPERTY_TEMP_SECTION_LIST_VALUE"]["SUB_VALUES"]["TEMP_SECTION_TITLE"]["VALUE"]["TEXT"];
        $elem["META_TEMPLATES"][$elem["CODE"]]["TEMP_SECTION_DESCRIPTION"] = $arFields["PROPERTY_TEMP_SECTION_LIST_VALUE"]["SUB_VALUES"]["TEMP_SECTION_DESCRIPTION"]["VALUE"]["TEXT"];
        $elem["META_TEMPLATES"][$elem["CODE"]]["TEMP_SECTION_HEADING"] = $arFields["PROPERTY_TEMP_SECTION_LIST_VALUE"]["SUB_VALUES"]["TEMP_SECTION_HEADING"]["VALUE"]["TEXT"];
        $elem["META_TEMPLATES"][$elem["CODE"]]["TEMP_SECTION_DOPTEXT"] = $arFields["PROPERTY_TEMP_SECTION_LIST_VALUE"]["SUB_VALUES"]["TEMP_SECTION_DOPTEXT"]["VALUE"]["TEXT"];

        $idProp  = $arFields["PROPERTY_LIST_META_PROPS_VALUE"]["SUB_VALUES"]["META_PROPS_ID"]["VALUE"];
        $valProp = $arFields["PROPERTY_LIST_META_PROPS_VALUE"]["SUB_VALUES"]["META_PROPS_TEXT"]["VALUE"];

        $elem["LIST_META_PROPS"][$idProp] = $valProp;

        $dopText_idSection  = $arFields["PROPERTY_DOP_TEXT_VALUE"]["SUB_VALUES"]["DOP_TEXT_ID"]["VALUE"];
        $dopText_type       = $arFields["PROPERTY_DOP_TEXT_VALUE"]["SUB_VALUES"]["DOP_TEXT_TYPE"]["VALUE_XML_ID"];
        $dopText_text       = $arFields["PROPERTY_DOP_TEXT_VALUE"]["SUB_VALUES"]["DOP_TEXT_VALUE"]["VALUE"];

        $keyDoptext = "ADETA_PROP_".$dopText_idSection;

        $elem["LIST_META_DOPTEXT"][$keyDoptext]["type"] = $dopText_type;
        $elem["LIST_META_DOPTEXT"][$keyDoptext]["text"] = $dopText_text;
    }

    return $elem;

}
/* ============================================== */
/* ============================================== */

creacteMeta() — заменяет ключи на реальные значения

К моменту начала работы данной функции мы уже получили все шаблоны и информацию по значениям. На данном этапе у нас 2 массива: в первом информация по значениям, во втором шаблоны для SEO.

Данная функция подставляем значения в ключи и на выходе отдает массив с SEO информацией.

Параметры:

  • $infoFilter — массив с информацией о фильтрации
  • $infoMeta — массив с шаблонами фильтра
  • $categoryCode — символьный код категории
  • $dopSeoKeys — массив с дополнительными ключами

/* ============================================== */
/* ФОРМИРУЕМ META ОПИСАНИЕ ДЛЯ ФИЛЬТРОВ */
/* ============================================== */
function creacteMeta($infoFilter, $infoMeta, $categoryCode, $dopSeoKeys = false) {

    if(!$infoMeta["META_TEMPLATES"][$categoryCode]) {
        $metaCategory = $infoMeta["META_TEMPLATES"]["all_section"];
    }
    else {
        $metaCategory = $infoMeta["META_TEMPLATES"][$categoryCode];
    }

    $strTemplate_title  = $metaCategory["TEMP_SECTION_TITLE"];
    $strTemplate_desc   = $metaCategory["TEMP_SECTION_DESCRIPTION"];
    $strTemplate_h1     = $metaCategory["TEMP_SECTION_HEADING"];
    $strTemplate_dopText = $metaCategory["TEMP_SECTION_DOPTEXT"];

    $arrDopText_forProp = $infoMeta["LIST_META_DOPTEXT"];

    $arrMeta = $infoMeta["LIST_META_PROPS"];

    $fullMetaStr = $strTemplate_title." ".$strTemplate_desc." ".$strTemplate_h1." ".$strTemplate_dopText;

    preg_match_all('/ADETA_PROP_[0-9]+/', $fullMetaStr, $matchesTempMeta);

    $arrReplace = array();
    foreach($matchesTempMeta[0] as $temp) {
        $arrReplace[$temp] = implode(", ", $infoFilter[$temp]["value"]);
    }

    foreach($arrReplace as $temp=>$val) {

        if($arrDopText_forProp[$temp]) {
            if($arrDopText_forProp[$temp]["type"] == "before") {
                $val = $arrDopText_forProp[$temp]["text"]." ".$val;

            }
            else if($arrDopText_forProp[$temp]["type"] == "after") {
                $val .= " ".$arrDopText_forProp[$temp]["text"];
            }
            
        }

        /* преобразуем title */
        $strTemplate_title = str_replace($temp, $val, $strTemplate_title);
        /* преобразуем description */
        $strTemplate_desc = str_replace($temp, $val, $strTemplate_desc);
        /* преобразуем h1 */
        $strTemplate_h1 = str_replace($temp, $val, $strTemplate_h1);
        /* преобразуем описание страницы */
        $strTemplate_dopText = str_replace($temp, $val, $strTemplate_dopText);
    }

    /* ПРЕОБРАЗУЕМ БАЗОВЫЕ SEO КЛЮЧИ */
    if($dopSeoKeys) {
        foreach($dopSeoKeys as $temp=>$val) {
            /* преобразуем title */
            $strTemplate_title = str_replace($temp, $val, $strTemplate_title);
            /* преобразуем description */
            $strTemplate_desc = str_replace($temp, $val, $strTemplate_desc);
            /* преобразуем h1 */
            $strTemplate_h1 = str_replace($temp, $val, $strTemplate_h1);
            /* преобразуем описание страницы */
            $strTemplate_dopText = str_replace($temp, $val, $strTemplate_dopText);
        }
    }

    $metaArray["meta_title"] = $strTemplate_title;
    $metaArray["meta_description"] = $strTemplate_desc;
    $metaArray["meta_h1"] = $strTemplate_h1;
    $metaArray["meta_doptext"] = $strTemplate_dopText;

    foreach($metaArray as $key=>$metaText) {
        $metaArray[$key] = preg_replace('/[\s]{2,}/', ' ', $metaText);
    }

    return $metaArray;

}
/* ============================================== */
/* ============================================== */

createMetaInfo() — функция которая включает в себя работу всех функций

Последняя функция, это собрание все перечисленных функций. Я её создал для того чтобы в нее записать всю работу и в итоге получить массив с полной информацией.

/* ============================================== */
/* ФОРМИРУЕМ ПОЛНОЕ META ОПИСАНИЕ ДЛЯ ФИЛЬТРА */
/* ============================================== */
function createMetaInfo($filterArray, $category = "all_section", $arrDopSeoKeys = false) {

    $arrInfoFilter = getParamsFilter($filterArray);
    $arrMetaQuery = queryMeta($arrInfoFilter, $category);

    /* ЗАМЕНЯЕМ ЗНАЧЕНИЯ В МАССИВЕ С ФИЛЬТРАМИ */
    /* ============================================== */
    foreach($arrMetaQuery["LIST_META_PROPS"] as $idValue=>$text) {
        
        foreach($arrInfoFilter as $key=>$val) {
            if($val["value"][$idValue]) {
                $arrInfoFilter[$key]["value"][$idValue] = $text;
            }
        }

    }
    /* ============================================== */

    $arrMetaInfo["metaTitle"] = creacteMeta($arrInfoFilter, $arrMetaQuery, $category, $arrDopSeoKeys);

    return $arrMetaInfo["metaTitle"];

}
/* ============================================== */
/* ============================================== */

Код для result_modifier

/* МАССИВ ДОП. КЛЮЧЕЙ */
$arrSeoKeys = [
    "ADETA_NAME_SECTION" => $arResult["NAME"]
]; 

/* КОД ТЕКУЩЕГО РАЗДЕЛА */
$sectionCode = $arResult["ORIGINAL_PARAMETERS"]["SECTION_CODE"];

/* ПРЕОБРАЗУЕМ МЕТА ДАННЫЕ НА СТРАНИЦЕ ФИЛЬТРА */
$metaGenerator = createMetaInfo($GLOBALS['arrFilter'], $sectionCode, $arrSeoKeys);
На этом всё!
Больше интересных статей в нашей группе - https://vk.com/progtime
Вы так же можете разместить свой вопрос на нашем форуме, где другие программисты смогут вам помочь в решение вашей задачи - https://vk.com/prog_time
Так же прокачивайте свои навыки на нашем канале - https://www.youtube.com/c/ProgTime
Наши планы
  • Написание материала для курса по разработке ботов на Telegram
  • Разработка универсального парсера на PHP

Поддержите мой сайт!

Каждый переведённый донат, мотивирует на создание новых записей и уроков на YouTube

Контакты для связи

Технология на prog-time
Telegram
https://t.me/prog_time_bot