Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Angular JS SEO

Angular JS SEO

Search bots do not execute the javascript and, thus, all they see is the empty template for AngularJS applications. It is ok if the app is password protected (the pages would not be indexed anyway) but is unacceptable if we want our application pages indexed in search engines.
How can we solve this? What are the different approaches to do so?

This talk was held at the AngularJS Barcelona Meetup on April 15th 2014.

You can find the source code here https://github.com/joseraya/angular-seo under the slides directory (content is in the slides.md file)

Jose Raya

April 15, 2014
Tweet

Other Decks in Technology

Transcript

  1. DISCLAIMER DISCLAIMER I am no SEO expert. I am just

    a developer who was considering AngularJS for two 'non-application' situations: My company web site An ecommerce web site
  2. IS A SPA THE RIGHT CHOICE FOR YOU? IS A

    SPA THE RIGHT CHOICE FOR YOU? let's assume that it is ;) SEO implies you want a broad audience what about users with JS disabled or with old browsers?
  3. HOW TO MAKE GOOGLE SEE MY CONTENT? HOW TO MAKE

    GOOGLE SEE MY CONTENT? What you see:
  4. WHERE ARE MY PHONES? WHERE ARE MY PHONES? We need

    to tell google that our application is crawlable should become and will become http://angularjs-seo-talk.herokuapp.com/app/#/phones http://angularjs-seo-talk.herokuapp.com/app/#!/phones http://angularjs-seo-talk.herokuapp.com/app/?_escaped_fragment_=/phones https://developers.google.com/webmasters/ajax-crawling/docs/getting-started
  5. We need to handle this at the server app.get('/app/*', function

    (req, res) { if (req.query._escaped_fragment_) { console.log(req.query._escaped_fragment_); res.send("Your phones should be here"); res.end(); } else { res.sendfile(req.originalUrl, { root: __dirname + '/../' }); } });
  6. and configure angular to use hashbangs: or use the 'fragment'

    meta see phonecatApp.config(['$locationProvider', function ($locationProvider) { $locationProvider.hashPrefix('!'); }] ); <meta name="fragment" content="!" /> https://developers.google.com/webmasters/ajax-crawling/docs/specification
  7. Alternatively, we can use the html5 mode in the router

    but then we have to be able to respond to /app/phones at the server and return the appropiate HTML $locationProvider .html5Mode(true);
  8. HOW DO I RENDER MY VIEW AT THE SERVER? HOW

    DO I RENDER MY VIEW AT THE SERVER? We can render 'on demand' (and cache the snapshots) We can pregenerate 'snapshots' on build time
  9. SERVER SIDE RENDERING SERVER SIDE RENDERING We need a browser

    environment to render our pages server side rendering has been in the roadmap but does not seem likely to be implemented in the short term -> Headless webkit -> Gecko alternative to phantom.js, not truly headless -> Simulated browser (lightweight) phantom.js slimer.js zombie.js
  10. SNAPSHOT GENERATION AT BUILD TIME SNAPSHOT GENERATION AT BUILD TIME

    If you have a sitemap or a robots.txt (and you should) you can use any of the grunt tasks grunt-html-snapshots grunt-html-snapshot
  11. If you don't, you can always crawl your site yourself:

    var Browser = require('zombie') ... var promise = browser.visit(uri) .then(function() { ... var links = browser.queryAll('a'); links.forEach(function(link) { ... }); ... });
  12. HAS THE TEMPLATE BEEN RENDERED YET? HAS THE TEMPLATE BEEN

    RENDERED YET? Angular may take some time to completely render the template and then poll for the status: or you can wait for a predetermined amount of time (like 1s per page) <html lang="en" ng-app="phonecatApp" data-status="{{status}}"> var intervalId = setInterval(function() { var status = browser.body.getAttribute('data-status'); if (status === "ready") { clearInterval(intervalId); ... // Now the templates have been rendered } }, 500);
  13. CAN IT BE EASIER? CAN IT BE EASIER? YES! There

    are many ajax crawling services that will handle the snapshot generation and caching for you Just google ajax SEO :) prerender Brombone SEO4Ajax
  14. I like prerender because it is open source $ npm

    install prerender-node --save app.use(require('prerender-node')); $ export PRERENDER_TOKEN=...