SEO мета-теги без плагінів: title, description, robots, Open Graph

Є багато плагінів для SEO, але майже всі з них головне завдання – це створити SEO мета-теги (метадані) для сторінки: title, description, robots, Open Graph. Іноді є сенс не підключати подібні плагіни, а використовувати свій невеликий код – з ним простіше керуватися і вирішувати нестандартні завдання… У цій статті я поділяюсь своїм «велосипедом» у цій галузі.

Код нижче був написаний вже давно для статті: Порівняння СЕО плагінів platinum SEO Pack і All in One SEO Pack . І, незважаючи на те, що є плагіни, раз у раз з’являється необхідність користуватися цим кодом. Він використовується іноді як альтернатива, і судячи з коментарів це буває потрібно не тільки мені. Тому було ухвалено стратегічне рішення smileвинести цей код в окрему статтю та підтримувати його вже тут.

Одна з переваг цього коду над плагінами – зрозумілість та максимальна простота. Все робиться через хуки і тут і в плагінах, тільки знайти потрібних хук у плагіні зазвичай займає більше часу. Крім того, ви можете переписати частину коду під своє конкретне завдання.

Якщо ви не розумієтеся на PHP, то настійно рекомендую використовувати SEO плагіни – це набагато зручніше! Втім, іноді плагіни зручніші і для тих, хто знає PHP, я припустимо не завжди юзаю цей код, і плагінами на кшталт SEO Yoast не гидую.

Код виведення title, description, robots, Open Graph, twitter

Базове завдання SEO плагінів – це дати можливість створювати чотири метаполі для сторінки: title, description, robots та keywords. А також створення додаткових Open Graph даних.

Код, який все це реалізує (див. коментарі у коді):

GitHub

<?php

/**
 * Simple SEO class for WordPress для створення page metatags:
 * title, description, robots, keywords, Open Graph.
 *
 * IMPORTANT! Since version 1.7.0 robots code logic chenged. Changed your code after update!
 * IMPORTANT! Since version 1.8.0 title code logic chenged. Changed your code after update!
 *
 * @see https://github.com/doiftrue/Kama_SEO_Tags
 *
 * @author Kama
 *
 * @version 1.9.11
 */
class Kama_SEO_Tags {

	static function init(){

		// force WP document_title function to run
		add_theme_support( 'title-tag');
		add_filter( 'pre_get_document_title', [__CLASS__, 'meta_title'], 1);

		add_action( 'wp_head', [ __CLASS__, 'meta_description' ], 1 );
		add_action( 'wp_head', [ __CLASS__, 'meta_keywords' ], 1 );
		add_action( 'wp_head', [__CLASS__, 'og_meta'], 1); // Open Graph, twitter дані

		// WP 5.7+
		add_filter( 'wp_robots', [__CLASS__, 'wp_robots_callback'], 11);
	}

	/**
	 * Open Graph, twitter data в `<head>`.
	 *
	 * @See Documentation: http://ogp.me/
	 */
	static function og_meta(){

		$obj = get_queried_object();

		if( isset( $obj->post_type ) ) $post = $obj;
		elseif( isset( $obj->term_id ) ) $term = $obj;

		$ is_post = isset ($ post);
		$ is_term = isset ($ term);

		$title = self::meta_title();
		$desc = preg_replace( '/^.+content="([^"]*)".*$/s', '$1', self::meta_description() );

		// Open Graph
		$els = [];
		$els['og:locale'] = get_locale();
		$els['og:site_name'] = get_bloginfo('name');
		$els['og:title'] = $title;
		$els['og:description'] = $desc;
		$els['og:type'] = is_singular() ? 'article': 'object';

		// og:url
		if( 'url' ){

			if( $is_post ) $url = get_permalink( $post );
			if( $is_term ) $url = get_term_link( $term );

			if( ! empty( $url ) ){

				$els['og:url'] = $url;

				// relative (not allowed)
				if( '/' === $url[0] ){

					// без протоколу тільки: //domain.com/path
					if( substr( $url, 0, 2 ) === '//' ){
						$els['og:url'] = set_url_scheme($url);
					}
					// без вдома
					else {
						$parts = wp_parse_url($url);
						$els['og:url'] = home_url( $parts['path'] ) . ( isset( $parts['query'] ) ? "?{$parts['query']}" : '' );
					}
				}

			}
		}

		/**
		 * Allow to disable `article:section` property.
		 *
		 * @param bool $is_on
		 */
		if( apply_filters( 'kama_og_meta_show_article_section', true ) && is_singular() ){
			$post_taxname = get_object_taxonomies( $post->post_type );

			if( $post_taxname ){

				$post_terms = get_the_terms( $post, reset( $post_taxname ) );
				if( $post_terms && $post_term = array_shift( $post_terms ) ){
					$els['article:section'] = $post_term->name;
				}
			}
		}

		// og:image
		if( 'image' ){

			/**
			 * Allow to change `og:image` `og:image:width` `og:image:height` values.
			 *
			 * @param int|string|array|WP_Post $image_data WP attachment ID or Image URL or Array [ image_url, width, height ].
			 */
			$image = apply_filters( 'pre_kama_og_meta_image', null );

			if(! $image) {

				$attach_id_from_text__fn = static function( $text ){

					if(
						preg_match( '/<img +src *= *['"]([^'"]+)['"]/', $text, $mm )
						&&
						( '/' === $mm[1][0] || strpos($mm[1], $_SERVER['HTTP_HOST']) )
					) {
						$ name = basename ($ mm [1]);
						$name = preg_replace( '~-[0-9]+x[0-9]+(?=..{2,6})~', '', $name ); // Видалимо розмір (-80x80)
						$name = preg_replace( '~.[^.]+$~', '', $name ); // видалимо розширення
						$name = sanitize_title( sanitize_file_name( $name ) );

						Global $wpdb;
						$attach_id = $wpdb->get_var( $wpdb->prepare(
							"SELECT ID FROM $wpdb->posts WHERE post_name = %s AND post_type = 'attachment'", $name
						)));

						return (int) $attach_id;
					}

					return 0;
				};

				if($is_post) {

					$image = get_post_thumbnail_id($post);

					if(! $image) {

						/**
						 * Натисніть на turn off the image search in post content.
						 *
						 * @param bool $is_on
						 */
						if( apply_filters( 'kama_og_meta_thumb_id_find_in_content', true ) ){

							$image = $attach_id_from_text__fn( $post->post_content );

							// Перше вкладення посту
							if(! $image) {

								$ attach = get_children ([
									'numberposts' => 1,
									'post_mime_type' => 'image',
									'post_type' => 'attachment',
									'post_parent' => $post->ID,
								]);

								if( $attach && $attach = array_shift( $attach ) ){
									$image = $attach->ID;
								}
							}
						}
					}
				}
				elseif( $is_term ){

					$ image = get_term_meta ($ term-> term_id, '_thumbnail_id', 1);

					if(! $image)
						$image = $attach_id_from_text__fn( $term->description );
				}

				/**
				 * Allow to set `og:image` `og:image:width` `og:image:height` values ​​if it's not.
				 *
				 * @param int|string|array|WP_Post $image WP attachment ID or Image URL or [ image_url, width, height ] array.
				 */
				$image = apply_filters( 'kama_og_meta_image', $image );
				$image = apply_filters( 'kama_og_meta_thumb_id', $image ); // backcompat
			}

			if($image) {

				if(
					$image instanceof WP_Post
					||
					( is_numeric( $image ) && $image = get_post( $image ) )
				) {

					// full size
					[
						$els['og:image[1]'],
						$els['og:image[1]:width'],
						$els['og:image[1]:height'],
						$els['og:image[1]:alt'],
						$els['og:image[1]:type']
					] = array_merge(
						array_slice( image_downsize( $image->ID, 'full' ), 0, 3 ),
						[ $image->post_excerpt, $image->post_mime_type ]
					);

					if( ! $els['og:image[1]:alt'] ){
						unset( $els['og:image[1]:alt'] );
					}

					// thumbnail size
					[
						$els['og:image[2]'],
						$els['og:image[2]:width'],
						$els['og:image[2]:height']
					] = array_slice( image_downsize( $image->ID, 'thumbnail' ), 0, 3 );
				}
				elseif( is_array( $image ) ){
					[
						$els['og:image[1]'],
						$els['og:image[1]:width'],
						$els['og:image[1]:height']
					] = $ image;
				}
				else {
					$els['og:image[1]'] = $image;
				}

			}

		}

		// twitter
		$els['twitter:card'] = 'summary';
		$els['twitter:title'] = $els['og:title'];
		$els['twitter:description'] = $els['og:description'];
		if( ! empty( $els['og:image[1]'] ) ){
			$els['twitter:image'] = $els['og:image[1]'];
		}

		/**
		 * Застосовують зміна величини ог / twitter meta properties.
		 *
		 * @param array $els
		 */
		$els = apply_filters( 'kama_og_meta_elements_values', $els );
		$els = array_filter( $els );
		ksort($els);

		// make <meta> tags
		$ Metas = [];
		foreach( $els as $key => $val ){

			// og:image[1] > og:image || og:image[1]:width > og:image:width
			$fixed_key = preg_replace( '/[d]/', '', $key );

			if( 0 === strpos( $key, 'twitter:' ) )
				$metas[] = '<meta name="' . $fixed_key . '" content="' . esc_attr( $val ) . '" />';
			else
				$metas[] = '<meta property="' . $fixed_key . '" content="' . esc_attr( $val ) . '" />';
		}

		/**
		 * Filter resulting properties. Натисніть на будь-який інший або більше повідомлень / twitter properties.
		 *
		 * @param array $els
		 */
		$metas = apply_filters( 'kama_og_meta_elements', $metas, $els );

		echo "n". implode("n", $metas). "nn";
	}

	/**
	 * Generate string to show as document title.
	 *
	 * Для повідомлень і taxonomies specific title може бути визначений як metadata with name `title`. *
	 *
	 * @param string $title `pre_get_document_title` passed value.
	 *
	 * @return string
	 */
	static function meta_title( $title = '' ){
		global $post;

		// support for `pre_get_document_title` hook.
		if($title)
			return $title;

		static $cache; if( $cache ) return $cache;

		$l10n = apply_filters( 'kama_meta_title_l10n', [
			'404' => 'Помилка 404: такої сторінки не існує',
			'search' => 'Результати пошуку на запит: %s',
			'compage' => 'Коментарі %s',
			'author' => 'Статті автора: %s',
			'archive' => 'Архів за',
			'paged' => 'Сторінка %d',
		]);

		$parts = [
			'prev' => '',
			'title' => '',
			'page' => '',
			'after' => '',
		];

		// 404
		if( is_404() ){
			$parts['title'] = $l10n['404'];
		}
		// search
		elseif( is_search() ){
			$parts['title'] = sprintf( $l10n['search'], get_query_var( 's' ) );
		}
		// front_page
		elseif( is_front_page() ){

			if( is_page() && $parts['title'] = get_post_meta( $post->ID, 'title', 1 ) ){
				// $parts['title'] defined
			}
			else {
				$parts['title'] = get_bloginfo( 'name', 'display' );
				$parts['after'] = '{{description}}';
			}
		}
		//Singular
		elseif( is_singular() || ( is_home() && ! is_front_page() ) || ( is_page() && ! is_front_page() ) ){

			$parts['title'] = get_post_meta( $post->ID, 'title', 1);

			if( ! $parts['title'] ){
				/**
				 * Натиснути на meta meta title для окремого типу сторінки, до default title буде йти.
				 *
				 * @param string $title
				 * @param WP_Post $post
				 */
				$parts['title'] = apply_filters( 'kama_meta_title_singular', '', $post );
			}

			if( ! $parts['title'] ){
				$parts['title'] = single_post_title('', 0);
			}

			if( $cpage = get_query_var( 'cpage' ) ){
				$parts['prev'] = sprintf( $l10n['compage'], $cpage );
			}
		}
		//post_type_archive
		elseif( is_post_type_archive() ){
			$parts['title'] = post_type_archive_title('', 0);
			$parts['after'] = '{{blog_name}}';
		}
		// taxonomy
		elseif( is_category() || is_tag() || is_tax() ){
			$term = get_queried_object();

			$parts['title'] = $term? get_term_meta( $term->term_id, 'title', 1) : '';

			if( ! $parts['title'] ){
				$parts['title'] = single_term_title('', 0);

				if( is_tax() ){
					$parts['prev'] = get_taxonomy( $term->taxonomy )->labels->name;
				}
			}

			$parts['after'] = '{{blog_name}}';
		}
		// author posts archive
		elseif( is_author() ){
			$parts['title'] = sprintf( $l10n['author'], get_queried_object()->display_name );
			$parts['after'] = '{{blog_name}}';
		}
		// date archive
		elseif( ( get_locale() === 'ru_RU' ) && ( is_day() || is_month() || is_year() ) ){
			$rus_month = [
				'', 'січень', 'лютий', 'березень', 'квітень', 'травень', 'червень',
				'липень', 'серпень', 'вересень', 'жовтень', 'листопад', 'грудень'
			];
			$rus_month2 = [
				'', 'січня', 'лютого', 'березня', 'квітня', 'травня', 'червня',
				'липня', 'серпня', 'вересня', 'жовтня', 'листопада', 'грудня'
			];
			$year = get_query_var('year');
			$monthnum = get_query_var('monthnum');
			$day = get_query_var('day');

			if( is_year() ) $dat = "$year рік";
			elseif( is_month() ) $dat = "{$rus_month[ $monthnum ]} $year року";
			elseif( is_day() ) $dat = "$day {$rus_month2[ $monthnum ]} $year року";

			$parts['title'] = sprintf( $l10n['archive'], $dat);
			$parts['after'] = '{{blog_name}}';
		}
		// інші архіви
		else {
			$parts['title'] = get_the_archive_title();
			$parts['after'] = '{{blog_name}}';
		}

		// pagination
		$pagenum = get_query_var('paged')?: get_query_var('page');
		if( $pagenum && ! is_404() ){
			$parts['page'] = sprintf( $l10n['paged'], $pagenum );
		}

		/**
		 * Натисніть на зміну елементів у документі title.
		 *
		 * @param array $parts Title parts. It then will be joined.
		 * @param array $l10n Localisation strings.
		 */
		$parts = apply_filters( 'kama_meta_title_parts', $parts, $l10n);

		/** Цей filter is documented в wp-includes/general-template.php */
		$parts = apply_filters( 'document_title_parts', $parts);

		// handle placeholders
		if( '{{blog_name}}' === $parts['after'] ){
			$parts['after'] = get_bloginfo( 'name', 'display' );
		}
		elseif( '{{description}}' === $parts['after'] ){
			$parts['after'] = get_bloginfo( 'description', 'display' );
		}

		/** Цей filter is documented в wp-includes/general-template.php */
		$sep = apply_filters( 'document_title_separator', '-' );

		$title = implode(''. trim( $sep ) .' ', array_filter( $parts ) );

		//$title = wptexturize($title);
		//$title = convert_chars($title);
		$title = esc_html($title);
		$title = capital_P_dangit($title);

		return $cache = $title;
	}

	/**
	 * Display `description` metatag.
	 *
	 * Must be used on hook `wp_head`.
	 *
	 * Use `description` meta-field до set description for any posts.
	 * Вона також працює на сторінці, яку встановлюють як сторінку.
	 *
	 * Use `meta_description` meta-field до set description for any terms.
	 * або use default `description` field of a term.
	 *
	 * @return string Description.
	 */
	static function meta_description(){
		global $post;

		// Called from `wp_head` hook
		$echo_result = ( func_num_args() === 1 );

		static $cache = null;
		if ( isset ( $ cache ) ) {

			if($echo_result)
				echo $ cache;

			return $cache;
		}

		$desc = '';
		$ need_cut = true;

		// front
		if( is_front_page() ){

			// коли для головної встановлено сторінку
			if( is_page() ){
				$desc = get_post_meta($post->ID, 'description', true);
				$need_cut = false;
			}

			if( ! $desc ){

				/**
				 * Allow to change front_page meta description.
				 *
				 * @param string $home_description
				 */
				$desc = apply_filters( 'home_meta_description', get_bloginfo( 'description', 'display' ) );
			}
		}
		// any post
		elseif( is_singular() ){

			if( $desc = get_post_meta( $post->ID, 'description', true ) ){
				$need_cut = false;
			}

			if( ! $desc ){
				$desc = $post->post_excerpt?: $post->post_content;
			}

			$ Desc = trim (strip_tags ($ Desc));
		}
		// any term (taxonomy element)
		elseif( ( $term = get_queried_object() ) && ! empty( $term->term_id ) ){

			$desc = get_term_meta($term->term_id, 'meta_description', true);

			if(! $desc)
				$desc = get_term_meta($term->term_id, 'description', true);

			$need_cut = false;
			if( ! $desc && $term->description ){
				$desc = strip_tags($term->description);
				$ need_cut = true;
			}
		}

		$desc = str_replace(["n", "r"], '', $desc);

		// remove shortcodes, але leave markdown [foo](URL)
		$desc = preg_replace( '~[[^]]+](?!()~', '', $desc );

		/**
		 * Змінити зміну або налаштування meta description.
		 *
		 * @param string $desc Current description.
		 * @param string $origin_desc Description before cut.
		 * @param bool $need_cut Це потрібно?
		 * @param int $maxchar How many characters leave after cut.
		 */
		$desc = apply_filters( 'kama_meta_description', $desc );

		/**
		 * Дозволяє до специфічності is meta description необхідно для того, щоб cutted.
		 *
		 * @param bool $need_cut
		 */
		$need_cut = apply_filters( 'kama_meta_description__need_cut', $need_cut );

		if( $need_cut ){

			/**
			 * Allow set max length of meta description.
			 *
			 * @param int $maxchar
			 */
			$maxchar = apply_filters( 'kama_meta_description__maxchar', 260);

			$char = mb_strlen($desc);

			if( $char > $maxchar ){
				$ Desc = mb_substr ($ Desc, 0, $ Maxchar);
				$words = explode('', $desc);
				$maxwords = count($words) - 1; // remove last word, it incomplete в 90% випадків
				$desc = implode('', array_slice($words, 0, $maxwords)). '...';
			}
		}

		// remove multi-space
		$desc = preg_replace('/s+/s', '', $desc);

		$cache = $desc
			? sprintf( "<meta name="description" content="%s" />n", esc_attr( trim( $desc ) ) )
			: '';

		if($echo_result)
			echo $ cache;

		return $cache;
	}

	/**
	 * Wrpper for WP Robots API введено в WP 5.7+.
	 *
	 * Must be used on hook `wp_robots`.
	 *
	 * @param array $robots
	 */
	static function wp_robots_callback( $robots ){

		if( is_singular() ){
			$robots_str = get_post_meta( get_queried_object_id(), 'robots', true );
		}
		elseif( is_tax() || is_category() || is_tag() ){
			$robots_str = get_term_meta( get_queried_object_id(), 'robots', true );
		}

		if( ! empty( $robots_str ) ){

			// split by spece or comma
			$robots_parts = preg_split( '/(?<!:)[s,]+/', $robots_str, -1, PREG_SPLIT_NO_EMPTY );

			foreach( $robots_parts as $directive ){

				// for max-snippet:2
				if( strpos( $directive, ':' ) ){
					[$key, $value] = explode(':', $directive);
					$ robots [ $ key ] = $ value;
				}
				else {
					$ robots [ $ directive ] = true;
				}
			}
		}

		if( ! empty( $robots['none'] ) || ! empty( $robots['noindex'] ) ){
			unset( $robots['max-image-preview'] );
		}

		return $robots;
	}

	/**
	 * Generate `<meta name="keywords">` meta-tag fore <head> part of the page.
	 *
	 * Для того, щоб встановити свої ключові слова для post, створити meta-field with key `keywords`
	 * and set the keyword to the value.
	 *
	 * Default keyword for post generates from post tags nemes and categories names.
	 * Якщо "keywords" meta-field is не specified.
	 *
	 * Ви можете скористатися ключовими словами для будь-якого taxonomy element (term) using shortcode
	 * `[keywords=word1, word2, word3]` in the description field.
	 *
	 * @param string $home_keywords Keywords for home page. Ex: 'word1, word2, word3'
	 * @param string $def_keywords наскрізні ключові слова - вкажемо і вони додаватимуться
	 * До решти на всіх сторінках.
	 */
	static function meta_keywords( $home_keywords = '', $def_keywords = '' ){
		global $post;

		$out = [];

		if( is_front_page() ){
			$out[] = $home_keywords;
		}
		elseif( is_singular() ){

			$meta_keywords = get_post_meta( $post->ID, 'keywords', true );

			if( $meta_keywords ){
				$out[] = $meta_keywords;
			}
			elseif( $post->post_type === 'post' ){

				$res = wp_get_object_terms( $post->ID, [ 'post_tag', 'category' ], [ 'orderby' => 'none' ] );

				if( $res && ! is_wp_error( $res ) ){
					foreach( $res as $tag ){
						$out[] = $tag->name;
					}
				}
			}

		}
		elseif( is_category() || is_tag() || is_tax() ){
			$term = get_queried_object();

			// wp 4.4
			if( function_exists( 'get_term_meta' ) && $term ){
				$out[] = get_term_meta( $term->term_id, 'keywords', true );
			}
			else {
				preg_match( '![keywords=([^]]+)]!iU', $term->description, $match );
				$out[] = isset( $match[1] ) ? trim($match[1]): '';
			}
		}

		if( $def_keywords ){
			$out[] = $def_keywords;
		}

		/**
		 * Дозволяє змінювати результат string of meta_keywords() method.
		 *
		 * @param string $out
		 */
		$out = apply_filters( 'kama_meta_keywords', implode( ', ', $out ) );

		echo $out
			? '<meta name="keywords" content="'. esc_attr( $out ) .'" />' . "n"
			: '';
	}

}

Тепер потрібно підключити та запустити код

Для цього створіть файл class-Kama_SEO_Tags.php в корені теми (або ще десь) і скопіюйте в нього php код (який вище). Підключіть цей файл до файлу теми functions.php .

require_once __DIR__ . '/seo.php';

Kama_SEO_Tags::init();

Це все.

Якщо код не працює, то потрібно переконатися, чи використовується функція wp_head() у файлі теми header.php і чи не виводиться там жорстко тег <title> та інші SEO теги.

Метаполя в адмінці

Код вище лише виводить потрібні SEO мета-теги, але не додає метаполя для записів чи елементів таксономій – їх потрібно створити окремо.

На сторінці редагування запису або терміну вам потрібно створити метабокс з метаполями:

  • title– альтернативний SEO заголовок буде використовуватися в мета-теги <title> замість заголовка запису.

  • description– Опис для сторінки. Якщо його немає, то буде взяти текст із цитати, якщо його немає, то шматок з початку контенту запису.

    meta_description– так має називатися метапол опису для термінів, тому що ключ description для таксономій зайнятий…

  • keywords– метатег keywords. Не знаю чи потрібен він чи ні взагалі в сучасних реаліях.

  • robots– Вказане тут значення виводиться так, наприклад , noindex, nofollow .
Як створити метабокси з метаполями?

Зробити це можна з різними способами, наприклад, за допомогою:

Тонка настройка (використання хуків)

Код містить хуки, щоб повністю чи частково змінити виведення кожного метаполя.

Розглянемо деякі хуки, які можуть стати в нагоді для налаштування:

Open Graph

// disable `article:section` property.
add_filter( 'kama_og_meta_show_article_section', '__return_false');
// turn off the image search in post content.
add_filter( 'kama_og_meta_thumb_id_find_in_content', '__return_false');
// set `og:image` `og:image:width` `og:image:height` values ​​if it's not.
add_filter( 'kama_og_meta_image', function( $image ){

	// $image = WP attachment ID or Image URL or [ image_url, width, height ] array.

	if(! $image) {
		// Постер сайту
		$ image = [wp_get_attachment_image_url (125, 'full'), 350, 350];
	}

	return $image;
} );

Title

Розділювач у заголовку змінюється через рідний ВП хук document_title_separator :

// Змінимо роздільник для title
add_filter( 'document_title_separator', fn() => '-' );

Description

Опис для головної сторінки

// Змінимо опис для головної сторінки
add_filter( 'home_meta_description', fn() => 'Опис для головної');
// Змінимо опис
add_filter( 'kama_meta_description', 'change_meta_description');
function change_meta_description( $desc ){

	return $desc;
}

Robots

# robots metatag.
add_filter( 'wp_robots', 'wp_kama_robots_tag');

function wp_kama_robots_tag( $robots ){

	//close
	if(
		is_attachment() ||
		is_paged() ||
		is_post_type_archive()
	) {
		$robots['noindex'] = true;
		$robots['follow'] = true;
	}

	// close taxonomies

	// close draft
	if( is_preview() ){
		$robots['none'] = true;
	}

	return $robots;
}
Корисні посилання

Зробити плагін із SEO мета-теги без плагінів?

  • Додати відповідь


Залишити коментар

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *