Knockout JS and SEO
Making sure your webapp is searchable
by
Jason Dent
Revinate Inc.
What Knockout JS
- Knockout JS is a light weight functional reactive framework and templating system that helps with rapid web application development.
- Similar to AngularJS and EmberJS
- MVVM - Model View ViewModel
-
Copy/Pasted from knockoutjs.com
Knockout is a JavaScript library that helps you to create rich, responsive display and editor user interfaces with a clean underlying data model.
Inline Markup
The item is <span data-bind="text: priceRating"></span> today. It costs <span data-bind="text: price"></span> euros.
<script type="text/javascript"> var viewModel = {
price: ko.observable(24.95)
};
viewModel.priceRating = ko.computed(function() { return this.price() > 50 ? "expensive":"affordable"; }, viewModel); </script>
Motivation
- Goal: Enable Google to search
m.interglot.com
-- A translation web application aimed at mobile devices.
- Uses Knockout JS to render JSON from Ajax queries.
- Has over 1 million pages.
- PHP backend server.
- Challenge: To turn content generated by Knockout JS into something a crawler can download.
- This problem is not limited to Knockout JS
- Backbone.js, Meteor, Ember.js, Angular JS
- Any framework without a server-side renderer.
m.interglot.com
What a Crawler Sees
Today
Google's Advice
Overview of Solution
Briefly, the solution works as follows: the crawler finds a pretty AJAX URL (that is, a URL containing a #! hash fragment). It then requests the content for this URL from your server in a slightly modified form. Your web server returns the content in the form of an HTML snapshot , which is then processed by the crawler. The search results will show the original URL.
Aaaaaaaaaaaah! #! #! #!
Nice Diagram
Pushstate
Verify!
Fetch as Google
So, why take the chance.
What to do?
Use Pushstate
- To create nice urls:
http://m.interglot.com /en/nl/create
Green: webapp url
Red: dynamic state - These nice urls can be used by the crawlers to request the right dynamic content from the server.
- *** Have the server serve an Html Snapshot ***
Making an
HTML Snapshot
If a lot of your content is created in JavaScript, you may want to consider using a technology such as a headless browser to create an HTML snapshot.
Headless
Browsers
- phantomjs
- Webkit
- most platforms
- Actively under development
- zombiejs
- Webkit
- Node.js
- Actively under development
Headless Diagram
Using a
headless Browser
<html>
<head>
...
</head>
<body>
<div id="dynamic_content"
data-bind="template:
{name: 'template_pagecontent', data: $data}">
... will be filled in by rendered content from server ...
... Replaced by the knockoutjs binding ...
</div>
<script type="html/text" id="template_pagecontent">
... your html and knockout content
... that will replace dynamic_content element.
</script>
</body>
</html>
Page Speed
Do NOT make your visitors wait.
Cache HTML Snippets
You can use a cache to speed everything up.
This is very important if you have ads on your site. The user visit will cause the ad server to hit your site immediately afterwards. So a cache will make the second call much faster.
Think about using a soft expiration date. Meaning, if you have the item in the cache, but it is a little bit out of date, serve it anyway and launch a background cache refresh.
Google Bot
Real Person
Headless Browser
Tips for PhantomJS
- Capture and stub out Analytics, Ad code, facebook, etc.
To capture use:
To point to another location use:page.onResourceRequested = function(requestData, networkRequest) {...});
networkRequest.changeUrl("./blank.js");
networkRequest.changeUrl("./ga.js");
- Use a local copy of your JS files and common libraries like JQuery.
- Set the Agent String to a known value so your server knows it is a headless browser request.
Sample Stubs
Google Analytics:
// ga.js
var _gaq = _gaq || [];
Google Tag Services (DFP)
// gpt.js
window.googletag = window.googletag || {};
window.googletag.cmd = window.googletag.cmd || [];
window.googletag.display = window.googletag.display || function(){};
Things to Remember
-
Watch out for third-party scripts
Don't let the headless browser screw up your stats.
You need to stub out:
- Google Analytics
- Adsense/DFP
- Facebook and other social plugins.
-
Watch out for code that does document.write
-
For a better end user experience, include both the rendered html code and the JSON data for the model view template in the document from the server.
This will reduce the perceived wait time. - Don't get stuck in an infinite loop!
Other Solutions
-
Backbone.js -- Rendr by Airbnb https://github.com/airbnb/rendr
- Meteor -- uses PhantomJS
http://meteor.com/blog/2012/08/09/search-engine-optimization - Angular.js -- uses PhantomJS http://www.yearofmoo.com/2012/11/angularjs-and-seo.html
Now Hiring
We are looking for an Architect level developer for a total revamp of our frontend application using Angular JS and Bootstrap
http://www.revinate.com/about/jobs/
Jason@revinate.com
knockout js and seo
By Jason Dent
knockout js and seo
The truth is, Google most likely is not indexing your knockout.js web app. Find out why and how to fix it.
- 10,389