Здравствуйте, меня зовут Антонина, я работаю frontend-разработчиком в Rambler&Co, в команде Lenta.ru.

Content Indexing API — новый инструмент от Google, показывающий, какие страницы доступны в offline-режиме. Я расскажу, как работает Content Indexing API, когда его следует использовать и как его внедряла наша команда.

О проекте

Lenta.ru — это российское новостное интернет-издание. Суточное количество уникальных посетителей — ~7 млн., в пики фиксировали 12 млн. 20% пользуются десктопной версией, 80% — мобильной, у которой также есть offline-версия. Далее речь пойдёт именно о ней.

Статья написана по мотивам моего выступления, его можно посмотреть по ссылке:

Offline-версия Lenta.ru 

В качестве небольшого экскурса расскажу, как работает наша offline-версия.

Зачем она вообще нужна Lenta.ru? Для того чтобы предоставлять контент независимо от того, есть ли у пользователя интернет или нет. Основной упор идёт на информацию, поэтому в offline-версии у нас есть только главная разводящая страница, сами контентные страницы и страница с игрой в крестики-нолики на случай, если контент не сохранился.

Для offline-версии сохраняются:

  1. Необходимые ассеты и код: разметка, стили, JavaScript и шрифт;

  2. Данные: заголовки, тексты, время публикации и некоторые другие данные, необходимые для отображения контента.

Ассеты и код кэшируются с помощью CacheStorage, а данные сохраняются в IndexedDB. При первом обращении к m.lenta.ru происходит следующее:

  • загрузка материалов,

  • регистрация (или обновление) Service Worker,

  • кэширование файлов с помощью CacheStorage,

  • сохранение данных в IndexedDB.

Потом Service Worker слушает запросы (события fetch), и, если связи нет, то пользователю отдается index.html файл с SPA.

В результате, если пользователь перейдёт на страницу материала, который сохранился, то сможет его прочитать. Если же именно этот материал не сохранился, или пользователь перешёл на любую другую страницу (не контентную) – он попадёт на главную страницу offline-версии.

Если ничего не сохранилось, то отобразится страница с крестиками-ноликами. В любом случае пользователь будет видеть, что он находится в offline-режиме, а когда связь снова появится — получит уведомление с предложением вернуться в online.

Проблема, которую решает Content Indexing API

На иллюстрации изображён пользователь с нестабильным интернетом и разные сайты. У некоторых из них есть offline-версия. Как пользователю узнать, какой контент ему доступен? 

Скорее всего он попробует попасть на какой-то сайт. И вряд ли он будет проверять другие сайты, если увидел, что интернета нет:

Возникает вопрос: можно ли смотреть не каждый сайт в отдельности, а увидеть сразу все доступные страницы в одном месте?

Оказывается можно, и именно эту задачу решает Content Indexing API. Он создает единую точку входа в интерфейсе, благодаря которой пользователь может увидеть перечень всех страниц, которые доступны в offline:

Content Indexing API

Content Indexing API — это один из API, разрабатываемый в рамках проекта реализации новых возможностей. Цель проекта — позволить веб-приложениям делать всё, что могут делать нативные приложения на мобильных устройствах и на десктопах.

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

По сути Content Indexing API делает так, чтобы пользователь мог посмотреть в интерфейсе браузера список всех доступных без сети страниц. Со всех веб-приложений, которые используют этот API.

Как это работает (для пользователей)

Здесь важный момент и важная оговорка: из-за того, что функциональность новая, у пользователей ещё нет опыта взаимодействия с ней и нет нужного паттерна поведения. Поэтому поиск перечня доступных в браузере страниц может показаться квестом.

Посмотрим на путь пользователя к месту, где отображаются доступные в offline страницы:

  1. Заходим в меню в браузере.

  2. Выбираем пункт меню Downloads (Скачанные файлы).

  3. Выбираем правую вкладку “Explore offline” (“Офлайн-контент”).

Путь пользователя к проидексированным страницам

Мы на месте. В этой вкладке отображаются все страницы, которые доступны в offline и проиндексированы с помощью Content Indexing API. Если интернет есть — при клике пользователь попадёт на страницу обычной версии сайта. Если интернета нет — на offline-версию страницы.

Как это работает (для разработчиков)

Что вообще нужно, чтобы начать использовать этот API?

  1. У веб-приложения должна быть offline-версия.

  2. В offline-версии должны быть контентные страницы.

Сохранение и отображение страниц происходит силами offline-версии веб-приложения. Content Indexing API — это дополнение к ней, позволяющее отображать в интерфейсе браузера список доступных без интернета страниц, их адреса и превью. 

Алгоритм индексации выглядит так:

Алгоритм индексации страниц

Теперь посмотрим на код. Это фрагмент проверки поддержки Content Indexing API в браузере:

navigator.serviceWorker.ready
  .then((registration) => {
    if (!registration.index) {
      return;
    }
    
    // (1)
  }

Теперь посмотрим на код индексации (вместо строки с комментарием (1) из примера выше):

registration.index.add({
	url: page.url, // required
  id: page.id, // required
  title: page.title, // required
  description: page.description, //required
  icons: [{ // required
    src: page.image_url,
    sizes: 64x64,
    type: 'image/png',
  }],
  // Варианты: 'homepage', 'article', 'video', 'audio', ''
  category: 'article', // optional
});

Индексируем с помощью метода add этого API. При индексации нужно указать url, id, title, description, icons и category. Все параметры кроме category обязательные. Значение category по умолчанию — пустая строка, но можно указать одно из следующих значений: ‘homepage’, ‘article’, ‘video’, ‘audio’. Часть этих параметров используется для формирования превью проиндексированных страниц, а на id остановимся чуть позже.

Мы ответственны не только за запись, но и за удаление устаревших страниц из индексации. Варианта два: сделать интерфейс, чтобы пользователь мог удалить все проиндексированные страницы, либо мы сами должны периодически это делать.

В нашем случае мы удаляем страницы из индексации в момент обновления данных для offline-версии. Кроме этого, пользователь всегда может удалить материалы из самой вкладки “Офлайн-контент”, но, чтобы удалить всё, ему придётся вручную удалять каждую страницу. Поэтому стоит сделать интерфейс для удаления всего или автоудаление.

Lenta.ru — это новостное издание, а актуальность у новостей непродолжительная, поэтому данные offline-версии обновляются каждые полчаса. Индексация страниц и их удаление из индексации происходит в одно и то же время.

Алгоритм удаления страниц из индексации выглядит так:

Алгоритм удаления страниц из индексации

А так выглядит код, который нужен для удаления страниц из индексации:

registration.index.getAll() // (1)
	.then((entries) => {
    entries.forEach((entry) => {
      registration.index.delete(entry.id); // (2)
    });
  });

В строке с комментарием (1) с помощью метода этого API getAll получаем итерируемый объект с данными всех сохранённых страниц. А в строке с комментарием (2), уже зная id страниц, удаляем их с помощью метода этого API delete и передаём ему тот самый id, который указывали при индексации (теперь понятно, зачем он нужен).

Это позволяет удалить информацию о страницах только из индексации, то есть во вкладке “Офлайн-контент” её уже не будет. Но сами данные сохранённых страниц нужно удалять отдельно силами offline-версии.

3 фрагмента кода выше — это не упрощённое демо, а действительно весь необходимый код для работы с Content Indexing API. Если есть offline-версия, то добавить его в проект несложно. 

Как мы внедряли Content Indexing API на Lenta.ru

Наша задача — отдавать контент независимо от того, есть ли у пользователя интернет. Offline-версия в проекте существует более 3-х лет. Но как пользователь узнает, что Lenta.ru умеет работать без сети?

До сих пор был только один вариант: пользователь перейдёт на любую страницу Lenta.ru, когда нет связи, и попадёт в offline-версию. Но с помощью этого API появляется второй вариант: теперь пользователь может узнать о том, что ему доступны какие-то страницы из вкладки “Офлайн-контент” в интерфейсе браузера.

Теперь расскажу, что индексируем. Для offline-версии сохраняются материалы трёх списков новостей, в сумме — это около 100 материалов. Среди них есть маленький список — топ-10, новости из этого списка отображаются наверху главной страницы.

Так как API новый, решили не индексировать сразу все ~100 материалов, а начать с топ-10. Почему решили сначала ограничиться небольшим фрагментом:

  1. Чтобы быстрее зарелизить.

  2. Были опасения, что Content Indexing API может сохранять данные из материалов и дублировать их при сохранении. Это опасение не оправдалось.

  3. Не знали, сколько это займёт времени и сколько даст пользы.

  4. Было непонятно, как повлияет (лучше пусть хорошо повлияет на маленький фрагмент, чем плохо — на большой).

  5. Довольно большое количество посетителей в сутки, поэтому стараемся релизить аккуратно.

Cейчас единовременно индексируем около 10 страниц. Индексировать больше в ближайшее время не планируем.

Пара слов о метрике

В offline-версии мы считаем, сколько пользователей переходит на страницы благодаря Content Indexing API. Решение довольно простое:

registration.index.add({
  url: `${page.url}?utm_source=offline`,
  id: page.id,
  title: page.title,
  description: page.description,
  icons: [{
    src: page.image_url,
    sizes: 64x64,
    type: 'image/png',
  }],
  category: 'article',
});

При индексации материала этим API добавляем url материала с utm-меткой, по которой понимаем, что на страницу попали именно из вкладки Content Indexing API. Приводить цифры пока рано. Ощутимого трафика (относительно основного) это пока не даёт.

Поддержка

Content Indexing API доступен в стабильной версии, и его уже можно использовать в production. Относительно недавно у этого API появилась статья на MDN, в которой указано, что API доступен в Edge, Chrome Android и WebView Android v.84 и Opera Android v.60.

Но на chromestatus упомянуты только Chrome Android и Android WebView, а у остальных браузеров стоит пометка «No signal». Не нашла этого интерфейса ни в Opera v.62 на Android, ни в Edge v.84. Если у кого-то есть другая информация — буду благодарна, если поправите меня.

Поддержка браузерами Content Indexing API, информация с developer.mozilla.org

Интересно было бы перевести эту информацию в цифры, чтобы примерно понимать, у какого процента пользователей поддерживается Content Indexing API. Посмотрим на примере статистики Lenta.ru. 

У Lenta.ru количество пользователей Chrome на Android составляет примерно 60% от всех мобильных пользователей. 64%  всех пользователей Chrome на Android используют v.84 и выше. То есть примерно у 39% от всех мобильных пользователей есть поддержка Content Indexing API. Это цифры за последние 3 месяца.

Количество пользователей Chrome на Android v.84 (на примере статистики Lenta.ru)

Возможные перспективы

Есть 4 идеи, как Content Indexing API будет развиваться и чем может быть полезен:

  1. Бонусы по части SEO у проиндексированных материалов.

    У нас есть предположение, что в дальнейшем у материалов, проиндексированных с помощью Content Indexing API, может повыситься приоритет в поисковой выдаче или будут другие бонусы по части SEO.

  2. Найти проиндексированные материалы будет проще, а значит и пользоваться этим будут чаще.

    Больше наша надежда, чем догадка: путь к месту, где в браузере находится перечень доступных в offline страниц, сократится с трёх до (в идеале) одного шага.

  3. Content Indexing API можно использовать для сохранения закладок пользователя и для персональных рекомендаций.

    Это не догадка, так действительно можно делать. Этот API можно использовать для сохранения рекомендованных материалов и тех, которые пользователь добавил в закладки. Если, конечно, веб-приложение действительно сохраняет эти страницы для offline-режима.

  4. Со временем этой функциональностью начнёт пользоваться больше людей.

    Так как API новый и раньше такой опции не было, ещё не сформировался нужный пользовательский опыт: большинство просто не знает, что так можно. Возможно, что со временем этой функциональностью начнёт пользоваться больше людей. Будет хорошо, если к этому моменту в Lenta.ru она уже будет. Примерно такая же ситуация у проекта была с самой offline-версией: сначала сделали, а потом её наличие стало обязательным требованием, чтобы считаться PWA.

Плюсы и минусы

Плюсы:

  1. Стабильная версия, можно использовать в production.


  2. +1 инструмент вовлечения 
и точка входа.

  3. Мало кода 
(непосредственно для работы с Content Indexing API).


  4. Есть перспективы.

Минусы:

  1. Слабая поддержка браузерами.


  2. Пользовательский опыт ещё не сформировался.


  3. Нужна offline-версия, чтобы начать использовать.


  4. Пока не даёт больших результатов (трафик).

Рекомендации

Есть две рекомендации касательно того, когда стоит использовать Content Indexing API:

  1. Если веб-приложение — это контентный ресурс.

  2. И у веб-приложения есть offline-версия, в которой можно просматривать контентные страницы.

В качестве заключения

Content Indexing API решает проблему обнаружения контента, доступного в offline. Уже есть стабильная версия, которую можно использовать в production. Этот API только индексирует страницы, а сохранение и отображение — задачи offline-версии. Ещё раз подчеркну, что offline-версия и Content Indexing API — это не одно и то же, они не взаимозаменяемы.

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

Эффект от таких новых инструментов не всегда заметен сразу, но перспективы интересные. Возможно, через некоторое время это станет таким же привычным пользовательским опытом, как, например, AMP и offline.

Ссылка на материалы.