Задача - сделать AMP версию всего сайта на базе 1С-Битрикс и соблюсти следующие требования:
Содержание AMP страниц должно изменяться вместе с изменением оригинальных и соответствовать оригинальным;
Визуально страницы, чтобы повторяли оригинальный дизайн хоть и в облегченном виде;
В AMP нужно превратить как динамические страницы, генерирующиеся компонентами из инфоблоков (например: новости), так и статические страницы с контентом в теле страницы.
Неподходящие варианты
1. Автоматический парсинг
Есть модули позволяющие превращать обычные страницы в AMP, но данный вариант может сработать только с простейшими по виду страницами, состоящих из нескольких абзацев текста с картинками.
У меня сложные по структуре страницы состоящие из разных дизайнерских блоков. Данный метод если и сделает страницу формально проходящую под валидацию Google, то маркетинговая ценность данной страницы будет равна нулю.
2. Автономные AMP страницы
Следующий вариант, чтобы формально соблюсти требования поисковых систем по наличию AMP, сделать их как отдельный продукт. Они могут быть как полностью статичные, так и с использованием механизмов битрикса.
Проблема в том что о них забывают сразу после релиза, и дальше в поиске для мобильной выдачи будет присутствовать не актуальный контент.
Реализация
Для реализации проделал следующие шаги.
1. Обеспечил обработку URL с префиксом /amp/.
Для каждого URL должен быть аналог AMP, например: domain.com/about/ и domain.com/amp/about/, но вести эти оба URL должны на одну папку - /about/.
Реализую с помощью mod_rewrite в .htaccess, в случае обращения к URL с /amp/ делаю rewrite к соответствующим папкам без AMP и добавляю переменную HTML_TYPE=AMP , которую дальше буду использовать в init.php.
Пример .htaccess для обработки AMP
<IfModule mod_rewrite.c>
RewriteEngine On
# Google AMP
# Правило для URL вида /amp/about/delivery.php
RewriteRule ^amp/(.+)/(.+)\.(php|html)$ $1/$2.$3?HTML_TYPE=AMP [L,QSA]
# Правило для URL вида /amp/about/
RewriteRule ^amp/(.+)/?$ $1/index.php?HTML_TYPE=AMP [L,QSA]
# Правило для главной
RewriteRule ^amp/?$ index.php?HTML_TYPE=AMP [L,QSA]
</IfModule>
2. Научил битрикс понимать и работать с AMP страницам
Две основные проблемы, которые нужно решить:
весь CSS сделать inline в <head>
удалить весь Javascript
Объявляю две константы в init.php, которые дальше буду использовать в шаблоне и компонентах: HTML_TYPE и URL_PREFIX.
<?php
// Если в URL есть AMP, то объявляю две константы, чтобы по первой делать условие в шаблонах, а вторую подставлять в ссылки в шаблонах и страницах
if ($_REQUEST["HTML_TYPE"] == “AMP”)
{
define("HTML_TYPE",$_REQUEST["HTML_TYPE"]);
define("URL_PREFIX","/amp");
}
if (!defined("HTML_TYPE"))
{
define("HTML_TYPE","");
define("URL_PREFIX","");
}
?>
Перенёс CSS в inline
Для переноса CSS в inline делаю функцию AMP_CSS на событие OnEpilog, которую дальше буду использовать в шаблоне.
<?php
AddEventHandler("main","OnEpilog","AMP_CSS");
function AMP_CSS()
{
global $APPLICATION;
if (defined("HTML_TYPE") and HTML_TYPE == "AMP")
{
// Получаю все подключенные стандартами методами битрикса CSS, для этого использую не документированную функцию GetCSS;
$CSS_FILE = $APPLICATION->GetCSS();
if (!empty($CSS_FILE))
{
// Извлекаю адрес из href и получаю их содержимое
preg_match_all('/href="(.+?)\?.+?"/isu',$CSS_FILE,$CSS_FILE_MATCHES);
if (sizeof($CSS_FILE_MATCHES[1]) > 0)
{
foreach($CSS_FILE_MATCHES[1] as $CSS_FILE_MATCHES_VAL)
{
$CSS .= file_get_contents($_SERVER['DOCUMENT_ROOT'].$CSS_FILE_MATCHES_VAL);
}
}
if (!empty($CSS))
{
$CSS_TMP = str_replace(array('!important'),'',$CSS);
if (!empty($CSS_TMP))
{
$CSS = $CSS_TMP;
}
}
}
// Считаю размер CSS для отладки верстальщику, тк есть лимиты на стороне гугла в 70 кб
if (!empty($CSS))
{
$CSS =
'
<style amp-custom>
/*'.mb_strlen($CSS).'*/
'.$CSS.'
</style>
';
}
return $CSS;
}
}
?>
Удалил Javascript
Собственный Javascript в AMP версии подключать не буду ни в шаблоне ни в компонентах, а служебные "прилетающие" из ядра битрикса - удаляю на событии OnEndBufferContent.
<?php
AddEventHandler("main","OnEndBufferContent","OnEndBufferContentHandler");
function OnEndBufferContentHandler(&$content)
{
$content = OnEndBufferContentParse($content);
}
function OnEndBufferContentParse($HTML)
{
if (defined("HTML_TYPE") and HTML_TYPE == "AMP")
{
$HTML_TMP = preg_replace('/(<script type="text\/javascript".*?<\/script>|<script>.*?<\/script>)/isu',"",$HTML);
if (!empty($HTML_TMP)) {$HTML = $HTML_TMP;}
}
return $HTML;
}
?>
Отключаю композитный кеш для AMP версии, т.к. для его корректной работы нужен Javascript, а он в AMP не поддерживается и выше удалён.
Дополнительно делаю свойство AMP_ENABLE в "Структуре сайта", его буду использовать на переработанных страницах для включения ссылки на AMP страницу в <head>.
Данное свойство обрабатываю на событии OnEpilog.
<?php
AddEventHandler("main","OnEpilog","META_AMP");
function META_AMP()
{
global $APPLICATION;
$URL_CANONICAL = $_SERVER['REQUEST_URI'];
$AMP_ENABLE = $APPLICATION->GetProperty("AMP_ENABLE");
// Для AMP страниц указываю canonical на НЕ AMP
if (defined("HTML_TYPE") and HTML_TYPE == "AMP")
{
$APPLICATION->SetPageProperty("canonical",'https://'.SITE_SERVER_NAME.str_replace('/amp','',$URL_CANONICAL));
}
else
{
// Для НЕ AMP страниц, если они включены, указываю ссылку на AMP
if ($AMP_ENABLE == "Y")
{
$APPLICATION->AddHeadString('<link rel="amphtml" href="https://'.SITE_SERVER_NAME.'/amp'.$URL_CANONICAL.'" />',true);
}
}
}
?>
3. Переработал шаблон сайта
Шаблон сайта и компоненты использую общие для обеих версий, чтобы обе версии генерировались в одних и тех же точках.
В шаблоне сайта делаю условие для AMP и обычных страниц.
Основное отличие шаблонов с технической стороны, в функциях в <head>.
В обычном использую общую функцию, которая отображает всю мету:
<? $APPLICATION->ShowHead(); ?>
В AMP использую отдельные и плюс сделанную выше AMP_CSS:
<? $APPLICATION->ShowMeta("robots"); ?>
<? $APPLICATION->ShowMeta("keywords"); ?>
<? $APPLICATION->ShowMeta("description"); ?>
<? $APPLICATION->ShowLink("canonical"); ?>
<? $APPLICATION->ShowHeadStrings(); ?>
<? $APPLICATION->AddBufferContent("AMP_CSS"); ?>
ShowHead в AMP использовать нельзя, т.к. в ней "придут" не валидные для AMP элементы: <script> и ссылки на CSS.
Дальше подключаю необходимые Javascript и CSS для обычной версии:
Для AMP версии - CSS и разрешённые AMP JS-компоненты:
У AMP есть компоненты отвечающие за разные действия, например, за работу форм (компонент: amp-form), подключаю их с параметром data-skip-moving="true", чтобы они оставались в <head>, а не ушли вниз при объединении (если данная опция включена в настройках битрикса).
4. Переработал компоненты
Приведу пример на базе стандартного компонента Списка статей.
Копирую компонент в папку с шаблоном, добавляю файл .parameters.php и в него параметр HTML_AMP:
Данный параметр нужен для корректной работы кеша, без него будет закеширован либо один либо другой вариант.
В шаблоне компонента делаю условия, как и выше в шаблоне сайта.
В таком ключе необходимо переработать все компоненты сайта.
5. Переработал страницы
На страницах, где используется только компоненты и нет текста - делать ничего не нужно, они будут работать при условии, что компоненты были переработаны на шаге выше.
Для страниц, где есть текст в теле страниц, делаю компонент "Произвольный HTML" в котором должно быть 2 обязательных параметра HTML и HTML для AMP.
Внутри он выглядит так:
Вместо любых текстов в теле страницы нужно использовать его. При этом можно как убрать весь текст сразу, либо собрать страницу из нескольких таких блоков. Не обязательно полностью дублировать всё содержимое обычной версии в AMP, для последней можно сделать сокращенный вариант.
Если страницы имеют сложную структуру, и использование одного компонента "Произвольный HTML" не очень удобно, то нужно сделать набор статичных компонентов со стандартными html-блоками в дизайне сайта, которые можно использовать по сайту повсеместно. Они также должны иметь 2 версии внутри.
6. Включил AMP
Готовые AMP страницы включаю через параметр AMP_ENABLE:
У них в <head> появляется ссылка на AMP:
При этом на AMP страницах появляется ссылка на основную:
На выходе любая страница собранная таким образом страница будет иметь актуальный контент.
Дальше страницы начнут индексироваться гуглом.
Общие замечания
AMP поддерживает почти всё в CSS, за исключением ряда моментов (можно найти в официальной документации) и общего ограничения в объёме в 70 Кб на страницу.
По реализации, можно использовать общие стили для обеих версий. Можно для ряда стилей сделать классы с префиксом amp-. Можно на AMP версии подключать отдельные стили. Зависит от потребностей.
Javascript соответственно использую только на основной версии. На AMP использую JS-компоненты для форм, меню, увеличение картинок.
В ссылках (например, в меню в шаблоне) можно использовать объявленную выше константу URL_PREFIX: