06th Nov 2008

Passing on the POST

For some of my projects I have been implementing this tracking system that involves taking some values from a form and passing them as URL variables in the source of an image.

Here is the catch. The form is processed by an intermediary page that then forwards you to a confirmation page. This means that the form data is not available on the final page where the tracking code needs to access it.

The solution that chosen was to grab the values from the form during the validation process in JavaScript and append them to the URL of the redirect page that the intermediary page forwards you to.

This was fine, but each implementation wanted different variables and form values to be available for tracking. So I was constantly customizing the JavaScript to get the right form data and the request variables in JSP to retrieve the passed variables. This became tiresome really quickly after about the 4th implementation.

So, I created little system to streamline the process. Here is what I came up with (some sensitive data removed, but idea still there).

The JavaScript Class:

function TrackingPixel() {
/*Create a reference to the form that contains the data. This could be made more flexible, but for my purposes the form always has the same name. */
this.form = document.emailForm;
/*Iteration variable used to determine if an & needs to be appended between variables*/
this.i = 0
/*String to hold the URL variables that we are going to create*/
this.qs = “”;
}

/*Instance variable that holds a reference to a configuration object that specifies the URL variables to create and the form element to use for the value.*/
TrackingPixel.prototype.variableMap;

/*Certain form values are special cases such as birthdates which required the use of multiple form elements to create the final value. This object specified those cases, the processing method and the values required by the method. */
TrackingPixel.prototype.specialCases;

/*This function loops through the configuration objects defined above and handles any special cases to create the final query string. */
TrackingPixel.prototype.createVariables = function() {
/*Loop through the standard cases*/
for (v in this.variableMap) {
/*Find the form element that matches the key in the config object*/
var elem = this.form[this.variableMap[v]];
/*If the form element is a compound type, find the selected value. Right now I only needed to deal with radio buttons*/
if (elem.type == “radio”) {
this.buildString(v, this.getArrayValue(elem))
} else {
this.buildString(v, elem.value)
}
}
/*Loop through the special cases and return the value from the specified processing function*/
for (s in this.specialCases) {
this.buildString(s, this[this.specialCases[s].method]
(this.specialCases[s].elems))
}
/*If we found variables append the query string to the URL of the forwarding page*/
if (this.qs.length > 0) {
/*See if there are already variables on the URL of the forwarding page, other wise append the ?*/
if (this.form.targetPage.value.indexOf(“?”) > -1) {
this.form.targetPage.value += “&”
} else {
this.form.targetPage.value += “?”
}
this.form.targetPage.value += this.qs;
}
}
/*This is one of the special cases methods. Create a date string using the specified form values*/
TrackingPixel.prototype.birthDate = function(bDayElems) {
return this.form[bDayElems[0]].value + “/” + this.form[bDayElems[1]].value
+ “/” + this.form[bDayElems[2]].value
}
/*Create URL value using the passed key and value and append it to the query string*/
TrackingPixel.prototype.buildString = function(key, val) {
if (this.i > 0) {
this.qs += “&”;
}
this.qs += key + “=” + val;
this.i++;
}
/*Find the selected value of a complex form object such as a radio button*/
TrackingPixel.prototype.getArrayValue = function(arr) {
for (a = 0; a < arr.length; a++) {
if (arr[a].checked == true) {
return arr[a].value
}
}
}

Once I had this class set up, all I have to do in the page with the form is the following:

<script src=”/js/TrackingPixel.js” type=”text/javascript”></script>

//In form validation code:
function validateForm(){
…other validation code
var tp = new TrackingPixel ();
/*Create the standard configuration object specifying the variables to create and the form field that supply the values*/
tp.variableMap = {e:”emailAddress”, src:”contest”,f:”favoritecolor”}
/*Define any special cases, the method used to handle them, and specify the form values needed by that method*/
tp.specialCases={d:{method:”birthDate”, elems:[‘birthMo’,”birthDay”,”birthYr”]}}
/*Call this function to create and append the variable string*/
tp.createVariables();
}

The final piece of this system was to automate the output of the actual tracking image. In the first few implementations I would manually update the URL variables I wanted, which would look something like:

<div id=”trackingPixel”><img src=”https://trackingurl.com?e=<%=request.getParameter(“e”)%>& src=<%=request.getParameter(“src”)%>& f=<%=request.getParameter(“f”)%>’ width=”1″ height=”1″/> </div>

Where I was basically going in each time an updating the var=<%=request.getParameter(“key”)%> and adding & in between.

Since the var name always matched the key, I came up with this:

<%@ taglib prefix=”c” uri=”http://java.sun.com/jstl/core” %>
<c:set var=”eKeys”>e,src,b</c:set>
<!–Being pixel tracking–>
<div id=”trackingPixel”>
<img src=’https://trackingurl.com?sie=someSite<c:forTokens var = “k” items= “${eKeys}” delims=”,”><c:if test=”${! empty param[k]}”>&<c:out value= “${k}”/>=<c:out value= “${param[k]}”/></c:if></c:forTokens>&la=Y’ width=”1” height=”1″/>
</div>
<!–End pixel tracking–>

The only things I have to do to customize this is change the keys in

<c:set var=”eKeys”>e,src,b</c:set>

to match those passed in the URL and the rest is taken care of for me.

Then I just include the JSP file that contains the code final landing page and I am good to go.

I am sure there are improvements that can be made (there always are), but this has taken the implementation time of this system down from about an hour to about 10 minutes.

Comments are closed.