AngularJs and Google Bot experiment

Posted on

Problem

I have learned the question of solving Angular app optimization for search engines, and was frustrated that the most recommended option is prerendering HTML.

After some time spent, I suggested to create a directive that will load the bot after rendering templates or update scope.

Directive:

angular.module('test', []).directive('seoBot', ['$timeout', function($timeout){

    return {

        link: function($scope, element, attrs) {

            //publish event 
            $scope.$on('runbot', function(){

                //hint for start after render
                $timeout(function () {

                    //find previos google's bot
                    var googleBot = document.getElementById('googleBot');

                    //if found - remove
                    if(googleBot) googleBot.parentNode.removeChild(googleBot);

                    //this is standard code from GA, but with ID "googleBot"
                    (function(i,s,o,g,r,a,m){
                        i['GoogleAnalyticsObject']=r;
                        i[r]=i[r]||function(){
                            (i[r].q=i[r].q||[]).push(arguments)
                        },i[r].l=1*new Date();
                        a=s.createElement(o),
                        m=s.getElementsByTagName(o)[0];
                        a.id="googleBot";
                        a.async=1;
                        a.src=g;
                        m.parentNode.insertBefore(a,m);
                    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

                    ga('create', 'UA-46685745-1', 'rktdj.com');
                    ga('send', 'pageview');

                    //log that bot is loaded
                    console.log("seo-bot loaded");

                    //check page to be rendered completely
                    console.log(document.body.innerHTML);

                }, 0, false);

            });

        }

    };

}]);

In controller:

//get some data from server and update scope
$http.get(GLOBAL.api.SERVER_PATH + GLOBAL.api.facultiesByCourse + s_id)
        .success(function (data) {

            $scope.courses = data;
            console.dir($scope.courses);

            //broadcast event to seo-bot
            $scope.$broadcast('runbot');

        } );

seo-bot tag in the bottom of template:

    <div class="well" id="courseList">

        <!-- some template code -->

    </div>

    <div seo-bot></div>

It works, and the bot loads every time when template have update or route changed.
I can check that all elements with data was rendered before.

But… will this solution really work? Will Google bot correctly correlate rendered page with the domain? Can I be banned for this?

Solution

As you found yourself, this has to work.

I only have 2 minor nitpickings:

  • Do not use console.log() in production code..
  • You are not using element and attrs, you might as well declare function($scope)

Very nice code.

Leave a Reply

Your email address will not be published. Required fields are marked *