Микроразметка Open Graph для сайта на Cotonti
- 753 просмотра
- 9 октября, 2023
- Обновлено: 24 мая, 2024
- admin
- Время чтения: 7 минут
- 3 (Подробно)
![Применяем микроразметку Open Graph для сайта на Cotonti](pics/thumbs/25/img-25-966x644-crop.jpg)
Open Graph – это микроразметка, предназначенная для управления оформлением ссылок на сайт в социальных сетях и мессенджерах. Когда вы вставляете ссылку в пост, она обрабатывается по соответствующему алгоритму: подтягивается заголовок, описание и картинка. Если оставить это на откуп соцсети, текстовая информация может быть сформирована из случайных фрагментов текста, а в качестве изображения будет использован баннер, картинка карты оплаты из футера или любое другое нерелевантное изображение.
Теоретически визуал сниппета перед постингом можно отредактировать, однако возможности для этого сильно ограничены (например, не все картинки со страницы могут быть доступны), да и заниматься этим будут только админы страниц и пабликов. Простые пользователи вряд ли знают такие тонкости и скорее всего не будут утруждать себя. К тому же, в мессенджерах такая настройка невозможна в корне. Именно поэтому программистами Facebook был разработан Стандарт Open Graph, который не только стал удачным и востребованным, но и получил сегодня широкое распространение практически во всех соцсетях и мессенджерах.
Используя Open Graph, вы четко определяете все компоненты текстуально-графического анонса, тем самым делая его максимально привлекательным для пользователя и мотивируя его к переходу на ваш сайт.
Кстати, свою имплементацию протокола Open Graph разработал также и Твиттер. Но об этом ниже. Мы же для начала определим общий алгоритм использования данной микроразметки в CMF Cotonti.
Применяем Open Graph для Cotonti
Разметка Open Graph фактически представляет собой набор тегов meta с соответствующими метаданными, поэтому размещать эту историю мы будем в шаблоне header.tpl. В протоколе указывается, что обязательными для html-страницы являются четыре свойства:
- og:title – заголовок объекта
- og:type – тип объекта
- og:image – URL изображения
- og:url – канонический URL объекта
Разъяснений здесь требует только свойство type. Разработчики предлагают следующие варианты:
- music
- video
- article
- book
- profile
- website
Если для вас принципиальным является структурированное описание первых пяти типов, можно сделать это за счет использования соответствующих вертикалей. Если же специальные задачи не ставятся, достаточно будет универсального типа website.
Обязательные и опциональные свойства Open Graph
<!-- BEGIN: HEADER --> <!doctype html> <html lang="{PHP.cfg.defaultlang}"> <head> ... <!-- Open Graph --> <meta property="og:title" content="{HEADER_TITLE}"> <meta property="og:type" content="website"> <meta property="og:image" content="???"> <meta property="og:url" content="{HEADER_CANONICAL_URL}"> ... </head>
Краткое пояснение: в качестве заголовка мы выбрали TPL-тег HEADER_TITLE. Он доступен глобально и содержит либо заголовок страницы, либо (при заполнении) его meta title. Конечно, можно обыграть это свойство и по-другому, но HEADER_TITLE проще: он доступен глобально, а правильно сформированный meta-тег title прекрасно подходит для его наполнения. В качестве свойства og:url мы использовали еще один глобальный TPL-тег {HEADER_CANONICAL_URL} с каноническим URL'ом страницы. Это именно то, что нам необходимо, так что без вариантов и комментариев.
Самым спорным является свойство og:image. По нему действительно возможны варианты, так что рассмотрим его позднее, а пока добавим в наш блок необязательные, но достаточно важные свойства og:description и og:locale:
<!-- BEGIN: HEADER --> <!doctype html> <html lang="{PHP.cfg.defaultlang}"> <head> ... <!-- Open Graph --> <meta property="og:title" content="{HEADER_TITLE}"> <meta property="og:description" content="{HEADER_META_DESCRIPTION}"> <meta property="og:locale" content="{HEADER_OG_LOCALE}"> <meta property="og:type" content="website"> <meta property="og:image" content="???"> <meta property="og:url" content="{HEADER_CANONICAL_URL}"> ... </head>
Раз уж есть возможность указать описание, сделаем это с помощью глобального TPL-тега HEADER_META_DESCRIPTION. Опять же, при правильном заполнении поля meta description, в него "залетит" правильное и понятное описание объекта для перехода.
Что касается свойства og:locale, то его тоже желательно заполнить. Формат language_TERRITORY, по умолчанию en_US. Так что придется делать. Для языка используем $cfg['defaultlang'], а территорию зададим жестко.
Свойство og:image
Теперь решим как поступить с изображением. На форумах Cotonti пролетало предложение использовать для него универсальное изображение-заглушку. Пожалуй, это вариант для подростковой группы – не шаблонизатором же единым. Так что будем формировать данное свойство в глобальном и универсальном виде.
Прежде всего, создадим плагин или часть для уже существующего плагина с хуком header.tags, а для примера будем использовать плагин attach2. Понятно, что картинки у нас в разных локациях разные, а местами их и нет вообще. Так что придется конструировать логику. Для этого будем использовать массив $env:
<?php /* ==================== [BEGIN_COT_EXT] Hooks=header.tags [END_COT_EXT] ==================== */ defined('COT_CODE') or die('Wrong URL'); // Open Graph if ($env['location'] == 'home') { // Главная } elseif ($env['location'] == 'list') { // Раздел } elseif ($env['location'] == 'pages') { // Страница } elseif ($env['location'] == 'plugins') { // Плагин } else { // Все остальное }
В "корне" сайта создадим папку opengraph для статичных изображений, и для примера рассмотрим следующий алгоритм:
- для главной страницы используем картинку home.jpg
- для раздела catalog используем картинку последнего добавленного товара
- для раздела blog используем прикрепленное к нему изображение
- для остальных разделов используем "именные" картинки вида КОДРАЗДЕЛА.jpg
- для всех страниц используем прикрепленное и первое по порядку изображение
- для плагинов используем изображения вида ИМЯПЛАГИНА.jpg
- для всего остального применим изображение default.jpg
Дополним логикой наш файл header.tags.php:
<?php /* ==================== [BEGIN_COT_EXT] Hooks=header.tags [END_COT_EXT] ==================== */ defined('COT_CODE') or die('Wrong URL'); // Open Graph if ($env['location'] == 'home') { $og_image = 'opengraph/home.jpg'; } elseif ($env['location'] == 'list') { if ($cat['tpl'] == 'blog') { $og_image = att_thumb(att_get('list', $cat['id']), 966, 644, 'crop'); } elseif ($cat['tpl'] == 'catalog') { Cot::$db->registerTable('attach'); $db_attach = Cot::$db->attach; $db_pages = Cot::$db->pages; $res = Cot::$db->query("SELECT att_item FROM $db_attach WHERE att_area = 'page' AND att_item = ( SELECT page_id FROM $db_pages WHERE page_cat = '$c' ORDER BY page_date DESC LIMIT 1 ) ORDER BY att_order ASC LIMIT 1")->fetch(); $og_image = att_thumb(att_get('page', $res['att_item']), 966, 644, 'crop'); } else { $og_image = 'opengraph/' . $c . '.jpg'; } } elseif ($env['location'] == 'pages') { $og_image = att_thumb(att_get('page', $pag['page_id']), 966, 644, 'crop'); } elseif ($env['location'] == 'plugins') { $og_image = 'opengraph/' . $env['ext'] . '.jpg'; } else { $og_image = 'opengraph/default.jpg'; } $t->assign('HEADER_OG_IMAGE', $cfg['mainurl'] . $res['att_path']);
Самым слождным здесь является "ленивый" пример с разделом catalog, где картинку мы берем от самой свежей страницы данного раздела. Встречается редко, но сто́ит упоминания.
Вариант без него выглядит вообще просто:
<?php /* ==================== [BEGIN_COT_EXT] Hooks=header.tags [END_COT_EXT] ==================== */ defined('COT_CODE') or die('Wrong URL'); // Open Graph if ($env['location'] == 'home') { $og_image = 'opengraph/home.jpg'; } elseif ($env['location'] == 'list') { if ($cat['tpl'] == 'blog') { $og_image = att_thumb(att_get('list', $cat['id']), 966, 644, 'crop'); } else { $og_image = 'opengraph/' . $c . '.jpg'; } } elseif ($env['location'] == 'pages') { $og_image = att_thumb(att_get('page', $pag['page_id']), 966, 644, 'crop'); } elseif ($env['location'] == 'plugins') { $og_image = 'opengraph/' . $env['ext'] . '.jpg'; } else { $og_image = 'opengraph/default.jpg'; } $t->assign('HEADER_OG_IMAGE', $cfg['mainurl'] . $res['att_path']);
Вынесем значения в переменные-параметры и подытожим:
<?php /* ==================== [BEGIN_COT_EXT] Hooks=header.tags [END_COT_EXT] ==================== */ defined('COT_CODE') or die('Wrong URL'); // Open Graph $og_terr = 'RU'; $og_width = 966; $og_height = 644; $og_cat = 'opengraph/'; $og_appid = 1234567890123456; require_once cot_incfile('attach2', 'plug'); if (Cot::$env['location'] == 'home') { $og_image = $og_cat . 'home.jpg'; } elseif (Cot::$env['location'] == 'list') { $og_image = att_thumb(att_get('list', $cat['id']), $og_width, $og_height, 'crop'); empty($og_image) && $og_image = $og_cat . 'default.jpg'; } elseif (Cot::$env['location'] == 'pages') { $og_image = att_thumb(att_get('page', $id, 'id'), $og_width, $og_height, 'crop'); empty($og_image) && $og_image = $og_cat . 'default.jpg'; } elseif (Cot::$env['location'] == 'plugins') { $og_image = $og_cat . Cot::$env['ext'] . '.jpg'; } else { $og_image = $og_cat . 'default.jpg'; } $t->assign(array( 'HEADER_OG_LOCALE' => Cot::$cfg['defaultlang'] . '_' . $og_terr, 'HEADER_OG_IMAGE_WIDTH' => $og_width, 'HEADER_OG_IMAGE_HEIGHT' => $og_height, 'HEADER_OG_IMAGE' => $cfg['mainurl'] . '/' . $og_image, 'HEADER_OG_DOMAIN' => preg_replace('(^https?://)', '', Cot::$cfg['mainurl']), 'HEADER_OG_APPID' => $og_appid, ));
Добавился TPL-тег HEADER_OG_DOMAIN, о котором ниже.
Формируем Open Graph под Twitter
Разметка Open Graph для Твиттер ненамного отличается от стандартной:
<!-- Twitter --> <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:title" content="{HEADER_TITLE}"> <meta name="twitter:description" content="{HEADER_META_DESCRIPTION}"> <meta name="twitter:url" content="{HEADER_CANONICAL_URL}"> <meta name="twitter:domain" content="{HEADER_OG_DOMAIN}"> <meta name="twitter:image" content="{HEADER_OG_IMAGE}"> <meta name="twitter:site" content="@seditio">
Пояснения требуют свойства twitter:card, twitter:domain и twitter:site. Первое отвечает за формат предствления текстуально-графического анонса. Значение summary_large_image является типовым. Свойство twitter:domain должно передавать домен сайта. Свойство twitter:site отвечает за связанный с постом Твиттер-аккаунт. Не забывайте про формат: @ИМЯАККАУНТА. Для порядка добавим его в файл ресурсов темы:
$R['Twitter'] = 'seditio';
В итоге получаем финальный вариант для вставки в шаблон header.tpl. В него мы добавим необязательные, но важные параметры размеров изображения. Кроме этого, укажем параметр fb:app_id, необходимый для интеграции связанного с сайтом Facebook-приложения (спасибо Merlin):
<!-- Open Graph --> <meta property="og:type" content="website"> <meta property="og:title" content="{HEADER_TITLE}"> <meta property="og:description" content="{HEADER_META_DESCRIPTION}"> <meta property="og:url" content="{HEADER_CANONICAL_URL}"> <meta property="og:image" content="{HEADER_OG_IMAGE}"> <meta property="og:image:width" content="{HEADER_OG_IMAGE_WIDTH}"> <meta property="og:image:height" content="{HEADER_OG_IMAGE_HEIGHT}"> <meta property="og:locale" content="ru_RU"> <meta property="fb:app_id" content="{HEADER_OG_APPID}"> <!-- Twitter --> <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:title" content="{HEADER_TITLE}"> <meta name="twitter:description" content="{HEADER_META_DESCRIPTION}"> <meta name="twitter:url" content="{HEADER_CANONICAL_URL}"> <meta name="twitter:domain" content="{HEADER_OG_DOMAIN}"> <meta name="twitter:image" content="{HEADER_OG_IMAGE}"> <meta name="twitter:image:width" content="{HEADER_OG_IMAGE_WIDTH}"> <meta name="twitter:image:height" content="{HEADER_OG_IMAGE_HEIGHT}"> <meta name="twitter:site" content="@{PHP.R.Twitter}">
Выводы и заключение
Итак, мы сформировали схематичный, но вполне рабочий вариант размещения микроразметки Open Graph на сайте под управлением фреймворка Cotonti. С небольшими усилиями мы сделали ссылки на наш сайт красивыми и привлекательными для их размещения в соцсетях.
Логика вывода картинок закрывает практически все варианты по локациям. Свои собственные изображения получили:
- главная страница
- разделы и страницы (модуль Page)
- плагины
- все неучтенные локации (например, users)
Пространство для расширения или упрощения функционала большое: можно дополнить его кастомизацией форумов или пользовательских страниц, или наоборот, упростить за счет отказа от плагина attach2 и перехода на статичные картинки с привязками по id разделов и страниц. У каждого владельца сайта будут свои требования к формированию разметки Open Graph, поэтому создавать для нее специальный плагин будет или нецелесообразно или слишком сложно. Поэтому рекомендуем использовать приведенный выше код для расширения функционала "именного" плагина вашего проекта.
Минимальный размер – 200х200px, файл до 8Mb. В идеале это должно быть изображение с пропорциями 1,91:1 – чтобы при перекадрировании в соцсети или мессенджере миниатюра не обрезалась. Идеальный размер в пикселях рекомендуется 600х315px, а из расчета HD-разрешений – 1200х630px.
Какой должен быть размер у изображения? Нигде не могу найти требования, а валидатор иногда ругается почему-то.
Это стандартный HTML-комментарий
<!-- Open Graph -->
Это обязательная строка в шаблоне ?
Ниже в предыдущем комменте ссылка на валидатор. Проверить несложно.
Любопытно, это всё будет работать на сайте без доменного имени ?
Дополню: если указать картинку из тела страницы, и у этой картинки будет прописан alt, он автоматически подтянется в вертикаль свойства og:image:alt. А если использовать заглушку, альт нужно указать явно, иначе он не определится. Хотя ни ошибкой, ни предупреждением отладчик репостов Meta это не считает.
Единственный момент: валидатор Open Graph от Facebook считает ошибкой, требующей исправления, неуказание свойства fb:app_id
Дополнил примеры функцией att_thumb()
А если картинку не просто брать приаттаченную, а перекадрировать под необходимые размеры?
Новый комментарий