Visitors per day statistics with zooming and weekends (prototype)

I created a visitor statistics prototype for an application. With the statistics we would like to check if an application is used frequently or if it’s sensitive to corporate news updates.

The application help the user to select what type of meeting they should setup according to several parameters the user provide (e.g.  number of participants, duration, share & edit, see others, participants outside firewall, type of communication (top down, horizontal), type of meeting subject).

The application also is intended to promote the usage of electronic solutions instead of “expensive” “on-site” visits.

Conditions

  • In the first step we are only interested in the number of visits. In the next phase we are also interested what parameters the user provide when searching.
  • Only unique sessions are recorded.
  • Users are expected to be anonymous.
  • An export should be possible for spreadsheet addicts (not mentioning a specific Office product).

Architecture

The solution exists of the following (design) elements:

  • A custom control to record the visit.
    • Each unique visit is a Notes document storing date, browser, user, dateunix, page name.
      • We record also the browser type using the CGIVariables() function by Thomas Gumz.
  • A custom control to display the statistics. We have chosen to use a plot a time serie using Flot as a starter.
    • A Notes view categorized by a unix timestamp to provide data for the chart.
  • An XPage for the providing a spreadsheet output.
    • A Notes view that is used by the XPage for providing data for the output.

Implementation

  • Download and install the Flot resources via Package Explorer.
  • Create a custom control e.g. ccVisitRegister:

<xp:this.resources>
<xp:script src=”/xpCGIVariables.jss” clientSide=”false”></xp:script>
<xp:script src=”/xpFunctions.jss” clientSide=”false”></xp:script>
</xp:this.resources>
<xp:this.beforePageLoad><![CDATA[#{javascript:var v = sessionScope.get(“visit”);
var dt:NotesDateTime = session.createDateTime(“Today”);
dt.setNow();
function createDoc(){
var doc = database.createDocument(); // Create the document
doc.appendItemValue(“Form”,”count”); // Assign the form
doc.appendItemValue(“date”,dt); // Append something to a field

var udt:NotesDateTime = session.createDateTime(“Today”);

var unixDate = udt.toJavaDate().getTime()/1000;

doc.appendItemValue(“dateunix”,unixDate); // Append something to a field

var cgi = new CGIVariables()
var browser = cgi.HTTP_USER_AGENT
doc.appendItemValue(“browser”,browser); // Append something to a field
var user = @UserName();
doc.appendItemValue(“user”,user); // Append something to a field

var page = facesContext.getExternalContext().getRequest().getRequestURI();
doc.appendItemValue(“pagename”,@RightBack(page,”/”)); // Append something to a field

doc.save();
}
if (v == null){
//New session -> register
sessionScope.put(“visit”,dt);
sessionScope.put(“create”,”yes”);
if (isAuthor()==true){
createDoc();
}
}
else{
sessionScope.put(“visit”,dt);
sessionScope.put(“create”,”no”);
}}]]></xp:this.beforePageLoad>

xpFunctions is a library with helper functions e.g. the isAuthor() function:

function isAuthor(){
var level = database.getCurrentAccessLevel();
if (level >= NotesACL.LEVEL_AUTHOR) {
return true;
} else if (level < NotesACL.LEVEL_AUTHOR) {
return false;
}
}

  • Create a custom control to display the statistics:

<?xml version=”1.0″ encoding=”UTF-8″?>
<xp:view xmlns:xp=”http://www.ibm.com/xsp/core”&gt;
<link href=”flot/examples/examples.css” rel=”stylesheet” type=”text/css”></link>
<!–[if lte IE 8]><script language=”javascript” type=”text/javascript” src=”flot/excanvas.min.js”></script><![endif]–>
<script language=”javascript” type=”text/javascript” src=”flot/jquery.js”></script>
<script language=”javascript” type=”text/javascript” src=”flot/jquery.flot.js”></script>
<script language=”javascript” type=”text/javascript” src=”flot/jquery.flot.time.js”></script>
<script language=”javascript” type=”text/javascript” src=”flot/jquery.flot.selection.js”></script>
<xp:text escape=”false” id=”scriptBlock”>
<xp:this.value><![CDATA[#{javascript:
var v:NotesView = database.getView(“countsbyunixdate”);
v.setAutoUpdate(false);
var nav:NotesViewNavigator = v.createViewNav();
var entry:NotesViewEntry = nav.getFirst();
var nEntry:NotesViewEntry = null;
var newArr = new Array();
while(entry != null){
nEntry = nav.getNextCategory();
if(entry.isCategory()){
var values = entry.getColumnValues();
var children = entry.getChildCount();
newArr.push (“[” + values.get(0) + “,” + children + “]”);
}
try{
entry.recycle();
}catch(e){
}
entry = nEntry;
}
try{
nav.recycle();
v.recycle();
}catch(e){
}
var newArrString:String = newArr.join(“,”);

“<script type=\”text/javascript\”>”+
“$(function() {” +
“var d = [” + newArrString + “];” +
“for (var i = 0; i < d.length; ++i) {d[i][0] += 60 * 60 * 1000;}” +
“function weekendAreas(axes) {“+
“var markings = [],”+
“d = new Date(axes.xaxis.min);”+

“d.setUTCDate(d.getUTCDate() – ((d.getUTCDay() + 1) % 7));”+
“d.setUTCSeconds(0);”+
“d.setUTCMinutes(0);”+
“d.setUTCHours(0);”+
“var i = d.getTime();”+
“do {“+
“markings.push({ xaxis: { from: i, to: i + 2 * 24 * 60 * 60 * 1000} });”+
“i += 7 * 24 * 60 * 60 * 1000;”+
“} while (i < axes.xaxis.max);”+
“return markings;”+
“}”+
“var options = {“+
“xaxis: {“+
“mode: \”time\”,”+
“tickLength: 5″+
“},”+
“selection: {“+
“mode: \”x\””+
“},”+
“grid: {“+
“markings: weekendAreas”+
“}”+
“};”+

“var plot = $.plot(\”#placeholder\”, [d], options);”+
“var overview = $.plot(\”#overview\”, [d], {“+
“series: {“+
“lines: {“+
“show: true,”+
“lineWidth: 1″+
“},”+
“shadowSize: 0″+
“},”+
“xaxis: {“+
“ticks: [],”+
“mode: \”time\””+
“},”+
“yaxis: {“+
“ticks: [],”+
“min: 0,”+
“autoscaleMargin: 0.1″+
“},”+
“selection: {“+
“mode: \”x\””+
“}”+
“});”+
“$(\”#placeholder\”).bind(\”plotselected\”, function (event, ranges) {“+
“plot = $.plot(\”#placeholder\”, [d], $.extend(true, {}, options, {“+
“xaxis: {“+
“min: ranges.xaxis.from,”+
“max: ranges.xaxis.to”+
“}”+
“}));”+
“overview.setSelection(ranges, true);”+
“});”+
“$(\”#overview\”).bind(\”plotselected\”, function (event, ranges) {“+
“plot.setSelection(ranges);”+
“});”+
“$(\”#footer\”).prepend(\”Flot \” + $.plot.version + \” &ndash; \”);”+
“});”+

“</script>”

}]]>
</xp:this.value>
</xp:text>
<xp:panel tagName=”h1″>Visitors</xp:panel>
<xp:panel id=”content” tagName=”div”>
<div class=”demo-container”>
<div id=”placeholder” class=”demo-placeholder”></div>
</div>

<div class=”demo-container” style=”height:150px;”>
<div id=”overview” class=”demo-placeholder”></div>
</div>
</xp:panel></xp:view>

  • Create a Notes view categorized by a unix timestamp:

notesview

Result

plot

These are the main items on the statistics page (beside a link to the export function). You can zoom in/out on the time line.

Feedback

The idea is simple, also the implementation. I will create a small project on OpenNTF later this week. In case you have some valuable additions/suggestions please let me know.

Job Wanted

Looking for a creative brain? Choose me!

job-wanted

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s