it-swarm.dev

In che modo i motori di ricerca gestiscono le angolazioni?

Vedo due problemi con l'applicazione AngularJS per quanto riguarda i motori di ricerca e SEO:

1) Cosa succede con i tag personalizzati? I motori di ricerca ignorano l'intero contenuto di tali tag? suppongo di averlo

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

sarebbe <h1> essere indicizzato nonostante si trovasse all'interno di tag personalizzati?


2) C'è un modo per evitare che i motori di ricerca dell'indicizzazione {{}} si leghino letteralmente? cioè.

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

So che potrei fare qualcosa di simile

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

ma cosa succede se voglio davvero lasciare che il crawler "veda" il titolo? Il rendering lato server è l'unica soluzione?

692
luisfarzati

Aggiornamento maggio 2014

Google crawler ora esegue javascript - puoi usare/ Strumenti per i Webmaster di Google per capire meglio come vengono visualizzati i tuoi siti da Google.

Risposta originale
Se desideri ottimizzare la tua app per i motori di ricerca, purtroppo non c'è modo di offrire una versione pre-renderizzata al crawler. Puoi leggere ulteriori informazioni sui consigli di Google per ajax e javascript-heavy sites here .

Se questa è un'opzione, ti consiglio di leggere questo articolo su come fare SEO per Angular con il rendering lato server.

Non sono sicuro di ciò che fa il crawler quando rileva tag personalizzati.

402
joakimbl

Usa PushState e Precomposition

Il modo corrente (2015) per farlo è utilizzare il metodo JavaScript pushState.

PushState modifica l'URL nella barra superiore del browser senza ricaricare la pagina. Supponi di avere una pagina contenente schede. Le schede nascondono e mostrano il contenuto e il contenuto viene inserito dinamicamente, usando AJAX o semplicemente impostando display: none e display: blocco da nascondere e mostrare il contenuto corretto della scheda.

Quando si fa clic sulle schede, utilizzare pushState per aggiornare l'url nella barra degli indirizzi. Quando viene visualizzata la pagina, utilizzare il valore nella barra degli indirizzi per determinare quale scheda mostrare. Angular routing lo farà automaticamente.

Precomposizione

Esistono due modi per colpire un'applicazione PushState Single Page (SPA)

  1. Tramite PushState, dove l'utente fa clic su un collegamento PushState e il contenuto è AJAXed in.
  2. Colpendo direttamente l'URL.

L'hit iniziale sul sito coinvolgerà direttamente l'URL. I successi successivi saranno semplicemente AJAX nel contenuto mentre il PushState aggiorna l'URL.

I crawler raccolgono i link da una pagina e li aggiungono a una coda per l'elaborazione successiva. Ciò significa che per un crawler, ogni hit sul server è un hit diretto, non naviga tramite Pushstate.

La precomposizione raggruppa il carico utile iniziale nella prima risposta dal server, possibilmente come un oggetto JSON. Ciò consente al motore di ricerca di eseguire il rendering della pagina senza eseguire la chiamata AJAX.

Esistono prove che suggeriscono che Google potrebbe non eseguire AJAX richieste. Maggiori informazioni su questo qui:

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

I motori di ricerca possono leggere ed eseguire JavaScript

Google è stato in grado di analizzare JavaScript per qualche tempo, è per questo che in origine ha sviluppato Chrome, per fungere da browser headless completo per lo spider di Google. Se un link ha un attributo href valido, il nuovo URL può essere indicizzato. Non c'è nient'altro da fare.

Se facendo clic su un collegamento si attiva inoltre una chiamata pushState, il sito può essere navigato dall'utente tramite PushState.

Supporto del motore di ricerca per gli URL PushState

PushState è attualmente supportato da Google e Bing.

Google

Ecco Matt Cutts che risponde alla domanda di Paul Irish su PushState per SEO:

http://youtu.be/yiAF9VdvRPw

Ecco Google che annuncia il supporto JavaScript completo per lo spider:

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

Il risultato è che Google supporta PushState e indicizzerà gli URL PushState.

Vedi anche Strumenti per i webmaster di Google 'recupera come Googlebot. Verrà visualizzato il tuo JavaScript (incluso Angolare).

Bing

Ecco l'annuncio di Bing relativo al supporto per URL Pretty PushState datati marzo 2013:

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

Non usare HashBang #!

Gli URL di Hashbang erano un brutto ostacolo che richiedeva allo sviluppatore di fornire una versione pre-renderizzata del sito in una posizione speciale. Funzionano ancora, ma non è necessario usarli.

Gli URL di Hashbang hanno questo aspetto:

domain.com/#!path/to/resource

Questo sarebbe accoppiato con un metatag come questo:

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

Google non li indicizzerà in questo modulo, ma prenderà invece una versione statica del sito dall'URL _escaped_fragments_ e indicizzerà quello.

Gli URL pushstate hanno l'aspetto di qualsiasi URL normale:

domain.com/path/to/resource

La differenza è che Angular li gestisce per te intercettando la modifica in document.location trattandoci in JavaScript.

Se vuoi utilizzare gli URL di PushState (e probabilmente lo fai) estrai tutti i vecchi URL e metatag di stile hash e abilita semplicemente la modalità HTML5 nel tuo blocco di configurazione.

Test del tuo sito

Gli strumenti per i webmaster di Google ora contengono uno strumento che ti consentirà di recuperare un URL come google e renderizzare JavaScript mentre Google lo esegue.

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

Generazione degli URL PushState in Angolare

Per generare URL reali in Angular anziché in quelli con prefisso #, imposta la modalità HTML5 sull'oggetto $ locationProvider.

$locationProvider.html5Mode(true);

Lato server

Poiché stai utilizzando URL reali, dovrai assicurarti che lo stesso modello (più alcuni contenuti precomposti) venga spedito dal tuo server per tutti gli URL validi. Il modo in cui lo fai varia a seconda dell'architettura del tuo server.

Mappa del sito

La tua app potrebbe utilizzare forme di navigazione insolite, ad esempio il passaggio del mouse o lo scorrimento. Per assicurarti che Google sia in grado di guidare la tua app, probabilmente ti suggerisco di creare una Sitemap, un semplice elenco di tutti gli URL a cui la tua app risponde. Puoi posizionarlo nella posizione predefinita (/ sitemap o /sitemap.xml) o comunicarlo a Google utilizzando gli strumenti per i webmaster.

È comunque una buona idea avere una mappa del sito.

Supporto per il browser

Pushstate funziona in IE10. Nei browser meno recenti, Angular tornerà automaticamente agli URL di stile hash

Una pagina demo

Il seguente contenuto è reso utilizzando un URL pushstate con precomposizione:

http://html5.gingerhost.com/london

Come può essere verificato, a questo link , il contenuto è indicizzato e appare in Google.

Serve 404 e 301 codici di stato dell'intestazione

Poiché il motore di ricerca colpisce sempre il server per ogni richiesta, puoi fornire i codici di stato dell'intestazione dal server e aspettarti che Google li veda.

470
superluminary

Diventiamo definitivi su AngularJS e SEO

Google, Yahoo, Bing e altri motori di ricerca eseguono la scansione del Web in modo tradizionale utilizzando i crawler tradizionali. Eseguono robots che eseguono la scansione dell'HTML nelle pagine Web, raccogliendo informazioni lungo il percorso. Mantiene parole interessanti e cercano altri link ad altre pagine (questi link, la quantità di essi e il loro numero entrano in gioco con SEO).

Quindi perché i motori di ricerca non si occupano di siti javascript?

La risposta ha a che fare con il fatto che i robot dei motori di ricerca funzionano attraverso browser senza testa e spesso fanno not avere un motore di rendering javascript per rendere il javascript di una pagina. Questo funziona per la maggior parte delle pagine poiché la maggior parte delle pagine statiche non si preoccupa del rendering della pagina JavaScript, poiché il loro contenuto è già disponibile.

Cosa si può fare a riguardo?

Fortunatamente, i crawler dei siti più grandi hanno iniziato a implementare un meccanismo che ci consente di eseguire la scansione dei nostri siti JavaScript, ma it ci impone di implementare una modifica al nostro sito .

Se cambiamo hashPrefix in modo che sia #! anziché semplicemente #, allora i motori di ricerca moderni cambieranno la richiesta per usare _escaped_fragment_ anziché #!. (Con la modalità HTML5, vale a dire dove abbiamo collegamenti senza il prefisso hash, possiamo implementare questa stessa funzionalità osservando l'intestazione User Agent nel nostro backend).

Vale a dire, invece di una richiesta da un normale browser che assomiglia a:

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

Un motore di ricerca cercherà la pagina con:

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

Possiamo impostare il prefisso hash delle nostre app Angular utilizzando un metodo incorporato da ngRoute:

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

E, se utilizziamo html5Mode, dovremo implementarlo utilizzando il meta tag:

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

Promemoria, possiamo impostare html5Mode() con il servizio $location:

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

Gestire il motore di ricerca

Abbiamo un sacco di opportunità per determinare come tratteremo effettivamente consegnando il contenuto ai motori di ricerca come HTML statico. Possiamo ospitare noi stessi un back-end, possiamo usare un servizio per ospitare un back-end per noi, possiamo usare un proxy per consegnare il contenuto, ecc. Vediamo alcune opzioni:

Self-hosted

Possiamo scrivere un servizio per gestire la scansione del nostro sito utilizzando un browser headless, come phantomjs o zombiejs, scattare un'istantanea della pagina con i dati renderizzati e archiviarla come HTML. Ogni volta che vediamo la stringa di query ?_escaped_fragment_ in una richiesta di ricerca, possiamo fornire lo snapshot HTML statico che abbiamo preso sulla pagina invece della pagina pre-renderizzata attraverso solo JS. Questo ci richiede di avere un backend che fornisca le nostre pagine con la logica condizionale nel mezzo. Possiamo usare qualcosa come prerender.io's backend come punto di partenza per eseguirlo da soli. Ovviamente, dobbiamo ancora gestire il proxy e la gestione dei frammenti, ma è un buon inizio.

Con un servizio a pagamento

Il modo più semplice e veloce per ottenere contenuti nel motore di ricerca è utilizzare un servizio Brombone , seo.js , seo4ajax , e prerender.io sono buoni esempi di questi che ospiterà il rendering dei contenuti sopra per te. Questa è una buona opzione per le volte in cui non vogliamo gestire l'esecuzione di un server/proxy. Inoltre, di solito è super veloce.

Per ulteriori informazioni su Angular e SEO, abbiamo scritto un approfondito tutorial su http://www.ng-newsletter.com/posts/serious-angular-seo.html e lo abbiamo ulteriormente dettagliato nel nostro libro ng-book: The Complete Book on AngularJS . Dai un'occhiata a ng-book.com .

106
auser

Dovresti davvero dare un'occhiata al tutorial sulla costruzione di un sito AngularJS SEO-friendly nell'anno del blog moo. Ti guida attraverso tutti i passaggi descritti nella documentazione di Angular. http://www.yearofmoo.com/2012/11/angularjs-and-seo.html

Usando questa tecnica, il motore di ricerca vede l'HTML espanso invece dei tag personalizzati.

56
Brad Green

Questo è cambiato drasticamente.

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

Se si utilizza: $ locationProvider.html5Mode (true); sei impostato.

Niente più pagine di rendering.

41
user3330270

Le cose sono cambiate un po 'da quando è stata posta questa domanda. Ora ci sono opzioni per consentire a Google di indicizzare il tuo sito AngularJS. L'opzione più semplice che ho trovato è stata l'utilizzo dihttp://prerender.ioservizio gratuito che genererà per te le pagine sfogliabili e le offrirà ai motori di ricerca. È supportato su quasi tutte le piattaforme Web lato server. Recentemente ho iniziato a usarli e anche il supporto è eccellente.

Non ho alcuna affiliazione con loro, questo proviene da un utente felice.

17
Ketan

Il sito Web di Angular offre contenuti semplificati ai motori di ricerca: http://docs.angularjs.org/?_escaped_fragment_=/tutorial/step_09

Supponiamo che l'app Angular stia utilizzando un API JSON Node.js/Express, come /api/path/to/resource. Forse potresti reindirizzare qualsiasi richiesta con ?_escaped_fragment_ a /api/path/to/resource.html, e usare la negoziazione del contenuto per rendere un modello HTML del contenuto, piuttosto che restituire i dati JSON.

L'unica cosa è che i tuoi percorsi Angular dovrebbero corrispondere a 1: 1 con l'API REST.

EDIT: Mi sto rendendo conto che questo ha il potenziale per rendere davvero fangoso il tuo REST api e sconsiglio di farlo al di fuori di casi d'uso molto semplici dove potrebbe essere una scelta naturale.

Invece, puoi utilizzare un insieme completamente diverso di percorsi e controller per i tuoi contenuti compatibili con i robot. Ma poi stai duplicando tutti i tuoi percorsi e controller AngularJS in Node/Express.

Ho deciso di generare istantanee con un browser senza testa, anche se ritengo che sia un po 'meno che ideale.

9
Kevin C.
8
pixparker

A partire da ora Google ha cambiato la loro AJAX proposta di scansione.

I tempi sono cambiati. Oggi, a condizione che tu non blocchi Googlebot dalla scansione dei tuoi file JavaScript o CSS, siamo generalmente in grado di visualizzare e comprendere le tue pagine web come i browser moderni.

tl; dr: [Google] non sta più raccomandando la AJAX proposta di scansione [Google] creata nel 2009.

7
Thor

Lo standard Ajax Crawlable di Google, come riportato nelle altre risposte qui, è fondamentalmente la risposta.

Se sei interessato a come altri motori di ricerca e social bot affrontano gli stessi problemi, ho scritto lo stato dell'arte qui: http://blog.ajaxsnapshots.com/2013/11/googles-crawlable-ajax-specification .html

Lavoro per un https://ajaxsnapshots.com , una società che implementa le Specifiche Ajax Crawlable come servizio - le informazioni contenute in tale rapporto si basano sulle osservazioni dei nostri registri.

6
Robert AJS

Ho trovato una soluzione elegante che coprirebbe la maggior parte delle vostre basi. Ne ho scritto inizialmente here e ho risposto ad un'altra domanda simile a StackOverflow here che la referenzia.

FYI questa soluzione include anche i tag di fallback hardcoded nel caso in cui Javascript non venga prelevato dal crawler. Non l'ho esplicitamente delineato, ma vale la pena ricordare che dovresti attivare la modalità HTML5 per il corretto supporto degli URL.

Nota anche: questi non sono i file completi, solo le parti importanti di quelli rilevanti. Se hai bisogno di aiuto per scrivere lo standard per direttive, servizi, ecc. Che possono essere trovati altrove. Comunque, ecco qui ...

app.js

Qui è dove fornisci i metadati personalizzati per ciascuno dei tuoi percorsi (titolo, descrizione, ecc.)

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

Imposta le opzioni dei metadati personalizzati o usa i valori predefiniti come fallback.

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

Pacchetti i risultati del servizio di metadati per la vista.

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

Completa con i tag di fallback hardcoded menzionati in precedenza, per i crawler che non possono rilevare alcun 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>

Questo dovrebbe aiutare in modo drammatico con la maggior parte dei casi d'uso dei motori di ricerca. Se si desidera il rendering completamente dinamico per i crawler dei social network (che sono incerti sul supporto Javascript), sarà comunque necessario utilizzare uno dei servizi di pre-rendering menzionati in alcune delle altre risposte.

Spero che questo ti aiuti!

4
Andrew

Con Angular Universal, puoi generare pagine di destinazione per l'app che assomigliano all'app completa e quindi caricare l'app Angular dietro di essa.
Angular Universal genera puro HTML vuol dire pagine senza javascript sul lato server e li offre agli utenti senza ritardi. Quindi puoi gestire qualsiasi crawler, bot e utente (che hanno già cpu bassa e velocità di rete). Poi puoi reindirli tramite link/pulsanti alla tua vera app angolare che è già caricata dietro di essa. Questa soluzione è raccomandata dal sito ufficiale. -Ulteriori informazioni su SEO e Angular Universale-

2
erginduran

Usa qualcosa come PreRender, rende le pagine statiche del tuo sito in modo che i motori di ricerca possano indicizzarlo.

Qui puoi scoprire quali piattaforme sono disponibili: https://prerender.io/documentation/install-middleware#asp-net

2
NicoJuicy

I crawler (o bot) sono progettati per eseguire la ricerca per indicizzazione del contenuto HTML delle pagine Web, ma a causa di AJAX operazioni per il recupero di dati asincroni, questo è diventato un problema poiché richiede del tempo per eseguire il rendering della pagina e mostrare contenuti dinamici. Allo stesso modo, AngularJS utilizza anche un modello asincrono, che crea problemi ai crawler di Google.

Alcuni sviluppatori creano pagine html di base con dati reali e servono queste pagine dal lato server al momento della scansione. Possiamo eseguire il rendering delle stesse pagine con PhantomJS sul lato di servizio che ha _escaped_fragment_ (perché Google cerca #! nei nostri url del sito e quindi prende tutto dopo il #! e lo aggiunge nel parametro di query _escaped_fragment_). Per maggiori dettagli leggi questo blog .

1
Rubi saini

I crawler non hanno bisogno di un gui con stile piuttosto ricco, vogliono solo vedere il contenuto , quindi non è necessario dare loro un'istantanea di una pagina che è stata costruita per gli umani.

La mia soluzione: to dai al crawler ciò che vuole il crawler :

Devi pensare a cosa vuole il crawler e dargli solo questo.

SUGGERIMENTO non scherzare con la schiena. Basta aggiungere un piccolo frontview lato server usando la stessa API

0
pykiss