Use Omniture’s Data Insertion API to avoid insanely long URL query strings

If you have not already found the Web Analytics Land blog, you need to check it out! I was re-reading another post out there A Robust SiteCatalyst Implementation Could Fail In Internet Explorer, where he talks about the issue you could face with a SiteCatalyst Implementation in IE is the URL string to the Javascript Beacon exceed 2083 characters.

From Web Analytics Land: Why do we need to care about this? It lies in an inherent deficiency of Internet Explorer. IE can not accept a URL that is longer than 2083 characters. If your implementation is pretty complex and you are passing in a lot of variables, your image request can easily approach if not exceed that amount. Since Microsoft still commands the lion’s share of the browser marketplace, this is something we need to keep an eye on. If this was a problem with Opera or another third or forth tier browser then we may not worry about it. But this is not the case with Internet Explorer.

I have made no effort to conceal my hatred of IE 6. timesup

However,  like many others out there, it is the reality that we have to deal with.  So I looked at the example url that was provided over at Web Analytics Land and wondered if I could take that url string and convert it into an xml object that I would then be able to use Omniture’s Data Insertion API instead of the Javascript Beacon to send as long of a data push as needed.

My plan was to using ColdFusion, my preferred development language, take the nasty url and convert it into a Structure and then build an XML document to post to Omniture.

First I needed to just copy the url string into a ColdFusion variable to begin the process.

<cfset variables.testurl2 = "AQB=1&pccr=true&vidn=2555563F85011AB6-6000010100004DB6&&ndh=1&t=26/5/2009%2016%3A47%3A53%205%20240&ns=classifiedventures1&pageName=results&g=http%3A//www.apartments.com/Results.aspx%3Fpage%3Dresults%26state%3Dva%26rgn1%3D141%26helicon%3D0%26area3%3Dy%26prvpg%3D5%26Rent_Minimum%3D0%26Rent_Maximum%3D99999%26twobdrm%3D1%26threebdrm%3D1%26fourbdrm%3D1%26am39%3D0%26am43%3D0%26am22%3D0%26am26%3D0%26am24%3D0%26am25%3D0%26am49%3D0%26am23%3D0%26am48%3D0%26am47%3D0%26am9%3D0%26am13%3D0%26am1%3D0%26am1&r=http%3A//www.apartments.com/Rent.aspx%3Fstate%3Dva%26rgn1%3D141%26page%3Dsubarea%26prvpg%3D3%26type_listing%3D1%26helicon%3D0%26Area3%3DY&cc=USD&events=event8%2Cevent11%2Cevent2&products=%3Bmanaged%3B%3B%3Bevent11%3D4%2C%3Bfrbo%3B%3B%3Bevent11%3D0%2C%3Bclassified%3B%3B%3Bevent11%3D13&h1=Apt%2Bresults%2Bresults%2Bresults%2Bresults&c2=17&v2=results&c5=national&v5=national&c6=results&v6=results&c7=results&v7=results&c8=results&v8=results&c9=none&c11=Data%20Not%20Available&v11=Data%20Not%20Available&c12=Data%20Not%20Available&v12=Data%20Not%20Available&c13=Data%20Not%20Available&v13=Data%20Not%20Available&c14=national&c15=national%3Aresults&v15=Less%20than%201%20day&c16=virginia&v16=national&c18=99999&v18=virginia&c19=0&v20=99999&c21=http%3A//www.apartments.com/Results.aspx%3Fpage%3Dresults%26state%3Dva%26rgn1%3D141%26helicon%3D0%26area3%3Dy%26prvpg%3D5%26Rent_Minimum%3D0%26Rent_Maximum%3D99999%26twobdrm%3D1%26threebdrm%3D1%26fourbdrm%3D1%26am39%3D0%26am43%3D0%26am22%3D0%26am26%3D0%26am24%3D0%26am25%3D0%26am49%3D0%26am23%3D0%26am48%3D0%26am47%3D0%26am9%3D0%26am13%3D0%26am1%3D0%26am15%3D0%26am16%3D0%26am30%3D0%26am4%3D0%26am5%3D0%26am6%3D0&v21=0&c22=Apt&c23=hampton%20roads%20%26%20vicinity&v23=SFH%3ACTD%3AFurnished&c24=virginia%20beach%20%26%20vicinity&v24=Four%3AThree%3ATwo&v25=map&c26=SFH%3ACTD%3AFurnished&c27=Four%3AThree%3ATwo&v27=Apt&c28=WasherDryer%3AInternet%3AKitchenDining%3ADishwasher%3ABDPP%3AAirCond&c29=map&v29=hampton%20roads%20%26%20vicinity&c30=Wheelchair%3AStorage%3APool%3AParking%3ALaundry%3AClubhouse%3ABusinessC%3ASpecialO&v30=virginia%20beach%20%26%20vicinity&c32=.&v33=0&c34=LargeDogs%3ASmallDogs%3ACats&c35=Priv_0%3ANews_13%3AManage_4&c36=national%3Aresults&c44=0&v49=national&s=1920x1200&c=24&j=1.7&v=Y&k=Y&bw=1918&bh=1019&p=Java%20Embedding%20Plugin%200.9.6.4%3BDefault%20Plug-in%3BWebEx%20General%20Plugin%20Container%3BPicasa%3BQuickTime%20Plug-in%207.6.2%3BShockwave%20Flash%3BDivX%20Web%20Player%3BSilverlight%20Plug-In%3BCoupons%20Inc.%20Plugin%3BFlip4Mac%20Windows%20Media%20Plugin%20%202.2.1%3B&pid=rent&pidt=1&oid=http%3A//www.apartments.com/images/btn_continue.gif&ot=IMAGE&AQE=1">

What a mess! Next I needed a Struct to be able to reference later that held the accepted XML tags for the Data Insertion API and the codes from the url.

NOTE: This is not meant to be a complete list of all options!

<!--- build static stuct for use in building the xml --->
<cfset variables.OmnitureXMLConverter = structnew()>
<cfset variables.OmnitureXMLConverter.bh = "browserHeight">
<cfset variables.OmnitureXMLConverter.bw = "browserWidth">
<cfset variables.OmnitureXMLConverter.v0 = "campaign">
<cfset variables.OmnitureXMLConverter.ch = "channel">
<cfset variables.OmnitureXMLConverter.c = "colorDepth">
<cfset variables.OmnitureXMLConverter.ct = "connectionType">
<cfset variables.OmnitureXMLConverter.k = "cookiesEnabled">
<cfset variables.OmnitureXMLConverter.cc = "currencyCode">
<cfset variables.OmnitureXMLConverter.events = "events">
<cfloop from="1" to="50" index="x">
 <cfset variables.OmnitureXMLConverter["c#x#"] = "prop#x#">
</cfloop>
<cfloop from="1" to="50" index="x">
 <cfset variables.OmnitureXMLConverter["v#x#"] = "eVar#x#">
</cfloop>
<cfloop from="1" to="5" index="x">
 <cfset variables.OmnitureXMLConverter["h#x#"] = "hier#x#">
</cfloop>
<cfset variables.OmnitureXMLConverter.hp = "homePage">
<cfset variables.OmnitureXMLConverter.v = "javaEnabled">
<cfset variables.OmnitureXMLConverter.j = "javaScriptVersion">
<cfset variables.OmnitureXMLConverter.pev2 = "linkName">
<cfset variables.OmnitureXMLConverter.Pe = "linkType">
<cfset variables.OmnitureXMLConverter.pev1 = "linkURL">
<cfset variables.OmnitureXMLConverter.pageName = "pageName">
<cfset variables.OmnitureXMLConverter.pageType = "pageType">
<cfset variables.OmnitureXMLConverter.g = "pageURL">
<cfset variables.OmnitureXMLConverter.p = "plugins">
<cfset variables.OmnitureXMLConverter.products = "products">

This provided a nice CFML struct omnixmlstruct

The next step would be to take the long url and break it up into a list or it’s own structure.   I bounced a few ideas off of a fellow CFML coder and ended up with the following code block:

<cfset variables.urlStructSample = structnew() >
<!--- Break up the url into sections --->
<cfloop list="#variables.testurl2#" index="listItem" delimiters="&">
 <!--- split into smaller sections --->
 <cfset variables.varName = listgetat("#listItem#",1,"=")>
 <cfset variables.varValue = urldecode(listgetat("#listItem#",2,"="))>
 <!--- build a new struct with values --->
 <cfif StructKeyExists(variables.OmnitureXMLConverter, "#variables.varName#")>
 <cfset variables.tempHolder = variables.OmnitureXMLConverter['#variables.varName#']>
 <cfset variables.urlStructSample["#variables.tempHolder#"] = "#urldecode(variables.varValue)#">
 </cfif>
 <!--- <cfset variables.urlStructSample["#variables.varName#"] = "#urldecode(variables.varValue)#"> --->
</cfloop>

This code will take the url, and break into a list using & as a delimiter.  Then it will compare the list to the struct holding the xml tags and if a match is found it will build a new struct that has the xml tag as the struct keys and the values needed to be passed as the values.  Resulting in a struct like this:

omnicompletedstruct

Next, we take this struct and build a properly formatted xml object to push to Omniture:

<cfset variables.OmnitureURLList = StructKeyList(variables.urlStructSample)>

<cfset variables.xmlString = "">
<cfloop list="#variables.OmnitureURLList#" index="newListItem">
 <cfset variables.tempValue = variables.urlStructSample["#newListItem#"] >
 <cfset variables.xmlString = variables.xmlString & "<"  &  "#newListItem#"  & ">"  &  "<![CDATA[#variables.tempValue#]]>" &   "</"  &  "#newListItem#"  & ">" >
</cfloop>

<cfxml variable="xml2Omniture" >
 <?xml version="1.0" encoding="utf-8" ?>
 <request>
 <sc_xml_ver>1.0</sc_xml_ver>
 <reportSuiteID>your-report-suite-id-here</reportSuiteID>
 <IPaddress><cfoutput>#cgi.REMOTE_ADDR#</cfoutput></IPaddress>
 <cfoutput>#variables.xmlString#</cfoutput>
 </request>
</cfxml>

This code will result in an xml object like this:

omniXMLObj

Last step would be to push the xml object to Omniture:

<cfhttp
url="http://namesSpace.112.2O7.net/b/ss//6"
method="POST"
useragent="#CGI.http_user_agent#"
result="objGet">
<cfhttpparam type="XML" value="#xml2Omniture#"	 />
</cfhttp>

I have not done any testing to see what impact this process would have on site performance or how it performs against the normal JS beacon.  But if you have a situation where the amount of data that had to be passed to Omniture exceed the magic 2083 characters, this is an approach you could take.

Thanks to Web Analytics Land for his original post, and thanks to Craig for bouncing some ideas back and forth on this.

-Rudi

Leave a comment

Your email address will not be published. Required fields are marked *

Are you human? Or are you Dancer? *

6 thoughts on “Use Omniture’s Data Insertion API to avoid insanely long URL query strings”