IT-инфраструктура для бизнеса и творчества

Инструкция: пишем первое письмо с помощью AMP Статьи редакции

На примере каталога бездомных котов из документации Google.

26 марта Google объявила о начале поддержки технологии AMP для интерактивных сообщений в Gmail.

Accelerated Mobile Pages (AMP) — это технология ускоренных мобильных страниц, разработанная Google в 2015 году. Она позволяет загружать страницы на более высокой скорости, улучшая пользовательский опыт.

Однако у AMP гораздо более широкая область применения. Например, компании могут «транслировать» рекламу и актуальные предложения со своего сайта через разные платформы и приложения, при этом сохраняя полный контроль над размещаемой информацией.

Одной из таких платформ стала почта — AMP позволяет сделать письма более интерактивными.

Получатель может прямо в письме отвечать на комментарии в «Google Документах», управлять подписками, давать обратную связь, принимать приглашения на мероприятия, проходить опросы и бронировать билеты — причём для этого не нужно переходить на внешние сайты. Информация в письмах будет обновляться автоматически, отображая новейшие комментарии и рекомендации.

Интерактивность обеспечивается динамическими компонентами AMP — это могут быть изображения, которые увеличиваются и показывают подробное описание при клике на них, а также карусели, аккордеоны и другие элементы.

Помимо Gmail, технологию AMP внедрили такие почтовые сервисы, как Yahoo Mail, Outlook и Mail.Ru.

Преимущества AMP-рассылок:

  • Возможность взаимодействовать с контентом, не переходя на сторонние сайты.
  • Актуальность и автоматическое обновление информации, сервер извлекает актуальный контент из удалённых конечных точек.
  • Большая персонализация.
  • Безопасность: AMP-письма не обращаются к третьесторонним сервисам, не позволяют использовать рекламные компоненты и дают доступ только к заданной (то есть проверенной и безопасной) функциональности.
  • Совместимость и масштабируемость. AMP-письма совместимы с классическими электронными письмами.

Пишем первое AMP-письмо

Команда AMP создала среду для Gmail, где можно разрабатывать, тестировать и отправлять самому себе AMP-письма — AMP4Email.

Чтобы воспользоваться сервисом, необходимо авторизоваться в Gmail-аккаунте и проверить, что в правом верхнем углу отображается строчка «Hello, AMP4Email world».

AMP4Email

В рабочей области — вся необходимая разметка и минимальный код для создания валидного AMP-письма.

<!doctype html> <html ⚡4email> <head> <meta charset="utf-8"> <script async src="https://cdn.ampproject.org/v0.js"></script> <style amp4email-boilerplate>body{visibility:hidden}</style> </head> <body> Hello, AMP4EMAIL world. </body> </html>

Основные «опознавательные знаки» AMP-писем:

  • Они помечаются записями «⚡4email» или «amp4email» в теге <html>.
  • Тег <head> должен содержать тег <script>, который загружает среду выполнения AMP: <script async src="https://cdn.ampproject.org/v0.js"></script>.
  • Должен быть загружен бойлерплейт на CSS, он будет скрывать контент до загрузки AMP: <style amp4email-boilerplate>body{visibility:hidden}</style>.

Если вы раньше работали с почтовыми рассылками, скрипт в письме может вас насторожить.

Разработчики из Google советуют не беспокоиться: почтовые сервисы, которые поддерживают AMP, обеспечивают высокую безопасность и позволяют выполнять в своих клиентах только проверенные AMP-скрипты для разрешённых компонентов.

Добавляем изображение

Большинство HTML-тегов, которые используются в обычных электронных письмах, могут быть использованы и в AMP-письмах . Однако некоторые теги, например, <img>, заменяются эквивалентами: <amp-img>.

<amp-img src="https://link/to/img.jpg" alt="photo description" width="100" height="100"></amp-img>

Для тега <amp-img> необходимо задать ширину и высоту изображения. Кроме того, необходимо использовать закрывающий тег </amp-img>. GIF-изображения поддерживаются через <amp-anim>.

Поскольку письма не хранятся на вашем сервере, для указания URL необходимо использовать абсолютный путь c протоколом HTTPS.

Выбрать размер изображения прямо в URL можно через сервис Placekitten, который «заполняет» места для будущих картинок изображениями котят.

Добавьте изображение в письмо, используя такой код:

<body> <amp-img src="https://placekitten.com/800/400" alt="Welcome" width="800" height="400"> </amp-img> </body>

Делаем письмо отзывчивым

Электронная почта может открываться на разных устройствах с разными размерами экранов. Для этого в AMP есть встроенная система макетирования.

Система amp-layout и медиазапросы позволяют легко создавать отзывчивые письма. Чтобы подогнать изображение под нужный размер экрана, добавьте атрибут layout="responsive" в <amp-image>.

<amp-img layout="responsive" src="https://placekitten.com/800/400" alt="Welcome" height="400" width="800"></amp-img>

Растяните или сожмите окно браузера, и вы увидите, что изображение само меняет размер. Список элементов, доступных в системе amp-layout, можно посмотреть в документации.

Модифицируем презентацию и макет

Одно изображение — хорошо, но что если нужно вставить что-то ещё? AMP поддерживает такие элементы, как аккордеоны (вертикально сложенный список элементов) и боковые панели.

Здесь мы используем тег <amp-carousel> — сделаем для рассылки галерею с котиками, которых можно приютить.

Чтобы вставить карусель, добавьте скрипт amp-carousel внутрь тега <head> .

<head> ... <script async custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js"></script> ... </head>

Затем поместите ранее добавленное изображение котика между тегами <amp-carousel>.

<amp-carousel layout="responsive" width="800" height="400" type="slides"> <amp-img layout="fill" src="https://placekitten.com/800/400" alt="Welcome" height="400" width="800"></amp-img> </amp-carousel>

Если ничего не изменилось — это хороший знак. Карусель имеет заданный атрибут type=”slides”, который означает, что она будет показывать по одному фото. И поскольку пока вы добавили только одно изображение, навигационные стрелки не появились.

Замените тестовое изображение с Placekitten на нужные изображения внутри <amp-carousel>.

<amp-carousel id="carousel-with-preview" width="800" height="400" layout="responsive" type="slides" on="slideChange:AMP.setState({currentCat: event.index})"> <amp-img layout="fill" src="https://amp.dev/static/img/docs/tutorials/firstemail/photo_by_caleb_woods.jpg" alt="photo courtesy of Unsplash"></amp-img> <amp-img layout="fill" src="https://amp.dev/static/img/docs/tutorials/firstemail/photo_by_craig_mclaclan.jpg" alt="photo courtesy of Unsplash"></amp-img> <amp-img layout="fill" src="https://amp.dev/static/img/docs/tutorials/firstemail/photo_by_lightscape.jpg" alt="photo courtesy of Unsplash"></amp-img> <amp-img layout="fill" src="https://amp.dev/static/img/docs/tutorials/firstemail/photo_by_nick_karvounis.jpg" alt="photo courtesy of Unsplash"></amp-img> </amp-carousel>

Теперь вы можете листать изображения, кликая по стрелкам с правой и левой сторон карусели.

Делаем письмо стильным

AMP позволяет определять стиль заголовка документа тегом <style amp-custom>. Кроме того, теперь становятся доступны ранее запрещённые классы и псевдоклассы CSS (их список можно посмотреть документации).

Поменяйте текст «Hello, AMP4EMAIL world» на настоящий заголовок.

<body> <h1>Adorable Adoptable Animals</h1> ... </body>

Выберите стиль заголовка.

<head> ... <style amp-custom> h1 { font-family: arial; margin: 10px; } .center { text-align: center; } .carousel-preview { margin-top: 10px; } </style> </head>

Добавляем динамику

AMP позволяет добавлять различные динамические элементы. Добавим котикам имена и описание, а затем воспользуемся тегом <amp-bind>, чтобы они менялись при клике на следующее изображение в галерее.

Сначала добавьте скрипт amp-bind внутрь тега <head>.

<head> ... <script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script> ... </head>

Затем объявите переменную связывания myState как JSON внутри тега <amp-state>. Если фотографий кошек будет четыре, то параметр состояния ("state") нужно включить для каждой из них.

<body> ... <amp-state id="myState"> <script type="application/json"> { "cats": [ { "name": "Aakash", "description": "Very sweet gentleman that is quite shy in a shelter environment. He may hide under his blanket upon initial approach, but he is an affectionate lovebug." }, { "name": "Filip", "description": "Friendly and enjoys pets and head rubs. Is known to sit on keyboards and refuses to touch anything with catnip on it." }, { "name": "Julian", "description": "Both bold and extremely sweet. Wastes no time in investigating new smells, objects, and places, but enjoys lazing in the sun!" }, { "name": "John", "description": "This playful and spirited cat would like to be outside his kennel and will be so happy when he gets to his forever home with more room to move." } ] } </script> </amp-state> </body>

AMP-действия и события запускают различные состояния. В нашем случае мы хотим обновить состояние, когда пользователь кликает на навигационные стрелки карусели.

Amp-carousel триггерит событие slideChange, с помощью которого мы будем обновлять переменную currentCat, используя AMP.setState.

<h1>Adorable Adoptable Animals</h1> <amp-carousel id="carousel-with-preview" width="800" height="400" layout="responsive" type="slides" on="slideChange:AMP.setState({ currentCat: event.index} )"> <!-- Здесь — изображения котиков --> </amp-carousel>

Благодаря этому коду состояние currentCat фотографии котика соответствует индексу карусели. Таким образом, если мы находимся на слайде event.index=2, состояние будет соответствовать предмету по индексу 2 данного массива.

Единственное, что осталось отобразить, — это имя и описание нашего котика. Добавьте этот код после закрывающего тега amp-carousel.

</amp-carousel> <div class="center"> <h1> <span [text]="myState.cats[currentCat].name">Aakash</span> is available for adoption! </h1> </div>

Расширение amp-bind использует выражения и привязки, чтобы динамически менять контент. В примере выше используется привязка [text], которая обновляет текст в теге <span> при каждом изменении состояния (необходимость обновления определяется выражением myState.cats[currentCat].name).

Не забудьте добавить описание котика в после тега </div>.

</div> <p class="center">About <span [text]="myState.cats[currentCat].name"> Aakash</span></p> <p class="center" [text]="myState.cats[currentCat].description">Very sweet gentleman that is quite shy in a shelter environment. He may hide under his blanket upon initial approach, but he is an affectionate lovebug.</p>

Теперь, когда вы меняете фото котиков в карусели, их имена и описания тоже будут меняться.

Полный код:

<!doctype html> <html ⚡4email> <head> <meta charset="utf-8"> <script async src="https://cdn.ampproject.org/v0.js"></script> <script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script> <script async custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js"></script> <style amp4email-boilerplate>body{visibility:hidden}</style> <style amp-custom> h1 { font-family: roboto; margin: 10px; } .center { text-align: center; } .carousel-preview { margin-top: 10px; } </style> </head> <body> <h1>Adorable Adoptable Animals</h1> <amp-carousel id="carousel-with-preview" width="800" height="400" layout="responsive" type="slides" on="slideChange:AMP.setState({ currentCat: event.index} )"> <amp-img layout="fill" src="https://amp.dev/static/img/docs/tutorials/firstemail/photo_by_caleb_woods.jpg" alt="photo courtesy of Unsplash"></amp-img> <amp-img layout="fill" src="https://amp.dev/static/img/docs/tutorials/firstemail/photo_by_craig_mclaclan.jpg" alt="photo courtesy of Unsplash"></amp-img> <amp-img layout="fill" src="https://amp.dev/static/img/docs/tutorials/firstemail/photo_by_lightscape.jpg" alt="photo courtesy of Unsplash"></amp-img> <amp-img layout="fill" src="https://amp.dev/static/img/docs/tutorials/firstemail/photo_by_nick_karvounis.jpg" alt="photo courtesy of Unsplash"></amp-img> </amp-carousel> <div class="center"> <h1> <span [text]="myState.cats[currentCat].name">Aakash</span> is available for adoption! </h1> </div> <p class="center">About <span [text]="myState.cats[currentCat].name"> Aakash</span></p> <p class="center" [text]="myState.cats[currentCat].description">Very sweet gentleman that is quite shy in a shelter environment. He may hide under his blanket upon initial approach, but he is an affectionate lovebug.</p> <amp-state id="myState"> <script type="application/json"> { "cats": [ { "name": "Aakash", "description": "Very sweet gentleman that is quite shy in a shelter environment. He may hide under his blanket upon initial approach, but he is an affectionate lovebug." }, { "name": "Filip", "description": "Friendly and enjoys pets and head rubs. Is known to sit on keyboards and refuses to touch anything with catnip on it." }, { "name": "Julian", "description": "Both bold and extremely sweet. Wastes no time in investigating new smells, objects, and places, but enjoys lazing in the sun!" }, { "name": "John", "description": "This playful and spirited cat would like to be outside his kennel and will be so happy when he gets to his forever home with more room to move." } ] } </script> </amp-state> </body> </html>

Отправляем письмо

В инструменте AMP4Email есть встроенный валидатор. Если разметка валидна, система позволит отправить письмо на почтовый ящик, привязанный к аккаунту Google. Для этого необходимо:

  • Не закрывая вкладку с AMP4Email зайти в свою почту.
  • Перейти в «Настройки» → «Общие» → «Динамический контент» → «Разработка динамического контента».
  • В поле «Адрес электронной почты отправителя» ввести amp@gmail.dev
  • После этого вернуться на вкладку AMP4Email и кликнуть по кнопке «Send».

Поздравляем! Вы отправили своё первое AMP-письмо.

{ "author_name": "Дарья Смирнова", "author_type": "self", "tags": ["\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438"], "comments": 13, "likes": 34, "favorites": 54, "is_advertisement": false, "subsite_label": "dev", "id": 63425, "is_wide": true, "is_ugc": true, "date": "Thu, 04 Apr 2019 12:10:23 +0300", "is_special": false }
(function () { let cdnUrl = `https://specialsf378ef5-a.akamaihd.net/SelectelBranding/images/` let previousArticleNumber = null let currentArticleNumber = 0 let platform = 'Desktop' let articles = [ // { // name: 'camera', // url: `${cdnUrl}CameraCat`, // text: 'умную камеру для\u00A0наблюдения за\u00A0котиками', // link: '1', // }, { name: 'chill', url: `${cdnUrl}ChillCat`, text: 'трекер, который подскажет, когда пора отдохнуть', link: 'https://vc.ru/promo/288561-eye-tracker', }, // { // name: 'cloud', // url: `${cdnUrl}CloudCat`, // text: 'котика: даёшь ему «пять», а\u00A0он делает бэкап в облако', // link: '3', // } ] let buttonCycle = document.querySelector('.button--cycle') let textField = document.querySelector('.selectel-footer-subtitle') let imageAgent = document.querySelector('.image--agent') let banner = document.querySelector('.selectel-footer') buttonCycle.addEventListener('click', cycleClick) let media = window.matchMedia("(max-width: 570px)") media.addEventListener('change', matchMedia) function matchMedia() { if (media.matches) { platform = 'Mobile' } else { platform = 'Desktop' } update() } matchMedia() function cycleClick(event) { if (event) { event.preventDefault() event.stopPropagation() } window.open('https://vc.ru/tag/selectelDIY', '_blank') //cycle(event) } function cycle(event) { // incrementArticleNumber() textField.innerHTML = generatedText() imageAgent.src = articles[currentArticleNumber].url + platform + '.svg?5' imageAgent.setAttribute("class", "") imageAgent.classList.add('image--agent', articles[currentArticleNumber].name) banner.href = articles[currentArticleNumber].link } function update() { banner.href = articles[currentArticleNumber].link imageAgent.src = articles[currentArticleNumber].url + platform + '.svg?5' textField.innerHTML = generatedText() } function incrementArticleNumber() { previousArticleNumber = currentArticleNumber if (currentArticleNumber >= articles.length - 1) { currentArticleNumber = 0 } else { currentArticleNumber++ } } function generatedText() { let defaultText if (platform === 'Desktop') { defaultText = `Мы тут собрали %text%. Хотите почитать?` } else { defaultText = `Мы тут собрали %text%.` } return defaultText.replace('%text%', articles[currentArticleNumber].text) } function getRandom(min, max) { min = Math.ceil(min) max = Math.floor(max) return Math.floor(Math.random() * (max - min + 1)) + min } (function create() { currentArticleNumber = getRandom(0, articles.length - 1) cycle() let page = document.querySelector('.page--entry') if (page) { function insertAfter() { let parents = page.querySelectorAll('[data-id="7"]') let referenceNode = parents[0] referenceNode.parentNode.insertBefore(banner, referenceNode.nextSibling); loaded() } setTimeout(() => insertAfter(), 0) } }()) function loaded() { banner.classList.add('loaded') } loadImages([ `${cdnUrl}CameraCatDesktop.svg`, `${cdnUrl}ChillCatDesktop.svg`, `${cdnUrl}CloudCatDesktop.svg`, `${cdnUrl}CameraCatMobile.svg`, `${cdnUrl}ChillCatMobile.svg`, `${cdnUrl}CloudCatMobile.svg`, ]) function loadImages(urls) { return Promise.all(urls.map(function (url) { return new Promise(function (resolve) { var img = document.createElement('img'); img.onload = resolve; img.onerror = resolve; img.src = url; }); })); } }())
0
13 комментариев
Популярные
По порядку
Написать комментарий...
5

А как будет выглядеть вся это красота в условном Бате или Тандербёрде?

Ответить
0

Какой процент от ваших подписчиков использует The Bat! или Thunderbird? Сколько их в абсолютных числах?

Ответить
3

У меня нет точных данных, но процентов 30-50

Ответить
0

А изображение при отправке в тело письма будет загружено или будет от каждого получателя запрос к серверу с изображением? Если второе, то это не будет ли являться потенциальной уязвимостью, которая позволит аналитику собирать?

Ответить
5

Но ведь это так и работает много-много лет: при помощи т.н. пикселей (невидимых изображений) собирается статистика открытий

Ответить
1

Тема интересная, дождаться пока все почтовики ее введут и огонь.
Предвижу новую услугу у web-студий)

Ответить
0

Услуга по верстке красивых html писем уже давно существует, тут просто добавится вариативности.

Ответить
1

Актуальность и автоматическое обновление информации, сервер извлекает актуальный контент из удалённых конечных точек.

Безопасность: AMP-письма не обращаются к третьесторонним сервисам, не позволяют использовать рекламные компоненты и дают доступ только к заданной (то есть проверенной и безопасной) функциональности.

Взаимоисключающие параграфы.

Ответить
0

gmail не показывает пример, отправляя в несуществующие настройки Gmail Settings > General > Dynamic email > Dynamic email development

Ответить
0

Что-то письма с такими возможностями пахнут дырами в безопасности

Ответить
0
Ответить
0

Спасибо за статью!

Ответить
0

Подскажите пожалуйста, как письмо будет выглядеть у клиентов, которые не поддерживают AMP?

Ответить
Читать все 13 комментариев
Я задолбался пропускать интересные статьи на vc.ru и создал Capitan

Это самый удобный рабочий стол для браузера

Как работать удалённо по московскому времени, если живёшь в Сибири

Команда ИТ-компании Southbridge — о преодолении трудностей часовых поясов: графике работы, планировании и отдыхе.

Дайджест новостей Сбера: AR-экскурсия, распознавание животных и премия для учёных

Прогулки по Политехническому музею с роботом Сепулькой, чудеса компьютерного зрения, научная премия — начало сентября в Сбере выдалось насыщенным. Делимся с вами самыми интересными новостями компании во втором выпуске нашего дайджеста.

«Вам звонок из Циан»: зачем компания скупает номера телефонов и как call-tracking помогает клиентам сервиса

Подменные номера телефонов защищают от нежелательных звонков и упрощают аналитику продаж

Почему не стоит заказывать товары 18+ на Озоне, если вы не готовы их потом нести в пункт самовывоза

Хочу поделиться неудачной историей заказа товара 18+ на Озоне. И как Озон не хочет помогать решить проблему. Текст могут читать только совершеннолетние пользователи сайта.

«Яндекс» оставляет только положительные отзывы о своих сервисах

После ситуации с не доставленным заказом из Яндекс Лавки, я оставил отзыв на сервисе Карт. Его приняли и разместили, но доступен он только для аккаунта, с которого я его оставлял)))

Что может быть важнее прибыли. ESG-словарь для инвестора

В 2020–2021 гг. резко возросла популярность темы ответственного инвестирования, или ESG. Идея о том, что инвестиции должны не только приносить прибыль, но и поддерживать экологию и социальную справедливость, привела к тому, что ESG-фонды стали играть значимую роль на мировых рынках капитала.

«Сбербанк» через час после личного визита позвал 84-летнюю бабушку еще раз в прийти офис

Казалось бы удобно - оформил получение пенсии на карту и нет проблем. Но это не про историю со Сбербанком. Здесь через час после получения карты лично в отделении прилетело смс о блокировке онлайн сервисов банка.

Sports.ru рекламирует запрещенных мошеннических букмекеров. Потерял 59 000 рублей

Добрый день! Пишу на vc, так как больше нигде не могу добиться ответа ни от представителей казино, ни от представителей Sports,ru, которые рекламируют нелегальное на территории РФ казино и букмекера 1xbet.

Выборы, выборы, кандидаты

Нет, не в рифму известной песни. "Всего лишь" педофилы... Делюсь своим негодованием после посещения избирательного участка.

null