Saya melihat dua masalah dengan aplikasi AngularJS mengenai mesin pencari dan SEO:
1) Apa yang terjadi dengan tag khusus? Apakah mesin pencari mengabaikan seluruh konten di dalam tag itu? misalkan saya punya
<custom>
<h1>Hey, this title is important</h1>
</custom>
apakah <h1>
akan diindeks meskipun ada di dalam tag khusus?
2) Apakah ada cara untuk menghindari mesin pencari mengindeks {{}} mengikat secara harfiah? yaitu.
<h2>{{title}}</h2>
Saya tahu saya bisa melakukan sesuatu seperti
<h2 ng-bind="title"></h2>
tetapi bagaimana jika saya ingin membiarkan crawler "melihat" judulnya? Apakah rendering sisi-server adalah satu-satunya solusi?
Pembaruan Mei 2014
Google crawlers sekarang menjalankan javascript - Anda dapat menggunakan Google Webmaster Tools untuk lebih memahami bagaimana situs Anda di-render oleh Google.
Jawaban asli
Jika Anda ingin mengoptimalkan aplikasi Anda untuk mesin pencari, sayangnya tidak ada jalan lain untuk menyajikan versi yang telah dirender ke crawler. Anda dapat membaca lebih lanjut tentang rekomendasi Google untuk situs berat ajax dan javascript di sini .
Jika ini merupakan opsi, saya akan merekomendasikan membaca artikel ini tentang bagaimana melakukan SEO untuk Angular dengan rendering sisi server.
Saya tidak yakin apa yang dilakukan perayap ketika menemukan tag khusus.
Cara saat ini (2015) untuk melakukan ini adalah menggunakan metode JavaScript pushState.
PushState mengubah URL di bilah peramban atas tanpa memuat ulang laman. Katakanlah Anda memiliki halaman yang berisi tab. Tab menyembunyikan dan menampilkan konten, dan konten disisipkan secara dinamis, baik menggunakan AJAX atau dengan hanya mengatur tampilan: tidak ada dan menampilkan: memblokir untuk menyembunyikan dan menampilkan konten tab yang benar.
Ketika tab diklik, gunakan pushState untuk memperbarui url di bilah alamat. Saat laman diberikan, gunakan nilai di bilah alamat untuk menentukan tab mana yang akan ditampilkan. Angular routing akan melakukan ini untuk Anda secara otomatis.
Ada dua cara untuk menekan Aplikasi Halaman Tunggal PushState (SPA)
Hit awal di situs akan melibatkan pemukulan URL secara langsung. Hit berikutnya hanya akan AJAX dalam konten sebagai PushState memperbarui URL.
Crawler memanen tautan dari sebuah halaman kemudian menambahkannya ke antrian untuk diproses lebih lanjut. Ini berarti bahwa untuk perayap, setiap klik di server adalah klik langsung, mereka tidak menavigasi melalui Pushstate.
Prekomposisi menggabungkan muatan awal ke respons pertama dari server, mungkin sebagai objek JSON. Ini memungkinkan Mesin Pencari untuk merender halaman tanpa menjalankan panggilan AJAX.
Ada beberapa bukti yang menunjukkan bahwa Google mungkin tidak menjalankan permintaan AJAX. Lebih lanjut tentang ini di sini:
Google telah dapat mem-parsing JavaScript untuk beberapa waktu sekarang, itu sebabnya mereka awalnya mengembangkan Chrome, untuk bertindak sebagai browser tanpa kepala berfitur lengkap untuk spider Google. Jika tautan memiliki atribut href yang valid, URL baru dapat diindeks. Tidak ada lagi yang bisa dilakukan.
Jika mengklik tautan sebagai tambahan memicu panggilan pushState, situs dapat dinavigasi oleh pengguna melalui PushState.
PushState saat ini didukung oleh Google dan Bing.
Berikut Matt Cutts menanggapi pertanyaan Paul Irish tentang PushState untuk SEO:
Ini Google yang mengumumkan dukungan penuh JavaScript untuk laba-laba:
http://googlewebmastercentral.blogspot.de/2014/05/understanding-web-pages-better.html
Hasilnya adalah bahwa Google mendukung PushState dan akan mengindeks URL PushState.
Lihat juga alat Google webmaster sebagai Googlebot. Anda akan melihat JavaScript Anda (termasuk Angular) dieksekusi.
Berikut ini pengumuman dukungan Bing untuk URL PushState cantik bertanggal Maret 2013:
http://blogs.bing.com/webmaster/2013/03/21/search-engine-optimization-best-practices-for-ajax-urls/
URL Hashbang adalah pengganti sementara yang jelek yang mengharuskan pengembang untuk menyediakan versi situs yang dirender sebelumnya di lokasi khusus. Mereka masih berfungsi, tetapi Anda tidak perlu menggunakannya.
URL Hashbang terlihat seperti ini:
domain.com/#!path/to/resource
Ini akan dipasangkan dengan metatag seperti ini:
<meta name="fragment" content="!">
Google tidak akan mengindeks mereka dalam bentuk ini, tetapi sebaliknya akan menarik versi statis situs dari URL _escaped_fragments_ dan mengindeksnya.
URL pushstate terlihat seperti URL biasa:
domain.com/path/to/resource
Perbedaannya adalah bahwa Angular menanganinya untuk Anda dengan menyadap perubahan ke dokumen.lokasi berurusan dengannya di JavaScript.
Jika Anda ingin menggunakan URL PushState (dan mungkin Anda lakukan), keluarkan semua URL gaya lama dan metatag dan cukup aktifkan mode HTML5 di blok konfigurasi Anda.
Alat Webmaster Google sekarang berisi alat yang akan memungkinkan Anda untuk mengambil URL sebagai google, dan merender JavaScript saat Google membuatnya.
https://www.google.com/webmasters/tools/googlebot-fetch
Untuk menghasilkan URL nyata di Angular, bukan # yang diawali, setel mode HTML5 pada objek $ locationProvider Anda.
$locationProvider.html5Mode(true);
Karena Anda menggunakan URL sungguhan, Anda perlu memastikan templat yang sama (ditambah beberapa konten yang sudah dikomposisi sebelumnya) dikirimkan oleh server Anda untuk semua URL yang valid. Cara Anda melakukannya bervariasi tergantung pada arsitektur server Anda.
Aplikasi Anda dapat menggunakan bentuk navigasi yang tidak biasa, misalnya melayang atau gulir. Untuk memastikan Google dapat mendorong aplikasi Anda, saya mungkin menyarankan untuk membuat peta situs, daftar sederhana semua url yang ditanggapi aplikasi Anda. Anda dapat menempatkan ini di lokasi default (/ sitemap atau /sitemap.xml), atau memberi tahu Google tentang hal itu menggunakan alat webmaster.
Lagipula itu ide yang bagus untuk memiliki sitemap.
Pushstate berfungsi di IE10. Di browser lama, Angular akan secara otomatis kembali ke URL gaya hash
Konten berikut ini dirender menggunakan URL pushstate dengan prasyarat:
http://html5.gingerhost.com/london
Seperti yang dapat diverifikasi, pada tautan ini , konten diindeks dan muncul di Google.
Karena mesin pencari akan selalu menekan server Anda untuk setiap permintaan, Anda dapat melayani kode status tajuk dari server Anda dan mengharapkan Google melihatnya.
Google, Yahoo, Bing, dan mesin pencari lainnya merayapi web dengan cara tradisional menggunakan crawler tradisional. Mereka menjalankan robot yang merayapi HTML di halaman web, mengumpulkan informasi di sepanjang jalan. Mereka menyimpan kata-kata yang menarik dan mencari tautan lain ke halaman lain (tautan ini, jumlah mereka, dan jumlah mereka yang ikut bermain dengan SEO).
Jawabannya ada hubungannya dengan fakta bahwa robot mesin pencari bekerja melalui browser tanpa kepala dan mereka paling sering tidak memiliki mesin rendering javascript untuk merender javascript suatu halaman. Ini berfungsi untuk sebagian besar halaman karena sebagian besar halaman statis tidak peduli tentang JavaScript membuat halaman mereka, karena kontennya sudah tersedia.
Untungnya, perayap situs yang lebih besar sudah mulai menerapkan mekanisme yang memungkinkan kami membuat situs JavaScript kami dapat dijelajahi, tetapi itu mengharuskan kami menerapkan perubahan ke situs kami .
Jika kita mengubah hashPrefix
menjadi #!
alih-alih hanya #
, maka mesin pencari modern akan mengubah permintaan untuk menggunakan _escaped_fragment_
alih-alih #!
. (Dengan mode HTML5, mis. Di mana kami memiliki tautan tanpa awalan hash, kami dapat menerapkan fitur yang sama ini dengan melihat tajuk User Agent
di backend kami).
Artinya, alih-alih permintaan dari peramban normal yang terlihat seperti:
http://www.ng-newsletter.com/#!/signup/page
Mesin pencari akan mencari halaman dengan:
http://www.ng-newsletter.com/?_escaped_fragment_=/signup/page
Kita dapat mengatur awalan hash dari aplikasi Angular kami menggunakan metode bawaan dari ngRoute
:
angular.module('myApp', [])
.config(['$location', function($location) {
$location.hashPrefix('!');
}]);
Dan, jika kita menggunakan html5Mode
, kita perlu mengimplementasikan ini menggunakan meta tag:
<meta name="fragment" content="!">
Sebagai pengingat, kita dapat mengatur html5Mode()
dengan layanan $location
:
angular.module('myApp', [])
.config(['$location',
function($location) {
$location.html5Mode(true);
}]);
Kami memiliki banyak peluang untuk menentukan bagaimana kami akan menangani pengiriman konten ke mesin pencari sebagai HTML statis. Kita dapat meng-host backend sendiri, kita dapat menggunakan layanan untuk menjadi Host back-end untuk kita, kita dapat menggunakan proxy untuk mengirimkan konten, dll. Mari kita lihat beberapa opsi:
Kita dapat menulis layanan untuk menangani berurusan dengan merayapi situs kami sendiri menggunakan browser tanpa kepala, seperti phantomjs atau zombiejs, mengambil snapshot halaman dengan data yang diberikan dan menyimpannya sebagai HTML. Setiap kali kami melihat string kueri ?_escaped_fragment_
dalam permintaan pencarian, kami dapat mengirimkan snapshot HTML statis yang kami ambil dari halaman alih-alih halaman yang dirender melalui hanya JS. Ini mengharuskan kami untuk memiliki backend yang memberikan halaman kami dengan logika kondisional di tengah. Kita dapat menggunakan sesuatu seperti prerender.io's backend sebagai titik awal untuk menjalankan ini sendiri. Tentu saja, kita masih perlu menangani proxy dan penanganan snippet, tapi ini awal yang baik.
Cara termudah dan tercepat untuk memasukkan konten ke mesin pencari adalah dengan menggunakan layanan Brombone , seo.js , seo4ajax , dan prerender.io adalah contoh yang baik dari ini yang akan menjadi tuan rumah rendering konten di atas untuk Anda. Ini adalah opsi yang bagus untuk saat-saat ketika kita tidak ingin berurusan dengan menjalankan server/proxy. Juga, biasanya sangat cepat.
Untuk informasi lebih lanjut tentang Angular dan SEO, kami menulis tutorial ekstensif di http://www.ng-newsletter.com/posts/serious-angular-seo.html dan kami lebih detail dalam buku kami buku: Buku Lengkap tentang AngularJS . Lihat di ng-book.com .
Anda harus benar-benar memeriksa tutorial membangun situs AngularJS SEO-friendly di tahun blog moo. Dia memandu Anda melalui semua langkah yang diuraikan pada dokumentasi Angular. http://www.yearofmoo.com/2012/11/angularjs-and-seo.html
Dengan menggunakan teknik ini, mesin pencari melihat HTML yang diperluas alih-alih tag kustom.
Ini telah berubah secara drastis.
Jika Anda menggunakan: $ locationProvider.html5Mode (true); Anda sudah siap.
Tidak ada lagi halaman render.
Banyak hal telah berubah sejak pertanyaan ini diajukan. Sekarang ada opsi untuk membiarkan Google mengindeks situs AngularJS Anda. Opsi termudah yang saya temukan adalah menggunakan http://prerender.io layanan gratis yang akan menghasilkan halaman crwalable dan sajikan itu ke mesin pencari. Ini didukung pada hampir semua platform web sisi server. Saya baru-baru ini mulai menggunakannya dan dukungannya juga luar biasa.
Saya tidak memiliki afiliasi dengan mereka, ini berasal dari pengguna yang bahagia.
Situs web Angular sendiri menyajikan konten yang disederhanakan ke mesin pencari: http://docs.angularjs.org/?_escaped_fragment_=/tutorial/step_09
Katakanlah aplikasi Angular Anda mengkonsumsi api JSON Node.js/Express-driven, seperti /api/path/to/resource
. Mungkin Anda bisa mengalihkan permintaan dengan ?_escaped_fragment_
ke /api/path/to/resource.html
, dan menggunakan negosiasi konten untuk merender template HTML konten, daripada mengembalikan data JSON.
Satu-satunya hal adalah, rute Angular Anda perlu mencocokkan 1: 1 dengan REST API Anda.
SUNTING: Saya menyadari bahwa ini memiliki potensi untuk benar-benar mengeruhkan REST api Anda dan saya tidak merekomendasikan melakukannya di luar kasus penggunaan yang sangat sederhana di mana itu mungkin cocok secara alami.
Sebagai gantinya, Anda dapat menggunakan serangkaian rute dan pengontrol yang sama sekali berbeda untuk konten yang ramah robot Anda. Tapi kemudian Anda menduplikasi semua rute dan pengendali AngularJS Anda di Node/Express.
Saya telah memutuskan untuk membuat snapshot dengan browser tanpa kepala, meskipun saya merasa itu kurang ideal.
Praktik yang baik dapat ditemukan di sini:
http://scotch.io/tutorials/javascript/angularjs-seo-with-prerender-io?_escaped_fragment_=tag
Sampai sekarang Google telah mengubah proposal perayapan AJAX mereka.
tl; dr: [Google] tidak lagi merekomendasikan AJAX proposal perayapan [Google] dibuat pada tahun 2009.
Google's Crawlable Ajax Spec, seperti yang dirujuk dalam jawaban lain di sini, pada dasarnya adalah jawabannya.
Jika Anda tertarik pada bagaimana mesin pencari lain dan bot sosial menangani masalah yang sama dengan yang saya tulis di sini: http://blog.ajaxsnapshots.com/2013/11/googles-crawlable-ajax -specification.html
Saya bekerja untuk https://ajaxsnapshots.com , sebuah perusahaan yang mengimplementasikan Spec Ajax yang Dapat Dirayapi sebagai layanan - informasi dalam laporan tersebut didasarkan pada pengamatan dari log kami.
Saya telah menemukan solusi elegan yang akan mencakup sebagian besar pangkalan Anda. Saya menulis tentang hal itu awalnya di sini dan menjawab pertanyaan StackOverflow serupa lainnya di sini yang referensi itu.
FYI solusi ini juga mencakup tag fallback hardcoded jika Javascript tidak diambil oleh crawler. Saya belum secara eksplisit menguraikannya, tetapi perlu disebutkan bahwa Anda harus mengaktifkan mode HTML5 untuk dukungan URL yang tepat.
Perhatikan juga: ini bukan file lengkap, hanya bagian penting dari file yang relevan. Jika Anda perlu bantuan menulis pelat untuk arahan, layanan, dll. Yang dapat ditemukan di tempat lain. Bagaimanapun, ini dia ...
app.js
Di sinilah Anda memberikan metadata khusus untuk setiap rute Anda (judul, deskripsi, dll.)
$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 (layanan)
Tetapkan opsi metadata khusus atau gunakan default sebagai 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 (direktif)
Paket hasil layanan metadata untuk tampilan.
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
Lengkap dengan tag fallback hardcoded yang disebutkan sebelumnya, untuk crawler yang tidak dapat mengambil Javascript apa pun.
<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>
Ini akan membantu secara dramatis dengan sebagian besar kasus penggunaan mesin pencari. Jika Anda ingin perenderan sepenuhnya dinamis untuk perayap jaringan sosial (yang rapuh pada dukungan Javascript), Anda masih harus menggunakan salah satu layanan pra-perenderan yang disebutkan dalam beberapa jawaban lain.
Semoga ini membantu!
Dengan Angular Universal, Anda dapat membuat halaman pendaratan untuk aplikasi yang terlihat seperti aplikasi lengkap dan kemudian memuat aplikasi Angular Anda di belakangnya.
Angular Universal menghasilkan HTML murni berarti halaman tanpa javascript di sisi server dan melayani mereka untuk pengguna tanpa penundaan. Jadi Anda dapat berurusan dengan perayap, bot, dan pengguna apa pun (yang sudah memiliki cpu dan kecepatan jaringan rendah). Lalu Anda dapat mengarahkan mereka dengan tautan/tombol ke aplikasi sudut aktual Anda yang sudah dimuat di belakangnya. Solusi ini direkomendasikan oleh situs resmi. - Info selengkapnya tentang SEO dan Angular Universal -
Gunakan sesuatu seperti PreRender, itu membuat halaman statis situs Anda sehingga mesin pencari dapat mengindeksnya.
Di sini Anda dapat menemukan platform apa yang tersedia: https://prerender.io/documentation/install-middleware#asp-net
Crawler (atau bot) dirancang untuk merayapi konten HTML dari halaman web tetapi karena operasi AJAX untuk pengambilan data yang tidak sinkron, ini menjadi masalah karena dibutuhkan waktu untuk merender halaman dan menampilkan konten dinamis di atasnya. Demikian pula, AngularJS
juga menggunakan model asinkron, yang menciptakan masalah bagi perayap Google.
Beberapa pengembang membuat halaman html dasar dengan data nyata dan melayani halaman ini dari sisi server pada saat perayapan. Kita dapat merender halaman yang sama dengan PhantomJS
di sisi penayangan yang memiliki _escaped_fragment_
(Karena Google mencari #!
di url situs kami dan kemudian mengambil semuanya setelah #!
dan menambahkannya dalam parameter permintaan _escaped_fragment_
) Untuk detail lebih lanjut silakan baca ini blog .
Perayap tidak memerlukan gui kaya fitur yang cukup bergaya, mereka hanya ingin melihat konten, jadi Anda tidak perlu memberi mereka snapshot halaman yang telah dibuat untuk manusia.
Solusi saya: untuk berikan crawler apa yang diinginkan crawler:
Anda harus memikirkan apa yang diinginkan perayap, dan hanya memberinya itu.
TIP jangan main-main dengan bagian belakang. Tambahkan saja tampilan depan sisi-server menggunakan API yang sama