Hoe gaan zoekmachines om met AngularJS-applicaties?

Ik zie twee problemen met de AngularJS-toepassing met betrekking tot zoekmachines en SEO:

1) Wat gebeurt er met aangepaste tags? Negeren zoekmachines de hele inhoud binnen die tags? d.w.z. stel dat ik heb

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

zou <h1>worden geïndexeerd ondanks dat het in aangepaste tags staat?

2) Is er een manier om te voorkomen dat zoekmachines het indexeren van {{}} letterlijk binden? d.w.z.

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

Ik weet dat ik zoiets zou kunnen doen

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

maar wat als ik de crawler de titel wil laten “zien”? Is server-side rendering de enige oplossing?


Antwoord 1, autoriteit 100%

Gebruik PushState en Precomposition

De huidige (2015) manier om dit te doen is het gebruik van de JavaScript pushState-methode.

PushState wijzigt de URL in de bovenste browserbalk zonder de pagina opnieuw te laden. Stel dat u een pagina heeft met tabbladen. De tabbladen verbergen en tonen inhoud, en de inhoud wordt dynamisch ingevoegd, ofwel met AJAX of door simpelweg display:none en display:block in te stellen om de juiste tabbladinhoud te verbergen en weer te geven.

Wanneer op de tabbladen wordt geklikt, gebruikt u pushState om de url in de adresbalk bij te werken. Wanneer de pagina wordt weergegeven, gebruikt u de waarde in de adresbalk om te bepalen welk tabblad moet worden weergegeven. Hoekroutering doet dit automatisch voor u.

Precompositie

Er zijn twee manieren om een ​​PushState Single Page App (SPA) te bereiken

  1. Via PushState, waarbij de gebruiker op een PushState-link klikt en de inhoud wordt AJAX-ingesteld.
  2. Door rechtstreeks op de URL te klikken.

De eerste treffer op de site houdt in dat u rechtstreeks de URL raakt. Volgende treffers zullen eenvoudig AJAX in inhoud hebben als de PushState de URL bijwerkt.

Crawlers verzamelen links van een pagina en voegen ze toe aan een wachtrij voor latere verwerking. Dit betekent dat voor een crawler elke hit op de server een voltreffer is, ze navigeren niet via Pushstate.

Precomposition bundelt de initiële payload in het eerste antwoord van de server, mogelijk als een JSON-object. Hierdoor kan de zoekmachine de pagina weergeven zonder de AJAX-aanroep uit te voeren.

Er zijn aanwijzingen dat Google mogelijk geen AJAX-verzoeken uitvoert. Hier meer over:

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

Zoekmachines kunnen JavaScript lezen en uitvoeren

Google kan JavaScript al enige tijd ontleden, daarom hebben ze oorspronkelijk Chrome ontwikkeld om te fungeren als een volledige headless browser voor de Google-spider. Als een link een geldig href-attribuut heeft, kan de nieuwe URL worden geïndexeerd. Er is niets meer te doen.

Als het klikken op een link bovendien een pushState-aanroep activeert, kan de gebruiker door de site navigeren via PushState.

Ondersteuning voor zoekmachines voor PushState-URL’s

PushState wordt momenteel ondersteund door Google en Bing.

Google

Hier is Matt Cutts die reageert op de vraag van Paul Irish over PushState voor SEO:

http://youtu.be/yiAF9VdvRPw

Hier kondigt Google volledige JavaScript-ondersteuning voor de spider aan:

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

Het resultaat is dat Google PushState ondersteunt en PushState-URL’s zal indexeren.

Zie ook het ophalen van Google-webmasterhulpprogramma’s als Googlebot. U zult zien dat uw JavaScript (inclusief Angular) wordt uitgevoerd.

Bing

Hier is Bing’s aankondiging van ondersteuning voor mooie PushState-URL’s van maart 2013:

http ://blogs.bing.com/webmaster/2013/03/21/search-engine-optimization-best-practices-for-ajax-urls/

Gebruik geen HashBangs #!

Hashbang-urls waren een lelijke noodoplossing waarbij de ontwikkelaar een vooraf gerenderde versie van de site op een speciale locatie moest leveren. Ze werken nog steeds, maar je hoeft ze niet te gebruiken.

Hashbang-URL’s zien er als volgt uit:

domain.com/#!path/to/resource

Dit zou gepaard gaan met een metatag zoals deze:

<meta name="fragment" content="!">

Google indexeert ze niet in deze vorm, maar haalt in plaats daarvan een statische versie van de site uit de _escaped_fragments_ URL en indexeert die.

Pushstate-URL’s zien eruit als elke gewone URL:

domain.com/path/to/resource

Het verschil is dat Angular ze voor u afhandelt door de wijziging in document.location die ermee omgaat in JavaScript te onderscheppen.

Als je PushState-URL’s wilt gebruiken (en dat doe je waarschijnlijk), verwijder dan alle oude hash-stijl-URL’s en metatags en schakel eenvoudig de HTML5-modus in je configuratieblok in.

Uw site testen

Webmasterhulpprogramma’s van Google bevatten nu een hulpmiddel waarmee u een URL als Google kunt ophalen en JavaScript kunt weergeven zoals Google deze weergeeft.

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

PushState-URL’s genereren in Angular

Als u echte URL’s in Angular wilt genereren in plaats van # voorvoegsels, stelt u de HTML5-modus in op uw $locationProvider-object.

$locationProvider.html5Mode(true);

Serverzijde

Aangezien u echte URL’s gebruikt, moet u ervoor zorgen dat dezelfde sjabloon (plus wat vooraf samengestelde inhoud) door uw server wordt verzonden voor alle geldige URL’s. Hoe u dit doet, hangt af van uw serverarchitectuur.

Sitemap

Je app kan ongebruikelijke vormen van navigatie gebruiken, bijvoorbeeld zweven of scrollen. Om ervoor te zorgen dat Google uw app kan aansturen, raad ik u waarschijnlijk aan een sitemap te maken, een eenvoudige lijst met alle URL’s waarop uw app reageert. U kunt dit op de standaardlocatie (/sitemap of /sitemap.xml) plaatsen of Google hierover informeren met behulp van webmasterhulpprogramma’s.

Het is sowieso een goed idee om een ​​sitemap te hebben.

Browserondersteuning

Pushstate werkt in IE10. In oudere browsers zal Angular automatisch terugvallen op hash-stijl URL’s

Een demopagina

De volgende inhoud wordt weergegeven met behulp van een pushstate-URL met precompositie:

http://html5.gingerhost.com/london

Zoals kan worden geverifieerd, op deze link, de inhoud wordt geïndexeerd en wordt weergegeven in Google.

Serving 404 en 301 Header statuscodes

Omdat de zoekmachine altijd uw server zal bereiken voor elk verzoek, kunt u headerstatuscodes van uw server weergeven en verwachten dat Google ze ziet.


Antwoord 2, autoriteit 86%

Update mei 2014

Google-crawlers voert nu javascript uit– u kunt de Webmasterhulpprogramma’s van Googleom beter te begrijpen hoe uw sites door Google worden weergegeven.

Oorspronkelijk antwoord
Als u uw app voor zoekmachines wilt optimaliseren, is er helaas geen manier om een ​​vooraf gegenereerde versie aan de crawler te leveren. U kunt hiermeer lezen over de aanbevelingen van Google voor ajax- en javascript-zware sites.

Als dit een optie is, raad ik u aan dit artikelte lezen over hoe u doe SEO voor Angular met server-side rendering.

Ik weet niet zeker wat de crawler doet als hij aangepaste tags tegenkomt.


Antwoord 3, autoriteit 23%

Laten we definitief zijn over AngularJS en SEO

Google, Yahoo, Bing en andere zoekmachines crawlen het web op traditionele manieren met behulp van traditionele crawlers. Ze gebruiken robotsdie de HTML op webpagina’s crawlen en onderweg informatie verzamelen. Ze behouden interessante woorden en zoeken naar andere links naar andere pagina’s (deze links, het aantal en het aantal spelen een rol bij SEO).

Dus waarom gaan zoekmachines niet om met javascript-sites?

Het antwoord heeft te maken met het feit dat de robots van zoekmachines werken via headless browsers en dat ze meestal geeneen javascript-renderingengine hebben om de javascript van een pagina weer te geven. Dit werkt voor de meeste pagina’s, omdat de meeste statische pagina’s er niet om geven dat JavaScript hun pagina weergeeft, omdat hun inhoud al beschikbaar is.

Wat kan eraan gedaan worden?

Gelukkig zijn crawlers van de grotere sites begonnen met het implementeren van een mechanisme waarmee we onze JavaScript-sites crawlbaar kunnen maken, maar het vereist dat we een wijziging op onze site doorvoeren.

Als we onze hashPrefixveranderen in #!in plaats van gewoon #, dan zullen moderne zoekmachines het verzoek om _escaped_fragment_in plaats van #!. (In de HTML5-modus, d.w.z. waar we links hebben zonder het hash-voorvoegsel, kunnen we dezelfde functie implementeren door naar de User Agent-header in onze backend te kijken).

Dat wil zeggen, in plaats van een verzoek van een normale browser dat eruitziet als:

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

Een zoekmachine zal de pagina doorzoeken met:

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

We kunnen het hash-voorvoegsel van onze Angular-apps instellen met behulp van een ingebouwde methode van ngRoute:

angular.module('myApp', [])
.config(['$location', function($location) {
  $location.hashPrefix('!');
}]);

En als we html5Modegebruiken, moeten we dit implementeren met de metatag:

<meta name="fragment" content="!">

Herinnering, we kunnen de html5Mode()instellen met de service $location:

angular.module('myApp', [])
.config(['$location', 
function($location) {
  $location.html5Mode(true);
}]);

Omgaan met de zoekmachine

We hebben veel mogelijkheden om te bepalen hoe we omgaan met het daadwerkelijk leveren van inhoud aan zoekmachines als statische HTML. We kunnen zelf een backend hosten, we kunnen een service gebruiken om een ​​backend voor ons te hosten, we kunnen een proxy gebruiken om de inhoud te leveren, enz. Laten we eens kijken naar een paar opties:

Zelf gehost

We kunnen een service schrijven voor het omgaan met het crawlen van onze eigen site met behulp van een headless browser, zoals phantomjs of zombiejs, waarbij we een momentopname maken van de pagina met weergegeven gegevens en deze opslaan als HTML. Telkens wanneer we de zoekreeks ?_escaped_fragment_in een zoekopdracht zien, kunnen we de statische HTML-snapshot leveren die we van de pagina hebben gemaakt in plaats van de vooraf weergegeven pagina via alleen JS. Dit vereist dat we een backend hebben die onze pagina’s levert met voorwaardelijke logica in het midden. We kunnen iets als prerender.io’sbackend gebruiken als startpunt om dit zelf uit te voeren. Natuurlijk moeten we nog steeds de proxy- en snippet-verwerking afhandelen, maar het is een goed begin.

Met een betaalde dienst

De gemakkelijkste en snelste manier om inhoud in de zoekmachine te krijgen, is door gebruik te maken van een service Brombone, seo.js, seo4ajaxen prerender.iozijn goede voorbeelden hiervan die de bovenstaande inhoudsweergave voor u zullen hosten. Dit is een goede optie voor de keren dat we geen server/proxy willen draaien. Bovendien is het meestal supersnel.

Voor meer informatie over Angular en SEO hebben we er een uitgebreide tutorial over geschreven op http:/ /www.ng-newsletter.com/posts/serious-angular-seo.htmlenwe hebben het nog uitgebreider beschreven in ons boek ng-book: The Complete Book on AngularJS . Bekijk het op ng-book.com.


Antwoord 4, autoriteit 12%

Je moet echt de tutorial bekijken over het bouwen van een SEO-vriendelijke AngularJS-site in het jaar van moo-blog. Hij leidt u door alle stappen die worden beschreven in de documentatie van Angular. http://www.yearofmoo.com/2012/11/angularjs-and-seo.html

Met deze techniek ziet de zoekmachine de uitgebreide HTML in plaats van de aangepaste tags.


Antwoord 5, autoriteit 9%

Dit is drastisch veranderd.

http://searchengineland.com/bing-offers -aanbevelingen-voor-seo-vriendelijke-ajax-suggests-html5-pushstate-152946

Als je het volgende gebruikt:
$locationProvider.html5Mode(true);
je bent klaar.

Geen pagina’s meer weergeven.


Antwoord 6, autoriteit 4%

Er is nogal wat veranderd sinds deze vraag werd gesteld. Er zijn nu opties om Google je AngularJS-site te laten indexeren. De gemakkelijkste optie die ik vond, was om de gratis service http://prerender.iote gebruiken die de crwalable pagina’s voor u en dienen die aan de zoekmachines. Het wordt ondersteund op bijna alle webplatforms aan de serverzijde. Ik ben ze onlangs gaan gebruiken en de ondersteuning is ook uitstekend.

Ik heb geen enkele band met hen, dit komt van een tevreden gebruiker.


Antwoord 7, autoriteit 2%

De eigen website van Angular biedt vereenvoudigde inhoud aan zoekmachines: http://docs.angularjs.org/?_escaped_fragment_= /tutorial/step_09

Stel dat uw Angular-app een door Node.js/Express aangestuurde JSON-api gebruikt, zoals /api/path/to/resource. Misschien kunt u verzoeken met ?_escaped_fragment_omleiden naar /api/path/to/resource.htmlen inhoudsonderhandelingom een ​​HTML-sjabloon van de inhoud weer te geven, in plaats van de JSON-gegevens te retourneren.

Het enige is dat uw Angular-routes 1:1 moeten overeenkomen met uw REST API.

BEWERK: ik realiseer me dat dit de potentie heeft om je REST-api echt te vertroebelen en ik raad het niet aan om het te doen buiten zeer eenvoudige gebruikssituaties waar het een natuurlijke fit zou kunnen zijn .

In plaats daarvan kun je een geheel andere set routes en controllers gebruiken voor je robotvriendelijke inhoud. Maar dan dupliceer je al je AngularJS-routes en -controllers in Node/Express.

Ik heb gekozen voor het maken van snapshots met een headless browser, ook al vind ik dat een beetje minder dan ideaal.


Antwoord 8, autoriteit 2%

Een goede praktijk vindt u hier:

http://scotch.io/tutorials/javascript/angularjs-seo -with-prerender-io?_escaped_fragment_=tag


Antwoord 9

Vanaf nu heeft Google hun voorstel voor het crawlen van AJAX gewijzigd.

De tijden zijn gewijzigd. Zolang u Googlebot niet blokkeert om uw JavaScript- of CSS-bestanden te crawlen, kunnen we uw webpagina’s over het algemeen weergeven en begrijpen zoals moderne browsers.

tl;dr: [Google] beveelt het AJAX-crawlvoorstel [Google] uit 2009 niet langer aan.


Antwoord 10

Google’s Crawlable Ajax Spec, zoals vermeld in de andere antwoorden hier, is in feite het antwoord.

Als u geïnteresseerd bent in hoe andere zoekmachines en sociale bots met dezelfde problemen hebben met dezelfde problemen die ik hier de stand van de techniek schreef: http://blog.ajaxsnapshots.com/2013/11/gogles-crawlable-ajax-specification.html

Ik werk voor een https://ajaxsnapshots.com , een bedrijf dat de kruiperbare Ajax Spec als een service implementeert – De informatie in dat rapport is gebaseerd op waarnemingen van onze logs.


11

Ik heb een elegante oplossing gevonden die de meeste van je bases dekt. Ik schreef erin in eerste instantie hier en beantwoordde een andere soortgelijke stackoverflow vraag die het verwijst.

FYI Deze oplossing bevat ook hardcodeerde fallback-tags in het geval dat JavaScript niet wordt opgehaald door de crawler. Ik heb het niet uitdrukkelijk geschetst, maar het is de moeite waard om te vermelden dat u de HTML5-modus moet activeren voor de juiste URL-ondersteuning.

Opmerking: deze zijn niet de volledige bestanden, alleen de belangrijke delen van die relevant zijn. Als u hulp nodig heeft bij het schrijven van de boilerplaat voor richtlijnen, diensten, enz. Die elders te vinden is. Hoe dan ook, hier gaat …

app.js

Hier verstrekt u de aangepaste metadata voor elk van uw routes (titel, beschrijving, enz.)

$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 (service)

Stelt de aangepaste metadata-opties in of gebruik standaardinstellingen als fallbacks.

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 (richtlijn)

PAKKEN DE METADATA SERVICE RESULTATEN VOOR DE BEKIJK.

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

Compleet met de eerder vermelde fallback-tags voor crawlers die geen JavaScript kunnen ophalen.

<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>

Dit zou drastisch moeten helpen bij het gebruik van de meeste cases voor zoekmachines. Als u volledig dynamisch weergave voor sociale netwerkcrawlers wilt (die op JavaScript-ondersteuning zijn), moet u nog steeds een van de pre-rendering-services gebruiken die in sommige van de andere antwoorden worden genoemd.

Ik hoop dat dit helpt!


12

Gebruik iets als Prerender, het maakt statische pagina’s van uw site, zodat zoekmachines het kunnen indexeren.

Hier kunt u ontdekken voor welke platforms het beschikbaar is: HTTPS: // Prerender. io / documentatie / install-middleware # ASP-NET


13

Crawlers (of bots) zijn ontworpen om HTML-inhoud van webpagina’s te kruipen, maar als gevolg van Ajax-operaties voor asynchrone gegevens die ophalen, werd dit een probleem omdat het ergens nodig is om pagina te maken en dynamische inhoud erop te tonen. Evenzo, AngularJSGebruik ook asynchrone model, wat een probleem maakt voor Google Crawlers.

Sommige ontwikkelaars maken standaard HTML-pagina’s met echte gegevens en serveren deze pagina’s van de serverzijde op het moment van kruipen. We kunnen dezelfde pagina’s weergeven met PhantomJSAan Serveerzijde die _escaped_fragment_heeft (omdat Google op zoek is naar #!in onze site-URL’s en vervolgens alles in beslag nemen De #!en voegt het toe in _escaped_fragment_query parameter). Lees dit voor meer informatie blog .


14

De crawlers hebben geen rijke uitgesproken behoorlijk gestileerde GUI nodig, ze willen alleen de inhoud , dus je hoeft ze niet een momentopname van een pagina te geven die voor mensen is gebouwd.

Mijn oplossing: naar Geef de crawler wat de Crawler wil :

Je moet bedenken aan wat de crawler wil, en geef hem alleen dat.

Tip rot niet met de achterkant. Voeg gewoon een klein serverzijdig frontview toe met dezelfde API

Other episodes