Как создать товарный фид в WordPress без плагина?

Как создать товарный фид в WordPress без плагина?
разработка wordpress
Обложка Как создать товарный фид в WordPress без плагина?
Автор:
Руслан Шкарбан — автор статьи Руслан Шкарбан
207
#Кейсы

Одним из способов продвижения бизнеса является заполнение и поддержка информации в сервисах карт. В данной статье расскажем о том, как можно без сторонних сервисов и решений улучшить отображение вашей организации на Яндекс картах и 2GIS, добавив для нее товарный фид. Данное руководство актуально, если сайт работает на CMS-системе WordPress (WP).

Начнем с небольшой теории. Товарный фид - файл с информацией о товарах или услугах. Там содержатся: названия, фотографии, цены и характеристики.

Яндекс товарному фиду в документации дает следующее определение: Товарный фид — это файл формата YML с информацией о магазине и товарах. YML (Yandex Market Language) — это собственный стандарт Яндекса, основанный на XML. В товарном фиде можно описать каталог магазина в формате, удобном для автоматической генерации.

Скорее всего, вы постоянно натыкаетесь на товарные фиды разных компаний, но для примера продемонстрируем несколько фидов наших клиентов:

Товарный фид Марс Мебель в Яндекс картах
Товарный фид Марс Мебель
Товарный фид СЗПК78 в Яндекс картах
Товарный фид СЗПК78

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

Решения по товарным фидам от Яндекса

В данном руководстве будет много PHP кода, который в рамках вашего сайта придется серьезно доработать, иначе ничего не получится. Материал подразумевает, что вы знакомы с основными функциями и классами WP такими как: get_terms(); WP_Query(); get_field(); get_post_thumbnail_id() и другими из представленного кода.

Перейдем к написанию собственного товарного фида. Файл с товарным фидом должен лежать в корневой папке сайта, за пределами папок WP.

В качестве примера мы рассмотрим товарный фид, который делали для СЗПК78, пошагово рассмотрим каждый этап создания. Обратите внимание, что в составлении фида мы будем опираться на документацию и примеры.

Шаг 1. Создаем файл и определяем базовые настройки

В корневой папке сайта "/" мы создаем файл yandex.php.

Данный код создаёт XML-документ с правильной кодировкой (UTF-8 + BOM для кириллицы), подключает WordPress для доступа к базе данных, формирует «шапку» YML-файла с названием магазина, URL и текущей датой генерации.


<?php
// Прописываем значения, чтобы файл читался и открывался как XML
header("Content-type: text/xml; charset=UTF-8");
print (pack('CCC', 0xef, 0xbb, 0xbf));
print
"<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE yml_catalog SYSTEM 'shops.dtd'>
<yml_catalog date='".date('Y-m-d H:i')."'>
<shop>
<name>СЗПК78</name>
<url>https://szpk78.ru/</url>
";
// Подключаем библиотеки CMS WordPress
define('WP_USE_THEMES', false);
require_once('wp-load.php');
				

Шаг 2. Добавим категории товаров

Создаём функцию, которая получает и выводит категории товаров из WordPress. Каждая категория выводится с указанием её ID и, если есть, родительской категории. Вызываем для каждой из категорий.


function printCategories($category) {
	$args = array(
		'taxonomy'   => $category,
		'hide_empty' => false,
	);
	$terms = get_terms($args);
	foreach($terms as $item){
		print "<category id='".$item->term_id."'";
		if($item->parent != 0){
			print " parentId='".$item->parent."'";
		}
		print ">".htmlspecialchars(trim($item->name))."</category>\n";
	}
}
				
print "<categories>";
printCategories('garden_cat');
printCategories('package_cat');
printCategories('products_cat');
print "</categories>";
		

Шаг 3. Выводим товары

Получаем опубликованные товары определённого типа и формируем блоки <offer>. В блоках указывается цена, ссылка, категория, изображение, название и описание товара. Если у товара нет цен, он пропускается.


function printOffers($post_type, $category) {
	$args = array(
		'post_type' => $post_type,
		'posts_per_page' => -1,
		'post_status'    => 'publish',
	);
				
	$query = new WP_Query;
	$allproducts = $query->query($args);
				
	foreach($allproducts as $allproduct){
	$pricesArr = get_field('block_price_product', $allproduct->ID);
	if (empty($pricesArr)) continue;
				
	// Определяем конечную категорию товара
	$lastcateg = '';
	if ($categorys = get_the_terms($allproduct->ID, $category)) {
		if (count($categorys) > 1) {
			$arrtemp = array();
			foreach($categorys as $category){
				$arrtemp[] = $category->term_id;
			}
			foreach($arrtemp as $arrtempz){
				$termchildren = get_term_children($arrtempz, $category);
				if ($termchildren == null) {
						$lastcateg = $arrtempz;
						break;
				}
				foreach($termchildren as $child){
					if (!in_array($child, $arrtemp)) {
						$lastcateg = $arrtempz;
						break 2;
						}
					}
				}
			} else {
					$lastcateg = $categorys[0]->term_id;
			}
		}
				
		$product_img = wp_get_attachment_image_src(get_post_thumbnail_id($allproduct->ID), 'full');
				
		foreach ($pricesArr['info_product'] as $price_key => $price) {
			$offer_id = $allproduct->ID + $price_key;
				
			print "<offer id='".$offer_id."' available='true'>";
			print "<url>".get_permalink($allproduct->ID)."</url>";
			print "<price>".$price['price_product']."</price>";
			print "<currencyId>RUR</currencyId>";
			print "<categoryId>".$lastcateg."</categoryId>";
			print "<vendor>СЗПК78</vendor>";
				
			if($product_img[0])
								print "<picture>".$product_img[0]."</picture>";
				
			$product_title = $allproduct->post_title . ' ' . $price['width_product'] . 'х' . $price['length_product'] . 'х' . $price['height_product'] . ' см';
			$product_descr = $allproduct->post_title;
				
			if (!empty($price['explanation'])) {
				$product_title .= ' (' . $price['explanation'] . ')';
				$product_descr .= ' (' . $price['explanation'] . ')';
			}
				
			$product_descr .= '. Размеры: ' . $price['width_product'] . ' см (ширина), ';
			$product_descr .= $price['length_product'] . ' см (длина), ';
			$product_descr .= $price['height_product'] . ' см (высота).';
				
			print "<name>".htmlspecialchars($product_title)."</name>";
			print "<description><![CDATA['".htmlspecialchars(strip_tags($product_descr))."]]></description>";
			print "</offer>";
			}
		}
	}
				
print "<offers>";
printOffers('garden', 'garden_cat');
printOffers('package', 'package_cat');
printOffers('products', 'products_cat');
print "</offers>";
						

Шаг 4. Завершаем генерацию

Закрываем все ранее открытые XML-теги </shop> и </yml_catalog>, завершив генерацию файла.


print "</shop>
</yml_catalog>
";
?>
			

Полный код для удобства:


		<?php
		header("Content-type: text/xml; charset=UTF-8");
		print (pack('CCC', 0xef, 0xbb, 0xbf));
		print "<?xml version='1.0' encoding='UTF-8'?>
		<!DOCTYPE yml_catalog SYSTEM 'shops.dtd'>
		<yml_catalog date='".date('Y-m-d H:i')."'>
		<shop>
		<name>СЗПК78</name>
		<url>https://szpk78.ru/</url>
		";
		
		define('WP_USE_THEMES', false);
		require_once('wp-load.php');
		
		print "<currencies><currency id='RUB' rate='1'/></currencies>";
		
		function printCategories($category) {
			$args=array(
				'taxonomy'   => $category,
				'hide_empty' => false,
			);
			$terms=get_terms($args);
			foreach($terms as $item){
				print "<category id='".$item->term_id."'";
				if($item->parent!=0){
					print " parentId='".$item->parent."'";
				}
				print ">".htmlspecialchars(trim($item->name))."</category>
				";
			}
		}
		
		print "<categories>";
		printCategories('garden_cat');
		printCategories('package_cat');
		printCategories('products_cat');
		print "</categories>";
		
		function printOffers($post_type, $category) {
			$args=array(
				'post_type'      => $post_type,
				'posts_per_page' => -1,
				'post_status'    => 'publish',
			);
		
			$query = new WP_Query;
			$allproducts = $query->query($args);
		
			foreach($allproducts as $allproduct){
				$pricesArr = get_field('block_price_product', $allproduct->ID);
				if (empty($pricesArr)) {  
					continue;
				}
		
				$lastcateg='';
				if($categorys=get_the_terms($allproduct->ID,$category)){
					if(count($categorys)>1){
						$arrtemp=array();
						foreach($categorys as $category){
							$arrtemp[]=$category->term_id;
						}
						foreach($arrtemp as $arrtempz){
							$termchildren=get_term_children($arrtempz,$category);
							if($termchildren==null){
								$lastcateg=$arrtempz;
								break;
							}
							foreach($termchildren as $child){
								if(!in_array($child,$arrtemp)){
									$lastcateg=$arrtempz;
									break 2;
								}
							}
						}     
					}else{
						$lastcateg=$categorys[0]->term_id;
					}
				}  
				
				$product_img=wp_get_attachment_image_src(get_post_thumbnail_id($allproduct->ID),'full');  
			
				foreach ($pricesArr['info_product'] as $price_key => $price) {
					$offer_id = $allproduct->ID+$price_key;
		
					print 
					"
					<offer id='".$offer_id."' available='true'>
					<url>".get_permalink($allproduct->ID)."</url>
					<price>".$price['price_product']."</price>
					<currencyId>RUR</currencyId>
					<categoryId>".$lastcateg."</categoryId>
					<vendor>СЗПК78</vendor>
					";
					
					if($product_img[0])
					print "<picture>".$product_img[0]."</picture>
					";
					
					$product_title = $allproduct->post_title;
					$product_title .= ' ' . $price['width_product'] . 'х' . $price['length_product'] . 'х' . $price['height_product'] . ' см';
		
					$product_descr = $allproduct->post_title;
					if (!empty($price['explanation'])) {
						$product_title .= ' (' . $price['explanation'] . ')';
						$product_descr .= ' (' . $price['explanation'] . ')';
					}
					$product_descr .= '. Размеры: ' . $price['width_product'] . ' см (ширина), ';
					$product_descr .= $price['length_product'] . ' см (длина), ';
					$product_descr .= $price['height_product'] . ' см (высота).';
		
					print "<name>".htmlspecialchars($product_title)."</name>
					<description><![CDATA['".htmlspecialchars(strip_tags($product_descr))."]]></description>
					</offer>
					";
				}
			
			}
		}
		
		print "<offers>";
		printOffers('garden', 'garden_cat');
		printOffers('package', 'package_cat');
		printOffers('products', 'products_cat');
		print "</offers>";
		
		print "</shop>
		</yml_catalog>
		";
		?>
		

Проверим работу нашего фида

Чтобы проверить, как прошла генерация нам нужно в браузере перейти по адресу: доменное имя/название файла. В нашем случае szpk78.ru/yandex.php. Если все сделано верно, то на странице вы увидите xml файл с информацией о продукции.

Товарный фид СЗПК78 в браузере

Публикация фида в сервисы карты

Яндекс карты

На момент написания данного материала Яндекс принимает файл в расширении xml. Чтобы получить файл нам нужно сохранить страницу, это можно сделать сочетанием клавиш "ctrl(command)+s" или "ctrl(command)+shift+s". Будет скачан файл с расширением php, вручную меняем расширение в xml.

Если на прошлых этапах проблем не возникло, то переходим к отправке фида в сервисы карт. Для того, чтобы опубликовать товары в яндекс картах нужно авторизоваться в яндекс бизнесе с аккаунта, с которым связана ваша организация. Затем, открыть вкладку "О компании" и там выбрать "товары и услуги". В открывшемся окне жмем на кнопку "Загрузить XLS/YML" и добавить наш файл.

Товарный фид СЗПК78 публикация в яндексе

После недолгой модерации товары будут загружены или отобразится ошибка.

Товарный фид СЗПК78 в яндексе

2GIS

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

После авторизации переходим по "Моя компания/Товары и услуги". Дальнейшие шаги схожи с Яндекс картами, но отметим, что тут мы можем передать урл нашего фида. Таким образом, обновляя данные в файле, он автоматически будет обновляться и в 2GIS, примерно раз в сутки.

Товарный фид СЗПК78 загрузка в 2гис

Если у вас не было проблем с публикацией в Яндексе, то не должно быть и тут. После модерации должны появиться товары:

Товарный фид СЗПК78 в 2гис

В данной статье мы разобрались как создать товарный фид для сервисов карт без использования сторонних решений и сервисов, а затем разместить в Яндексе и 2GIS.