Как поисковые системы работают с приложениями AngularJS?


Я вижу две проблемы с приложением AngularJS относительно поисковых систем и SEO:

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

<custom>
  <h1>Hey, this title is important</h1>
</custom>

б <h1> индексироваться, несмотря на то, что внутри пользовательских тегов?


2) есть ли способ избежать поисковых систем индексирования {{}} привязки буквально? то есть

<h2>{{title}}</h2>

Я знаю, что я мог бы сделать что-то как

<h2 ng-bind="title"></h2>

но что, если я действительно хочу, чтобы искатель "видел" название? Является ли рендеринг на стороне сервера единственным решением?

15 688

15 ответов:

Обновление

Google crawlers теперь выполняет javascript - вы можете использовать Google Webmaster Tools чтобы лучше понять, как ваши сайты отображаются Google.

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

Если это вариант, я бы рекомендовал читать в этой статье о том, как сделать SEO для Angular с рендерингом на стороне сервера.

Я не уверен, что искатель делает, когда он сталкивается с пользовательскими тегами.

используйте PushState и Precomposition

текущий (2015) способ сделать это с помощью метода JavaScript pushState.

PushState изменяет URL в верхней панели браузера без перезагрузки страницы. Допустим, у вас есть страница, содержащая вкладки. Вкладки скрывают и показывают содержимое, а содержимое вставляется динамически, либо с помощью AJAX, либо просто установив display:none и display:block, чтобы скрыть и показать правильное содержимое вкладки.

при нажатии на вкладки, использовать pushState, чтобы обновить URL-адрес в адресной строке. При отображении страницы, Используйте значение в адресной строке, чтобы определить, какие вкладки показывать. Угловая маршрутизация сделает это за вас автоматически.

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

есть два способа попасть в приложение PushState Single Page (SPA)

  1. через PushState, где пользователь нажимает на ссылку PushState и содержимое AJAXed В.
  2. нажав на URL-адрес напрямую.

в первоначальное попадание на сайт будет включать в себя попадание по URL напрямую. Последующие хиты будут просто AJAX в содержимом, поскольку PushState обновляет URL.

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

предварительная композиция связывает начальную полезную нагрузку в первый ответ от сервера, возможно, как объект JSON. Это позволяет осуществлять поиск Движок для визуализации страницы без выполнения вызова AJAX.

есть некоторые доказательства того, что Google может не выполнять запросы AJAX. Подробнее об этом здесь:

https://web.archive.org/web/20160318211223/http://www.analog-ni.co/precomposing-a-spa-may-become-the-holy-grail-to-seo

поисковые системы могут читать и выполнять JavaScript

Google уже некоторое время может анализировать JavaScript, поэтому они изначально разработан Chrome, чтобы выступать в качестве полнофункционального безголового браузера для Google spider. Если ссылка имеет допустимый атрибут href, новый URL-адрес может быть проиндексирован. Больше делать нечего.

если щелчок по ссылке дополнительно запускает вызов pushState, сайт может перемещаться пользователем через PushState.

поддержка поисковой системы для pushState URLs

PushState в настоящее время поддерживается Google и Bing.

Google

вот Мэтт Каттс отвечая на вопрос пола Айриша о PushState для SEO:

http://youtu.be/yiAF9VdvRPw

вот Google объявляет о полной поддержке JavaScript для паука:

http://googlewebmastercentral.blogspot.de/2014/05/understanding-web-pages-better.html

результат заключается в том, что Google поддерживает PushState и будет индексировать URL-адреса PushState.

см. также Google webmaster tools' fetch as Googlebot. Вы увидите, что ваш JavaScript (в том числе угловой) выполнен.

Бинг

вот объявление Bing о поддержке довольно PushState URLs от марта 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_ и проиндексирует его.

pushState URL-адреса выглядят как любой обычный URL:

domain.com/path/to/resource

разница это угловой обрабатывает их для вас, перехватывая изменение в документе.место работы с ним в JavaScript.

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

тестирование сайта

Google Webmaster tools теперь содержит инструмент, который позволит вам получить URL-адрес как google, а также визуализировать JavaScript как Google renders оно.

https://www.google.com/webmasters/tools/googlebot-fetch

генерация URL-адресов PushState в Angular

чтобы генерировать реальные URL-адреса в угловых, а не # с префиксом, установите режим HTML5 на свой объект $locationProvider.

$locationProvider.html5Mode(true);

На Стороне Сервера

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

Карта сайта

ваше приложение может использовать необычные формы навигации, например наведение курсора или прокрутки. Чтобы убедиться, что Google может управлять вашим приложением, я бы, вероятно, предложил создать карту сайта, простой список всех URL-адресов, на которые реагирует ваше приложение. Вы можете разместить его в расположении по умолчанию (/sitemap или / sitemap.xml), или расскажите об этом Google с помощью инструментов веб-мастера.

это хорошая идея, чтобы иметь sitemap в любом случае.

поддержка браузеров

Pushstate работает в IE10. В старых браузерах Angular автоматически возвращается к URL-адресам хэш-стиля

демо-страницы

следующее содержимое отображается с помощью URL-адреса pushstate с предварительной композицией:

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, т. е. там, где у нас есть ссылки без префикса хэша, мы можем реализовать эту же функцию, посмотрев на в нашем внутренний.)

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

http://www.ng-newsletter.com/#!/signup/page

поисковая система будет искать страницы с:

http://www.ng-newsletter.com/?_escaped_fragment_=/signup/page

мы можем установить хэш-префикс наших угловых приложений с помощью встроенного метода от 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. Мы можем сами разместить бэкэнд, мы можем использовать сервис для размещения бэкэнда для нас, мы можем использовать прокси для доставки контента и т. д. Давайте рассмотрим несколько вариантов:

Self-hosted

мы можем написать обслуживание для того чтобы отрегулировать общаться с обход нашего собственного сайта с помощью безголового браузера, такого как phantomjs или zombiejs, делает снимок страницы с визуализированными данными и сохраняет ее в виде HTML. Когда мы видим строку запроса ?_escaped_fragment_ в поисковом запросе мы можем доставить статический HTML-снимок, который мы сделали для страницы, а не предварительно отрисованную страницу только через JS. Это требует от нас иметь бэкэнд, который доставляет наши страницы с условной логикой в середине. Мы можем использовать что-то вроде prerender.io ' s backend как a отправная точка для запуска этого сами. Конечно, нам все еще нужно обрабатывать проксирование и обработку фрагментов, но это хорошее начало.

с платной услугой

самый простой и быстрый способ получить контент в поисковике воспользоваться услугой Brombone, seo.js, seo4ajax, иprerender.io являются хорошими примерами из них, которые будут размещены выше содержание рендеринга для вас. Это хороший вариант для тех случаев, когда мы не хотим иметь дело с запуском сервера/прокси. Кроме того, это обычно очень быстро.

для получения дополнительной информации об Angular и SEO, мы написали обширный учебник по нему на http://www.ng-newsletter.com/posts/serious-angular-seo.html и мы его еще больше в нашей книге ng-book: Полная книга по AngularJS. Проверьте это наng-book.com.

вы действительно должны проверить учебник по созданию SEO-дружественного сайта AngularJS в год блога moo. Он проведет вас через все шаги, описанные в документации Angular. http://www.yearofmoo.com/2012/11/angularjs-and-seo.html

используя этот метод, поисковая система видит расширенный HTML вместо пользовательских тегов.

Это кардинально изменилось.

http://searchengineland.com/bing-offers-recommendations-for-seo-friendly-ajax-suggests-html5-pushstate-152946

Если вы используете: $locationProvider.html5Mode (true); вы настроены.

больше нет страниц рендеринга.

все изменилось совсем немного с тех пор, как был задан этот вопрос. Теперь есть варианты, чтобы позволить Google индексировать ваш сайт AngularJS. Самый простой вариант, который я нашел, был использовать http://prerender.io бесплатный сервис, который будет генерировать crwalable страницы для вас и служить, что в поисковых системах. Он поддерживается практически на всех серверных веб-платформах. Я недавно начал использовать их, и поддержка тоже отличная.

У меня нет ни одного принадлежность к ним, это исходит от счастливого пользователя.

собственный сайт Angular предлагает упрощенный контент для поисковых систем:http://docs.angularjs.org/?_escaped_fragment_=/tutorial/step_09

сказать, что ваш угловой приложения, потребляющего узла.JS / Express-управляемый JSON api, например /api/path/to/resource. Возможно, вы могли бы перенаправить любые запросы с ?_escaped_fragment_ to /api/path/to/resource.html, и использовать содержание переговоров чтобы отобразить HTML-шаблон содержимого, а не возвращать данные JSON.

единственное, ваш угловой маршруты должны будут соответствовать 1: 1 с вашим REST API.

EDIT: я понимаю, что это может действительно испортить ваш 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 году.

спецификация Ajax для обхода Google, как указано в других ответах здесь, в основном является ответом.

Если вас интересует, как другие поисковые системы и социальные боты справляются с теми же проблемами, которые я написал здесь:http://blog.ajaxsnapshots.com/2013/11/googles-crawlable-ajax-specification.html

Я работаю на https://ajaxsnapshots.com, компания, которая реализует спецификацию Ajax для обхода как сервис - информация в основу этого отчета легли наблюдения из наших журналов.

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

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

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

приложение.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' }
   })

метаданные-службе.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);
});

метасвойства.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);
  }
};

.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), вам все равно придется использовать одну из служб предварительного рендеринга, упомянутых в некоторых других ответах.

надеюсь, что это помогает!

Используйте что-то вроде PreRender, он делает статические страницы вашего сайта, чтобы поисковые системы могли его индексировать.

здесь вы можете узнать, для каких платформ он доступен:https://prerender.io/documentation/install-middleware#asp-net

с помощью Angular Universal вы можете создавать целевые страницы для приложения, которые выглядят как полное приложение, а затем загружать свое Угловое приложение за ним.
Angular Universal генерирует чистые HTML-страницы без javascript на стороне сервера и обслуживает их пользователям без задержки. Таким образом, вы можете иметь дело с любым искателем, ботом и пользователем (у которых уже есть низкая скорость процессора и сети).Затем вы можете изменить их по ссылкам/кнопкам на угловой приложение, которое уже загружено за ним. Это решение рекомендовано официальным сайтом. - дополнительная информация о SEO и Angular Universal -

искатели (или боты) предназначены для обхода HTML-содержимого веб-страниц, но из-за операций AJAX для асинхронной выборки данных это стало проблемой, поскольку требуется некоторое время, чтобы отобразить страницу и показать на ней динамическое содержимое. Точно так же,AngularJS использовать асинхронную модель, которая создает проблемы для роботов Google.

некоторые разработчики создают базовые html-страницы с реальными данными и обслуживают эти страницы со стороны сервера во время обхода. Мы можем сделать те же страницы с PhantomJS на служить стороне, которая имеет _escaped_fragment_ (потому что Google ищет #! в нашем сайте URL-адреса, а затем принимает все после #! и добавляет его в _escaped_fragment_ параметр запроса). Для более подробной информации, пожалуйста, прочитайте это блог .

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

мое решение:дайте искателю то, что он хочет:

вы должны думать о том, чего хочет краулер, и дать ему только это.

совет не связывайтесь со спиной. Просто добавьте небольшой серверный вид спереди, используя тот же API