Author: jkoster
Date: 2010-07-15 11:59:30 +0200 (Thu, 15 Jul 2010)
New Revision: 42899

Added:
   CMSContainer/trunk/CMSContainer/migration/migration_1.8.3_to_1.8.4.txt
Modified:
   
CMSContainer/trunk/CMSContainer/cmsc/taglib/src/java/com/finalist/cmsc/taglib/stats/GoogleAnalyticsTag.java
   CMSContainer/trunk/CMSContainer/cmsc/taglib/src/tld/cmsc.tld
Log:
CMSC-1704 - Update Google Analytics code to latest version; use Asynchronous 
tracking. Also added force-attribute for testing.

Modified: 
CMSContainer/trunk/CMSContainer/cmsc/taglib/src/java/com/finalist/cmsc/taglib/stats/GoogleAnalyticsTag.java
===================================================================
--- 
CMSContainer/trunk/CMSContainer/cmsc/taglib/src/java/com/finalist/cmsc/taglib/stats/GoogleAnalyticsTag.java
 2010-07-15 09:37:14 UTC (rev 42898)
+++ 
CMSContainer/trunk/CMSContainer/cmsc/taglib/src/java/com/finalist/cmsc/taglib/stats/GoogleAnalyticsTag.java
 2010-07-15 09:59:30 UTC (rev 42899)
@@ -38,6 +38,7 @@
    private final static String TYPE_SCRIPT = "script"; // init script
    private final static String TYPE_PAGE_COUNTER = "pagecounter"; // page 
counter code
    private final static String TYPE_EVENT = "event"; // event code, category 
and action are required
+   private static boolean isLiveProduction;
 
    private String accountParameter;
    private String categoryParameter;
@@ -46,115 +47,136 @@
    private String labelParameter;
    private String valueParameter;
    private String typeParameter = TYPE_BASIC;
+   private boolean force; //testing purposes
+   
 
    private static String contextAccount;
    static {
       InitialContext context;
       try {
+         isLiveProduction = (ServerUtil.isProduction() && (ServerUtil.isLive() 
|| ServerUtil.isSingle()));
+         
          context = new InitialContext();
          Context env = (Context) context.lookup("java:comp/env");
          contextAccount = (String) env.lookup("googleAnalytics/account");
       } catch (NamingException e) {
-         log.info("No default account found in the context. Provide account 
information as attribute.");
+         log.info("No default Google Analytics account found in the context. 
Provide account information as attribute.");
       }
    }
 
    @Override
    public void doTag() throws IOException {
-
       /*
-       * Find out where to get our account from, search order: 
+       * Find out where to get the Google Analytics account from, search 
order: 
        * 1) The "account"-parameter passed to the tag (only when available, 
live and production) 
-       * 2) The "googleAnalytics/account" setting in the context XML (only 
when available, one of the two prefered methods) 
+       * 2) The "googleAnalytics/account" setting in the context XML (only 
when available, one of the two preferred methods) 
        * 3) The "googleanalytics.account" system property, from the system 
properties (only  when available, live and production)
-       * 4) The googleanaliticsId field of the site (only when available, the 
other prefered method)
+       * 4) The googleanalyticsId field of the site (only when available, the 
other preferred method)
        */
       String account = null;
-      boolean isLiveProduction = (ServerUtil.isProduction() && 
(ServerUtil.isLive() || ServerUtil.isSingle()));
+      
       String parameterAccount = 
PropertiesUtil.getProperty("googleanalytics.account");
       
-      if (StringUtils.isNotBlank(accountParameter) && isLiveProduction) {
+      if (force) {
+         if (ServerUtil.isProduction()) {
+            log.error("Google Analytics tag: the 'force' attribute should NOT 
be used in production environments!");
+         }
+      }
+      
+      if (StringUtils.isNotBlank(accountParameter) && (isLiveProduction || 
force)) {
          account = accountParameter;
       } else if (StringUtils.isNotBlank(contextAccount)) {
          account = contextAccount;
-      } else if (StringUtils.isNotBlank(parameterAccount) && isLiveProduction) 
{
+      } else if (StringUtils.isNotBlank(parameterAccount) && (isLiveProduction 
|| force)) {
          account = parameterAccount;
-      } else if (isLiveProduction) {
+      } else if (isLiveProduction || force) {
          Site site = SiteManagement.getSiteFromPath(getPath());
          account = site.getGoogleanalyticsid();
       }
 
-      // Include the google analytics code
+      // Include the Google Analytics code
       if (StringUtils.isNotBlank(account)) {
+         
+         PageContext ctx = (PageContext) getJspContext();
+         final String domain = ctx.getRequest().getServerName();
 
          StringBuilder javascript = new StringBuilder();
          if (typeParameter.equals(TYPE_BASIC)) {
+            appendPageCounter(javascript, account, domain);
             appendGAScript(javascript);
-            appendPageCounter(javascript, account);
          }
          if (typeParameter.equals(TYPE_SCRIPT)) {
             appendGAScript(javascript);
          }
          if (typeParameter.equals(TYPE_PAGE_COUNTER)) {
-            appendPageCounter(javascript, account);
+            appendPageCounter(javascript, account, domain);
          }
 
-         
          if (typeParameter.equals(TYPE_EVENT)) {
-            javascript.append("<script type=\"text/javascript\">");
-            if (StringUtils.isNotBlank(nodeNumberParameter)) {
-               actionParameter = getActionFromNodeNumber(nodeNumberParameter);
-            }
-
-            if (StringUtils.isBlank(categoryParameter)
-                  || StringUtils.isBlank(actionParameter)) {
-               throw new IllegalArgumentException(
-                     "Both category and (action or nodeNumber) parameters are 
required when using type "
-                           + TYPE_EVENT);
-            }
-            javascript.append("pageTracker._trackEvent('");
-            javascript.append(escapeParameter(categoryParameter));
-            javascript.append("','");
-            javascript.append(escapeParameter(actionParameter));
-            if (StringUtils.isNotBlank(labelParameter)) {
-               javascript.append("','");
-               javascript.append(escapeParameter(labelParameter));
-               if (StringUtils.isNotBlank(valueParameter)) {
-                  javascript.append("','");
-                  javascript.append(valueParameter);
-               }
-            }
-            javascript.append("');\r\n");
-            javascript.append("</script>\r\n");
+            appendTrackEvents(javascript);
          }
-
-         PageContext ctx = (PageContext) getJspContext();
+         
          ctx.getOut().write(javascript.toString());
       }
    }
 
    private void appendGAScript(StringBuilder javascript) {
-      javascript.append("<script type=\"text/javascript\">\r\n");
-      javascript.append("var gaJsHost = ((\"https:\" == 
document.location.protocol) ? \"https://ssl.\"; : \"http://www.\";);\r\n");
-      javascript.append("document.write(unescape(\"%3Cscript src='\" + 
gaJsHost + \"google-analytics.com/ga.js' 
type='text/javascript'%3E%3C/script%3E\"));\r\n");
+      if (! typeParameter.equals(TYPE_BASIC)) {
+         javascript.append("<script type=\"text/javascript\">\r\n");
+      }
+      javascript.append("try{\r\n" +
+            " (function() {\r\n" + 
+               "    var ga = document.createElement('script'); ga.type = 
'text/javascript'; ga.async = true;\r\n" + 
+               "    ga.src = ('https:' == document.location.protocol ? 
'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\r\n" + 
+               "    var s = document.getElementsByTagName('script')[0]; 
s.parentNode.insertBefore(ga, s);\r\n" + 
+               "  })();\r\n" +
+            "} catch(err) {}\r\n");
       javascript.append("</script>\r\n");
    }
 
-   private void appendPageCounter(StringBuilder javascript, String account) {
-      PageContext ctx = (PageContext) getJspContext();
-      String domain = ctx.getRequest().getServerName();
+   private void appendPageCounter(StringBuilder javascript, final String 
account, final String domain) {
+      javascript.append("<script type=\"text/javascript\">\r\n");
       
-      javascript.append("<script type=\"text/javascript\">\r\n");
-      javascript.append("try{\r\n");
-      javascript.append("var pageTracker = 
_gat._getTracker(\"").append(account).append("\");\r\n");
       // Workaround for http://support.microsoft.com/kb/310676
-      // Internet Explorer does not set a cookie for two-letter domains like 
12.nl
-      
javascript.append("pageTracker._setDomainName(\"").append(domain).append("\");\r\n");
-      javascript.append("pageTracker._trackPageview();\r\n");
-      javascript.append("} catch(err) {}\r\n");
+      // Internet Explorer 6 does not set a cookie for two-letter domains like 
12.nl
+      
+      javascript.append("var _gaq = _gaq || [];\r\n" +
+                        "_gaq.push(['_setAccount', 
'").append(account).append("'],\r\n" +
+                        "          ['_setDomainName', 
'").append(domain).append("'],\r\n" +
+                           "          ['_trackPageview']);\r\n");
+      if (! typeParameter.equals(TYPE_BASIC)) {
+         javascript.append("</script>\r\n");
+      }
+   }
+   
+   private void appendTrackEvents(StringBuilder javascript) {
+      javascript.append("<script type=\"text/javascript\">");
+      if (StringUtils.isNotBlank(nodeNumberParameter)) {
+         actionParameter = getActionFromNodeNumber(nodeNumberParameter);
+      }
+
+      if (StringUtils.isBlank(categoryParameter)
+            || StringUtils.isBlank(actionParameter)) {
+         throw new IllegalArgumentException(
+               "Both category and (action or nodeNumber) parameters are 
required when using type "
+                     + TYPE_EVENT);
+      }
+      javascript.append("_gaq.push(['_trackEvent', '");
+      javascript.append(escapeParameter(categoryParameter));
+      javascript.append("', '");
+      javascript.append(escapeParameter(actionParameter)+"'");
+      if (StringUtils.isNotBlank(labelParameter)) {
+         javascript.append(", '");
+         javascript.append(escapeParameter(labelParameter) + "'");
+         if (StringUtils.isNotBlank(valueParameter)) {
+            javascript.append(", " + valueParameter);
+         }
+      }
+      javascript.append("]);\r\n");
       javascript.append("</script>\r\n");
    }
 
+
    private String escapeParameter(String parameter) {
       return parameter.replace("'", "\\'");
    }
@@ -199,7 +221,7 @@
       } else {
          throw new IllegalArgumentException(
                "type parameter should be empty, \"" + TYPE_BASIC
-                     + "\", \"" + TYPE_EVENT + "\"");
+                     + "\", or \"" + TYPE_EVENT + "\"");
       }
    }
 
@@ -222,5 +244,32 @@
    public void setValue(String valueParameter) {
       this.valueParameter = valueParameter;
    }
+   
+   public void setForce(boolean force) {
+      this.force = force;
+   }
 
+   public boolean isForce() {
+      return force;
+   }
+   
+   /* For testing purposes only
+   public static void main(String args[]) {
+      GoogleAnalyticsTag gat = new GoogleAnalyticsTag();
+      GoogleAnalyticsTag.contextAccount = "UA-17606XX-1";
+      
+      StringBuilder javascript = new StringBuilder();
+      String domain = "www.cmscontainer.org";
+      gat.categoryParameter ="content";
+      gat.actionParameter = "action";
+      
+      gat.appendPageCounter(javascript,contextAccount,domain);
+      gat.appendGAScript(javascript);
+      
+      gat.appendTrackEvents(javascript);
+      
+      System.out.println(javascript.toString());
+   }
+   */
+
 }

Modified: CMSContainer/trunk/CMSContainer/cmsc/taglib/src/tld/cmsc.tld
===================================================================
--- CMSContainer/trunk/CMSContainer/cmsc/taglib/src/tld/cmsc.tld        
2010-07-15 09:37:14 UTC (rev 42898)
+++ CMSContainer/trunk/CMSContainer/cmsc/taglib/src/tld/cmsc.tld        
2010-07-15 09:59:30 UTC (rev 42899)
@@ -1562,10 +1562,10 @@
         Meant to put in the body of a page, please note that if you want to 
use events, 
         there has to be a normal tag first. 
         Search order of the google analytics account used:
-       * 1) The "account"-parameter passed to the tag (only when available, 
live and production) 
-       * 2) The "googleAnalytics/account" setting in the context XML (only 
when available, one of the two prefered methods) 
-       * 3) The "googleanalytics.account" system property, from the system 
properties (only  when available, live and production)
-       * 4) The googleanaliticsId field of the site (only when available, the 
other prefered method)
+        * 1) The "account"-parameter passed to the tag (only when available, 
live and production) 
+        * 2) The "googleAnalytics/account" setting in the context XML (only 
when available, one of the two preferred methods) 
+        * 3) The "googleanalytics.account" system property, from the system 
properties (only  when available, live and production)
+        * 4) The googleanalyticsId field of the site (only when available, the 
other preferred method)
         </description>
         <name>google-analytics</name>
         
<tag-class>com.finalist.cmsc.taglib.stats.GoogleAnalyticsTag</tag-class>
@@ -1614,6 +1614,12 @@
             <required>false</required>
             <rtexprvalue>true</rtexprvalue>
         </attribute>
+        <attribute>
+            <description>Forces output for testing purposes, while not in 
production and not live.</description>
+            <name>force</name>
+            <required>false</required>
+            <rtexprvalue>false</rtexprvalue>
+        </attribute>
     </tag>
 
     <!-- ################ -->

Added: CMSContainer/trunk/CMSContainer/migration/migration_1.8.3_to_1.8.4.txt
===================================================================
--- CMSContainer/trunk/CMSContainer/migration/migration_1.8.3_to_1.8.4.txt      
                        (rev 0)
+++ CMSContainer/trunk/CMSContainer/migration/migration_1.8.3_to_1.8.4.txt      
2010-07-15 09:59:30 UTC (rev 42899)
@@ -0,0 +1,25 @@
+Migration document:
+
+Part: core
+From version: 1.8.3
+To version: 1.8.4
+
+Name: Upgrade to use the new Google Analytics tag.
+Goal: upgrade tag usage location
+Type:  manual action
+--- Start script ---
+Note: the new Google Analytics tag uses the Asynchronous Snippet. 
+http://code.google.com/apis/analytics/docs/tracking/asyncTracking.html
+Therefore, the normal usage of the tag needs to be started in the <head> 
instead 
+of in the body!
+
+Action
+- search for google-analytics in all client JSPs (layouts) and move the tag 
location to inside the head.
+
+New
+- the attribute 'force' is added for testing purposes. Usage: force="true".
+
+--- End script ---
+
+
+

_______________________________________________
Cvs mailing list
Cvs@lists.mmbase.org
http://lists.mmbase.org/mailman/listinfo/cvs

Reply via email to