Archives

 

Track Copied Text SiteCatalyst Plugin

UPDATED: March 29, 2013 – Track Copied Text plugin version 2.0k

This was a bit of code that was in desperate need of an update, so thats exactly what it got. Here I have the updated version of the Track Copied Text plugin, version 2.0k.

Improvements with this version include:

  • The entire code has been completely rewritten and is now in a standard SiteCatalyst plugin format.
  • The ability to set any combination of eVars, props, events, or nothing but an empty custom link call.
  • Prevents copied text longer than 255 characters from being set in any variable (100 characters in a prop).
  • Prevents the same highlighted text to be copied multiple times in a row.
  • The ability to include or not include variables set in s.linkTrackVars or s.linkTrackEvents.
  • The ability to use a custom link name.

Implementing this version is quick and easy. First include the Track Copied Text plugin code below in your s_code file with all the rest of your plugins:

/* Track Copied Text v2.0k */
s.trackCopiedText=new Function("v","e","a","n",""
+"var s=this,x=arguments;s.ea=!1;if(!s.ea){s.ea=!0;s.cf=!1;function t"
+"ct(x){if(!s.cf){var b=s.linkTrackVars,c=s.linkTrackEvents,d=',event"
+"s',g=h='',f,i;e=e?e:'';n=n?n:'text copied';if(a){if(b&&b!='None')g="
+"','+b;if(c&&c!='None')h=','+c}if(e||h)g=g+',events';s.linkTrackVars"
+"=v+g;s.linkTrackEvents=s.events=e+h;j=gct();j=(String(j)).substring"
+"(0,255);if(v){f=v.split(',');for(i=0;i<f.length;i++){if(f[i].charAt"
+"(0)=='p'){s[f[i]]=j.substring(0,100)}else{s[f[i]]=j}}}s.tl(true,'o'"
+",n);s.cf=!0}};function gct(){if(s.d.selection){return s.d.selection"
+".createRange().text}else if(s.wd.getSelection){return s.wd.getSelec"
+"tion()}return ''};if(s.wd.attachEvent){s.wd.attachEvent('oncopy',tc"
+"t)}else if(s.wd.addEventListener){s.wd.addEventListener('copy',tct,"
+"false)}}");

Next add a call to the plugin in the s_doPlugins section of your s_code file (preferably near the bottom of the s_doPlugins section). The plugin call will accept 4 parameters, all of them being optional.

s.trackCopiedText(v,e,a,n);

v = The variable’s that you would like the copied text recorded to. Insert as many as you would like, each one comma separated. Any copied text will be trimmed to 255 characters, except for props which will get trimmed to 100 characters.
e = The events that you would like to set when text is copied. Again, feel free to set as many as you would like, or you can choose not to set any events.
a = This is a flag that when set to 1 indicates if you have s.linkTrackVars or s.linkTrackEvents set on any page to also include those variables with the Copied Text function call. If this variable is not included then no additional variables will be included with the call.
n = This is the name of the call that will appear in the Custom Links report in SiteCatalyst. If this is not set then the default value of “text copied” will be used.

Examples

To capture the copied text in s.eVar20 and set event15 (this is how I have it set on this site):


s.trackCopiedText('eVar20','event15');

To capture the copied text in s.eVar20, s.prop35, set event25, and include anything currently set in s.linkTrackVars or s.linkTrackEvents:


s.trackCopiedText('eVar20,prop35','event25',1);

To capture the copied text in s.prop30 and use the custom link name of “visitor selection”:


s.trackCopiedText('prop30','','','visitor selection');

To just fire a custom link call when the visitor copies some text (not capturing the copied text or setting any events):


s.trackCopiedText();

As with all code, make sure you fully test it to ensure it works with your site. Also let me know of any changes or additions you’d like to see with this plugin, and of any insights you were able to gain by using this plugin. I’d love to hear how its working for your site.

Enjoy!

Original Post: December 21, 2009

To me Web Analytics is the science of analyzing visitor behavior in order to improve the Web Site for the purpose of increasing conversion. Anytime I can use web analytics to help the visitor find what they are looking for, I feel I’m doing my job. But lets say your visitors are finding what they are looking for, but it is just not as easy as it could be? How would I know?

One thing I have been playing with is to monitor what content my visitors are selecting and copying from the site. If I see a lot of visitors copying my email address, maybe I should make the contact form a little easier to be found. If I see a lot of copying of some sample code, maybe I should make it easier to download it, or include a pdf copy. But how do I find out how to capture what my visitors copy? Here you go.

This is all done by adding a plug-in and a bit of code to the s_code file. This code looks for any time some text is copied and sets it in a prop and fires an event. This will work if the visitor highlights text and goes the right click/copy route, or by hitting Control/Command + C. You will need either 1 eVar and 1 event, or a 1 prop to use. If you want to go the eVar and event route, take this code and place it some where BEFORE the function s_doPlugins(s) call:

var eventAttached=false; 
if(!eventAttached){eventAttached = true;
function trackCopy(){
var overrides = {'events':'event8','eVar18':getCopiedText()};
	s.templtv=s.linkTrackVars;
	s.templte=s.linkTrackEvents;
   	s.linkTrackVars='eVar18,events';
	s.linkTrackEvents=s.events='event8';
	s.tl(true, 'o', 'Text Copied', overrides);
	if(s.templtv) s.linkTrackVars=s.templtv;
	if(s.templte) s.linkTrackEvents=s.templte; 
}

Insert the eVar and event you are going to use where you see them in the code. If you decide to just use a single prop instead, then use this bit of code, again before the function s_doPlugins(s) call:

var eventAttached=false;
if(!eventAttached){eventAttached = true;
function trackCopy(){
var overrides = {'prop49':getCopiedText()};
	s.templtv=s.linkTrackVars;
   	s.linkTrackVars='prop49';
	s.tl(true, 'o', 'Text Copied', overrides);
	if(s.templtv) s.linkTrackVars=s.templtv;
}

Insert the prop you want to use where you see it set. Next take this code and put it in the plug-in’s section of the s_code file:

function getCopiedText() {
if (document.selection){return document.selection.createRange().text;}
else if (window.getSelection){return window.getSelection();}return '';}
if(document.body && document.body.attachEvent){
document.body.attachEvent("oncopy", trackCopy);}
else if (document.body && document.body.addEventListener){
document.body.addEventListener('copy',trackCopy, false);}}

What are we going to end up with? You will get a report that looks like this:
Copied Text Report

It’s pretty interesting to see what your visitors are choosing to copy. Now do I expect to find huge some game changing incite that will lead me to make a change to the Web Site that will increase my conversion rate 100% with this report? Probably not. Do I expect to find one more place that allows me to make another 1% improvement? I sure do. Remember, all those 1% improvements add up. ;)

Big thanks to kgs/ksmith in the Omniture Developer Connection for the original idea to do this.

Enjoy!

Google Changes Referrer Values Again For Secure Searches

Over the past 6 months Google has made changes to their search experience in an attempt to increase the privacy and security of their signed in users. What this has meant for analytics tools is that the referring URL for those signed in users was stripped of any searched keywords when clicking on Google organic search results.

Here’s what has been happening behind the scenes. All signed in users are now on a secure version of Google (https), and a redirect has been added to each search results click. That redirect is to a non-secure page (http), where the referring URL is changed before the visitor arrives at the page they requested. That new referring URL value has had its keywords removed, but still contains enough information to determine it was a Google Secure search. Workarounds were created to help identify a Google Secure search in SiteCatalyst keyword reporting, as well as Omniture making a change to try and account for those searches.

Since making that change Google has determined that the additional redirect is unnecessary and potentially slowed down the users experience, so they have decided to eliminate it (unfortunately that does not mean analytics tools will be able to see those keywords again).

Today Google announced a change to the way they plan on handling referring URL’s starting in April 2012. Google has decided that they will now begin to use the referrer meta tag for browsers that will support it, as opposed to the redirect to the non secure page. Currently the only major browser that supports it is Google Chrome.

If you are not familiar with the referrer meta tag, what it does is it lets each web page decide how referrer from it should be handled. For example, here’s what a meta referrer tag looks like:

<meta name="referrer" content="never">

What this tag will do is that it tells the browser to never pass any referring information from the page its on. The browser should then set the referrer header value to a blank string for referrers from that page.

Fortunately Google is not going to that extreme. They have decided to use the “origin” value:

<meta name="referrer" content="origin">

This is the referrer meta tag value that Google will begin to use in April 2012. When the change goes live, all search clicks from signed in users will now only have the referrer value of https://www.google.com/. There will be no other information in the referring URL, so no way to determine that it was specifically a Google secure search other than the URL being simply that host value. Non-secure searches, ones made from a user not logged into a Google account, will continue to function in the same way as they do now.

Currently the referrer meta tag is not currently supported in all browsers. I tried it using Chrome 17 and it is working. Testing it in Safari 5.1.4 and Firefox 11, the referrer meta tag has no impact.

So what does this mean as far as SiteCatalyst reporting? According to the Knowledge Base answer #5329, “If the domain of the referrer corresponds to that of a recognized search engine (e.g. “google.com”) and contains the recognized search keyword query parameter for the given search engine domain (e.g. for Google this is “q=”), then the referrer is considered a search engine, and the value of the keyword query parameter is taken as the search keyword.” So no search keyword query parameter, no search is counted. Currently for a Google secure search, the parameter is still there, but it’s unpopulated. Now Google plans to remove it all together.

Hopefully before Google rolls this out publicly Adobe will come up with a solution for SiteCatalyst so there are no interruptions in the Search Engine reporting. If Adobe does not get to it in time, or if Google decides to push the change out before April, then a couple of lines of code added to your s_code.js file will keep the impact to a minimum while Adobe works out a solution.

if(document.referrer=="https://www.google.com/"){
	s.referrer="https://www.google.com/?q=google%20secure%20search";
}

What this will do is look for a referrer with the exact value of https://www.google.com/ and append a q= value to it with the keyword of google secure search. If the .com version of Google is not the one most used by your visitors, then just replace it with the correct tld version applicable to your site. This snippet of code will make sure the search is still counted, and you will continue to keep the same level of reporting that you have now.

UPDATE: If your your visitors are coming to your site from multiple country specific versions of Google, then I have you covered. Just include this plugin in your s_code file and all Google secure searches from every Google domain will automatically be handled. All you need to do is cut and paste.

s.getGoogle=new Function(""
+"var s=this,a=document.referrer,b=a.split('/')[3],c=a.substring(0,19"
+");a&&26>=a.length&&(b||c=='https://www.google.'&&(this.s.referrer=a"
+"+'?q=google%20secure%20search'));return this.s.referrer")();

enjoy!

Improve Accuracy & Identify Traffic That SiteCatalyst Can’t

I’ve been doing a lot of work recently with my Traffic Sources reports. My goals have been to clean up messy data that could come in, and to make it easier to look at traffic from different sections of the same referrer. Now I would like to see what I can do to make the standard Referrer and Referring Domains reports a little more accurate, and try to fill in some of the holes they create which prevent me from getting a really good summary view of my traffic.

Overall the standard Referrer and Referring Domains reports do a pretty good job at telling me where my visitors came from, but there is one item that is a major problem for me. That one item is called “Typed/Bookmarked”.

According to the SiteCatalyst Knowledge Base, “Typed/Bookmarked line items occur in reporting where a referrer for an image request is not present.” So in other words, if SiteCatalyst does not see a referrer value, then it simply can not tell you where that visitor came from, so they get dropped into the Typed/Bookmarked bucket. Typically that’s fine. There is no way to know completely where every single one of your visitors came from. Thats just the nature of the beast. But one problem I have is that even though SiteCatalyst may not know where that visitor came from, I possibly do. So how do I know but SiteCatalyst doesn’t you ask? Tracking codes.

Yesterday Omniture shared a study that was done by BtoB Magazine which said “email is used by 88% of marketers surveyed and ranked as their No. 1 form of digital outreach”. Its been no secret that running email campaigns is a great way to get more visits for your site, and ultimately more conversions. Judging by my inbox there are a lot of marketers out there that agree. Email marketing best practices recommend that tracking codes are included on all of the URL’s in the email. This is typically the best way to determine the effectiveness of those email campaigns, and hopefully it’s something you’ve been doing with your own email campaigns. The problem with this is that most email applications are not going to pass a referrer value to the site. So even though we are able to track the performance of these emails in our campaign reporting, when looking at our Referrer reports we are not able to see that traffic credited to the correct source. No referring value means the Traffic Sources reports consider it to be Typed/Bookmarked traffic, when we know it isn’t. Our Typed/Bookmarked values get over inflated, and the email campaign traffic doesn’t get properly credited. So what can be done about it?

Here’s what I like to do. I add in a tiny bit of code to the doPlugins section of my s_code.js file that checks to see if the image request has no referring URL, and if the current URL has a tracking code associated with one of my email campaigns. If that criteria is met then inject a specific referring domain value to my traffic sources report, correctly attributing that visit as being from one of my email campaigns. The code to do this is quite simple:

if(!document.referrer){
	var s_eml = s.getQueryParam('eml');
	if(s_eml){s.referrer="mail://email.campaign/"+s_eml;}
}

Now lets say I’m running an email campaign which contains links to my home page. I made sure that the URL’s for those links have the query string parameter eml=56789. The parameter eml is the tracking code I use specifically for my email campaigns, and 56789 is the identifier for that specific campaign. When a visitor tries to access a page of my site using one of those URL’s containing my email tracking code and they do not have a referring URL value, my normal campaign tracking does it’s job, and this new snippet of code inject’s the value of mail://email.campaign/56789 as the referring domain. If the visitor was using using an email application that did pass a referrer value, then that passed value will always take precedence. Injecting that new value as the referring URL will accomplish a couple of things. First that whole value will now appear in my Referrers report. With that I’m able to compare the traffic generated from specific email campaigns to other traffic sources. Comparing traffic generated from an email campaign to traffic generated from an organic source wasn’t always the easiest thing to do in a single SiteCatalyst report.
Email Referrer

Next in my Referring Domains report I will get the value of email.campaign, and more importantly I won’t register another instance of Typed/Bookmarked. With this I can get a look at the traffic generated from the email campaign compared to all my other known referrers as a whole to see how it stacks up.
Email Referring Domains

Here’s an additional bonus I get from doing this. If you take a look at that URL value I used as the referrer value, it does not begin with http://, but it begins with mail://. In the Traffic Sources reports you will find a report called Referrer Type. This report is basically a glorified SAINT classification that looks at each referring URL and assigns it to a different bucket. When a SiteCatalyst see’s a referring URL beginning with the value of mail:// or the value of imap:// it then gets classified to the Mail bucket in the Referrer Type report. I’m now starting to get a better view of all my traffic sources in one pretty graph.

Email Referrer Types

Another source of traffic for some sites that is also not being accurately represented in the Traffic Sources reports is when a visitor comes to the site by clicking a link in a pdf. Last week after the latest iPad was announced, a friend sent me a pdf that came from Apple about using the iPad at Work. It contained good information, so I passed it along to a couple of other friends. Looking at the pdf a little closer, there was one thing that caught my eye. It contained 25 individual links back to apple.com. I wasn’t viewing this email in a web browser but in the simple Preview app on my Mac, yet every single one of those links was clickable. I thought that was great, another opportunities to drive traffic to the site. But this was also not so great because it was another opportunities to take a visitor and classify them as being Typed/Bookmarked, even though Apple could know easily and specifically where they were coming from.

Much like with emails, all it takes is a tiny couple of lines of code to identify that traffic. I like to use the value of pdf= as the query string parameter for links embedded in pdf’s, but you can obviously change it to whatever you like.

if(!document.referrer){
	var s_pdf = s.getQueryParam('pdf');
	if(s_pdf){s.referrer="file://pdf.document/"+s_pdf;}
}

Just like before with the emails, the current URL needs to contain that tracking code and there must be no referrer value present for this to work.

Taking a look at that snippet of code, I used the referring URL domain value of file://pdf.document combined with a unique identifier for that pdf. Unlike with the email’s, this time I started the value with file://. This will now get assigned a new value in the Referrer Type report, the value of Hard Drive. Not the best description of what’s going on, but that’s the only value left. The Referrer Type report is set to classify all referrers into 6 different buckets, and there is no way to add any additional categories to it.

All Referrer Types

Another popular source of traffic I’ve seen that does not get proper credit in Traffic Sources reports are visits that come from a mobile application. There are tons of mobile apps which have some component to them that can take the visitor from the app to their website. Like all the other links, you hopefully have the ones in your mobile app tagged with a tracking code. If so then just one more snippet of code and that traffic can be accounted for:

if(!document.referrer){
	var s_app = s.getQueryParam('app');
	if(s_app){s.referrer="file://mobile.application/"+s_app;}
}

I used the tracking code of app, but you can use what ever you would like. This app referred traffic will also be listed in the referrer type report as Hard Drive. Since I used up all the options in that report, all the extras such as mobile app traffic and pdf traffic will need to share the Hard Drive bucket.

I like to keep all three snippets of code wrapped up in one clean package:

if(!document.referrer){
	var s_eml = s.getQueryParam('eml');
	var s_pdf = s.getQueryParam('pdf');
	var s_app = s.getQueryParam('app');

	if(s_eml){
		s.referrer = "mail://email.campaign/"+s_eml;
	}else if(s_pdf){
		s.referrer = "file:///pdf.document/"+s_pdf;
	}else if(s_app){
		s.referrer = "file:///mobile.application/"+s_app;
	}
}

Now in my Referrer and Referring Domains reporting, I get a better look at how my visitors are arriving to my site.
All New Referrers

All New Referring Domains

Maybe you have some other kind of web app, or some kind of shared widget, or some other totally different way for visitors to follow a link to get to your site. So long as you can add a tracking code to that link you can get that traffic correctly represented in your Traffic Sources reports, and stop over inflating the Typed/Bookmarked metric. This is not meant to replace the Marketing Channels reports, the Channel Manager plugin, or the Unified Sources VISTA rule, but to improve the functionality and accuracy of some of the core SiteCatalyst reports.

I hope this helps.
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.

Don’t Forget Your SiteCatalyst Utility Functions!

Have you ever tried to use a new plug-in and found it did not work? You were probably missing a utility function. Utility functions are designed to work with SiteCatalyst plug-ins. There are 6 utility functions that are commonly used. They are apl, p_c, p_gh, split, replace, and join.

These functions do things like join elements of an array into a string delimiter by a string, replaces characters in a string, splits a string on a specific character, append a value to any delimited lists, and more. THese utility functions are referenced by several standard plug-ins.

Here’s how I do it. I take all these utility functions and wrap them all up in one neat package, and include this as one of my standard plug-ins to add when creating a s_code file. This way not thing is missed, nothing is forgotten and all of my plug-ins will work no problem.

Here’s what it looks like:

/*
 * Utility Functions: apl, p_c, p_gh, split, replace, join
 */
s.apl=new Function("L","v","d","u",""
+"var s=this,m=0;if(!L)L='';if(u){var i,n,a=s.split(L,d);for(i=0;i<a."
+"length;i++){n=a[i];m=m||(u==1?(n==v):(n.toLowerCase()==v.toLowerCas"
+"e()));}}if(!m)L=L?L+d+v:v;return L");
s.p_c=new Function("v","c",""
+"var x=v.indexOf('=');return c.toLowerCase()==v.substring(0,x<0?v.le"
+"ngth:x).toLowerCase()?v:0");
s.p_gh=new Function(""
+"var s=this;if(!s.eo&&!s.lnk)return '';var o=s.eo?s.eo:s.lnk,y=s.ot("
+"o),n=s.oid(o),x=o.s_oidt;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);x=o.s_oidt}}return o.href?o.href:'';");
s.split=new Function("l","d",""
+"var i,x=0,a=new Array;while(l){i=l.indexOf(d);i=i>-1?i:l.length;a[x"
+"++]=l.substring(0,i);l=l.substring(i+d.length);}return a");
s.repl=new Function("x","o","n",""
+"var i=x.indexOf(o),l=n.length;while(x&&i>=0){x=x.substring(0,i)+n+x."
+"substring(i+o.length);i=x.indexOf(o,i+l)}return x");
s.join = new Function("v","p",""
+"var s = this;var f,b,d,w;if(p){f=p.front?p.front:'';b=p.back?p.back"
+":'';d=p.delim?p.delim:'';w=p.wrap?p.wrap:'';}var str='';for(var x=0"
+";x<v.length;x++){if(typeof(v[x])=='object' )str+=s.join( v[x],p);el"
+"se str+=w+v[x]+w;if(x<v.length-1)str+=d;}return f+str+b;");

I just make sure that is block is included in every s_code file. Then I am assured that every plug-in I use can find the correct utility function it needs to work properly.

Enjoy!

Optimize the Time Parting Plugin to get More Detail and Use Less Variables

The Time Parting Plug-in is one of the more popular SiteCatalyst plug-ins available. A standard implementation of the Time Parting plug-in will consume 3 variables. One for Time of Day, one for the Day of Week, and one for Weekday/Weekend. How can we improve this to get more information, and more importantly use less variables? Here is how I have been doing it.

I use a combination of stacking the variables and SAINT uploads. For those of you who are not familiar with SAINT, Omniture describes it as, “…an acronym for SiteCatalyst Attribute Importing and Naming Tool. This tool enables you to download the classifications template, apply attributes to it, and then upload the data, thereby enhancing your SiteCatalyst reports with the new attributes.” This will allow us to upload a lot of detail about any variable you record.

Here’s how I’m doing it on this site. First I am using the 2.0 version of the plug-in and not the 1.4 version that I describe in a previous post. The 2.0 version includes support for Daylight Savings time and globalizes the year. You can find the 2.0 version from the SiteCatalyst Knowledge Base. If you prefer to use the 1.4 version, you can find it on this site.

/* Set Time Parting Variables */
s_hour=s.getTimeParting('h','-5'); 
s_day=s.getTimeParting('d','-5');
s_timepart=s_day+"|"+s_hour;
s.prop16=s_timepart.toLowerCase();
if (s.visEvent) s.eVar16=s.prop16;   

Ok, let me explain whats going on here. As I said before the Time Parting plug-in captures 3 variables. If you notice in my code I am only using two of them. I don’t need to capture Weekday/Weekend anymore. I will take care of that later. The other two, I capture in two blank variables I created, s_day and s_hour. Next I combine the two of them in a single variable I call s_timepart, separated by a pipe. Then to ensure everything is consistent I copy the variable in all lower case to the prop that I am going to use. This next part is a little different. In the eVar I only want capture this value once per visit. Typically a simple getValOnce will be enough to get it done. Well then what happens when the visit extends from one time part into another? In that situation the Time Parting value will be different and therefore getValOnce will capture this as a new value since it has changed. I don’t want that to happen, I only want it once per visit. So this is when I tie in using the get Visit Start plug-in. This guarantees I will only capture the value only one time per visit.

This will return a report that looks like this:
Time Parting Report in SiteCatalyst

We now have a total of 672 possible options in this report. The next thing we want to do is to classify these using SAINT. I set up 5 different categories to use. Weekday/Weekend (this is why we don’t need to capture it in the code, Day of Week, Hour of Day, Hour Part and AM/PM.
SAINT Setup

I then created the template to use that contains all of these values.
SAINT Template
You can download a copy of the template that I use here.
Upload the template and that’s all there is to it. Do you have more conversions in the bottom of the hour or the top of the hour? How about morning vs afternoon? Which whole hour is the most profitable? Now you have an easy way to break down your time parting with finer granularity, at the sime time saving your self a couple of variables.

Enjoy!

Enhance Your SiteCatalyst S_Code Using Server-Side Scripting

I receive a lot of questions from people working on their own SiteCatalyst implementations and I’m always happy to help. One that I got recently is “why is your s_code file a php file”? I figured there were not too many people out there doing it like this or even know about this, so I thought I would help out those that were interested in what the advantages of using server side code to enhance your data collection.

The reason I use a php file to house all of my s_code script is simple. I want to be able to do what is not easily done with using standard JavaScript. Here are a couple of examples.

First things first. How do I get a php file to act like JavaScript? It’s actually pretty easy. First thing you do is in the top of your file add this small bit of code:

<?php header('Content-type: application/javascript'); ?>

The purpose of this line is just to say ‘hey, unless instructed otherwise, treat everything you are going to see here as JavaScript. Next change your file extension from .js to .php. That’s all you need to do to start adding in some php scripting into your file.

Here are some things I am using it for. I like capturing the IP address of my visitors. I like to track this because I have had problems with spammers, scraper bots and general bad visitors in the past, and I just like keeping my eye on things. Here is the code to capture IP address.

s.eVar17="<?php echo $_SERVER['REMOTE_ADDR']?>";

I also have this matched with the get Val Once plug-in.

Another thing I like to capture is User Agent. How many people come to my site from a specific build of IE6? Is Googlebot executing my JavaScript when crawling my site? Here is how I capture User Agent.

s.eVar23="<?php echo $_SERVER['HTTP_USER_AGENT']?>";

Again I match this up with the get Val Once plug-in.

Another thing I like to do is use php to populate the configuration variables of the Time Parting plug-in. The latest version of the plug-in, 2.0, uses specific daylight savings time variables (the 2.0 version is available from the Omniture Help section. The version I host here on the site is the older 1.4 version). The 3 variables that need to be configured for the plug-in are Daylight Savings Time start day for the current year, Daylight Savings Time end day for the current year, and the Current Year. Now all of these can be hard coded, but I’d rather do a little bit of one time coding and never have to worry about it again. Here is how I set those variables using php.

s.dstStart="<?php echo date('m/d/Y', strtotime("Second Sunday March 0"));?>";
s.dstEnd="<?php echo date('m/d/Y', strtotime("First Sunday November 0"));?>";
s.currentYear="<?php echo date('Y');?>";

All of these take advantage of the date() functionality of php. Combine that with a little bit of extra code, and with the fact that I know that daylight savings time always begins the second Sunday of March and ends on the first Sunday of November, I never need to touch those variables again.

Increase SiteCatalyst Clickmap Functionality with Dynamic Object IDs Plug-in

ClickMap. Pretty useful tool. It gives you a neat overlay that shows you what links are clicked on a page and the associated traffic. I wonder how we can make it better? Knock knock. Oh who is that at the door? Why its the Dynamic Object IDs Plugin. Please step right in.

The Dynamic Object IDs Plug-in dynamically adds an object ID to the click thru URL. You can see it using the debugger. It is designed to improve the function of the Clickmap.

Let’s take a look at an example. From the home page of this site, there are 3 links that take you to the Contact page. I click the last one on the page, then open the debugger on the page I land on. Here you can see that the click thru URL has been appended with the number of the order that it happened to appear in on the page. So now when I have multiple links on a single page each one is easily spotted in the debugger, even though they all have the same anchor text and click thru URL.
Dynamic Object ID Plug-in

Now what do we get? If you look at the clickmap report, Site Content>Links>ClickMap, you will now see a number attached to each URL.
Clickmap Report
Now you know exactly which link was clicked.

Here is how I have it implemented on this site. Before the function s_doPlugins(s) I include the code:

/* DynamicObjectIDs config */
function s_getObjectID(o) {
	var ID=o.href;
	return ID;
}
s.getObjectID=s_getObjectID

Then within the s_doPlugins(s) function, I include:

/* To setup Dynamic Object IDs */
s.setupDynamicObjectIDs();

And finally in the Plug-ins section I have the plug-in code itself.

/*
 * DynamicObjectIDs
 */
s.setupDynamicObjectIDs=new Function(""
+"var s=this;if(!s.doi){s.doi=1;if(s.apv>3&&(!s.isie||!s.ismac||s.apv"
+">=5)){if(s.wd.attachEvent)s.wd.attachEvent('onload',s.setOIDs);else"
+" if(s.wd.addEventListener)s.wd.addEventListener('load',s.setOIDs,fa"
+"lse);else{s.doiol=s.wd.onload;s.wd.onload=s.setOIDs}}s.wd.s_semapho"
+"re=1}");
s.setOIDs=new Function("e",""
+"var s=s_c_il["+s._in+"],b=s.eh(s.wd,'onload'),o='onclick',x,l,u,c,i"
+",a=new Array;if(s.doiol){if(b)s[b]=s.wd[b];s.doiol(e)}if(s.d.links)"
+"{for(i=0;i<s.d.links.length;i++){l=s.d.links[i];c=l[o]?''+l[o]:'';b"
+"=s.eh(l,o);z=l[b]?''+l[b]:'';u=s.getObjectID(l);if(u&&c.indexOf('s_"
+"objectID')<0&&z.indexOf('s_objectID')<0){u=s.repl(u,'\"','');u=s.re"
+"pl(u,'\\n','').substring(0,97);l.s_oc=l[o];a[u]=a[u]?a[u]+1:1;x='';"
+"if(c.indexOf('.t(')>=0||c.indexOf('.tl(')>=0||c.indexOf('s_gs(')>=0"
+")x='var x=\".tl(\";';x+='s_objectID=\"'+u+'_'+a[u]+'\";return this."
+"s_oc?this.s_oc(e):true';if(s.isns&&s.apv>=5)l.setAttribute(o,x);l[o"
+"]=new Function('e',x)}}}s.wd.s_semaphore=0;return true");

To see this code in the s_code file running this site, you can check it out here.

Ok great. Now what else can we do with this plug-in? Lets say I want to track how many contact form submissions I received from clicking the third Contact link that appears on the Home Page? Well I could add a custom onclick function. I could add a tracking code on the end of the click thru URL. But how can I use this new plug-in to track this?

Recently there was a post on the Omniture blog about using Dynamic Variables. Using these variables we can now grab the value of oid, which is the click thru URL with the new object id added to it, and you can get the pid which is the page the click happened on. I have it set up on this site:

s.prop20=s.eVar20="D=oid";
s.prop22=s.eVar22="D=pid";

Now with a simple subrelation I can get what link was clicked on what page and what events occurred, all without adding any additional code to the page.

Enjoy!

How To Add Page Views And Visits To All SiteCatalyst eVars

Here is a simple way to add Page Views and Visits to all of your eVar reports (see the update below). While Client Care has the ability to turn on a few things, flip some switches here and there to add visits to some reports, I like having full control over it as much as possible myself (and I’m not really in the mood to wait on hold to get it done). To make this happen we are going to have to use 2 events and a pair of plug-ins. Hopefully you should have a couple of events available to use, and you can find the plug-in code on the SiteCatalyst Plugins page. Here’s how to do it.

First lets get Page Views. To do this we are going to use the Append List plug-in. The Append List (or apl) plug-in utility provides a simple mechanism to append a value to any delimited lists, with the option of a case sensitive or case-insensitive check to insure the value doesn’t already exist in the list. The apl plug-in is referenced by several standard plug-ins but can be used directly in a variety of situations. This is an Omniture supported plug-in and you can find more information about it by accessing the Knowledge Base.

s.apl(L,v,d,u)

L = source list, empty list is accepted
v = value to append
d = list delimiter
u (optional, defaults to 0) Unique value check. 0=no unique check, value is always appended. 1=case insensitive check, append only if value isn’t in list. 2=case sensitive check, append only if value isn’t in list.

What we are going to do is in the s_code.js file, set up this plug-in to fire off an event on every single page view of the site, exactly mimicking the standard Page View metric.

/* Set Page View Event */
s.events=s.apl(s.events,'event1',',',1);

Here is the plug-in code:

/*
* Plugin Utility: apl v1.1
*/
s.apl=new Function("L","v","d","u",""
+"var s=this,m=0;if(!L)L='';if(u){var i,n,a=s.split(L,d);for(i=0;i<a."
+"length;i++){n=a[i];m=m||(u==1?(n==v):(n.toLowerCase()==v.toLowerCas"
+"e()));}}if(!m)L=L?L+d+v:v;return L");

UPDATE: In my eagerness to share this with everyone I skipped the testing process I usually do. Upon testing I realized I a critical, basic error in my logic. By doing it this way, you are setting an event prior to any of the eVars, so they would not be associated with each other, and there for show up as “None” in your report. It is such a simple oversight that I am actually embarrassed that I missed. So now I throw it out to you, the Omniture community, how do you guys think we should try to figure this one out? Or is it even possible to do? Let me know what you think!

Just to be super clear, this will work if you want to add visits to some of your Traffic Sources reports. For example if you want visits from the original referring domains, this will work perfectly for that.

Now lets get Visits. I thought a lot about how to get this. One method you could use would be do the exact same thing we did to get the Page Views event. Set it up on a different event, then call up Omniture Client Care to have them set that event to only record once per visit. Again I wanted to try to avoid using Client Care. I also did not want to go that route since I want this to mimic the Visits metric as close as possible, so I want it to be cookie based. Here I decided to use the Get Visit Start plug-in.

What the Get Visit Start plug-in was designed to do is to determine first page of a visit. It returns 1 on the first plug-in call of the visit, otherwise returns nothing. It uses a 30 minute cookie if possible, otherwise reverts to a session cookie. Always returns nothing if 30 minute or session cookie can’t be set, so it functions very much like the standard Visit’s metric. What I have done is set the plug-in up to populate a variable, then use basic JavaScript to determine if there is a value to the variable that was just set, and if so fire off the Append List plug-in. The theory behind this is the Get Visit Start plug-in will only return a value one time per visit, on the first page view, and at that one and only time fire off a single event.

s.getVisitStart(c)

c=cookie name for tracking (“s_visit” is standard)

Here is how I have it set up. I made up a variable s.visEvent to hold the value of the Get Visit Start Plugin, then fire off event6 if it has a value.

	
/* Set Visit Event */
s.visEvent=s.getVisitStart("s_visit");
if (s.visEvent) s.events=s.apl(s.events,'event6',',',1);

Here is the plug-in code:

/*
 * Get Visit Start
 */
s.getVisitStart=new Function("c",""
+"var s=this,v=1,t=new Date;t.setTime(t.getTime()+1800000);if(s.c_r(c"
+")){v=0}if(!s.c_w(c,1,t)){s.c_w(c,1,0)}if(!s.c_r(c)){v=0}return v;");

Pretty simple. Typically I would have just used the Get Val Once plug-in when I want to get a value of a variable only once per visit, but it didn’t want to work well with the s.events variable.

Enjoy!