My wife and I watched the movie High Fidelity on TV with friends over the week­end, so “top five” lists are on my brain. When I arrived at work on Mon­day, I imme­di­ately started brain­storm­ing the top five imple­men­ta­tion issues that make their way through the Client­Care orga­ni­za­tion here at Omniture.

My cri­te­ria in review­ing issues and com­ing up with this list were 1.) the fre­quency with which Client­Care sees the issue or some­thing related to it and 2.) the trick­i­ness of the issue. (For exam­ple, not ref­er­enc­ing the s_code.js file cor­rectly might be a com­mon issue, but I’m not going to blog about it because it’s fairly eas­ily caught, diag­nosed, and solved by the rock stars man­ning phones, e-mail, and chat for Client­Care. It doesn’t make for very inter­est­ing discussion.)

The imple­men­ta­tion prob­lems I’ll explain below may or may not be affect­ing your site; because Site­Cat­a­lyst imple­men­ta­tions vary so widely, even the most com­mon prob­lems do not come up all that often. Still, even if your cur­rent imple­men­ta­tion seems per­fect, know­ing these “gotchas” may well save you from headaches in the future, and at the very least will hope­fully explain some of the intri­ca­cies of the Site­Cat­a­lyst JavaScript code’s basic functionality.

1. Code in the <head> tag

Don’t do it. The attrac­tion used to be that plac­ing the Site­Cat­a­lyst code in between the <head> and </head> tags pre­vented the 1×1 pixel image that was returned by the request that sent data into our servers from affect­ing your page lay­out in any way, but this isn’t how the code works any­more. It now cre­ates an image object—a non-visible image that doesn’t show up on your page at all. Beyond that, putting the code in the doc­u­ment head also means that the code appears ear­lier in the code, allow­ing it to exe­cute sooner, which is sig­nif­i­cant inas­much as it allows you to count page views for par­tial page loads more effectively.

Sounds great. But here’s the prob­lem: Cer­tain ele­ments of the code require the exis­tence of the body object. Since web browsers exe­cute code in the order they receive it, if the Site­Cat­a­lyst JavaScript code is in the doc­u­ment head, then it exe­cutes before the body object exists. As a result, you don’t get ClickMap data. You don’t get auto­matic track­ing of file down­loads or exit links. You also don’t get Con­nec­tion Type data or Vis­i­tor Home Page data. Tech­ni­cally, putting the code in the doc­u­ment head will work, but you’ll get a very lim­ited ver­sion of Site­Cat­a­lyst and your users may begin to won­der why ClickMap isn’t dis­play­ing anything.

2. Use of s.linkTrackVars and s.linkTrackEvents

A few weeks ago, I wrote about link track­ing, of which Site­Cat­a­lyst offers two basic ver­sions: auto­matic and cus­tom. Cus­tom link track­ing is gen­er­ally used to track user actions, such as link clicks and inter­ac­tions with Flash appli­ca­tions on your site; the auto­matic ver­sion tracks file down­loads and exit link clicks for you.

Key to a suc­cess­ful link track­ing imple­men­ta­tion is an under­stand­ing of the s.linkTrackVars and s.linkTrackEvents vari­ables, which allow you to pass cus­tom vari­able val­ues on these user actions. If you are imple­ment­ing cus­tom link track­ing and want to pass vari­ables and events, make sure that your s.linkTrackVars vari­able con­tains a comma-separated list of all vari­ables that you will be pass­ing, includ­ing the events vari­able. Make sure that s.linkTrackEvents includes a comma-separated list of all events that you will be pass­ing. Note that set­ting s.linkTrackVars and s.linkTrackEvents does not actu­ally set these variables/events; it only pre­pares the Site­Cat­a­lyst code to do so. You still need to set the vari­ables man­u­ally, as shown in the exam­ple below.

Link Tracking Example

Notice that “events” is listed in the s.linkTrackVars vari­able; the indi­vid­ual events that may be passed are included in the s.linkTrackEvents vari­able and are also included within s.events. Each of the vari­ables that are passed are listed in s.linkTrackVars before they are pop­u­lated later in the func­tion. Also, as described above, I have included “event9” in s.linkTrackEvents, but have not included it in s.events. It will not be passed, but could be passed if I had included it in s.events.

Note that auto­matic file down­load and exit link track­ing works dif­fer­ently. You have prob­a­bly seen that s.linkTrackVars and s.linkTrackEvents are included in the basic s_code.js file that you received when you began your imple­men­ta­tion, and both are set to “none.” You may have won­dered why I am not rec­om­mend­ing set­ting those vari­ables within the global JavaScript file so that you do not need to worry about set­ting them when using cus­tom link track­ing. The rea­son is that auto­matic link track­ing will use the s.linkTrackVars and s.linkTrackEvents val­ues that you set in the global JavaScript file and will pass what­ever the exist­ing val­ues of those vari­ables are.

For exam­ple, let’s say that on page load, s.channel=“Home.” Now, let’s say that you have s.linkTrackVars=“channel” in your s_code.js file. If a user clicks to down­load a file, auto­matic file down­load track­ing will pass data into Site­Cat­a­lyst, includ­ing the value of s.channel that was set on page load. “Home” will be passed a sec­ond time, lead­ing to infla­tion in page view data for this value in the Site Sec­tions report. This can be even more damaging

Thus we strongly rec­om­mend leav­ing the s.linkTrackVars and s.linkTrackEvents set to “none” in the global JavaScript file, and set­ting them explic­itly as nec­es­sary with your cus­tom link track­ing implementation.

3. Seem­ingly inno­cent mis­takes in s.products

I don’t think any­one would argue with me if I said that the s.products vari­able is the most syn­tac­ti­cally com­plex vari­able that Site­Cat­a­lyst offers. Com­mas, semi-colons, pipes, and equals signs all play spe­cific roles in the vari­able. It has no over­all max­i­mum length, but each indi­vid­ual prod­uct entry can­not be longer than 100 bytes. Mis­takes in imple­men­ta­tion of this vari­able are under­stand­able, but unfor­tu­nately for devel­op­ers s.products is often a site’s most impor­tant vari­able, as it makes pos­si­ble the track­ing of rev­enue, units, prod­uct names, etc.

This vari­able is explained in detail in the Site­Cat­a­lyst Imple­men­ta­tion Man­ual and the online Knowl­edge Base, but here are a few extremely easy-to-make mis­takes that can wreak havoc on any implementation.

Make sure that your cat­e­gory, prod­uct name, and rev­enue totals are devoid of com­mas and semi-colons. The comma is used to sep­a­rate entries in the s.products string, as hap­pens when you have two prod­ucts in the same trans­ac­tion; the semi-colon is used to delimit fields within an entry. If you use a comma or semi-colon in any other way, Site­Cat­a­lyst will assume that you are sep­a­rat­ing prod­uct entries. Con­sider the fol­low­ing example:

s.products=“widgets;large wid­get, 40’x40’;1;19.99,wugs;tiny wug;2;1,999.98″;

In this imple­men­ta­tion, it is obvi­ous that the devel­oper intended for Site­Cat­a­lyst to read this as:

Cat­e­gory 1: wid­gets
Prod­uct 1: large wid­get, 40’x40’
Units 1: 1
Rev­enue 1: 19.99
Cat­e­gory 2: wugs
Prod­uct 2: tiny wug
Units 2: 2
Rev­enue 2: 1,999.98

How­ever, note the com­mas in the “Prod­uct 1″ and “Rev­enue 2″ entries. These indi­cate a new prod­uct entry. Site­Cat­a­lyst would actu­ally inter­pret the above as:

Cat­e­gory 1: wid­gets
Prod­uct 1: large wid­get
Cat­e­gory 2: 40’x40’
Prod­uct 2: 1
Units 2: 19.99
Cat­e­gory 3: wugs
Prod­uct 3: tiny wug
Units 3: 2
Rev­enue 3: 1
Cat­e­gory 4: 999.98

If you see a “1” as a line item in the Prod­ucts report, this is almost cer­tainly what is happening.

Make sure that your prod­uct and cat­e­gory names do not con­tain unsup­ported char­ac­ters. This is espe­cially dif­fi­cult in the s.products string, because prod­uct names are often likely to con­tain char­ac­ters such as ™, ©, and ®. These will need to be stripped out of the prod­uct and cat­e­gory val­ues before they are placed into s.products. You will also need to make sure that cur­rency sym­bols are not included in your rev­enue val­ues. Sup­ported char­ac­ters are num­bers 1–127 from the ASCII table.

4. White space in vari­able values

Take a look at the fol­low­ing example:

<head>
   <title>
      Home Page
   </title>
</head>
<body>
<script language="javascript">
      s.pageName=document.title
</script>

Looks inno­cent enough; we’re using document.title to pop­u­late s.pageName, so s.pageName should receive a value of “Home Page.” The prob­lem is that not all browsers will inter­pret this the same way because of the white space before “Home Page” in between the <title> and </title> tags. Some browsers will strip out this lead­ing white space, but oth­ers will not.

The result is that you will end up pass­ing either this:

s.pageName="Home Page"

or this:

s.pageName="      Home Page"

and may not know it, until you notice that Site­Cat­a­lyst han­dles this sce­nario in an inter­est­ing way. It will treat these as dis­tinct val­ues, but the report­ing inter­face will also strip out the lead­ing white space. The result is a report which looks like this:

Pages Report

To make mat­ters worse, SAINT does not allow lead­ing white space in a key value, which means that it can­not be used to “group” mul­ti­ple line items as a workaround if this issue is affect­ing your site. The only way to fix the prob­lem is to pre-process the desired vari­able value (in this case, the title prop­erty) to remove any lead­ing (or trail­ing, I might add) white space.

(Note that I am using the s.pageName vari­able with the document.title prop­erty as an exam­ple. Omni­ture does not rec­om­mend using document.title as the page name, nor does this issue only affect the s.pageName vari­able. Any vari­able that may have leading/trailing white space in its value can be affected.)

5. Not set­ting the off­set when call­ing s.Media.play() and s.Media.stop().

This one per­tains only to Media Track­ing in JavaScript and Action­Source. Two key method calls that help you under­stand how end users are inter­act­ing with your videos are s.Media.play() and s.Media.stop(), which are sim­i­lar in that they both require two arguments:

s.Media.play(mediaName, mediaOffset)
s.Media.stop(mediaName, mediaOffset)

For exam­ple, when the user pushes the “Play” but­ton ini­tially, you might call s.Media.play(‘My_Video’,0). Now let’s say the user pauses the video after 10 sec­onds because he notices that he’s spilled cof­fee all over him­self. There, you would call s.Media.stop(‘My_Video’,10). Once he’s cleaned him­self up, he real­izes he’s going to be late to a meet­ing and doesn’t have time to watch the whole video. He drags the progress bar to the 45-second mark and clicks “Play” again. This time, you would call s.Media.play(‘My_Video’,45).

The sec­ond argu­ment, mediaOff­set, may at first seem triv­ial. Its def­i­n­i­tion is “The num­ber of sec­onds into the video that the play (or stop/pause, for s.Media.stop) occurs. Spec­ify the off­set based on the video start­ing at sec­ond zero.” Why is it impor­tant to tell the method at what point dur­ing play­back the play/stop/pause event occurred? Well, in part because if this is not spec­i­fied, the video data that is passed will be dis­carded. If this argu­ment is left out of s.Media.play and s.Media.stop, the image requests that pass the video data into Site­Cat­a­lyst will con­tain “NaN” (which stands for “not a num­ber”) val­ues where these num­bers should be, which tells Site­Cat­a­lyst that it doesn’t have valid infor­ma­tion about the video playback.

If you are debug­ging this your­self, look for the pev3= para­me­ter in the image request. If it ends with val­ues such as S0E10S45E70, your imple­men­ta­tion is sound. This can be inter­preted as “started at zero, ended at 10 sec­onds; started again at 45 sec­onds, ended at 70 seconds.”

As I sug­gested at the begin­ning of this post, these issues may be affect­ing some of you, but the odds are that you haven’t run up against these issues in the past. If not, great. If so, hope­fully this helped you under­stand what went wrong and how to get back on track. If you’ve got other issues that you’ve seen trip up oth­er­wise suc­cess­ful imple­men­ta­tions, I’d love to hear about them—some of them might even make for great blog posts (I won’t men­tion you or your com­pany by name, of course!). Feel free to leave me a com­ment, or con­tact me via Twit­ter (Omni­ture­Care) or by e-mail (my twit­ter user­name at omni­ture dot com).

  • http://www.actualinsights.com Matthew Nieder­berger

    Hi Ben,
    Great lit­tle arti­cle on some of the pit­falls of a Site­cat­a­lyst imple­men­ta­tion. This is really use­ful. Those not imple­ment­ing code every­day can use this as a mini refresher course of what points to con­sider when per­form­ing an imple­men­ta­tion. It would be good to see more of these short, rich in knowl­edge arti­cles!
    Take care,
    Matthew

  • http://emptymind.org Jason

    Another great post Ben. Can I tell you the the biggest imple­men­ta­tion gotcha that I saw as an imple­men­ta­tion con­sul­tant? Incor­rect path to the JS file. Seem­ingly so sim­ple, yet when errors occur it is often over looked to check the sim­ple things.

    I can remem­ber many calls going some­thing like this:

    Client: omni­ture is broken

    Jason: the path to your JS file is incorrect

    Client: OMG, we have been look­ing at this for hours. thank you.

  • http://www.acceleration.biz Riaan Jacobs

    Hi Ben,

    Great arti­cle and really clar­i­fies the rea­son­ing behind the imple­men­ta­tion best prac­tices. As noted, the incor­rect path to the s_code.js include file is a very com­mon mis­take which is eas­ily picked up by the Site­Cat­a­lyst JavaScript Debug­ger (which would imme­di­ately show that no image request has occurred) but what I did find also hap­pens quite often is that the incor­rect report suite id is used. Case in point, we had a client who mistyped “tourism” as “toruism” but was using the cor­rect spelling for weeks before we noticed the error.

    Another uncom­mon one which we have encoun­tered is that some­times generic s_code.js files which have not been gen­er­ated from the Code Man­ager in Site­Cat­a­lyst are sent to new clients and what hap­pens is that the incor­rect data col­lec­tion server id for that account is used. That’s why I insist on gen­er­at­ing all new code for clients directly from the code man­ager for that spe­cific report suite.

    With ref­er­ence to your first point about hav­ing the 1×1 pixel affect­ing the lay­out of a web page, we have only encoun­tered one client where it did actu­ally affect the lay­out of their menu. They had tried numer­ous ways of embed­ding the pixel in their JavaScript includes etc. but we came up with a very sim­ple solu­tion. We placed the s_code.js include file within a tag whose z-index was above any of their exist­ing CSS lay­outs and it worked perfectly.

    Look­ing for­ward to your fur­ther posts.

    Regards,
    Riaan

  • http://blogs.omniture.com/author/bgaines Ben Gaines

    Riann: Thanks for the com­ment. The 112/122 prob­lem could def­i­nitely have been on this list; it’s SO easy to miss, espe­cially for devel­op­ers imple­ment­ing for mul­ti­ple cus­tomers, some of whom may need 112 and oth­ers of whom may need 122 in s.dc. Your sug­ges­tion to always use a fresh set of code out of the Code Man­ager is a good one; it’s the best way to make 100% sure that the s.dc value is correct.

    And you’re right that the 1×1 pixel image doesn’t really cause lay­out issues; it used to be a prob­lem, but isn’t one any­more. The code now cre­ates an image object in the DOM that is not vis­i­ble on the page. Prob­lem solved.

  • RRS_ATL

    Very handy info. Sure wish I had found this a few weeks back :\

  • http://AdamDotCom.com Adam Kah­tava

    Great post.

    It would be great if you guys could mod­ify Omniture’s JavaScript includes. Things like adding a name­space, remov­ing the unneeded script post­fix (), and offer­ing an un-minified ver­sions of your JavaScript resources would make a devel­op­ers life easier.

    –Adam

    • http://blogs.omniture.com/author/bgaines Ben Gaines

      Thanks for these sug­ges­tions, Adam. I know from per­sonal expe­ri­ence that our JavaScript devel­op­ment team takes opti­miza­tion very seri­ously. I’ll make sure that they see your feed­back here.

  • http://www.jacksonhealthcare.com Will Crowther

    Hey Ben, Great article!

    What is the nor­mal way to enable Auto­matic link track­ing for exter­nal links and down­loads when you want to pass some cus­tom infor­ma­tion with the request
    with­out get­ting dou­ble results? Can the page request just be fil­tered out in the reporting?

    Right now the only way I can see to do it is to set the prop name in s.linkTrackVars, then pop­u­late the value of prop on the page.

    Will

    • http://blogs.omniture.com/author/bgaines Ben Gaines

      Will,

      Great ques­tion. In fact, it’s so great that sev­eral oth­ers asked some­thing sim­i­lar, lead­ing a col­league and I to develop a lit­tle piece of code that helps you do just what you’re sug­gest­ing. Take a look at my post enti­tled Enhanc­ing Auto­matic Exit Links for the details. (Obvi­ously, that code works for exit links, but not file down­loads. It could eas­ily be tweaked, how­ever, to use s.linkDownloadFileTypes instead of s.linkInternalFilters, and to use ‘d’ instead of ‘e’ in the s.tl() func­tion call.) One thing to note: Appar­ently, the blog shows the quotes in that code as smart quotes, which will break the JavaScript. Make sure to replace any smart quotes with straight quotes before deploying!

      Enjoy!

      Ben