7
\$\begingroup\$

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?

\$\endgroup\$
2
  • \$\begingroup\$ Do you make the difference between the google bot and google analytics? The googlebot (search engine) is not executing the javascript (at least most of the time it is not...). This is why you need to pre-render the page if the request comes from the google bot. If you are talking about google analytics then alright your solution will work. Though I would suggest you to take a look at this project luisfarzati.github.io/angulartics. It does exactly what you are trying to do and even more. \$\endgroup\$ Mar 19, 2014 at 20:22
  • \$\begingroup\$ Wawaweewa it's a very nice! \$\endgroup\$
    – pilau
    Aug 31, 2014 at 13:58

1 Answer 1

2
\$\begingroup\$

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.

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.