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

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

О проекте

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

Офлайн-версия Lenta.ru

В качестве небольшого отступления расскажу, как работает наша оффлайн версия.

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

Для оффлайн версии сохраняется следующее:

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

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

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

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

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

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

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

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

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

Проблема, которую необходимо решить с помощью Content Indexing API

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

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

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

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

API индексации контента

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

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

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

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

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

  1. Зайдите в меню в браузере.
  2. Выберите элемент в меню «Загрузки».
  3. Выберите вкладку «Исследовать в автономном режиме» справа.

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

Потенциально этот функционал мог бы иметь больший эффект, но его расположение слишком неясно. Я думаю, что зона роста заключается в том, чтобы облегчить пользователям путь к вкладке.

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

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

  1. Веб-приложение должно иметь автономную версию.
  2. В автономной версии должны быть страницы с контентом.

Страницы сохраняются и отображаются с помощью автономной версии веб-приложения. 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',
  }],
  // Variants: 'homepage', 'article', 'video', 'audio', ''
  category: 'article', // optional });

Мы индексируем его с помощью метода add этого API. При индексировании url, id, заголовок, описание, значки и >категория должна быть указана. Все параметры, кроме категории, являются обязательными. Значение по умолчанию category — пустая строка, но вы можете указать одно из следующих значений: 'homepage', 'article', 'видео', 'аудио'. Некоторые из этих параметров используются для генерации превью проиндексированных страниц, а на id мы остановимся чуть позже.

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

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

«Лента.ру» — новостное издание, а обновления новостей недолговечны, поэтому офлайн-версия обновляется каждые полчаса. Страницы индексируются и деиндексируются одновременно.

Алгоритм деиндексации страниц следующий:

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

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

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

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

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

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

Наша цель — доставлять контент независимо от того, есть ли у пользователя подключение к Интернету. Выполняется потому, что офлайн-версия в проекте существует более 3-х лет. Но откуда пользователь знает, что «Лента.ру» способна работать без сети?

До сих пор был только один вариант: пользователь заходил на любую страницу «Ленты.ру», когда нет связи, и попадал в офлайн-версию. Но с этим API появляется второй вариант: теперь пользователь может узнать, что какие-то страницы ему доступны из вкладки «Offline Content» в интерфейсе браузера.

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

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

  1. Его быстрее выпустить.
  2. Были опасения, что Content Indexing API может сохранять данные из материалов и дублировать их при сохранении. Этот страх не оправдался.
  3. Мы не знали, сколько времени это займет и какие преимущества это принесет.
  4. Было неясно, каким будет удар (лучше хорошо ударить по маленькому фрагменту, чем плохо ударить по большому).
  5. Достаточно большое количество посетителей в день, поэтому мы стараемся выпускать его осторожно.

В настоящее время мы индексируем около 10 страниц за раз. Мы не планируем больше индексировать в ближайшее время.

Несколько слов о метрике

В офлайн-версии мы подсчитываем, сколько пользователей переходят на страницы, благодаря 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 доступен в стабильной версии, и его уже можно использовать в продакшене. Недавно была статья об этом API на MDN, в которой указано, что API доступен в Edge, Chrome Android и WebView Android v. 84 и Opera Android v. 60.

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

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

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

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

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

  1. SEO-бонусы за проиндексированные материалы.
    У нас есть предположение, что в будущем у материалов, проиндексированных с помощью Content Indexing API, может повыситься приоритет в поисковой выдаче или появятся другие бонусы с точки зрения SEO.
  2. Стало легче найти проиндексированные материалы, а значит, и использовать их будут чаще.
    Больше надеемся, чем догадываемся: путь, по которому браузер выводит список страниц, доступных офлайн, сократится с трех до (в идеале) один шаг.
  3. Content Indexing API можно использовать для сохранения пользовательских закладок и личных рекомендаций.
    Это не предположение, это действительно можно сделать. Этот API можно использовать для сохранения рекомендуемого контента и того, что пользователь добавил в закладки. Если, конечно, веб-приложение на самом деле сохраняет эти страницы для офлайн-режима.
  4. Со временем этим функционалом начнет пользоваться больше людей.
    Поскольку API новый и такой опции раньше не было, то и необходимый пользовательский опыт еще не сформирован: большинство просто не знает, что такое возможно. Вполне возможно, что со временем этим функционалом воспользуется больше людей. Хорошо, если к тому времени он будет у «Ленты.ру». Примерно такая же ситуация была у проекта и с самой офлайн-версией: сначала сделали, а потом стало требованием считаться PWA.

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

Плюсы:

  1. Стабильная версия, которую можно использовать в продакшене.
  2. +1 инструмент взаимодействия и точка входа.
  3. Небольшой код (непосредственно для работы с Content Indexing API).
  4. Есть перспективы.

Минусы:

  1. Плохая поддержка браузеров.
  2. Пользовательский опыт еще не сформирован.
  3. Для начала использования необходима офлайн-версия.
  4. Пока больших результатов (трафик) не дает.

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

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

  1. Если веб-приложение является ресурсом контента.
  2. Веб-приложение имеет автономную версию, где вы можете просматривать страницы контента.

В заключение

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

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

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

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