Showing posts with label Google Analytics. Show all posts
Showing posts with label Google Analytics. Show all posts

Tuesday, June 26, 2018

PeopleTools - Opt-out option for Google Analytics

With GDPR taking effect on May 25th 2018, an "opt-out" option for tracking cookies is a prevalent topic in many forums. This post is not intended to provide guidance for GDPR compliance. FWIW, before implementing anything at the PeopleTools layer, we must first consider the privacy policy implications at a much broader organizational level.

That said, I have written several posts on how to implement Google Analytics in PeopleTools. The most recent approach uses gtag.js.
PeopleTools - Using Google Analytics (gtag.js)

This post describes a proof of concept to extend the gtag.js implementation to provide a simple "opt-out" feature for end users using client side code (javascript).

Demo

In the following video, we can see that the user selects the "opt-out" option and the custom opt-out cookie is created. Any subsequent requests will not be tracked in Google Analytics.


Google Analytics Real-Time Data


In the following video, we can see that the user dismisses the "opt-out" option and the custom opt-out cookie is not created. Any subsequent requests will continue to be tracked in Google Analytics.


Google Analytics Real-Time Data


Script for reference

Notes

- This version of javascript, identifies the existence of Google Analytics related cookies to check if the session is new.
- If the session is new, a popup message is displayed to the end user. The message also provides a link to "opt-out" of Google Analytics. For the purposes of this demo, I used the delivered ptSetConfirmationMessage and ptCloseConfirmation javascript functions (which are part of PT_UTIL_BASIC HTML object) to display this message.
- If the user chooses to "opt-out" of Google Analytics, the following window property is set to true.
window['ga-disable-UA-XXXXXX-Y'] = true;
- Additionally, a custom cookie (ga-disable-UA-XXXXXXXX-Y) is created to identify this choice for subsequent requests.
- This cookie preference/choice will persist as long as this custom cookie is present.

This proof of concept is only intended to provide implementation ideas. You will most certainly need to tweak this code based on your organization's privacy policy.

Useful Resources

https://developers.google.com/analytics/devguides/collection/analyticsjs/user-opt-out
https://developers.google.com/analytics/devguides/collection/gajs/
https://www.robert-matthees.de/datenschutz-cookies/

Related Posts

Implementing Google Analytics in PeopleTools using gtag.js
Implementing Google Analytics in PeopleTools using analytics.js
Implementing Google Analytics in PeopleTools using ga.js

Thursday, May 3, 2018

PeopleTools - Using Google Analytics (gtag.js)

In the past I have written about implementing Google Analytics in PeopleSoft.

Using analytics.js
Using ga.js

If we look at the latest script provided by Google Analytics, it uses the new JavaScript tagging framework gtag.js. This framework allows us to send event data to different products (Analytics, AdWords, DoubleClick, etc.) without managing them separately.

More on gtag.js: https://developers.google.com/gtagjs/
Global Tracking Code Snippet: https://developers.google.com/analytics/devguides/collection/gtagjs/

If we want to implement Google Analytics in PeopleTools using this latest framework, we cannot simply take the sample code provided by Google and include it in a HTML object in PeopleTools. If you notice, even in my previous Google Analytics posts, I modified the sample code to make it PeopleTools friendly. This is because the script tags within the sample code (which involves loading an external script) will cause issues with PeopleTools when created as a JavaScript (HTML) object.

So, we need a way to first load the gtag.js (external) script and then execute the subsequent code provided in the sample. Here is a good example of how we can load an external script using javascript.
https://www.nczonline.net/blog/2009/07/28/the-best-way-to-load-external-javascript/

Using this approach, I re-wrote the Google Analytics javascript sample as follows. The loadScript function is very similar to the cskLoadJS function in my JavaScript Injection Framework - CSK_FL_BOOTSTRAP_JS.

Script for reference

Note: You will need to find and replace UA-XXXXXXXX-Y with your GA_TRACKING_ID.

CSK_ANALYTICS_JS JavaScript (HTML) Object


Next we need to find a way to inject this javascript within all PeopleSoft pages. A simple approach would be to add a line of code at the end of a global delivered javascript such as PT_COMMON or PT_UTIL. For example:


Alternatively, we could use a JavaScript Injection Framework as described here:
https://pe0ples0ft.blogspot.com/p/javascript-injection-framework.html

Regardless of whether we use analytics.js or gtag.js, when we setup the Google site configuration, we should only include the hostname in the default URL.

E.g.: If this is our login URL
http://pi023.hcm92.com:8000/psp/ps/EMPLOYEE/HRMS/?cmd=login

The Default URL should be configured as follows:


Tuesday, November 22, 2016

Piwik: Open-Source Web Analytics Platform

While presenting at Oracle OpenWorld 2016, I demonstrated the integration of Google Analytics (GA) with PeopleSoft Applications for generating usage metrics. One of the big reasons that many find GA an attractive option aside from its superior features, is the fact that it is free. Of course, there are some limits to the term 'free'. After my presentation, I had an informative conversation with Greg Kelly from Oracle, who pointed out that just because a product is free, it does not necessarily mean it is the right solution for everyone. Greg also mentioned Piwik (hat tip), which is one of the most popular open-source web analytics platform and has an unique selling proposition of 100% data ownership.

In my personal opinion, Google Analytics is far more superior when it comes to functionality and features but I am aware that not everyone would be able to leverage Google Analytics due to various reasons (primarily data ownership). That said, Piwik is a great alternative for such customers to create a locally or cloud hosted web analytics platform which provides full control of their data. I am stating the obvious but Piwik does come with the cost of setting up and maintaining the infrastructure to host it somewhere.

Here are some resources that I found interesting and relevant to this topic (there may be many more out there):
https://zenincognito.com/piwik-vs-google-analytics-a-detailed-review/
https://piwik.pro/2016/05/infographic-piwik-vs-google-analytics/
http://www.kaushik.net/avinash/how-to-choose-a-web-analytics-tool-a-radical-alternative/

Here is my recent blog on how to integrate Google Analytics with PeopleSoft Applications:
https://pe0ples0ft.blogspot.com/2016/09/peopletools-using-ga-analytics-js.html

Here are the steps that I followed to setup and integrate Piwik with a PeopleSoft instance (HCM 9.2 PUM 17 - PeopleTools 8.55.06).

Step 1: Download and install Piwik

Resource: http://piwik.org/docs/installation/

In my cases, I downloaded Piwik from the Microsoft Windows Web App Gallery.
http://piwik.org/blog/2013/02/piwik-microsoft-windows-web-app-gallery/

Then, I followed the installation wizard to install Piwik on my Windows 7 desktop computer where my PUM image is also running.

Some gotchas for Windows installation based on my experience.

Windows Firewall Inbound Rules:

I had to punch a hole in the Windows Firewall and set up an inbound rule to allow requests on a port of choice.

Windows Firewall > Advanced Settings > Inbound Rules


IISExpress - Site Binding Configuration (applicationhost.cfg):

I also had to add site bindings to the IISExpress applicationhost.cfg to handle URL binding failures.
https://www.iis.net/learn/extensions/using-iis-express/handling-url-binding-failures-in-iis-express


Add trusted hosts to Piwik config.ini.php:

Finally, I had to add my localhost ip+port combination to the config.ini.php file as a trusted host.

WebMatrix > Piwik > config > environment > config.ini.php > trusted_hosts


Step 2: Login to the Piwik Admin Console and add a new site

Reference: http://piwik.org/docs/manage-websites/

Step 3: Obtain Piwik Tracking Code JavaScript snippet

Piwik > Administration > Websites > Manage Websites > View Tracking Code

You will find code similar to the following screenshot:


Next, I created a Branding Object in PeopleTools with the preceding javascript:

Navigation: PeopleTools > Portal > Branding > Branding Objects


Note: I only used the code snippet inside the script tag and also commented out the noscript portion for this proof of concept.

Step 4: Inject custom javascript in PeopleSoft

This part is similar to the Google Analytics javascript injection. To inject this custom javascript object across the PeopleSoft application, I used a custom framework for Global JS Injection. Details are in the following link:
Global JavasScript Injection Framework


Note: You don't have to use the same Global JS Injection Framework. You could use any other technique that might work best for your environment. The idea is to make sure the javascript is executed on every single page across the PeopleSoft application to send the usage metrics to the Piwik server.

Results:

Here is a screenshot of the Piwik Dashboard.


Wednesday, September 14, 2016

PeopleTools - Using Google Analytics (analytics.js)

In one of my branding posts, I described how we could inject the Google Analytics javascript (ga.js) code snippet using the Branding Framework.

As most of you know, the latest version of Google Analytics library is analytics.js.
https://developers.google.com/analytics/devguides/collection/upgrade/reference/gajs-analyticsjs

To start using analytics.js, all we have to do is update our custom Google Analytics injection code.

Here are the steps to migrate/implement analytics.js.

Development Environment: HCM 9.2 PUM Image 17 - PeopleTools 8.55.03

Create a custom javascript object with analytics.js code snippet:

Make sure you substitute your property id on line 6.


Inject custom javascript object to the application globally:

In my case, I am using a custom Global JS Injection Framework that I described previously (refer: post 1 and post 2). You are free to use other options that might work best for you.

At a high level, PT_UTIL ---includes--- CSK_FL_BOOTSTRAP_JS ---includes--- CSK_INJECT_JS. CSK_INJECT_JS is where we can list all the javascript objects that we want to load (globally or targeting specific conditions).

Here are jsfiddle links to the versions of CSK_FL_BOOTSTRAP_JS and CSK_INJECT_JS at the time of writing.

Results:


Wednesday, December 31, 2014

PeopleTools 8.54 - Branding - Part 3

This post is a continuation of my previous articles on Branding PeopleTools 8.54 applications.

Part 1 detailed the basics of what's new with Branding in PeopleTools 8.54 and provided steps to change the logo of the application. Part 2 detailed steps to achieve several common branding requirements such as changing the background color of the branding header, changing the background color and the font color of the Navigation Drop-Down Menu, changing the font color of the Branding System Links, adding a hyperlink to the Branding Logo, moving branding elements (div) using css and adding database name to the Branding Header. We were able to perform all these tasks simply by using the online configuration pages for Branding provided as part of PeopleTools 8.54.

In this post we will dive into some of the more advanced Branding requirements that may potentially require the use of Application Designer.

Branding the Timeout Popup Warning Message:




What is this popup and where is it coming from? This popup message is the PeopleSoft delivered Timeout Warning Message that is displayed to warn the user of an impending timeout of their session (due to inactivity).

If we examine the URL of this Popup message we can see that it is generated by an IScript.

http://pt854.hcm92.com:8000/psc/ps/EMPLOYEE/HRMS/s/WEBLIB_TIMEOUT.PT_TIMEOUTWARNING.FieldFormula.IScript_TIMEOUTWARNING

This IScript is configured on the web profile which is currently being used by the web server.

PeopleTools > Web Profile > Web Profile Configuration (Security Tab)



In the screenshot above, we can see the configuration that triggers this popup message. A handy tip while testing changes to the timeout warning is to change the "Inactivity Warning" seconds to a shorter period like 120 or 180 seconds. This helps in triggering the popup without having to wait for extended periods of time (Note: Any changes to the web profile requires a reboot of the web server to take effect).

As this popup is generated through an IScript, I don't see a way we can override the Oracle Logo on the popup by overriding the stylesheet or by using other Branding Configuration.

There are two ways we can go about this customization:
1. Create a custom IScript that is a clone of the delivered IScript and then perform all customizations in the custom IScript. This option requires us to update the Web Profile to Override the Timout Warning Script to reference our custom IScript.
2. Simply customize the delivered IScript.

For the purposes of this post, I would be customizing the delivered IScript (second option) because I just want to replace the Oracle Logo with my custom logo.

- Update Timeout Warning IScript:

Open IScript Record PeopleCode using App Designer.



Change the reference to the Oracle Logo (Image.NEW_PS_LOGO) to use Custom Logo.

Customized Timout Warning IScript Code:

Declare Function SetDocDomainForPortal PeopleCode FUNCLIB_PORTAL.TEMPLATE_FUNC FieldFormula;
Declare Function PTGetStyleSheetURL PeopleCode FUNCLIB_PORTAL.PORTAL_GEN_FUNC FieldFormula;

Function IScript_TIMEOUTWARNING()
   &howLong = %Request.Timeout * 1000 - %Request.WarningTimeout * 1000 - 2000;
   &timeoutWarningMsg = MsgGetText(146, 91, "Your session is about to be timed out. As a security precaution, sessions end after ");
   &timeoutWarningMsg = &timeoutWarningMsg | " " | Integer(%Request.Timeout / 60) | " " | MsgGetText(146, 92, "minutes of inactivity. Click OK to continue your current session.");
   
   &domainScript = SetDocDomainForPortal();
   
   /* CSK - Timeout Warning Logo Customization - Start */
   
   rem commenting delivered code &HTML = GetHTMLText(HTML.PT_TIMEOUTWARNING, PTGetStyleSheetURL(), %Response.GetJavaScriptURL(HTML.PT_SAVEWARNINGSCRIPT), &howLong, %Response.GetImageURL(Image.NEW_PS_LOGO), &timeoutWarningMsg, %Request.ResetTimeoutURL, %Response.GetImageURL(Image.PT_OK), MsgGetText(146, 95, "Please - note"), &domainScript);
   &HTML = GetHTMLText(HTML.PT_TIMEOUTWARNING, PTGetStyleSheetURL(), %Response.GetJavaScriptURL(HTML.PT_SAVEWARNINGSCRIPT), &howLong, %Response.GetImageURL(Image.CSK_LOGO), &timeoutWarningMsg, %Request.ResetTimeoutURL, %Response.GetImageURL(Image.PT_OK), MsgGetText(146, 95, "Please - note"), &domainScript);
   
   /* CSK - Timeout Warning Logo Customization - End */
   
   %Response.Write(&HTML);
End-Function;

Notice that I commented the delivered line and replaced it with a custom line which references the custom logo image (Image.CSK_LOGO).

- Test Changes:



Display Dynamic and User Specific Greeting Message using Custom Branding Elements:


In this section we will examine how we can replace the delivered ptgreetingmessage Branding Element with a custom Branding Element.



We can see from the screenshot that the ptgreetingmessage element is using the Branding Element Type of Greeting Message.

The Branding Element Type Configuration can be found in the following navigation:

PeopleTools > Portal > Branding > System Data > Define Element Types



We can see that the delivered Greeting Message is being generated by the Application Class PTBR_BRANDING.SystemElements.GreetingText (review class implementation in App Designer to understand how the greeting message is generated).

Before we can go ahead and add a custom element (using a custom element type) to the Branding Header, we must create the custom branding element type and also develop the application class that supports this element type.

- Create Supporting Application Class for Custom Branding Element Type:

Create Custom Application Package.



Create Custom Application Class.

Note: The custom Application Class CSKGreetingText is cloned and improvised from PTBR_BRANDING.SystemElements.GreetingText.

import PTBR_BRANDING:Elements:BaseElement;

/**
  * CSKGreetingText Class
  */
class CSKGreetingText extends PTBR_BRANDING:Elements:BaseElement
   /* --- Properties --- */
   
   /* --- Methods --- */
   method CSKGreetingText(&pId As string);
   method clone() Returns PTBR_BRANDING:Elements:BaseElement;
   
   method getHTML(&pPreview As boolean) Returns string;
  
end-class;

/**
  * Constructor
  *
  * @param pId ID of the object.
  *
  */
method CSKGreetingText
   /+ &pId as String +/
   
   %Super = create PTBR_BRANDING:Elements:BaseElement(&pId);
   
   %This.setElementType("CSKGreetingText");
   rem %this.setAdvancedOptionsPage (Page.);
   
   /* Initialize attributes */
   %This.StyleClass = "cskgreeting";
   
end-method;

/**
  * Make an exact copy of this object.
  * NOTE: Only create the object here, do not copy any class properties.
  *       If there are new class properties, override the copyProperties
  *       method and do it there.  Should invoke the %Super.copyProperties
  *       in that method though.
  *
  * @return BaseElement New object exactly matching this object.
  *
  */
method clone
   /+ Returns PTBR_BRANDING:Elements:BaseElement +/
   /+ Extends/implements PTBR_BRANDING:Elements:BaseElement.clone +/
   
   Local CSK_BRANDING:SystemElements:CSKGreetingText &newObj = create CSK_BRANDING:SystemElements:CSKGreetingText(%This.ID);
   
   /* Call the copy properties function */
   %This.copyProperties(&newObj);
   
   Return &newObj;
   
end-method;


/**
  * Get HTML of the element
  *
  * @param pPreview  True - preview mode.
  *
  * @return String - HTML
  *
  */
method getHTML
   /+ &pPreview as Boolean +/
   /+ Returns String +/
   /+ Extends/implements PTBR_BRANDING:Elements:BaseElement.getHTML +/
   
   Local string &getHTML = "";
   
   Local ApiObject &portalObj;
   
   If (&pPreview) Then
      &getHTML = EscapeHTML(MsgGetText(25000, 3, "<message not found> Sample Greeting Text"));
   Else
      
      <* Commenting Delivered Greeting
      &portalObj = %This.Utility.PortalRegistry;
      If (All(&portalObj)) Then
         &getHTML = EscapeHTML(&portalObj.Homepage.Greeting);
      End-If;
      *>
      
      &getHTML = EscapeHTML("Welcome to CSK " | %UserDescription);
      
   End-If;
   
   &getHTML = GetHTMLText(HTML.PTBR_ELM_CONTAINER_SPAN, EscapeHTML(%This.ID), EscapeHTML(%This.StyleClass), &getHTML);
   
   Return &getHTML;
   
end-method;

In the custom PeopleCode above, we have added logic to generate a dynamic and personalized greeting message that displays the text "Welcome to CSK " appended with the User's Description text using the %UserDescription system variable. Note: The type of greeting could vary significantly from organization to organization and this can be addressed appropriately in the getHTML method implementation.

- Create Custom Branding Element Type:

PeopleTools > Portal > Branding > System Data > Define Element Types



We can see in the screenshot that we are referencing our custom CSKGreetingText Application Class in the new Element Type (CSK_GREETING_TEXT).

- Create custom style for Custom Greeting Message:



#pthdr2container.pthdr2container #cskgreetingmessage.cskgreeting {
    position: absolute;
    right: 0;
    bottom: 0;
    color: #426a92;
    font-family: Arial,Helvetica,sans-serif;
    font-size: 12pt;
    font-weight: normal;
}

- Delete delivered ptgreetingmessage element from the Branding Header:



- Add custom greeting element to the Branding Header:





- Test Changes:

Recommendations if you are experiencing caching issues:
  1. Clear local browser cache.
  2. Shutdown, purge cache and reboot the web server(s).








We can see in the screenshot that some of the links on the Branding Header such as MultiChannel Console are not specifically useful for a majority of the users. Links such as Process Monitor and Report Monitor would be a lot more useful on the Branding Header (this requirement is well documented in the PeopleSoft Wiki blog post).

Let us see how we can remove the 'MultiChannel Console' link and add links to Process Monitor and Report Monitor on the header in PeopleTools 8.54.

- Create Custom Supporting Application Classes for Process Monitor and Report Monitor:



Application Class Implementation for Process Monitor: 

Note: This Application Class was cloned and improvised from PTBR_BRANDING.SystemElements.WorklistLink Application Class.

import PT_BRANDING:HeaderLinkPIA;

import PTBR_BRANDING:Elements:BaseElement;
import PTBR_BRANDING:SystemElements:SystemLink;
import PTBR_BRANDING:UTILITY:Utility;

/**
  * ProcessMonitorLink Class
  */
class ProcessMonitorLink extends PTBR_BRANDING:SystemElements:SystemLink
   /* --- Properties --- */
   
   /* --- Methods --- */
   method ProcessMonitorLink(&pId As string);
   method clone() Returns PTBR_BRANDING:Elements:BaseElement;
   
protected
   /* --- Protected properties --- */
   
   /* --- Protected Methods --- */
   method setupLink(&pPreview As boolean);
   
private
   /* --- Private Properties --- */
   Constant &cstCTIConsole = "PopupCTIConsole();";
   Constant &cstMCFConsole = "PopupMCFConsole();";
   
   /* --- Private Methods --- */
   
end-class;

/**
  * Constructor
  *
  * @param pId ID of the object.
  *
  */
method ProcessMonitorLink
   /+ &pId as String +/
   
   %Super = create PTBR_BRANDING:SystemElements:SystemLink(&pId);
   
   %This.setElementType("ProcessMonitorLink");
   rem %this.setAdvancedOptionsPage (Page.);
   
   /* Initialize attributes */
   %This.Label.setMessageText(25000, 1, "Process Monitor");
   
end-method;

/**
  * Make an exact copy of this object.
  * NOTE: Only create the object here, do not copy any class properties.
  *       If there are new class properties, override the copyProperties
  *       method and do it there.  Should invoke the %Super.copyProperties
  *       in that method though.
  *
  * @return BaseElement New object exactly matching this object.
  *
  */
method clone
   /+ Returns PTBR_BRANDING:Elements:BaseElement +/
   /+ Extends/implements PTBR_BRANDING:SystemElements:SystemLink.clone +/
   
   Local CSK_BRANDING:SystemElements:ProcessMonitorLink &newObj = create CSK_BRANDING:SystemElements:ProcessMonitorLink(%This.ID);
   
   /* Call the copy properties function */
   %This.copyProperties(&newObj);
   
   Return &newObj;
   
end-method;

/*****************************
*   Protected methods
*****************************/

/**
  * Setup the link properties
  *
  */
method setupLink
   /+ &pPreview as Boolean +/
   
   Local ApiObject &crefObj;
   
   Local PTBR_BRANDING:UTILITY:Utility &utility = %This.Utility;
   
   Local string &linkUrl = "";
   
   If (&pPreview) Then
      %Super.setupLink(&pPreview);
   Else
      
      &crefObj = &utility.PortalRegistry.FindCRefByName("PT_PROCESSMONITOR_GBL");
      
      If (All(&crefObj) And
            &crefObj.Authorized And
            &crefObj.IsVisible) Then
         
         If ((&utility.HeaderLink As PT_BRANDING:HeaderLinkPIA) <> Null) Then
            &linkUrl = &crefObj.AbsolutePortalURL;
         Else
            &linkUrl = &crefObj.RelativeURL;
         End-If;
         
         %This.URL = &linkUrl;
         
      End-If;
      
   End-If;
   
end-method;

Application Class Implementation for Report Manager:

import PT_BRANDING:HeaderLinkPIA;

import PTBR_BRANDING:Elements:BaseElement;
import PTBR_BRANDING:SystemElements:SystemLink;
import PTBR_BRANDING:UTILITY:Utility;

/**
  * ReportManagerLink Class
  */
class ReportManagerLink extends PTBR_BRANDING:SystemElements:SystemLink
   /* --- Properties --- */
   
   /* --- Methods --- */
   method ReportManagerLink(&pId As string);
   method clone() Returns PTBR_BRANDING:Elements:BaseElement;
   
protected
   /* --- Protected properties --- */
   
   /* --- Protected Methods --- */
   method setupLink(&pPreview As boolean);
   
private
   /* --- Private Properties --- */
   Constant &cstCTIConsole = "PopupCTIConsole();";
   Constant &cstMCFConsole = "PopupMCFConsole();";
   
   /* --- Private Methods --- */
   
end-class;

/**
  * Constructor
  *
  * @param pId ID of the object.
  *
  */
method ReportManagerLink
   /+ &pId as String +/
   
   %Super = create PTBR_BRANDING:SystemElements:SystemLink(&pId);
   
   %This.setElementType("ReportManagerLink");
   rem %this.setAdvancedOptionsPage (Page.);
   
   /* Initialize attributes */
   %This.Label.setMessageText(25000, 2, "Report Manager");
   
end-method;

/**
  * Make an exact copy of this object.
  * NOTE: Only create the object here, do not copy any class properties.
  *       If there are new class properties, override the copyProperties
  *       method and do it there.  Should invoke the %Super.copyProperties
  *       in that method though.
  *
  * @return BaseElement New object exactly matching this object.
  *
  */
method clone
   /+ Returns PTBR_BRANDING:Elements:BaseElement +/
   /+ Extends/implements PTBR_BRANDING:SystemElements:SystemLink.clone +/
   
   Local CSK_BRANDING:SystemElements:ReportManagerLink &newObj = create CSK_BRANDING:SystemElements:ReportManagerLink(%This.ID);
   
   /* Call the copy properties function */
   %This.copyProperties(&newObj);
   
   Return &newObj;
   
end-method;

/*****************************
*   Protected methods
*****************************/

/**
  * Setup the link properties
  *
  */
method setupLink
   /+ &pPreview as Boolean +/
   
   Local ApiObject &crefObj;
   
   Local PTBR_BRANDING:UTILITY:Utility &utility = %This.Utility;
   
   Local string &linkUrl = "";
   
   If (&pPreview) Then
      %Super.setupLink(&pPreview);
   Else
      
      &crefObj = &utility.PortalRegistry.FindCRefByName("PT_CONTENT_LIST_GBL");
      
      If (All(&crefObj) And
            &crefObj.Authorized And
            &crefObj.IsVisible) Then
         
         If ((&utility.HeaderLink As PT_BRANDING:HeaderLinkPIA) <> Null) Then
            &linkUrl = &crefObj.AbsolutePortalURL;
         Else
            &linkUrl = &crefObj.RelativeURL;
         End-If;
         
         %This.URL = &linkUrl;
         
      End-If;
      
   End-If;
   
end-method;

- Create custom Branding Element Types for Process Monitor and Report Manager Links:





Note: Each Branding Element Type is referencing its corresponding custom supporting Application Class.

- Delete 'MultiChannel Console' and 'Performance Trace' links from Branding Header:





- Add Process Monitor and Report Monitor Elements to Branding Header:









- Test Changes:

Recommendations if you are experiencing caching issues:
  1. Clear local browser cache.
  2. Shutdown, purge cache and reboot the web server(s).





Implementing Google Analytics:


Google Analytics is a free service that is offered by Google that helps us gather statistics on traffic, traffic sources, conversions, page visits and other useful information about websites.

There are some good presentations on the Higher Education User Group (HEUG) forum for more details on how organizations are using Google Analytics to track, monitor and analyze PIA traffic in PeopleSoft Applications.

To enable Google Analytics we need to create a new property using a google account. This would generate a tracking id that is specific to our website (property).

The tracking id is a string like UA-XXXXXX-Y where XXXXXX represents the account number and Y represents the property number.

Once we obtain the tracking id it is very easy to enable Google Analytics in a PeopleSoft Application. All we need to do is inject the Google Analytics javascript into our PeopleSoft Application.

Google Analytics JavaScript:

<script type="text/javascript">

  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-XXXXX-Y']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();

</script>

In the past (prior to PeopleTools 8.54), we would have had to insert the Google Analytics into our Branding Header or even at the template level (E.g.: PT_HNAV_TEMPLATE, PT_HNAV_TEMPLATE_INCLUDE).

With PeopleTools 8.54, it is very easy to inject JavaScript without any customizations.

- Create JavaScript Object for Google Analytics:



- Include Custom JavaScript Object on the Branding Systems Options Page:



Note: In this example, I am using the latest Asynchronous Syntax provided by Google which allows us to place/inject the JavaScript at any location (including the head) in the html without any page rendering performance issues.

- Test Changes:







Note: This post is only intended to provide information on how to implement Google Analytics in a PeopleSoft Application. This post does not cover details on how to use Google Analytics. There are several online resources that are available to understand the various ways to use the statistical data captured by Google Analytics both from a functional and technical point of view.

Migrating Branding to other environments:


Over the three part series of blogs, we have seen how we can achieve several Branding requirements in PeopleTools 8.54. Now let us look at how we can migrate all the objects we created using both app designer and online configuration pages.

Let us take stock of all the objects that we created and include them in project for migration.

- Include all the Images created for Branding:





- Include all the Style Sheets created for Branding:





- Include all the JavaScript Objects created for Branding:





- Include any URL definitions created for Branding:



Note: This URL definition was used as the Hyperlink URL for the Logo Image (in Part 2).

- Include all Application Classes created for Branding:



- Include Weblib Customization for Timeout Warning:



- Include all Message Catalog Entries created for Branding:



Note: These message catalog entries are referenced in the Application Classes created for supporting Branding Element Types.

- Migrating configuration that are not PeopleTools Managed Objects:

In all the posts detailing Branding in 8.54 we have tried to use the Branding Configuration Pages wherever we could. This is great from a quick development turn around and maintenance point of view. But how do we migrate these configurations (themes, headers, footers, branding element types, etc)? These configurations are not PeopleTools Managed Objects (yet!).

To overcome this challenge, PeopleSoft has delivered export/import dms scripts for these configurations. The scripts can be found in the following location on the app server:

/$PS_HOME/scripts/
    ptbr_setup_exp.dms
    ptbr_setup_imp.dms
    ptbr_theme_exp.dms
    ptbr_theme_imp.dms



Migrating Branding Element Types and User Attribute Types:

Use ptbr_setup_exp.dms to export these configurations from the source environment and ptbr_setup_imp.dms to import these configurations to the target environment.

The main tables that store these configurations are:
PS_PTBR_ETYPE
PS_PTBR_ETYPE_LN
PS_PTBR_UATYPE
PS_PTBR_UATYPE_LN

In our examples we created 3 custom Branding Element Types for the following:
- Greeting Message
- Process Monitor Link
- Report Manager Link

Note: We will need to update the exports scripts appropriately to include our custom Branding Element Types.

E.g.:

EXPORT PS_PTBR_ETYPE WHERE PTBR_ETYPE_ID IN ('CSK_GREETING_TEXT', 'CSK_PROCESSMONITOR_LINK', 'CSK_REPORTMANAGER_LINK');

Migrating Themes, Header and Footer Definitions:

Use ptbr_theme_exp.dms to export these configurations from the source environment and ptbr_theme_imp.dms to import these configurations to the target environment.

The main tables that store these configurations are:
PS_PTBR_THEME
PS_PTBR_THEME_LN
PS_PTBR_THMATTR
PS_PTBR_THMATTR_LN
PS_PTBR_THEME_CSS
PS_PTBR_THEME_DEL
PS_PTBR_LAYOUT
PS_PTBR_LAYOUT_LN
PS_PTBR_LTATTR
PS_PTBR_LTATTR_LN
PS_PTBR_LTELT
PS_PTBR_LTELT_LN
PS_PTBR_LTELTAT
PS_PTBR_LTELTAT_LN

In our examples we created a custom Theme and a custom Header Definition.

Note: We will need to update the exports scripts appropriately to include our custom Branding Definitions.

E.g.:

-- Export theme definitions

EXPORT PS_PTBR_THEME WHERE PTBR_THEME_ID IN ('CSK_THEME_TANGERINE');
-- EXPORT PS_PTBR_THEME_LN WHERE PTBR_THEME_ID IN ('CSK_THEME_TANGERINE');
EXPORT PS_PTBR_THMATTR WHERE PTBR_THEME_ID IN ('CSK_THEME_TANGERINE');
-- EXPORT PS_PTBR_THMATTR_LN WHERE PTBR_THEME_ID IN ('CSK_THEME_TANGERINE');
EXPORT PS_PTBR_THEME_CSS WHERE PTBR_THEME_ID IN ('CSK_THEME_TANGERINE');
EXPORT PS_PTBR_THEME_DEL WHERE PTBR_THEME_ID IN ('CSK_THEME_TANGERINE');


-- Export header/footer definitions

EXPORT PS_PTBR_LAYOUT WHERE PTBR_LAYOUT_ID IN ('CSK_HEADER_TANGERINE');
-- EXPORT PS_PTBR_LAYOUT_LN WHERE PTBR_LAYOUT_ID IN ('CSK_HEADER_TANGERINE');
EXPORT PS_PTBR_LTATTR WHERE PTBR_LAYOUT_ID IN ('CSK_HEADER_TANGERINE');
-- EXPORT PS_PTBR_LTATTR_LN WHERE PTBR_LAYOUT_ID IN ('CSK_HEADER_TANGERINE');
EXPORT PS_PTBR_LTELT WHERE PTBR_LAYOUT_ID IN ('CSK_HEADER_TANGERINE');
-- EXPORT PS_PTBR_LTELT_LN WHERE PTBR_LAYOUT_ID IN ('CSK_HEADER_TANGERINE');
EXPORT PS_PTBR_LTELTAT WHERE PTBR_LAYOUT_ID IN ('CSK_HEADER_TANGERINE');
-- EXPORT PS_PTBR_LTELTAT_LN WHERE PTBR_LAYOUT_ID IN ('CSK_HEADER_TANGERINE');

Message Catalog Entries created for Reference: