Angular HTML5 mode or pretty URLs on Apache (using htaccess)

2018 update: see the new post here Pretty URLs or HTML5 mode for any front-end SPA

Squeezing some SEO juice into our Angular applications became a lot easier since Google started crawling ajax sites. However, the hashbang (#!) has its limitations. I'm not going to get into details, because there are tons of articles on that. However, I will point out that if you are serious about analyzing your site traffic, you won't get far with the hashbang.

Take me to the code already!

Before the hashbang

What I was able to see in Google Analytics with the hashbang was not particularly helpful. All the pages were labeled as root (/), therefore making the Bounce Rate, Avg. Session Duration and the Behaviour data useless. That's about 1/3 of the data.

AngularJS: Google Analytics before HTML5 mode

How to convert to pretty URLs or HTML5 mode

The example I took for this post is my old company website. The code was hosted on your typical Apache shared server (such as GoDaddy, MediaTemple, HostGator; you name it).

The code

Note, if you are on Angular 2+, skip the snippet below. The router is set to HTML5 mode by default (uses pushState).

First thing you have to do is turn on HTML5 mode in your main Angular module's config block. That's pretty much a one liner:

angular.module('main', []).config(['$locationProvider', function($locationProvider) {

After doing this, you need to create a .htaccess file on the root of your shared Apache server.

RewriteEngine On
# If an existing asset or directory is requested go to it as it is
RewriteRule ^ - [L]

# If the requested resource doesn't exist, use index.html
RewriteRule ^ /index.html

That's it!

After the hashbang

Now that .htaccess is in place, we can use Analytics at full capacity.

AngularJS: Google Analytics after HTML5 mode

How does it work?

HTML5 mode is based on the HTML5 History API, which essentially allows setting a URL on the same domain with JavaScript. The .htaccess file makes it possible to reload a page (or go to a hashbang-less page for that matter) without getting a 404 response from the server.
Moreover, if the HTML5 History API is not available, your Angular application will automatically use the hashbang as a fallback.
Read more about it on this Angular docs page.

One more thing...

The issue with this is that now Google doesn't consider this an AJAX Single Page Application. Therefore, I was able to notice that the indexing (which was working fine with the hashbang) is very poor now.
So solving a problem resulted in creating a bigger problem.
There is a good part: Google itself suggests that to benefit from proper indexing, creating HTML Snapshots is a good idea. But that's another topic.

Looking forward to seeing your pretty URLs!