Как поисковые системы работают с приложениями AngularJS?
Я вижу две проблемы с приложением AngularJS относительно поисковых систем и SEO:
1) Что происходит с пользовательскими тегами? Игровые системы игнорируют весь контент в этих тегах? то есть предположим, что у меня есть
<custom>
<h1>Hey, this title is important</h1>
</custom>
было бы <h1>
индексироваться, несмотря на то, что он внутри пользовательских тегов?
2) Есть ли способ избежать поисковых систем индексирования {{}} буквально? т.е.
<h2>{{title}}</h2>
Я знаю, что могу сделать что-то вроде
<h2 ng-bind="title"></h2>
но что, если я действительно хочу, чтобы сканер "увидел" заголовок? Является ли рендеринг на стороне сервера единственным решением?
15 ответов
Обновление май 2014
Сканеры Google теперь выполняют JavaScript - вы можете использовать Инструменты Google для веб-мастеров, чтобы лучше понять, как Google отображает ваши сайты.
Оригинальный ответ
Если вы хотите оптимизировать свое приложение для поисковых систем, к сожалению, нет способа обойтись предварительно отрендеренной версией для сканера. Вы можете прочитать больше о рекомендациях Google для сайтов, работающих с ajax и javascript, здесь.
Если это вариант, я бы рекомендовал прочитать эту статью о том, как сделать SEO для Angular с рендерингом на стороне сервера.
Я не уверен, что делает сканер, когда сталкивается с пользовательскими тегами.
Используйте PushState и Precomposition
Текущий (2015) способ сделать это - использовать метод pushState в JavaScript.
PushState изменяет URL в верхней панели браузера без перезагрузки страницы. Скажем, у вас есть страница, содержащая вкладки. Вкладки скрывают и отображают содержимое, а содержимое вставляется динамически, либо с помощью AJAX, либо просто путем настройки display: none и display: block, чтобы скрыть и отобразить правильное содержимое вкладки.
При нажатии на вкладки используйте pushState, чтобы обновить URL-адрес в адресной строке. Когда страница отображается, используйте значение в адресной строке, чтобы определить, какую вкладку показывать. Угловая маршрутизация сделает это автоматически.
Precomposition
Существует два способа использования одностраничного приложения PushState (SPA).
- Через PushState, где пользователь нажимает на ссылку PushState и содержимое AJAXed.
- Нажав на URL напрямую.
Первоначальное попадание на сайт будет связано с прямым попаданием на URL. Последующие попадания просто AJAX в контенте, когда PushState обновляет URL.
Сканеры собирают ссылки со страницы, а затем добавляют их в очередь для последующей обработки. Это означает, что для сканера каждое попадание на сервер является прямым попаданием, они не перемещаются через Pushstate.
Предварительная композиция связывает начальную полезную нагрузку с первым ответом от сервера, возможно, в виде объекта JSON. Это позволяет поисковой системе отображать страницу без выполнения вызова AJAX.
Есть основания полагать, что Google может не выполнять запросы AJAX. Подробнее об этом здесь:
Поисковики могут читать и выполнять JavaScript
Google уже в течение некоторого времени может анализировать JavaScript, поэтому они изначально разработали Chrome, чтобы выступать в качестве полнофункционального безголового браузера для паука Google. Если ссылка имеет действительный атрибут href, новый URL может быть проиндексирован. Больше нечего делать.
Если дополнительно щелкнуть ссылку, запускается вызов pushState, пользователь может перемещаться по сайту через PushState.
Поддержка поисковой системы для PushState URL
PushState в настоящее время поддерживается Google и Bing.
Вот Мэтт Каттс, отвечающий на вопрос Пола Айриша о PushState для SEO:
Вот Google объявляет о полной поддержке JavaScript для паука:
http://googlewebmastercentral.blogspot.de/2014/05/understanding-web-pages-better.html
В результате Google поддерживает PushState и будет индексировать URL-адреса PushState.
Смотрите также выбор инструментов Google для веб-мастеров как Googlebot. Вы увидите, что ваш JavaScript (включая Angular) выполнен.
Bing
Вот объявление Bing о поддержке красивых URL-адресов PushState от марта 2013 года:
http://blogs.bing.com/webmaster/2013/03/21/search-engine-optimization-best-practices-for-ajax-urls/
Не используйте HashBangs #!
URL-адреса Hashbang были отвратительным временным промежутком, требующим от разработчика предоставить предварительно отрендеренную версию сайта в специальном месте. Они все еще работают, но вам не нужно их использовать.
URL-адреса Hashbang выглядят так:
domain.com/#!path/to/resource
Это будет связано с метатегом, как это:
<meta name="fragment" content="!">
Google не будет индексировать их в этой форме, а вместо этого извлечет статическую версию сайта из URL-адреса _escaped_fragments_ и проиндексирует ее.
URL-адреса Pushstate выглядят как любой обычный URL:
domain.com/path/to/resource
Разница в том, что Angular обрабатывает их для вас, перехватывая изменения в document.location, связанные с ним в JavaScript.
Если вы хотите использовать PushState URL-адреса (и вы, вероятно, делаете это), удалите все старые URL-адреса и метатеги в стиле хэширования и просто включите режим HTML5 в своем блоке конфигурации.
Тестирование вашего сайта
Инструменты Google для веб-мастеров теперь содержат инструмент, который позволит вам извлекать URL-адрес как google и отображать JavaScript так, как его отображает Google.
https://www.google.com/webmasters/tools/googlebot-fetch
Генерация PushState URL в Angular
Чтобы генерировать реальные URL-адреса в Angular, а не с префиксом #, установите режим HTML5 для вашего объекта $locationProvider.
$locationProvider.html5Mode(true);
Сторона сервера
Поскольку вы используете реальные URL-адреса, вам необходимо убедиться, что ваш сервер отправляет один и тот же шаблон (плюс некоторый предварительно составленный контент) для всех действительных URL-адресов. Как это сделать, зависит от архитектуры вашего сервера.
Карта сайта
Ваше приложение может использовать необычные формы навигации, например, при наведении курсора или прокрутке. Чтобы убедиться, что Google может управлять вашим приложением, я бы, вероятно, предложил создать карту сайта, простой список всех URL-адресов, на которые реагирует ваше приложение. Вы можете разместить его в расположении по умолчанию (/sitemap или /sitemap.xml) или сообщить об этом Google, используя инструменты для веб-мастеров.
В любом случае, хорошая идея иметь карту сайта.
Поддержка браузера
Pushstate работает в IE10. В старых браузерах Angular автоматически использует URL-адреса в стиле хэширования.
Демо-страница
Следующее содержимое отображается с помощью pushstate URL с предкомпозицией:
http://html5.gingerhost.com/london
Как можно убедиться, по этой ссылке контент проиндексирован и отображается в Google.
Обслуживающие коды статуса заголовка 404 и 301
Поскольку поисковая система всегда будет попадать на ваш сервер при каждом запросе, вы можете отправлять коды состояния заголовка со своего сервера и ожидать, что Google их увидит.
Давайте определимся с AngularJS и SEO
Google, Yahoo, Bing и другие поисковые системы сканируют Интернет традиционными способами, используя традиционные сканеры. Они запускают роботов, которые сканируют HTML на веб-страницах, собирая информацию по пути. Они хранят интересные слова и ищут другие ссылки на другие страницы (эти ссылки, их количество и количество вступают в игру с SEO).
Так почему же поисковые системы не работают с сайтами javascript?
Ответ связан с тем фактом, что роботы поисковых систем работают через браузеры без заголовка, и у них чаще всего нет движка рендеринга javascript для рендеринга javascript страницы. Это работает для большинства страниц, так как большинство статических страниц не заботятся о том, чтобы JavaScript отображал их страницу, так как их содержимое уже доступно.
Что с этим можно сделать?
К счастью, сканеры более крупных сайтов начали реализовывать механизм, который позволяет нам делать наши сайты JavaScript доступными для сканирования, но для этого нам необходимо внести изменения в наш сайт.
Если мы изменим наш hashPrefix
быть #!
вместо просто #
, тогда современные поисковые системы изменят запрос на использование _escaped_fragment_
вместо #!
, (В режиме HTML5, то есть там, где у нас есть ссылки без префикса хеша, мы можем реализовать эту же функцию, посмотрев на User Agent
заголовок в нашем бэкенде).
То есть вместо запроса от обычного браузера, который выглядит так:
http://www.ng-newsletter.com/#!/signup/page
Поисковая система будет искать страницу с:
http://www.ng-newsletter.com/?_escaped_fragment_=/signup/page
Мы можем установить хэш-префикс наших приложений Angular, используя встроенный метод из ngRoute
:
angular.module('myApp', [])
.config(['$location', function($location) {
$location.hashPrefix('!');
}]);
И, если мы используем html5Mode
нам нужно реализовать это, используя метатег:
<meta name="fragment" content="!">
Напоминание, мы можем установить html5Mode()
с $location
оказание услуг:
angular.module('myApp', [])
.config(['$location',
function($location) {
$location.html5Mode(true);
}]);
Обработка поисковой системы
У нас есть много возможностей определить, как мы будем справляться с фактической доставкой контента поисковым системам в виде статического HTML. Мы можем размещать сервер самостоятельно, мы можем использовать сервис для размещения сервера, мы можем использовать прокси-сервер для доставки контента и т. Д. Давайте рассмотрим несколько вариантов:
Самопринятый
Мы можем написать сервис для обработки сканирования нашего собственного сайта, используя браузер без заголовка, такой как phantomjs или zombiejs, делая снимок страницы с визуализированными данными и сохраняя его в виде HTML. Всякий раз, когда мы видим строку запроса ?_escaped_fragment_
в поисковом запросе мы можем доставить статический снимок HTML, который мы взяли со страницы, а не с предварительно обработанной страницы, только через JS. Это требует от нас иметь бэкэнд, который доставляет наши страницы с условной логикой посередине. Мы можем использовать что-то вроде бэкэнда prerender.io в качестве отправной точки для запуска этого самостоятельно. Конечно, нам все еще нужно обрабатывать прокси и обработку фрагментов, но это хорошее начало.
С платным сервисом
Самый простой и быстрый способ загрузить контент в поисковую систему - это использовать службы Brombone, seo.js, seo4ajax и prerender.io, которые являются хорошими примерами, которые будут размещать для вас вышеуказанный рендеринг контента. Это хороший вариант для тех случаев, когда мы не хотим иметь дело с запуском сервера / прокси. Кроме того, это обычно очень быстро.
Для получения дополнительной информации об Angular и SEO, мы написали обширный учебник по этому адресу на http://www.ng-newsletter.com/posts/serious-angular-seo.html и мы подробно описали его в нашей книге ng-book: Полная книга по AngularJS. Проверьте это на https://www.ng-book.com/.
Вы должны действительно изучить руководство по созданию SEO-дружественного сайта AngularJS в год блога moo. Он проведет вас через все шаги, описанные в документации Angular. http://www.yearofmoo.com/2012/11/angularjs-and-seo.html
Используя эту технику, поисковая система видит расширенный HTML вместо пользовательских тегов.
Это резко изменилось.
Если вы используете: $locationProvider.html5Mode(true); вы настроены
Нет больше рендеринга страниц.
С тех пор, как был задан этот вопрос, все немного изменилось. Теперь есть варианты, позволяющие Google индексировать ваш сайт AngularJS. Самым простым вариантом, который я нашел, было использование бесплатного сервиса http://prerender.io/, который сгенерирует для вас поддающиеся обработке страницы и предоставит их поисковым системам. Он поддерживается практически на всех серверных веб-платформах. Я недавно начал использовать их, и поддержка тоже отличная.
Я не имею никакого отношения к ним, это исходит от счастливого пользователя.
Собственный веб-сайт Angular предоставляет упрощенный контент для поисковых систем: http://docs.angularjs.org/?_escaped_fragment_=/tutorial/step_09
Скажем, ваше приложение Angular использует API-интерфейс JSON, управляемый Node.js / Express, например /api/path/to/resource
, Возможно, вы могли бы перенаправить любые запросы с ?_escaped_fragment_
в /api/path/to/resource.html
и использовать согласование содержимого для визуализации HTML-шаблона содержимого, а не для возврата данных JSON.
Единственное, ваши угловые маршруты должны соответствовать 1:1 с вашим REST API.
РЕДАКТИРОВАТЬ: Я понимаю, что это может действительно запутать ваш REST API, и я не рекомендую делать это вне очень простых случаев использования, где это может быть естественным подгонки.
Вместо этого вы можете использовать совершенно другой набор маршрутов и контроллеров для своего дружественного роботу контента. Но затем вы дублируете все ваши маршруты и контроллеры AngularJS в Node/Express.
Я остановился на создании снимков с помощью безголового браузера, хотя чувствую, что это не совсем идеально.
Хорошую практику можно найти здесь:
http://scotch.io/tutorials/javascript/angularjs-seo-with-prerender-io?_escaped_fragment_=tag
На данный момент Google изменил свое предложение по сканированию AJAX.
Времена изменились. Сегодня, пока вы не запрещаете роботу Googlebot сканировать файлы JavaScript или CSS, мы, как правило, можем отображать и понимать ваши веб-страницы, как современные браузеры.
tl; dr: [Google] больше не рекомендует предложение сканирования AJAX [Google], сделанное еще в 2009 году.
Google Crawlable Ajax Spec, как указано в других ответах здесь, является в основном ответом.
Если вас интересует, как другие поисковые системы и социальные боты решают те же проблемы, я описал состояние дел здесь: http://blog.ajaxsnapshots.com/2013/11/googles-crawlable-ajax-specification.html
Я работаю на https://ajaxsnapshots.com/, компанию, которая реализует Crawlable Ajax Spec в качестве службы - информация в этом отчете основана на наблюдениях из наших журналов.
Я нашел элегантное решение, которое охватило бы большинство ваших баз. Сначала я написал об этом здесь и ответил на другой подобный вопрос Stackru, который ссылается на него.
К вашему сведению, это решение также содержит жестко закодированные резервные теги на случай, если сканер не обнаружит Javascript. Я не обрисовал это явно, но стоит упомянуть, что вы должны активировать режим HTML5 для правильной поддержки URL.
Также обратите внимание: это не полные файлы, а важные части тех, которые имеют отношение к делу. Если вам нужна помощь в написании шаблона для директив, услуг и т. Д., Которые можно найти в другом месте. Во всяком случае, здесь идет...
app.js
Здесь вы предоставляете собственные метаданные для каждого из ваших маршрутов (заголовок, описание и т. Д.)
$routeProvider
.when('/', {
templateUrl: 'views/homepage.html',
controller: 'HomepageCtrl',
metadata: {
title: 'The Base Page Title',
description: 'The Base Page Description' }
})
.when('/about', {
templateUrl: 'views/about.html',
controller: 'AboutCtrl',
metadata: {
title: 'The About Page Title',
description: 'The About Page Description' }
})
metadata-service.js (сервис)
Устанавливает пользовательские параметры метаданных или использует значения по умолчанию в качестве запасных.
var self = this;
// Set custom options or use provided fallback (default) options
self.loadMetadata = function(metadata) {
self.title = document.title = metadata.title || 'Fallback Title';
self.description = metadata.description || 'Fallback Description';
self.url = metadata.url || $location.absUrl();
self.image = metadata.image || 'fallbackimage.jpg';
self.ogpType = metadata.ogpType || 'website';
self.twitterCard = metadata.twitterCard || 'summary_large_image';
self.twitterSite = metadata.twitterSite || '@fallback_handle';
};
// Route change handler, sets the route's defined metadata
$rootScope.$on('$routeChangeSuccess', function (event, newRoute) {
self.loadMetadata(newRoute.metadata);
});
metaproperty.js (директива)
Пакет результатов службы метаданных для представления.
return {
restrict: 'A',
scope: {
metaproperty: '@'
},
link: function postLink(scope, element, attrs) {
scope.default = element.attr('content');
scope.metadata = metadataService;
// Watch for metadata changes and set content
scope.$watch('metadata', function (newVal, oldVal) {
setContent(newVal);
}, true);
// Set the content attribute with new metadataService value or back to the default
function setContent(metadata) {
var content = metadata[scope.metaproperty] || scope.default;
element.attr('content', content);
}
setContent(scope.metadata);
}
};
index.html
В комплекте с жестко закодированными тегами возврата, упомянутыми ранее, для сканеров, которые не могут поднять Javascript.
<head>
<title>Fallback Title</title>
<meta name="description" metaproperty="description" content="Fallback Description">
<!-- Open Graph Protocol Tags -->
<meta property="og:url" content="fallbackurl.com" metaproperty="url">
<meta property="og:title" content="Fallback Title" metaproperty="title">
<meta property="og:description" content="Fallback Description" metaproperty="description">
<meta property="og:type" content="website" metaproperty="ogpType">
<meta property="og:image" content="fallbackimage.jpg" metaproperty="image">
<!-- Twitter Card Tags -->
<meta name="twitter:card" content="summary_large_image" metaproperty="twitterCard">
<meta name="twitter:title" content="Fallback Title" metaproperty="title">
<meta name="twitter:description" content="Fallback Description" metaproperty="description">
<meta name="twitter:site" content="@fallback_handle" metaproperty="twitterSite">
<meta name="twitter:image:src" content="fallbackimage.jpg" metaproperty="image">
</head>
Это должно существенно помочь в большинстве случаев использования поисковых систем. Если вы хотите полностью динамический рендеринг для сканеров социальных сетей (которые сомнительны в поддержке Javascript), вам все равно придется использовать один из сервисов предварительного рендеринга, упомянутых в некоторых других ответах.
Надеюсь это поможет!
С помощью Angular Universal вы можете создавать целевые страницы для приложения, которые выглядят как законченное приложение, а затем загружать приложение Angular за ним.
Angular Universal генерирует чистый HTML, то есть страницы без javascript на стороне сервера, и предоставляет их пользователям без задержки. Таким образом, вы можете иметь дело с любым сканером, ботом и пользователем (у которых уже есть низкий процессор и скорость сети). Затем вы можете перенаправить их по ссылкам / кнопкам в ваше реальное угловое приложение, которое уже загружено за ним. Это решение рекомендовано официальным сайтом. -Больше информации о SEO и Angular Universal-
Используйте что-то вроде PreRender, он создает статические страницы вашего сайта, чтобы поисковые системы могли его проиндексировать.
Здесь вы можете узнать, для каких платформ он доступен: https://prerender.io/documentation/install-middleware
Программы-обходчики (или боты) предназначены для сканирования содержимого веб-страниц в формате HTML, но из-за операций AJAX для асинхронной выборки данных это стало проблемой, поскольку для отображения страницы и отображения на ней динамического содержимого требуется некоторое время. Так же, AngularJS
также использовать асинхронную модель, которая создает проблему для сканеров Google.
Некоторые разработчики создают базовые HTML-страницы с реальными данными и обслуживают эти страницы со стороны сервера во время сканирования. Мы можем рендерить те же страницы с PhantomJS
на стороне подачи, которая имеет _escaped_fragment_
(Потому что гугл ищет #!
в нашем сайте URL-адреса, а затем принимает все после #!
и добавляет это в _escaped_fragment_
параметр запроса). Для более подробной информации, пожалуйста, прочитайте этот блог.
Искатели не нуждаются в богато представленном графическом интерфейсе, они только хотят видеть содержимое, поэтому вам не нужно давать им снимок страницы, созданной для людей.
Мое решение: дать сканеру то, что он хочет:
Вы должны подумать о том, чего хочет гусеничный робот, и дать ему только это.
СОВЕТ не связывайтесь со спиной. Просто добавьте немного серверного вида спереди, используя тот же API