XML карта сайта на WordPress без плагинов moneyinnetwork_xml_sitemap

16.12.2016 в 17:02
admin
Аватар админа
Регистрация: 17.02.2011
Сообщений: 4565
Рейтинг: 3593

Пару дней назад решил избавиться еще от одного увесистого и прожорливого плагина, который строил XML карту сайта на WordPress, причем, несмотря на множество настроек и отличную репутацию среди вебмастеров, этот плагин никак не хотел добавлять к карте дочерние страницы. Вернее, он их добавлял, но при этом уровень вложенности был не более одной страницы и то работало это как-то избирательно (кстати, соответствующую опцию в настройках я активировал). Плагин этот Google XML Sitemaps (может, у меня версия была не последняя, кто знает).

На эту проблему я обратил внимание несколько дней назад. Причем, очевидной лично для меня она стала в тот момент, когда я реализовал у себя на сайте этот простецкий форум, создал несколько разделов и тем и увидел, что в карте-то sitemap.xml нифига нет моих форумных страниц с темами. Во дела, подумал я, и, имея начальный опыт в программировании на php и mysql, решил-таки, что мне нужна XML карта сайта на WordPress без всяких там плагинов, чтобы я точно знал: что, как, куда, откуда и почему :) .

Порывшись в закромах интернета, подобных решений не нашел. Все вебмастера в сети, на которых меня выводил “Яша”, использовали готовые “плагинные” решения для XML карт WordPress. Засучив рукава, приступил к ночному ваянию кода (днем-то дела несколько иного плана). Вот, собственно, то, что вышло:

//обсуждение функции построения XML карт сайтов moneyinnetwork_xml_sitemap ведется на сайте автора в теме:
//https://moneyinnetwork.ru/forum/sajtostroenie-sistemy-upravleniya-sajtom-seo/vse-o-vordpress-wordpress/xml-karta-sajta-na-wordpress-bez-plaginov-moneyinnetwork_xml_sitemap
function moneyinnetwork_xml_sitemap ($home_priority='1.0', $page_priority='0.6', $post_priority='0.6', $other_priority = '0.3')
{
   global $wpdb;
   $result = $wpdb->get_results("SELECT ID, post_modified_gmt, post_type FROM $wpdb->posts WHERE post_status='publish' ORDER BY post_modified_gmt DESC", 'ARRAY_A');
   if( !empty($result) ) 
   {
      $f = '<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9">';
      $i = 0;
      foreach ($result as $row)   
      {
         $priority = $other_priority;
         if ( $row['post_type'] == 'page' ) $priority = $page_priority; 
         if ( $row['post_type'] == 'post' ) $priority = $post_priority;
         if ( $i == 0 )
         {
            $f = $f.'<url><loc>'.get_home_url().'</loc><lastmod>'.date('c', strtotime($row['post_modified_gmt'])).'</lastmod><changefreq>daily</changefreq><priority>'.$home_priority.'</priority></url>';
            $i = 1;
         }
         $f = $f.'<url><loc>'.get_permalink($row['ID']).'</loc><lastmod>'.date('c', strtotime($row['post_modified_gmt'])).'</lastmod><changefreq>daily</changefreq><priority>'.$priority.'</priority></url>';               						
      }
      $f = $f.'</urlset>';
      $fp = fopen($_SERVER['DOCUMENT_ROOT'].'/sitemap.xml', 'w');
      fwrite($fp, $f);
      fclose($fp);
      $result = wp_remote_get('https://www.google.com/ping?sitemap='.get_home_url().'/sitemap.xml');
      if ( ! is_wp_error( $result ) || wp_remote_retrieve_response_code( $result ) === 200 )
      {
         //Карта успешно отправлена в Google. 
         //Это просто под будущие разработки, если надо, конечно.
      }
   }
   return;
}

Итак, функция moneyinnetwork_xml_sitemap() строит XML карту сайта на WordPress, сохраняет ее в корневой директории сайта и “пингует” (отправляет) ее в Google (“примочка”, наверное, бесполезная, если у Вас есть кабинет вебмастера в Google, где Вы явно прописали карту сайта). Функцию moneyinnetwork_xml_sitemap() “укладываем” к функциям темы, то есть размещаем ее в functions.php.

Теперь оставалась задача за малым. Необходимо было сделать так, чтобы эта функция создавала новую XML карту сайта когда мы публикуем (обновляем) страницы и записи, а также когда эти страницы и записи удаляем. Для этого зарегистрируем нашу функцию, чтобы она выполнялась в тот момент, когда происходит одно из вышеуказанных событий. Установим функции низкий приоритет (1000) и не будем передавать ей никаких параметров (0 – число параметров, которые будет принимать наша функция. Приоритеты для страниц карты мы зададим в самой функции – это будут параметры по умолчанию).

add_action('delete_post', moneyinnetwork_xml_sitemap, 1000, 0);
add_action('publish_post', moneyinnetwork_xml_sitemap, 1000, 0);
add_action('publish_page', moneyinnetwork_xml_sitemap, 1000, 0);

Эти три строчки размещаем также в functions.php.

Вообще, функция moneyinnetwork_xml_sitemap() может принимать четыре параметра:

  • home_priority – приоритет главной страницы сайта (по умолчанию 1.0)
  • page_priority – приоритет для постоянных страниц (по умолчанию 0.6)
  • post_priority – приоритет для статей (по умолчанию 0.6)
  • other_priority – приоритет для других типов записей (по умолчанию 0.3)

Можно, конечно, добавить пару строчек в код и реализовать варьируемый в зависимости от даты модификации страниц приоритет их индексации, чтобы более новые страницы (измененные страницы) быстрее попали в индекс. При этом старым страницам можно задать минимальную нижнюю границу приоритета индексации, скажем, 0.2 или 0.3. В общем, если есть в этом необходимость, то реализовать это достаточно легко.

XML карта сайта на WordPress без плагинов теперь есть.

Поделиться в соц. сетях:
Получать информацию о новых темах:
Ответов в теме: 11 Просмотров темы: 2026

20.12.2016, в 18:44
admin
Аватар админа
Регистрация: 17.02.2011
Сообщений: 4565
Рейтинг: 3593
#1

admin 16.12.2016 в 17:02:
Можно, конечно, добавить пару строчек в код и реализовать варьируемый в зависимости от даты модификации страниц приоритет их индексации, чтобы более новые страницы (измененные страницы) быстрее попали в индекс. При этом старым страницам можно задать минимальную нижнюю границу приоритета индексации

Дописываю “пару строчек” кода и делаю функцию построения XML карты сайта с возможностью расчета приоритета для каждой страницы-записи:

//обсуждение функции построения XML карт сайтов moneyinnetwork_xml_sitemap ведется на сайте автора в теме:
//https://moneyinnetwork.ru/forum/sajtostroenie-sistemy-upravleniya-sajtom-seo/vse-o-vordpress-wordpress/xml-karta-sajta-na-wordpress-bez-plaginov-moneyinnetwork_xml_sitemap
function moneyinnetwork_xml_sitemap ($home_priority='1.0', $page_priority='1.0', $post_priority='0.6', $other_priority = '0.3', $auto=true)
{
	global $wpdb;
	$result = $wpdb->get_results("SELECT ID, post_modified_gmt, post_type FROM $wpdb->posts WHERE post_status='publish' ORDER BY post_modified_gmt DESC", 'ARRAY_A');
	if( !empty($result) ) 
	{
		$f = '<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9">';
		$i = 0;
		$date1 = date_create(date('c'));
		foreach ($result as $row)   
		{
			if ( $auto )
			{
				$date2 = date_create($row['post_modified_gmt']);
				$interval = date_diff($date1, $date2);
				$priority = '0.3';
				if ( $interval->days <= 30 ) 							$priority = '1.0';
				if ( $interval->days > 30 && $interval->days <= 60 ) 	$priority = '0.8';
				if ( $interval->days > 60 && $interval->days <= 90 ) 	$priority = '0.6';
			}
			else
			{
				$priority = $other_priority;
				if ( $row['post_type'] == 'page' ) $priority = $page_priority; 
				if ( $row['post_type'] == 'post' ) $priority = $post_priority;
			}
			if ( $i == 0 )
			{
				$f = $f.'<url><loc>'.get_home_url().'</loc><lastmod>'.date('c', strtotime($row['post_modified_gmt'])).'</lastmod><changefreq>daily</changefreq><priority>'.$home_priority.'</priority></url>';
				$i = 1;
			}
			$f = $f.'<url><loc>'.get_permalink($row['ID']).'</loc><lastmod>'.date('c', strtotime($row['post_modified_gmt'])).'</lastmod><changefreq>daily</changefreq><priority>'.$priority.'</priority></url>';               						
		}
		$f = $f.'</urlset>';
		$fp = fopen($_SERVER['DOCUMENT_ROOT'].'/sitemap.xml', 'w');
		fwrite($fp, $f);
		fclose($fp);
		$result = wp_remote_get('https://www.google.com/ping?sitemap='.get_home_url().'/sitemap.xml');
		if ( ! is_wp_error( $result ) || wp_remote_retrieve_response_code( $result ) === 200 )
		{ /* карта успешно отправлена в google */ }
	}
	return;
}

Параметр функции auto будет определять разрешение/запрещение автоматического вычисления приоритета индексации для страниц XML карты в зависимости от их “возраста”.
Так, для записей не старше 30 дней приоритет 1.0, для записей давностью от 31 до 60 дней – 0.8, от 61 до 90 дней – 0.6, для более ранних – 0.3.

+15 + -
Цитировать Ответить

23.02.2017, в 01:53
Алексеев
Аватар гостя
Регистрация: нет
Сообщений: 17
Рейтинг: 24
#2

Вы воистину универсал. Легко программируете как на php так и на mql. Я все сделал по вашим рекомендациям на своем блоге. Все отлично работает. Но думаю, для больших проектов с многими тысячами страниц такой вариант не подойдет. Так как скрипт будет выполняться слишком долго. А для большинства блогов – это настоящая находка. Еще раз спасибо.

+1 + -
Цитировать Ответить

16.05.2018, в 21:05
Лев
Аватар гостя
Регистрация: нет
Сообщений: 3
Рейтинг: 2
#3

Здравствуйте!
подскажите, почему яндекс не понимает эту карту?
Тип файла Неизвестный
Размер 34,7 КБ
Количество ссылок 0
Также вопрос, как убрать переадресацию с /sitemap.xml на главную сайта?

+ -
Цитировать Ответить

16.05.2018, в 22:05
admin
Аватар админа
Регистрация: 17.02.2011
Сообщений: 4565
Рейтинг: 3593
#4

Здравствуйте, Лев.
Карта, построенная этой функцией, у меня всегда принималась Яндексом.
Вот, только что запустил анализатор:
Результаты анализа «https://moneyinnetwork.ru/sitemap.xml»
Тип файла Файл Sitemap
Размер 48,79 КБ
Количество ссылок 237

Лев Сегодня, в 21:05:
Также вопрос, как убрать переадресацию с /sitemap.xml на главную сайта?

Посмотрите нет ли в файле .htaccess (корневая директория сайта) строчки, начинающейся на RewriteRule ^sitemap.xml$ ? Т.е. той самой переадресации.

+1 + -
Цитировать Ответить

17.05.2018, в 13:51
Лев
Аватар гостя
Регистрация: нет
Сообщений: 3
Рейтинг: 2
#5

Здравствуйте!
в файле .htaccess такого правила нету. Странная ситуация. Я уже все просмотрел, нигде явно указаного редиректа нету. CMS WordPress.

+ -
Цитировать Ответить

17.05.2018, в 22:53
admin
Аватар админа
Регистрация: 17.02.2011
Сообщений: 4565
Рейтинг: 3593
#6

Лев Сегодня, в 13:51:
в файле .htaccess такого правила нету. Странная ситуация

Лев, значит, редирект есть на уровне CMS. Возможно, какой-то плагин редиректит. Ничего не стоит из SEO-плагинов?

Лев Вчера, в 21:05:
почему яндекс не понимает эту карту?

Не поэтому ли Яндекс карту не принимает, потому что редирект идет с карты на главную? Если в корневой папке сайта на хостинге посмотреть содержимое файла sitemap.xml, то там, наверняка, все в норме.

+1 + -
Цитировать Ответить

18.05.2018, в 08:15
Лев
Аватар гостя
Регистрация: нет
Сообщений: 3
Рейтинг: 2
#7

УРА! Заработал!
У меня стоял плагин Google XML Sitemaps, после того, как нашел Вашу статью, решил его убрать. Из админки его удалил и поставил код, который Вы написали. После этого произошло, то что писал выше.

admin Сегодня, в 22:53:
Не поэтому ли Яндекс карту не принимает, потому что редирект идет с карты на главную?

Да, Вы правы. Яндекс и Гугл не понимал, почему вместо карты ему подсовывают страницу html.
Полдня вчера потратил на поиски этого редиректа. Отключал другие плагины, чистил БД, вобщем сделал все, что знал и нашел в гугле. В конце концов отчаявшись вернул обратно Google XML Sitemaps и полез в настройки. Снял все галочки, обновил и деактивировал. И ура, код заработал. В чем причина была я так и не понял. У меня есть подозрение, что этот плагин создает виртуальный robots, но где он его создает я не нашел.
Спасибо Вам за код и за помощь в поиске проблемы.

+2 + -
Цитировать Ответить

28.06.2018, в 00:31
Сергунок
Аватар гостя
Регистрация: нет
Сообщений: 1
Рейтинг: 0
#8

AND post_type=’page’
без этого в сайтмапе весь мусор будет!

+ -
Цитировать Ответить

29.11.2019, в 11:54
Женя
Аватар гостя
Регистрация: нет
Сообщений: 1
Рейтинг: 0
#9

Доброго времени,

скажите, можно ли реализовать следующее → в главном sitemap.xml ссылки ведут на следующие карты, например: sitemap-pages.xml, sitemap-posts.xml и т.д. (будет указано название карты и когда последний раз изменялась она) и уже внутри них список непосредственно постов/страниц по вашему коду.

+ -
Цитировать Ответить

15.12.2019, в 19:32
admin
Аватар админа
Регистрация: 17.02.2011
Сообщений: 4565
Рейтинг: 3593

Сергунок 28.06.2018, в 00:31:
AND post_type=’page’
без этого в сайтмапе весь мусор будет!

В таком случае в выборку из базы по запросу попадут только страницы, а, например, записи типа ‘post’ уже не попадут. Кроме того, возможны варианты, когда необходимо работать с произвольным (пользовательским) типом записей (например, форум средствами движка WP, вопросы-ответы и т.п.).
Разумеется, выборку можно ограничить путем внесения условия AND post_type=… Все на усмотрение конкретного пользователя. Добавлено сообщение 15.12.2019, в 20:03

Женя 29.11.2019, в 11:54:
Доброго времени,
скажите, можно ли реализовать

Здравствуйте.
Я так понимаю, речь идет об использование файлов индекса Sitemap (группа из нескольких файлов Sitemap).
Принципиально сложного нет. Мое видение алгоритма такое:
1. Читаем базу записей (делаем выборку из базы).
2. Определяем типы записей (type1, type2, type3, …).
3. Создаем файл sitemap.xml с группами файлов Sitemap из этих записей: sitemap-type1.xml, sitemap-type2.xml, sitemap-type3.xml, … (смотрим формат этого файла в соответствующих мануалах).
4. Создаем карту каждой группы: sitemap-type1.xml, sitemap-type2.xml, sitemap-type3.xml, …
5. Укладываем ссылки на записи в эти файлы по группам.

+ -
Цитировать Ответить

16.12.2019, в 00:12
admin
Аватар админа
Регистрация: 17.02.2011
Сообщений: 4565
Рейтинг: 3593

Вот такой вариант с группами из нескольких файлов Sitemap (разбивка по типам записей)

function moneyinnetwork_xml_sitemap ($home_priority='1.0', $page_priority='1.0', $post_priority='0.6', $other_priority = '0.3', $auto=true)
{
	global $wpdb;
	$result = $wpdb->get_results("SELECT ID, post_modified_gmt, post_type FROM $wpdb->posts WHERE post_status='publish' ORDER BY post_modified_gmt DESC", 'ARRAY_A');
	if(!empty($result)) 
	{
		$post_types = array();
		foreach ($result as $row) 
		{
			if (!in_array($row['post_type'], $post_types)) 
				$post_types[] = $row['post_type'];    
		}
		if (!empty($post_types))
		{
			$f = '<?xml version="1.0" encoding="UTF-8"?><sitemapindex xmlns="https://www.sitemaps.org/schemas/sitemap/0.9">';
			foreach ($post_types as $post_type)
			{
				$f = $f.'<sitemap><loc>'.get_home_url().'/sitemap-'.$post_type.'.xml</loc><lastmod>'.date('c').'</lastmod></sitemap>';
			}	
			$f=$f.'</sitemapindex>';
			$fp = fopen($_SERVER['DOCUMENT_ROOT'].'/sitemap.xml', 'w');
			fwrite($fp, $f);
			fclose($fp);
			reset($post_types);
			foreach ($post_types as $post_type)
			{
				reset($result);
				$f = '<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9">';
				$i = 0;
				$date1 = date_create(date('c'));
				foreach ($result as $row)   
				{
					if ($row['post_type'] == $post_type)
					{
						if ($auto)
						{	
							$date2 = date_create($row['post_modified_gmt']);
							$interval = date_diff($date1, $date2);
							$priority = '0.3';
							if ( $interval->days <= 30 ) 							$priority = '1.0';
							if ( $interval->days > 30 && $interval->days <= 60 ) 	$priority = '0.8';
							if ( $interval->days > 60 && $interval->days <= 90 ) 	$priority = '0.6';
						}
						else
						{
							$priority = $other_priority;
							if ($row['post_type'] == 'page') $priority = $page_priority; 
							if ($row['post_type'] == 'post') $priority = $post_priority;
						}
						if ($i == 0)
						{
							$f = $f.'<url><loc>'.get_home_url().'</loc><lastmod>'.date('c', strtotime($row['post_modified_gmt'])).'</lastmod><changefreq>daily</changefreq><priority>'.$home_priority.'</priority></url>';
							$i = 1;
						}
						$f = $f.'<url><loc>'.get_permalink($row['ID']).'</loc><lastmod>'.date('c', strtotime($row['post_modified_gmt'])).'</lastmod><changefreq>daily</changefreq><priority>'.$priority.'</priority></url>';
					}
				}
				$f = $f.'</urlset>';
				$fp = fopen($_SERVER['DOCUMENT_ROOT'].'/sitemap-'.$post_type.'.xml', 'w');
				fwrite($fp, $f);
				fclose($fp);
			}
			$result = wp_remote_get('https://www.google.com/ping?sitemap='.get_home_url().'/sitemap.xml');
			if (!is_wp_error($result) || wp_remote_retrieve_response_code($result) === 200)
			{ /* карта успешно отправлена в google */ }
		}
	}
	return;
}
+ -
Цитировать Ответить


Подписаться без комментирования