Search engine optimization is vital for getting your solution in front of the people who need it, and we found out the hard way that AngularJS poses its own set of SEO challenges. Here's how we improved our SEO in AngularJS.
The Wijmo on-line documentation is an AngularJS single-page application consisting of a page with a Table of Contents (ToC). When ToC links are clicked, AngularJS loads and displays help topics as Partial Views. The Partial Views are static HTML files generated from our source code. The result is a simple and fast website for viewing Wijmo documentation. Our Wijmo documentation, a single-page AngularJS app
We published this application and moved on. We later realized that Google was indexing it, but not the way we wanted it to. We hadn’t considered SEO for our documentation, which was a mistake. Once we realized this was a problem, we began investigating the root issues. There are two main problems we had when hosting content in an AngularJS application:
The good news is that Google DOES render the AngularJS application and indexes the content after the JavaScript has finished rendering! So people were finding our topics through Google, but the results they saw in Google were bad. To see how Google displays a page, you can use the info: command. Here's how Google indexed our FlexGrid Class documentation page: Search results showed the same title for all pages Things to note:
Here’s how we want our FlexGrid Class documentation to be displayed in Google: Display a reader-friendly, relevant title and description We now have a title specific to the FlexGrid Class topic and a more readable description. Here's how we did it.
Solving the issue of how Google displays our documentation topics in results is very simple. We need to update the <title>
tag and <meta name="description" content="" />
tag each time a topic gets loaded in by AngularJS’s router. This is a best practice, regardless of whether you want SEO. It’s always good to keep your title updated based on context in your application. It’s also important for accessibility to keep the title updated based on application context. In order to update these tags, we need to create an event handler.
// handle successful topic loading
app.run(function ($rootScope, $window) {
$rootScope.$on('$routeChangeSuccess', function () {
var interval = setInterval(function () {
if (document.readyState == 'complete') {
//code that executes when partial view is loaded
}
}, 200);
});
});
Now that we have the event handler, we can update the tags. You might want to make this based on data in your $scope. But we have static HTML that contains the information we need. So we will do some DOM querying to get it.
I also appended “Wijmo 5 Help” to it for some more context.
//find the main heading tag for the help topic
var heading = document.querySelector('#content h2');
if (heading !== null) {
// set page title to topic heading
document.title = heading.textContent.trim() + ' - Wijmo 5 Help';
}
}
Next, we need to update the meta description tag. This one uses a slightly more complicated DOM query. We use the attribute selector to find the meta description tag—there are many meta tags, so it’s important to update the description meta tag. The content we get for the description is the tricky selector.
//find meta description tag
var meta = document.querySelector('meta[name=description]');
//find first paragraph in the help topic that isn't empty
var content = document.querySelector('#content p:not(:empty)');
if (meta !== null && content !== null) {
// set meta description to content of first paragraph in topic
meta.setAttribute('content', content.textContent.trim());
}
That’s it! Now we’re properly updating our title and meta description for each topic in our documentation.
Another issue we had was that some of our links were not being followed by the Google crawler. After some investigation, we found that some links were using an ng-click attribute instead of the standard href attribute on hyperlinks. This was an easy fix for us, since we were routing to a new URL in the ng-click event. We simply needed to change those hyperlinks to have a href attribute set to a navigable path. Once we made that change, Google was able to follow all hyperlinks in our documentation.
In order to have more SEO-friendly URLs in our AngularJS application, we enabled HTML mode in our router. It consists of adding a element and calling $locationProvider.html5Mode(true). We also had to make some changes in our server config to map requests to subdirectories to our main page. You can follow other instructions on how to implement SEO friendly URLS.
Now that we have our application cleaned up, we’re going to make sure Google indexes all of the “pages” in our AngularJS application. In order to do that, we’re going to generate a sitemap for our help topics. A sitemap tells Google about all of the URLs that you want to be indexed, and how they’re structured on your site. This step isn’t required, but it’s recommended. We already have a Table of Contents for our help documentation, so I simply used that to generate a sitemap.
I use the “Fetch as Google” feature in Google Search Console to see if Google is rendering my Angular application correctly. This won’t give you a ton of information, but it’s helpful to verify that your AngularJS application is being indexed. Once everything looks good, you can submit the application to Google Index. Here’s how to do it:
Your application will be submitted to Google’s Index. Note that it takes some time for the site to be indexed and show results in Google.
It does take some time and it’s a little tedious, but making your AngularJS applications more SEO-friendly is definitely worth doing. We were able to greatly improve the results showing up in Google search using these steps. I hope these are helpful to you as well. Another option we didn’t cover here is rendering from the server. There are some interesting tools that render AngularJS applications into static html pages on the server. I did not test this approach, but it certainly has its merits.