Click here to Skip to main content
15,881,139 members
Articles / Web Development / IIS

AngularJS Social Sharing And SEO

Rate me:
Please Sign up or sign in to vote.
4.25/5 (3 votes)
14 Mar 2016CPOL4 min read 19.5K   6   4
As web application development become more dependent on JavaScript technology (AngularJS, React, etc) - the depend on JavaScript rendering become more important than ever, this article explains how to deal with SEO and Social Sharing on pure JavaScript applications

The Problem:

AngularJS freamwork is awesome, the two-way data binding is one of the main features and power of AngularJS. On the first day i started working on my AngularJS project - I couldn't go back.

This technic of Java Script rending HTML is great, if you compare to another freamworks like ASP.Net MVC - it's simpler and faster.

But, one question was always on my mind - what happens when we need to get the final rendered page (inculding all content and meta tags) without browser ? using, let's say, a web request ?  or some crawler ? What will be the result ?

In the following P.O.C exmple application, I created an angular application with simple service, which update the MetaTitle and MetaDescription values on the rootScope, and bind them to the title and description metatags :

    var $rootScope = $rootScope;
    retrun {
               function(title,description) {

                   this.$rootScope.MetaTitle = title;
                   this.$rootScope.MetaDescription = description;
          updatemymetaplease.UpdateNow('My App Title','Awsome Application');

and the page.html file :

<html ng-app="MyApp">
        <meta name="description" content="{{ MetaDescription }}">
  <body ng-controller="MainController">
        <p>Exemple App</p>
      <script src="app.js"></script>

 After the digest cycle of angular the output will be as the following :

        <title>My App Title</title>
        <meta name="description" content="Awsome Application">
  <script src="app.js"></script>

isn't it's great ? no static meta tags, my HTML file is fully dynamic, clean and readable, without any unreadable JS files and JQuery opertions on the global scope, and especially -  i don't need any server side framework (,php,java, etc.), I can bind my meta tags dynamiclly on client side.

Let's test our awesome site the Facebook Sharing preview box :

Image 1  - Facebook preview display


Why ?

Well, Javascript is a client side language (except NodeJS family), I meen the UI can run and render only by the browser - so what happen if your client not using a browser ? in this case Facebook scraper - the crawler expect to get a fully rendered HTML page , actully the caller seems to do GET request, which returns the following HTML page :

        <meta name="description" content="{{ MetaDescription }}">
        <p>Exemple App</p>

It's not a Bug !

We all know that google started rendering heavy JS application, which provide a solution to the google SEO problem spcificlly,  but what about Bing crawler  ? Facebook scraper? Twitter and many more.  at this point a pure angularJS app will be showing as the output html does, without JS rendering.

Do I really have to wrap my app with server side freamwork to solve this issue ?    - NO

Soultion Description :

We will use the awsome PhantomJS ( to render the AngularJS scripts before sending the responed back, that way we can be sure that the meta tags and content will be avalible to the engines, and the output of the html page will be the fully renderd html page. You can also set up a snapshot creator - that way you can respond quickly than ever.

This will be the final life cycel of the application:

Image 2

Once IIS get's an incoming request, the Rewrite module decides:

    - If it's Facebook,Twitter,Bing or anything you will define - then the request will be transferd to PhantomJS windows service - and the fully rendered HTML will be the output.

    - Else the regular website behavior.

Make sure you define the rewrite as expected, do not redirect all HTTP call's to the PhantomJS, only the ones you need.


Download the code :

Setup and Settings :

Tested Envierment : Window Server 2012 R2 ,IIS 8.5

Step 1 - Install's :

1) Download and install Url-Rewite Module :

2) Download and install Application-Request-Routing :

Step 2 - Phantom Windows Service :

1) Download the git project.

2) Go to PhantomService.exe.config and open with notepad - config the following :

      a) PathToPhantom - local path to phantom.exe (from zip).

      b) PhantomScript - local path to phantom script (Components\phantomWS.js).

      c) PhantomLogLocation - phantom logging location

      d) PhantomPort - local port to listen

      e) LocalHost - you're local app host (usually http://yourdnsname).

      f) CreateSnapshots - enable snapshots (1/0).

      g) SanpshootLocation - location to save snapshots.

3) Open cmd and navigate to "C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319"

4) Run the following command : InstallUtil.exe "\path\to\phantom\service\PhantomService.exe" - give the installation an admin user.

5)  Before stating the windows service go to "%systemroot%\system32\drivers\etc\"

       open hosts file and add yourdnsname  as  - test inside the server that you can reach : 


6) Go to Run and open  services.msc, start the PhantomJSWS service then  you can test if phantom is running by browsing to http://localhost:selectedport/ - you should see the IIS welcome screen.


Step 3 - IIS Settings :

Application Request Routing Configuration :

1) Open inetmgr, go to the top level (sever level) and select Features View.

2) Select Application Request Routing Catch (should be the first one).

3) On the right side select Sever Proxy Settings.

4) Select checkbox - Enable proxy.

5) Save settings.

Url-Rewrite Configuration :

1) Open inetmgr, and select you're site or Application.

2) In Features View - select Url Rewrite

3) Add the following settings :




Image 4

Rewrite Model

URL: http://localhost:selectedphantomport/{URL}

This setting will rewrite the the request to the phantom windows service.

Test It: add to the url : ?escaped_fragment_= you should get the page yout requested

Exemple: http://yourdnsname/?escaped_fragment_=.


Step 4 - AngularJS Side :

1) Add the directive RenderFinishedDirective.js to you're site and include it to you're AngularApp.

2) In your'e index.html file -> add the directive at the bottom of the body element : 


Note:  you can avoid adding this directive by adding this code when your app finish rendering (after all promises end their job) :

if (typeof window.callPhantom == 'function') {


That's it - you're done.

Please feel free if you need any help,

Ben Mizrahi




This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Written By
Team Leader Item-Soft
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

GeneralMessage Closed Pin
18-Mar-21 1:59
pixelette technologies18-Mar-21 1:59 
QuestionRenderFinishedDirective.js Pin
mouli_1357912-Sep-17 20:24
mouli_1357912-Sep-17 20:24 
QuestionRenderFinishedDirective.js File not found Pin
Nagaraju Musini28-Feb-17 4:39
Nagaraju Musini28-Feb-17 4:39 
I am having issues in SEO, I am trying your solution, but I am unable to find
File anywhere, can you please update that file in download attachment.

Thank you.
Questionwell written Pin
krarch2-Nov-16 22:14
krarch2-Nov-16 22:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.