Я вижу два вопроса с приложением AngularJS относительно поисковых систем и SEO:
1) Что происходит с пользовательскими тегами? Не игнорируют ли поисковые системы весь контент в этих тегах? т.е. предположим, что
<custom>
<h1>Hey, this title is important</h1>
</custom>
будет <h1>
индексироваться, несмотря на то, что внутри пользовательских тегов?
2) Есть ли способ избежать того, чтобы поисковые системы индексирования {{}} связывались буквально? то есть.
<h2>{{title}}</h2>
Я знаю, что могу сделать что-то вроде
<h2 ng-bind="title"></h2>
но что, если я хочу, чтобы на самом деле позволял сканеру "видеть" заголовок? Единственное решение для серверной части?
Обновление мая 2014 года
Google crawlers теперь выполняет javascript - вы можете использовать Инструменты Google для веб-мастеров, чтобы лучше понять, как ваши сайты предоставляются Google.
Оригинальный ответ
Если вы хотите оптимизировать свое приложение для поисковых систем, то, к сожалению, нет возможности обслуживать предварительно обработанную версию сканера. Вы можете больше узнать о рекомендациях Google для сайтов ajax и javascript-heavy здесь.
Если это вариант, я бы рекомендовал прочитать эту статью о том, как сделать SEO для Angular с помощью рендеринга на стороне сервера.
Я не уверен, что делает сканер, когда он сталкивается с пользовательскими тегами.
Текущий (2015) способ сделать это - использовать метод pushState JavaScript.
PushState изменяет URL-адрес в верхней строке браузера без перезагрузки страницы. Скажем, у вас есть страница с вкладками. Вкладки скрывают и отображают содержимое, а содержимое вставляется динамически, либо используя AJAX, либо просто устанавливая отображение: none и display: блок, чтобы скрыть и показать правильное содержимое вкладки.
При нажатии на вкладки используйте pushState для обновления URL-адреса в адресной строке. Когда страница отображается, используйте значение в адресной строке, чтобы определить, какую вкладку отображать. Angular маршрутизация сделает это для вас автоматически.
Есть два способа попасть в одностраничное приложение PushState (SPA)
Первоначальный хит на сайте будет включать прямой URL-адрес. Последующие хиты будут просто AJAX в содержимом, поскольку PushState обновляет URL-адрес.
Сканеры собирают ссылки со страницы, а затем добавляют их в очередь для последующей обработки. Это означает, что для искателя каждое попадание на сервер является прямым ударом, они не перемещаются через Pushstate.
Предкомпозиция связывает начальную полезную нагрузку с первым ответом с сервера, возможно, как объект JSON. Это позволяет поисковой системе отображать страницу без выполнения вызова AJAX.
Есть некоторые свидетельства того, что Google может не выполнять запросы AJAX. Подробнее об этом здесь:
http://www.analog-ni.co/precomposing-a-spa-may-become-the-holy-grail-to-seo
Google смог разобрать JavaScript уже некоторое время, поэтому они изначально разработали Chrome, чтобы выступать в качестве полнофункционального браузера без браузера для паука Google. Если ссылка имеет действительный атрибут href, новый URL-адрес может быть проиндексирован. Больше нечего делать.
Если нажатие ссылки дополнительно вызывает вызов pushState, сайт может быть перемещен пользователем через PushState.
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 о поддержке довольно PushState URL-адресов от марта 2013 года:
http://blogs.bing.com/webmaster/2013/03/21/search-engine-optimization-best-practices-for-ajax-urls/
URL-адреса Hashbang были уродливой остановкой, требующей от разработчика предоставить предварительно подготовленную версию сайта в специальном месте. Они все еще работают, но вам не нужно их использовать.
URL-адреса Hashbang выглядят следующим образом:
domain.com/#!path/to/resource
Это будет сопряжено с метатагом, подобным этому:
<meta name="fragment" content="!">
Google не будет индексировать их в этой форме, но вместо этого вытащит статическую версию сайта из URL-адреса _escaped_fragments_ и проиндексирует это.
Pushstate URLs выглядят как обычный URL:
domain.com/path/to/resource
Разница в том, что Angular обрабатывает их для вас, перехватывая изменение document.location, связанное с ним в JavaScript.
Если вы хотите использовать URL-адреса PushState (и, вероятно, вы это делаете), вытащите все старые URL-адреса и метатеги в стиле хэш-стиля и просто включите режим HTML5 в своем блоке конфигурации.
В Инструментах Google для веб-мастеров теперь есть инструмент, который позволит вам получать URL-адрес в качестве google и отображать JavaScript, как это делает Google.
https://www.google.com/webmasters/tools/googlebot-fetch
Чтобы создать реальные URL-адреса в Angular, а не # префиксные, установите режим HTML5 на объект $locationProvider.
$locationProvider.html5Mode(true);
Поскольку вы используете реальные URL-адреса, вам необходимо обеспечить, чтобы один и тот же шаблон (плюс некоторое предварительно настроенное содержимое) отправлялся сервером для всех допустимых URL-адресов. Как вы это сделаете, это зависит от архитектуры вашего сервера.
Ваше приложение может использовать необычные формы навигации, например, наведение или прокрутка. Чтобы Google мог управлять вашим приложением, я бы предложил создать файл Sitemap, простой список всех URL-адресов, на которые реагирует ваше приложение. Вы можете разместить это по умолчанию (/sitemap или /sitemap.xml) или сообщить об этом Google с помощью инструментов для веб-мастеров.
Хорошая идея иметь карту сайта в любом случае.
Pushstate работает в IE10. В старых браузерах Angular автоматически возвращается к URL-адресам стиля хэша
Следующий контент отображается с использованием URL-адреса pushstate с предкомпозицией:
http://html5.gingerhost.com/london
Как можно проверить, в этой ссылке содержимое индексируется и появляется в Google.
Поскольку поисковая система всегда будет ударять по вашему серверу для каждого запроса, вы можете обслуживать коды состояния заголовков со своего сервера и ожидать, что Google их увидит.
Google, Yahoo, Bing и другие поисковые системы сканируют Интернет традиционными способами, используя традиционные сканеры. Они запускают роботы, которые сканируют HTML на веб-страницах, собирая информацию на этом пути. Они содержат интересные слова и ищут другие ссылки на другие страницы (эти ссылки, количество их и количество их вступают в игру с SEO).
Ответ на этот вопрос связан с тем, что роботы поисковых систем работают без браузеров без браузера, и у них чаще всего нет механизма отображения 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: The Complete Book on AngularJS. Проверьте это на ng-book.com.
Вы должны действительно проверить учебник по созданию SEO-сайта AngularJS в год блога му. Он проведет вас по всем этапам, описанным в документации Angular. http://www.yearofmoo.com/2012/11/angularjs-and-seo.html
Используя этот метод, поисковая система видит расширенный HTML вместо пользовательских тегов.
Это резко изменилось.
Если вы используете: $ LocationProvider.html5Mode (истина); вы настроены.
Больше страниц рендеринга.
#!
, Из статьи: «Bing говорит мне, что, хотя они все еще поддерживают версию!! Для сканирования AJAX, первоначально выпущенную Google, они обнаруживают, что большую часть времени она не реализуется правильно, и вместо этого настоятельно рекомендуют pushState». Вам все еще нужно визуализировать статический HTML и использовать его для URL-адресов _escaped_fragment_
. Bing / Google не будет выполнять вызовы javascript / AJAX.
Все изменилось совсем немного, так как этот вопрос был задан. Теперь есть варианты, позволяющие Google индексировать ваш сайт AngularJS. Самый простой вариант, который я нашел, - использовать http://prerender.io бесплатный сервис, который будет генерировать для вас страницы, к поисковым системам. Он поддерживается практически на всех серверных веб-платформах. Я недавно начал использовать их, и поддержка тоже прекрасна.
У меня нет никакой связи с ними, это происходит от счастливого пользователя.
Angular собственный веб-сайт предлагает упрощенный контент для поисковых систем: http://docs.angularjs.org/?_escaped_fragment_=/tutorial/step_09
Скажите, что ваше приложение Angular потребляет Node.js/Express-JSON api, например /api/path/to/resource
. Возможно, вы можете перенаправить любые запросы с ?_escaped_fragment_
на /api/path/to/resource.html
и использовать согласование контента, чтобы отобразить HTML-шаблон содержимого, а не возвращать данные JSON.
Единственное, ваши маршруты Angular должны соответствовать 1:1 с вашим REST API.
РЕДАКТИРОВАТЬ. Я понимаю, что это может реально испортить ваш REST api, и я не рекомендую делать это за пределами очень простых случаев использования, где это может быть естественным образом.
Вместо этого вы можете использовать совершенно другой набор маршрутов и контроллеров для вашего удобного для робота контента. Но тогда вы дублируете все свои маршруты и контроллеры AngularJS в Node/Express.
Я решил создать моментальные снимки без браузера без браузера, хотя я чувствую, что немного меньше, чем идеальный.
Хорошую практику можно найти здесь:
http://scotch.io/tutorials/javascript/angularjs-seo-with-prerender-io?_escaped_fragment_=tag
На данный момент Google изменил предложение об обходах AJAX.
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 как услугу - информация в этом отчете основана на наблюдения из наших журналов.
Я написал статью, как сделать ваше приложение angularjs (под сервером nginx) доступным для поиска: http://senior-java-developer.com/html5angularjsnginx-crawlable-application/
Я нашел элегантное решение, которое будет охватывать большинство ваших баз. Я написал об этом вначале здесь и ответил на другой аналогичный вопрос StackOverflow здесь, который ссылается на него.
FYI это решение также включает в себя жестко закодированные резервные теги в случае, если 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 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), вам все равно придется использовать одну из служб предварительного рендеринга, упомянутых в некоторых других ответах.
Надеюсь, это поможет!
Используйте что-то вроде PreRender, оно делает статические страницы вашего сайта, чтобы поисковые системы могли его индексировать.
Здесь вы можете узнать, какие платформы доступны: https://prerender.io/documentation/install-middleware#asp-net
С Angular Universal вы можете создавать целевые страницы для приложения, которые выглядят как полное приложение, а затем загружать приложение Angular за ним.
Angular Universal генерирует чистый HTML-код, который означает не-javascript-страницы на стороне сервера и обслуживает их без задержки. Таким образом, вы можете иметь дело с любым искателем, ботом и пользователем (у которого уже есть низкая скорость процессора и скорость сети). Затем вы можете перенаправить их по ссылкам/кнопкам в свое фактическое приложение Angular, которое уже загружено за ним. Это решение рекомендуется на официальном сайте. - Дополнительная информация о SEO и Angular Universal -
Сканеры (или боты) предназначены для сканирования содержимого HTML-страниц на веб-страницах, но из-за операций AJAX для асинхронной выборки данных это стало проблемой, поскольку требуется некоторое время для рендеринга страницы и отображения на ней динамического содержимого. Аналогично, AngularJS
также использует асинхронную модель, которая создает проблему для искателей Google.
Некоторые разработчики создают базовые html-страницы с реальными данными и обслуживают эти страницы со стороны сервера во время обхода. Мы можем отображать те же страницы с PhantomJS
на стороне службы, которая имеет _escaped_fragment_
(поскольку Google ищет #!
в наших URL-адресах сайта, а затем берет все после #!
и добавляет его в параметр запроса _escaped_fragment_
). Для более подробной информации, пожалуйста, прочтите blog.
Сканерам не нужен богатый признанный стильный gui, они хотят видеть контент, поэтому вам не нужно давать им снимок страницы, созданной для людей.
Мое решение: до дать сканеру то, что хочет искатель:
Вы должны думать о том, чего хочет искатель, и дать ему только это.
СОВЕТ не путается со спиной. Просто добавьте немного серверного фронтального просмотра, используя тот же API