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?