Processing Rules in SiteCatalyst 15



Here is a quick look at what can be done with and how to set up processing rules in SiteCatalyst 15.

Enjoy.

How To Capture A Query String Parameter From A Referring URL In SiteCatalyst

Recently someone had asked the question, how do I capture a query string parameter that’s on referring URL? We all know how to grab a query string parameter from the current page URL by using the getQueryParam SiteCatalyst plug-in, but most people don’t know that plug-in can be used to get a query string parameter from the referring URL as well. I once had a real unique implementation that was not using that plug-in and needed to capture that value. I wanted to keep the implementation really light so I decided to give it a try using a smaller bit of code. I broke out a little JavaScript magic to see if I could make it happen simpler than using that plug-in. Turns out it’s not too difficult to accomplish, in fact I got it down to just a single line of code.

function getRefQueryParam(a){a=a.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");a=RegExp("[\\?&]"+a+"=([^&#]*)").exec(document.referrer);return a==null?"":a[1]};

Its a little function called getRefQueryParam. To use it just place that code in your s_code file, and then call it with the name of the query string parameter you want to capture. In this example I want to capture the value of the parameter forumID= from the referring URL and record it in s.prop1.

s.prop1=getRefQueryParam('forumID');

With a little JavaScript goodness it is an easy value to capture.

Enjoy.

SiteCatalyst 15 UI Updates



At the Omniture Summit earlier this month, SiteCatalyst 15 was announced. There has been a lot said about the new tools it will offer but not much about the overall UI appearance update. Here is a quick look showing some of the changes you will see in the UI of SiteCatalyst 15.

Enjoy.

Scatter Plot Graph Or Bubble Graph Use in SiteCatalyst



Recently someone asked me when was the best time to use the Scatter Plot graph type and the Bubble graph type in SiteCatalyst reports.

Enjoy.

Video Introduction To SiteCatalyst Target Reports



The SiteCatalyst Target report is one of my favorite reports that I don’t see used enough. THis video gives you a brief introduction to the report, and walks you through setting one up, and how to view the results.

Enjoy.

Bounce Rate Funnels – Action Depth SiteCatalyst Plug-In

Bounce Rates. For those of you who are unaware of what they are, bounce rate is essentially the percentage of single page visits, divided by your total visits. This metric can be pretty useful to figure out what pages of your site that your visitors enter on and decide not to venture any deeper into your site. Basically the visitor came to your site and the page they entered on did not entice them to view additional pages of your site so they left. This is obviously not what we want. We need our visitors to come to our sites and complete our desired action. This is where I run into a problem with the Bounce Rate metric. Lets say for example you have a lead generation site, which contains a form on the landing page which uses ajax or some other type of technology to process the form submission. That site would have a visitor enter, fill out the form (which is your desired action) and then leave the site. This would show up as a bounced visit since a second page view was not recorded. What can we do to record this action as a successful visit and not have it end up being considered as just another bounce?

One thing you could do would be to use the getVisitStart plug-in. With this plug-in you could set an event on the first page of the visit, and then using a conversion funnel you can see how many visits entered on your specified landing page and then completed your conversion event.



Pretty simple stuff so far. But what if I wanted to now know how many of those visits ventured on to view additional pages of my site, and how many left right after completing my conversion event? For this I would want to set a second different success event on the second page view of the site. For this we can use the getActionDepth plug-in.

What this plug-in will do is set a success event (or any SiteCatalyst variable you want) onto any page of the visit. In this case we want to set a success event on the second page view of the site. Using the Action Depth plug-in we can set individual events on only the first page view and the second page view of the visit. Now using the same conversion funnel we can see how many visits entered the site, completed our conversion action, and then stayed to view a second page of the site.



What if your site does not have an ajax type form conversion action and you just want to use the custom events funnel as a cool way to display how many bounces your site had? That can also be easily done.



By just including the event that fired on page 1 of the visit and the event that fired on the second page view of the visit we now have a nice graphical representation of how many of our visits left after viewing a single page and how many decided to move on to view additional pages of the site.

What if for your site only viewing 2 pages was not good enough? You need to see what percentage of your visits see at least three pages. The Action Depth plug-in can take care of that as well.



Now if you have spent more than couple minutes using SiteCatalyst you could probably be saying to yourself “I can find this information out already by using the Path Length report”. Yes that report will tell you what percentage of your visits saw any number of pages, but have you tried to add that report to a dashboard? It’s not pretty. This way you can easily show the exact information you need in a very easy to read format.

Let’s take a look at what the plug-in code looks like If we want to set an event on first page view of the visit, and another one on the second page view of the visit. First add this line in the top of your s_code file, in the config section.

s.ActionDepthTest=true;

Next this call to the plug-in should be placed in your s_code file in the s_doPlugins section.

if(s.ActionDepthTest){
	s.pdvalue=s.getActionDepth("s_depth");
	if(s.pdvalue == 1) {
		s.events=s.apl(s.events,'event1',',',1)
	}
	if(s.pdvalue == 2) {
		s.events=s.apl(s.events,'event2',',',1)
	}
}
s.ActionDepthTest=false;

And here is the actual plug-in that should be placed after the s_doPlugins section, along with your other plug-ins.

/*
 * Plugin: getActionDepth v1.0
 */
s.getActionDepth=new Function("c",""
+ "var s=this,v=1,t=new Date;t.setTime(t.getTime()+1800000);"
+ "if(!s.c_r(c)){v=1}if(s.c_r(c)){v=s.c_r(c);v++}"
+ "if(!s.c_w(c,v,t)){s.c_w(c,v,0)}return v;");

But there is one more thing (sorry I was feeling very Steve Jobs for a moment). Actually I have two more things but I couldn’t pass up on a good Steve Jobs reference. Let’s say you also need to set an additional event and an eVar on the 6th page view of the site, and only on the 6th page view. That can easily be done as well by just changing somethings around in the plug-in code. By looking at the call to the plug-in it should be pretty easy to see what’s going on. When the specific page view of the visit is reached, then the actions that are attached will occur.

s.ActionDepthTest=true;
if(s.ActionDepthTest){
	s.pdvalue=s.getActionDepth("s_depth");
	if(s.pdvalue == 1) {
		s.events=s.apl(s.events,'event1',',',1)
	}
	if(s.pdvalue == 2) {
		s.events=s.apl(s.events,'event2',',',1)
	}
	if(s.pdvalue == 6) {
		s.events=s.apl(s.events,'event3',',',1)
	        s.eVar="This is the sixth page view";
        }
}
s.ActionDepthTest=false;

Now how about you want to know how many page views deep do your visitors go when they complete your conversion action. A little change to the plug-in code and we can capture that as well. What we do here is just capture what the page number of the visit is on each page view in an eVar, then we can just add in our conversion event to that report and there we go. Then we can see directly in our optimization efforts if we are helping our visitors quickly get to our conversion event. Here is the code to capture the page number of each page of the visit in an eVar.

if(s.ActionDepthTest){
	s.pdvalue=s.getActionDepth("s_depth");
	if(s.pdvalue) {
		s.eVar1=s.pdvalue;
	}
}
s.ActionDepthTest=false;

Enjoy!

How To Stop Google Preview From Being Counted In SiteCatalyst – Updated

UPDATE: I have a much better way to block the Google Web Preview bot from being tracked as a visitor in SiteCatalyst. The original solution I had posted here, required a block of code to be placed at the very top of the s_code file, and your account ID was put into a function call. Then when the s_code was fired, a function would first check the user agent of the visitor to see if it was the Google Web Preview bot, and if so then swap out the account ID with a blank value. The SiteCatalyst code would still fire, but when Omniture received the image request it would get discarded because of the missing account ID. The more I thought about this I figured there had to be a better way. No reason to execute all the s_code javascript and fire off the beacon call when I don’t want that visitor (Google) to be tracked. So after a little brainstorming I came up with a new and improved way to do this. Now when the user agent is determined to be the Google Web Preview bot, then the SiteCatalyst code is prevented from even firing (how it should have been originally). Even better, this can now be done by simply adding a tiny bit of code to the plugin’s section of your s_code file, right next to all your other plugin code. Thats it. No other changes need to happen. No code at the top of the page, no adding calls to functions in the account variable. Just cut, paste, and done.

Here is the code. Just add this right next to all of your other plugins.

/*
 *  Block the Google Web Preview Bot from firing SiteCatalyst code
 */
if(s.u.toLowerCase().indexOf('google web preview')!=-1){s.t=function(){}}

If you are using the original version from below make sure you remove it. And as with any code, make sure you fully test it before deploying to a live site.
~kevin

Google Instant Preview, designed to show you a visual preview of your search results, rolled out in early November 2010. You now have the ability to click a small magnifying glass icon next to each search result to get a snapshot of what the page looks like.
Google Instant Preview

Seems like a pretty helpful feature, but how do they do it? Well it would appear that Google has a new spider that crawls the web and takes snapshots of each page in its results. In order for them to get an accurate look at what the page looks like, this new bot needs to able to execute JavaScript. Here is the problem. Since it is executing JavaScript that means it is also firing off the SiteCatalyst code and is being counted as another visitor and is registering page views.

How can you tell if this new Google Web Preview bot hit your site? If you are capturing User Agent you can see it show up in that report:
User Agent Report

NOTE: If you are not capturing user agent and would like to, a super simple way would be to use the SiteCatalyst Dynamic Variable functionality and include s.eVarX=”D=User-Agent”; in your s_code.js file. Just insert the number of the eVar you would like to use (a s.prop would work too) and you are all set.

Another way to see if you are being affected with spider traffic in your report suite from the Google Preview Bot would be to check out a Browser report (Visitor Profile > Technology > Browsers) and filter it to only show visitors using Safari 3.1 and then trend it.
Browser Report
We can see that this report suite has recorded about an additional 15,000 visitors over the last week that is just attributed to Safari 3.1. Checking the User Agent we saw earlier, the Google Web Preview bot is registering itself as Safari 3.1.

Now that we can see that the Google Web Preview bot is having an effect on our traffic how do we get rid of it? We could block that bot in our robots.txt file, but I like having that additional functionality available for my visitors in the Google search results. I just don’t want it to execute my SiteCatalyst code. Well here is how to do it.

I call this my bot detection code (real catchy title, right?). I currently have it just set to look for the Google Web Preview bot, but it could easily be modified to exclude other bots that can execute JavaScript. Here is how you implement it. In your s_code file, at the top you will have a s_account variable that contains your report suite id. It will look something like this:

var s_account="dead"

To implement the bot detection code you will want to change that line to include the function call. It should look like this:

var s_account=botCheck("dead")

Pretty simple so far, right? We just added the function call and included our report suite id in it. Next we have a block of code that needs to be added to the plug-ins section of the s_code file:

function botCheck(b){var c=navigator.userAgent.toLowerCase(),a="";a+=c.indexOf("google web preview")!=-1?"":b;return a};

And that’s all there is to it. So how does it work you ask? What it does is it removes your report suite id if it is the Google Web Preview bot that is accessing the page. The SiteCatalyst code will still fire off, but it will not include the report suite id so it will be discarded by SiteCatalyst and it will not affect your metrics.

Want to see it in action? I thought you’d never ask! Check out the page http://webanalyticsland.com/test.php. On this page I have a basic SiteCatalyst implementation, one line of code that displays your user agent, and then I print the results of the SiteCatalyst debugger right to the screen. Opening this page in a standard Firefox browser we can see that the SiteCatalyst code has fired off properly, it has displayed the correct user agent and the report suite id is contained within the image request string.
Test 1
So far so good. Using the User Agent switcher plug-in for Firefox, we can switch out user agent to the one that we found in the SiteCatalyst report to mimic the Google Web Preview bot.
Test 2
We can now see that when we use that bot’s user agent string, the report suite id is missing from the image request call. Any action that happens now will not be recorded in my report suite, and when SiteCatalyst receives this request it will be discarded. I’ve had this running for a few days now and have not found any issues, but since this is a pretty new chunk of code be sure to test it out before using it on your production site.

Enjoy!

Pro Tip: Keep a Solution Design Document For Your SiteCatalyst Implementation

A Solution Design Document is a complete blueprint of your web analytics implementation. It outlines where every variable is set and why. It can really be a lifesaver. You should start keeping a solution design document as soon as you begin your implementation. Every time you add a prop, an evar, an event or any other variable, make sure you add it in there. Every time you make a change to your implementation, make note of it in there. It’s an easy place to go to see what variables are being used for what where they are being set and which ones are still available.

“But do I really need to keep track of everything to that level of detail, just checking the Admin console has been working well for us.” Well have you ever opened a report and find information there that shouldn’t be there?
Bad Report
How did that get in there? It’s being set somewhere in our implementation, but where? What page sets that variable? What function could set it? A quick check of our solution design document and we can see every place were that particular prop is set, well where they should be set. If one of your developers decided to get the implementation and set a variable in a non traditional way, it can be a real nightmare trying to figure out what was done. Without that you could waste a lot of time hunting through code searching for where a random variable is being set.

Here is an example spreadsheet that you can use as a basis to start your Solution Design Document:
Sample Solution Design Document

If you have a large team that all have their hands in your web analytics implementation, it may be beneficial to could place the solution design document in a location where the different members of your team can have access and add to it, like for example Google Docs or some other shared folder or public drive.

Enjoy!

Track HBX Style Links in SiteCatalyst

I hear from a lot of people migrating from HBX to SiteCatalyst who are looking for ways to make that process a little easier. One of the hurdles I see is trying to migrate all of their HBX link tracking that is already in place to a format that SiteCatalyst can easily understand. That is an easy one to tackle. It’s called the setupLinkTrack plug-in.

Other than tracking all of you current HBX coded links, any SiteCatalyst user can get some benefit from it. Here is another great use for this plug-in. Recently I was reading a great article from @adamgreco about learning to track website navigation. It is a really great article and if you have not had a chance to read it you should go check it out. In one part of the article Adam writes “you should have your developer write code that will pass the name of the link to a Traffic Variable (sProp) when a visitor clicks on each link in your navigation”. Well I’m the guy responsible for the tracking code for my website, so how can I track those links without adding a whole ton of JavaScript onclicks or some other server side hacks? This plug-in will easily handle that, without adding the extra server calls that come with the standard SiteCatalyst link tracking.

First take the plug-in code and add it to the plug-in section of your s_code.js file. Make sure you have the utility functions s.split and s.apl.

/*
 * Plugin: setupLinkTrack 2.0 - return links for HBX-based link
 *         tracking in SiteCatalyst (requires s.split and s.apl)
 */
s.setupLinkTrack=new Function("vl","c",""
+"var s=this;var l=s.d.links,cv,cva,vla,h,i,l,t,b,o,y,n,oc,d='';cv=s."
+"c_r(c);if(vl&&cv!=''){cva=s.split(cv,'^^');vla=s.split(vl,',');for("
+"x in vla)s._hbxm(vla[x])?s[vla[x]]=cva[x]:'';}s.c_w(c,'',0);if(!s.e"
+"o&&!s.lnk)return '';o=s.eo?s.eo:s.lnk;y=s.ot(o);n=s.oid(o);if(s.eo&"
+"&o==s.eo){while(o&&!n&&y!='BODY'){o=o.parentElement?o.parentElement"
+":o.parentNode;if(!o)return '';y=s.ot(o);n=s.oid(o);}for(i=0;i<4;i++"
+")if(o.tagName)if(o.tagName.toLowerCase()!='a')if(o.tagName.toLowerC"
+"ase()!='area')o=o.parentElement;}b=s._LN(o);o.lid=b[0];o.lpos=b[1];"
+"if(s.hbx_lt&&s.hbx_lt!='manual'){if((o.tagName&&s._TL(o.tagName)=='"
+"area')){if(!s._IL(o.lid)){if(o.parentNode){if(o.parentNode.name)o.l"
+"id=o.parentNode.name;else o.lid=o.parentNode.id}}if(!s._IL(o.lpos))"
+"o.lpos=o.coords}else{if(s._IL(o.lid)<1)o.lid=s._LS(o.lid=o.text?o.t"
+"ext:o.innerText?o.innerText:'');if(!s._IL(o.lid)||s._II(s._TL(o.lid"
+"),'<img')>-1){h=''+o.innerHTML;bu=s._TL(h);i=s._II(bu,'<img');if(bu"
+"&&i>-1){eval(\"__f=/ src\s*=\s*[\'\\\"]?([^\'\\\" ]+)[\'\\\"]?/i\")"
+";__f.exec(h);if(RegExp.$1)h=RegExp.$1}o.lid=h}}}h=o.href?o.href:'';"
+"i=h.indexOf('?');h=s.linkLeaveQueryString||i<0?h:h.substring(0,i);l"
+"=s.linkName?s.linkName:s._hbxln(h);t=s.linkType?s.linkType.toLowerC"
+"ase():s.lt(h);oc=o.onclick?''+o.onclick:'';cv=s.pageName+'^^'+o.lid"
+"+'^^'+s.pageName+' | '+(o.lid=o.lid?o.lid:'no &lid')+'^^'+o.lpos;if"
+"(t&&(h||l)){cva=s.split(cv,'^^');vla=s.split(vl,',');for(x in vla)s"
+"._hbxm(vla[x])?s[vla[x]]=cva[x]:'';}else if(!t&&oc.indexOf('.tl(')<"
+"0){s.c_w(c,cv,0);}else return ''");
s._IL=new Function("a","var s=this;return a!='undefined'?a.length:0");
s._II=new Function("a","b","c","var s=this;return a.indexOf(b,c?c:0)");
s._IS=new Function("a","b","c",""
+"var s=this;return b>s._IL(a)?'':a.substring(b,c!=null?c:s._IL(a))");
s._LN=new Function("a","b","c","d",""
+"var s=this;b=a.href;b+=a.name?a.name:'';c=s._LVP(b,'lid');d=s._LVP("
+"b,'lpos');return[c,d]");
s._LVP=new Function("a","b","c","d","e",""
+"var s=this;c=s._II(a,'&'+b+'=');c=c<0?s._II(a,'?'+b+'='):c;if(c>-1)"
+"{d=s._II(a,'&',c+s._IL(b)+2);e=s._IS(a,c+s._IL(b)+2,d>-1?d:s._IL(a)"
+");return e}return ''");
s._LS=new Function("a",""
+"var s=this,b,c=100,d,e,f,g;b=(s._IL(a)>c)?escape(s._IS(a,0,c)):esca"
+"pe(a);b=s._LSP(b,'%0A','%20');b=s._LSP(b,'%0D','%20');b=s._LSP(b,'%"
+"09','%20');c=s._IP(b,'%20');d=s._NA();e=0;for(f=0;f<s._IL(c);f++){g"
+"=s._RP(c[f],'%20','');if(s._IL(g)>0){d[e++]=g}}b=d.join('%20');retu"
+"rn unescape(b)");
s._LSP=new Function("a","b","c","d","var s=this;d=s._IP(a,b);return d"
+".join(c)");
s._IP=new Function("a","b","var s=this;return a.split(b)");
s._RP=new Function("a","b","c","d",""
+"var s=this;d=s._II(a,b);if(d>-1){a=s._RP(s._IS(a,0,d)+','+s._IS(a,d"
+"+s._IL(b),s._IL(a)),b,c)}return a");
s._TL=new Function("a","var s=this;return a.toLowerCase()");
s._NA=new Function("a","var s=this;return new Array(a?a:0)");
s._hbxm=new Function("m","var s=this;return (''+m).indexOf('{')<0");
s._hbxln=new Function("h","var s=this,n=s.linkNames;if(n)return s.pt("
+"n,',','lnf',h);return ''");

Next in the s_doPlugins section of the s_code file you need a couple lines of setup.

s.hbx_lt = "auto" // manual, auto
s.setupLinkTrack("prop1,prop2,prop3,prop4","SC_LINKS");

The plug-in will use 4 variables and a name for a cookie it will set. For this example I am going to use props 1 thru 4.

Next we have the actual code that will appear in the anchor tag that the plug-in will look for. It is a simple name attribute tag of lid and lpos. This is what a link would look like with the code properly formatted.

<a href="my-page.php" name="&lid=Featured Articles&lpos=Left Nav">Cool Article Name</a>

Here’s what it will do. After clicking on a link that contains a lid and lpos (the exact link shown above), this is what you will find in the debugger on the page you land on:
Debugger 1
The plug-in entered the s.pageName value of the page that the click occurred into prop1, the value of lid into prop2, a combination of the prop1 and the value of lid into prop3 and the value of lpos in prop4.

Lets change up what we include in the actual link code. Lets remove the lid from the tag and just use this link:

<a href="my-page.php" name="&lpos=Left Nav">Cool Article Name</a>

This is what we will get from the debugger:
Debugger 2
You can see by not using the lid tag then the plug-in will use the actual anchor text in those positions.

Now lets say you are not interested in capturing the previous pageName value, or the combined previous pageName/lid value. You can just omit those variables in the plug-in setup. Change the code to:

s.hbx_lt = "auto" // manual, auto
s.setupLinkTrack(",prop2,,prop4","SC_LINKS");


You can see I left the commas in there as empty place holders. Clicking the link with that setup and a lid and lpos value will return this in the debugger:
Debugger 3

What about the other links on the page? What if they do not include a lid or lpos value? The plug-in will track those also. Clicking one of those links will return this in the debugger:
Debugger 4
The plug-in will still capture the previous pageName value, the anchor text and the combined values of the two.

I’m sure by now you noticed that auto/manual setting. Up to now its been set on auto. Let’s flip it to manual and click a link on the page that does not include any code. Here is what you will get:
Debugger 5
You will only get the two previous pageName values. If I would have omitted those two variables like I did earlier then it would have not returned anything. If you click on a link with a lid and lpos variables then it will perform the same as if it were set to auto.

If you want to not add the code to the links so you can track all of the links on a page, but you only want to do it on a specific page and not the whole site you can then wrap the code in an if statement like this:

if(s.pageName=='Home'){
s.hbx_lt = "auto" // manual, auto
s.setupLinkTrack(",prop2,,prop4","SC_LINKS");
}

You could also do that using document.location (or a million other ways to identify a specific page).

Since it also grabs the previous page value I no longer need the previous pageName plug-in (useful when using the getPercentPageViewed plug-in).

Enjoy!