As you all know portal 7.3 has an ajax framework page which means that not the whole page is reloaded but only the contentarea div. So where do you have to place your google analytic code so that every time a user visits a page/iview the data is send to google?

That’s an easy question: you have to place it somewhere in the contentarea. So the easiest way is to create an iView with your google analytic code in it and to add that iview in every page. But what if you already have a lot of iViews or pages and you do not want to go to every page and add that iView? And in some cases you only have an iView so you have to add you existed iView in a new page and also add your google analytic iview to it => overkill.

Another solution is to download the contentarea war file from your server and change the code and then overwrite SAP code. But that solution I prefer not to use in this case.

So what I did was create an iView and add it to the Ajax framework page/ custom ajax framework page and thats it!
I listen to the event “navigate” and every time that happens the data is send to google. Which means this also works for Web Page Composer(WPC) pages.

First you need to create a portal application. After you deployed it to the server you create an iView of it and then add it to the framework page you use.

You can find the source code here. After unzippen it you have to import into youre NWDS(Import > General > File system).(Don’t forget to change the google analytics id in the iview properties as explained below)

See below for the steps in detail:

Prerequisites:

Create a Google Analytics account(https://www.google.com/analytics/web/provision?et=&authuser=#provision/SignUp/)

Portal Server should be able to access(telnet) to www.google-analytics.com(check this with your basis team)

1) create a portal application

/wp-content/uploads/2013/09/create_portalapp_263167.png/wp-content/uploads/2013/09/create_portalapp_2_263177.png

Click Next > Finish.

After the application project is created you have to create an portal application object.

Right click on the portal application project you just created. Follow the next steps:

/wp-content/uploads/2013/09/create_portalapp_3_263210.png

/wp-content/uploads/2013/09/create_portalapp_4_263211.png

/wp-content/uploads/2013/09/create_portalapp_5_263212.png/wp-content/uploads/2013/09/create_portalapp_6_263213.png/wp-content/uploads/2013/09/create_portalapp_7_263214.png

After clicking Finish the portal object will be created and the googleanalytics.java file will be open in your NWDS.
The only code will put in the doContent method of the AbstractPortalComponent is:

package flexso.com;
import com.sapportals.portal.prt.component.*;
import com.sapportals.portal.prt.resource.IResource;
public class googleanalytics extends AbstractPortalComponent
{
    public void doContent(IPortalComponentRequest request, IPortalComponentResponse response)
    {
              response.include(request, request.getResource(IResource.JSP,
        "jsp/analytics.jsp"));
    }
}

(Don’t forget to add the import statement “import com.sapportals.portal.prt.resource.IResource;”)

The above code will load the jsp file that we still need to create.(see next step)

Next step is to create the JSP file where the google analytic code will be placed.

So first drilldown to the folder jsp under dist > PORTAL-INF > jsp and right click.

/wp-content/uploads/2013/09/create_portalapp_8_263218.png

/wp-content/uploads/2013/09/create_portalapp_9_263222.png

/wp-content/uploads/2013/09/create_portalapp_10_263223.png

Attention: the name that you use here has to be the same as the one you used in the doContent method in the java file.

Click Finish to proceed.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import = "com.sapportals.portal.prt.component.IPortalComponentRequest" %>
<%@ page import = "com.sapportals.portal.prt.component.IPortalComponentResponse" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>analytics</title>
<!-- begin part 1 -->
<%
          String googleID = componentRequest.getComponentContext().getProfile().getProperty("googleanalytics.id");
%>
<!-- end part 1 -->
<script>
// begin part 4
function callbackGetNodeInfo(currentNode){
          (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.async=1;a.src=g;m.parentNode.insertBefore(a,m)
                    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
                    ga('create', '<%=googleID%>', 'flexso.com');
                    ga('set', 'title', currentNode.getTitle());
                    ga('set', 'location', currentNode.getNodeURI());
                    var loggindUser = LSAPI.AFPPlugin.configuration.getUser().FirstName +
                                                                      ", "          +
                                                                      LSAPI.AFPPlugin.configuration.getUser().LastName +
                                                                      " ("+
                                                                      LSAPI.AFPPlugin.configuration.getUser().LogonUid +
                                                                      ")";
                    ga('set', 'dimension1', loggindUser);
                    ga('send', 'pageview',{
                                'dimension1': loggindUser
                    });
}
// end part 4
// begin part 3
function navigationEventHandler(eventObj) {
   //eventObj.dataObject.target.split("?")[0] this will split the target at "?" and [0] will return the first part of target value which is the navurl
  if(typeof eventObj.dataObject.target === "string"){
        LSAPI.AFPPlugin.model.getNode(eventObj.dataObject.target.split("?")[0],callbackGetNodeInfo);
   }else 
        LSAPI.AFPPlugin.model.getFirstNode(callbackGetNodeInfo);
// end part 3
// begin part 2
EPCM.subscribeEvent("urn:com.sapportals:navigation", "Navigate", navigationEventHandler);//when you are navigate in the portal
EPCM.subscribeEvent("urn:com.sapportals.portal:browser","load", navigationEventHandler);//when you load the page
// end part 2
</script>
</head>
<body>
</body>
</html>

The JSP is divided in 4 parts:

Part 1: Is some java code to get the value of our google analytics id.(Which is provided by Google) This property will be maintenable through the iview property of the application. Which makes it easy when you transport the iview to acceptance or production you then only need to change the value of the property.

Part 2: Is the subscribeEvent method. With that piece of code you will run your EventHandler method every time the navigation event is triggered.

Part 3: Is the actual method that will be executed. In that method I use the getNode method of the LSAPI object. For more information about the LSAPI navigation method see the url: http://help.sap.com/saphelp_nw73/helpdata/en/c8/5eacdc37434cfb8ec5e5288b884100/frameset.htm

Part 4: Is the code that you get from google analytics. You only need to change the actual id with <%=googleID%> so it gets the value stored in the iview property. In this part I also added some additional information like user name , firstname and loginid which can be viewed in a custom report.(For more information check google analytics documentation) Attention: do not forget to change ‘flexso.com’. You can find the value that you have to put there in your google analytic piece of code that is generated by google.

The last part of the portal object is to add the property googleanalytics in the portalapp.xml.

Replace the part <component-profile/> with:

      <component-profile>
        <property name="googleanalytics.id" value="UA-XXXXX-Y">
          <property name="category" value="Google Analytics"/>
        </property>
      </component-profile>

Now the application is done and you need to deploy it to the server.

Once it deployed on the server the last step is to create an iview of it and add it to the ajax framework page you use.

Steps to follow:

Go to Content Administration > Portal Content Management > Portal Application.

/wp-content/uploads/2013/09/create_iview_from_portalapp_263304.png

Create an iview from the application by copying it to a folder in the Portal Content.

/wp-content/uploads/2013/09/create_iview_from_portalapp_2_263305.png

/wp-content/uploads/2013/09/create_iview_from_portalapp_3_263307.png

/wp-content/uploads/2013/09/create_iview_from_portalapp_4_263308.png

After you created the iview you must change the property “googleanalyticsid” in the property of the iview.

/wp-content/uploads/2013/09/create_iview_from_portalapp_5_263309.png

Click on the button “Modify Properties” and change the value with the id from google.

Do not forget to change the property “authentication scheme” to anonymous if you also want to track anonymous user on your portal.

Now you still need to add this iview to your framework page. If you use the SAP standard ajax framework page it is best to copy that page and change that one.

If you have a custom framework page just add this iview to it. If you don’t have a container for “technical/hidden iviews” make sur the iview has no tray or something visible. (Maybe you can set the height to 1px).

In this example I will add the iview to standard framework.

You can find the standard SAP Ajax Framework page under: Portal Content > Portal Users > Standard Portal Users > Ajax Framework Content.

/wp-content/uploads/2013/09/add_iview_to_frameworkpage_263314.png

Open the page and select youre google analytic iview and right click on it and select Add iview to page > Delta link.

/wp-content/uploads/2013/09/add_iview_to_frameworkpage_2_263315.png

The last step is to change the container where the iview will be placed.

/wp-content/uploads/2013/09/add_iview_to_frameworkpage_3_263316.png

Now save your changes and go to your google account do some tests.

PS: this is my first blog.

Enjoy!

To report this post you need to login first.

28 Comments

You must be Logged on to comment or reply to a post.

  1. Rambabu Kancharla

    Hi,

    I like this blog and tried to implement the same by following the steps mentioned in this blog. But, I found that the data is not sending to my Google account.

    I have created a google account and generated Google Analitics ID and used the same in the application code.

    I wuld be greatful to you, if you let me know what would I missed and where.

    Thank you,

    Rambabu

    (ramkancharla003@gmail.com)

    (0) 
    1. Fouad Hjiyer Post author

      Hi Rambabu,

      First I need to say that I posted an url to source code of my application but the javascript code in the jsp is not the same as the one posted in the blog. The one in the jsp code is outdated(Copy paste the one from the blog). I still need to change it, I will try to change it later on today.

      But to answer to your question it can be different things.

      The first thing to check is if the data is send to google. You can do that with fiddler. It’s a tool to trace your http request (http://fiddler2.com). Normally you should see google-analytics in there.

      If it’s not the case you need to check if you don’t have any javascript errors. That you can do by pressing F12 in your browser.(Chrome > tab console, IE > tab script)

      What you also need to check is the permission of the iview. Like I mentioned in the blog.

      I hope this helps if not just send me an email with your source code so I can check it.

      Good luck!

      Kind Regards,

      Fouad

      (0) 
  2. Rambabu Kancharla

    Hi Fouad,

    Would you please help me to resolve my issue?

    I tried all the options and no script errors, but the data is not sending to account.

    Regards,

    Rambabu

    (0) 
  3. SG Sg

    Hi Fouad,

    Thanks For Sharing 🙂 🙂 ,  I will Implement today and check it once this is really new Concept and you explained with screen shots makes me to develop on my own 😉 😉 , Thank u  once again for Sharing 🙂 🙂 🙂

    Regards,

    Giri

    (0) 
    1. Fouad Hjiyer Post author

      Hi Giri,

      Good luck!

      I added some prerequisites in the blog.

      Just for your information:

      The problem for Rambabu was that the server had no access to Google analytics.

      Kind Regards,

      Fouad

      (0) 
    1. Fouad Hjiyer Post author

      Hi Noël,

      Good question!

      I don’t think this will work because what a quicklink actually does is refreshing the whole page and go to the iView/page from that quicklink so it is not triggered by the doNavigate method.

      This can be a problem because this means that the data will be send to google through this code:

      1. EPCM.subscribeEvent(“urn:com.sapportals.portal:browser”,”load”, navigationEventHandler);//when you load the page

      Which means it will send the firstpage from your portal which is not correct.


      But you have different options to solve this:

      The first one is very easy and is to check if you’re accessing the portal with a quicklink or not. This can be done by checking the url path in your javascript code

      1. document.location.pathname if its equal to “/irj/portal” then no quicklink is used but I’m not 100% sure if this is right in every case. And also you will not have access to the title name of the page.

      Second option (note that we did this in a custom framework but should also work in the standard framework): What we did in a project of ours, we didn’t used quicklinks(because the refreshing of the page was annoying for the customer) but we created a mechanism through the window.onhashchange function. The benefit of this is that not the whole page is reloaded.

      So how did we do that:

      http://<host&gt;:<port>/irj/portal#Content Administrator/Portal Display

      So when a user cliks on a link that point to the above url the onhashchange function will be triggered from there we collect some data and pass it to the donavigate method which will then trigger our google analytics code.

      I hope this is an answer to your question and that you have enough information to implement it.

      Kind Regards,

      Fouad

      (0) 
      1. Noël Hendrikx

        Thanks for your solution! The link is still user friendly, that’s one of my main concerns of the navurl or navigationtarget=. But will your link work also from outside the portal? As an example, when the user bookmarks the Portal Display page as you mentioned, does analytics trigger this?

        Also can you send parameters to a portal page with the # tag? I think that will be a side effect, right?

        Fortunately I am writing my own framework, so I will add on every page a js link to analytics (just like in the old days 🙂 ).

        (0) 
        1. Fouad Hjiyer Post author

          Hi Noël,

          That’s right the quicklink is user friendly but the only problem for us was that the content editor didn’t had access to the pcd which means he couldn’t know which quicklinks existed. With the way we work he can just follow the navigation and create his own link to every page.(Off course he needs to be careful, the page he wants to point to needs to be in a role the user have. But that’s the same for quicklinks. And another disadvantage of my way of working is that the url has to be correctly the same so Content Administration > Portal Display has to be #Content Administration/Portal Display with spaces etc…)

          I’m not sure but I think we added some piece of code in our javascript to check if the window.location.hash is empty or not. We did it in this part of code:

          EPCM.subscribeEventReliable(‘urn:com.sapportals:navigation’, ‘AFPisLoaded’, onAfpIsLoaded);

          And if it exists then the doNavigate method is triggerd which means or google analytics code is triggered.

          So normally if a user has a bookmark to the Portal Display it should trigger the analytics code.

          Either way you did some good thinking!

          Kind Regards,

          Fouad

          (0) 
  4. Suseelan Hari

    Hi Fouad,

    Big Wow! I understand how much time you have spend for this blog.

    Keep up the good work! 🙂

    Advanced New Year 2014 Wishes! 🙂

    Regards,

    Hari Suseelan

    (0) 
  5. Vera Gutbrod

    Hi Fouad!

    Exceptional blog. You will be rewarded for this from the SAP Portal team. Wait for further announcements in the next days.

    Regards

    Vera

    SAP Portal Product Management Team

    (0) 
  6. Vincent Noiset

    Hello,

    we intended to use Google Analytics for page statistics.  But not all user have internet access…

    Did you try to get statistics (on iView, Page,…) with the SAP Standard service that is Activity Data Collector ?

    Best regards.

    Vincent

    (0) 
    1. Fouad Hjiyer Post author

      Hi Vincent,

      Yes we use it sometimes it depends on what the customer wants. If it’s only to show basic data you can use the standard reporting iViews from SAP.(You probably know that)

      But sometimes that is not enough so we write a custom(java) application that will read the tracefiles and do something with it. That application will run everyday and once its done it will archive the trace file so only the trace file of the current day will be treated. Most of the time we write the data from the trace file into a database and then a report is made of that data.(We also read kmActivity trace file, with this information you can see which a document has been read by a which user, or get statistics like top 10 documents,…)

      You know that when you activate the Activity Data Collector trace files will be created on the server I think the default path is /server{N}/portalActivity and /server{N}/kmActivity I don’t have access to a portal now so I’m not 100% sure and of course you can change the folder where the trace files will be saved.

      I hope this is an answer to your question. If not just let me know.

      Kind Regards,

      Fouad

      (0) 
  7. Joelle Wilson

    Fouad,

    Thank you for the great detail on implementing in 7.3!      I am wondering if you have information about adding Google Analytics to prior versions?  Specifically we are running 7.02 and would like to implement on our current system.

    Thank you,

    Joelle

    (0) 
    1. Fouad Hjiyer Post author

      Hi Sebastian,

      Sorry for the late response.

      I did not had the chance yet to work with a portal 7.4. But that’s something that you can easily check. If you open the console in the browser(F12) after accessing the url of the portal you can type EPCM and see if the object exists.

      If that is the case you can try to copy paste the following in the console.

      function navigationEventHandler(eventObj) { 

        alert(“navigation works as before”);

      }  

      EPCM.subscribeEvent(“urn:com.sapportals:navigation”, “Navigate”, navigationEventHandler);

      EPCM.subscribeEvent(“urn:com.sapportals.portal:browser”,”load”, navigationEventHandler);

      If it there is no error you can try to navigate in the portal and an alert should be shown.

      It is also possible that the EPCM object is not available and that you will need to put a breakpoint in a random js script from SAP where it is available.

      Hope this helps. Again I could not test this so it is possible that it does not work and then you should try to implement the whole solution as described in the blog.

      Kind Regards,

      Fouad

      (0) 
  8. NS Hussain

    Hi Fouad,

     

    Thanks for excellent blog!!

     

    I am getting compiler error in analytics.jsp

    Error message: componentRequest cannot be resolved.

     

    Thanks

    Maha

     

     

    (0) 

Leave a Reply