function CSPReporting(companyName, companyId, pageTitle, wtTag) {
    var $that = this;
    this.parameters = {};
    this._tag = wtTag;
    this.conversionShown = "";
    this.conversionClick = "";
    this.companyName = companyName;
    this.companyId = companyId;
    this.pageTitle = pageTitle;
    this.emailId = "";
    this.scenarioStep = "";
    this.isTrackScenario = false;
}

//log for debugging
CSPReporting.prototype.log = function() {
    if (typeof (console) != "undefined") { console.log(arguments); }
}
//track conversion
CSPReporting.prototype.trackConversion = function(nodes, value, type) {
    // nodes: the html tags that we want to track for conversion (i.e: <a class='buybutton'>Buy</a> ) nodes = .buybutton
    // value:
    // type:
    var _nodes = null;
    if (typeof (nodes) == "string") { _nodes = $(nodes); }
    else if (typeof (nodes) == "object") { _nodes = nodes; }
    if (_nodes.length > 0) {
        value = value.replace(/^\s+|\s+$/g, "");
        this.setValue("ConversionShown", value.replace(/^\s+|\s+$/g, "")); //set values
        this.setValue("ConversionType", type); //set type
        this.setValue("ConversionContent", value);
        this.trackClick(_nodes, "Conversion", "ConversionClick", value, type); //assign click events
    }
}
//track click with events
CSPReporting.prototype.trackClickWithScenario = function(nodes, scenarioName, scenarioStep, isFinalStep) {
    if (!isFinalStep) this.trackClick(nodes, "Conversion", "", "", "", "WT.si_n", scenarioName, "WT.si_x", scenarioStep);
    else this.trackClick(nodes, "Conversion", "", "", "", "WT.si_n", scenarioName, "WT.si_x", scenarioStep, "WT.si_cs", "1");
}
//track onclick only
CSPReporting.prototype.trackClickOnly = function(nodes, value, type, isFireNow) {
    var _nodes = $(nodes);
    if (_nodes.length > 0) {
        value = value.replace(/^\s+|\s+$/g, "");
        this.trackClick(_nodes, "Click", "ClickValue", value, type);
        if (isFireNow) {
            this.setValue("ClickValue", value);
            this.setValue("ClickType", type);
            this.setValue("ClickContent", value);
        }
    }
}
//track click
//assign click event

CSPReporting.prototype.trackClick = function() { //nodes, 1.clicktype (click or conversion), 2.name, 3.value, 4.type, option arguments 
    if (arguments.length >= 5) {
        var that = this;
        var args = arguments;
        var r = /^(.*)[.](.*)$/;
        var m = null;
        var _nodes = null;
        if (typeof $(arguments[0]) === "string") _nodes = $(arguments[0]);
        else _nodes = $(arguments[0]);
        _nodes.each(function(index, item) {
            $(item).bind("mousedown", { "clicktype": args[1], "name": args[2], "value": args[3].replace(/^\s+|\s+$/g, ""), "type": args[4], "others": args }, function(e) {
                var cleanUpParams = [];
                if (e.data.others.length > 5) {
                    var j = 0;
                    for (var i = 5; i < e.data.others.length; i++) {
                        m = r.exec(e.data.others[i]);
                        if (m != null) {
                            that.setWTValue(m[1], m[2], e.data.others[i + 1]);
                            var tmp = { "node": m[1], "propertyName": m[2] };
                            cleanUpParams[j] = tmp;
                            j++;
                        }
                        i++;
                    }
                }
                if (e.data.name != "") that.setWTValue("DCSext", e.data.name, e.data.value);
                if (e.data.type != "") that.setWTValue("DCSext", e.data.clicktype + "Type", e.data.type);
                if (e.data.value != "") that.setWTValue("DCSext", e.data.clicktype + "Content", e.data.value);
                that._tag.dcsMultiTrack(); // send data to WT
                //clean up
                that.clearWTValues([{ "node": "DCSext", "propertyName": e.data.name }, { "node": "DCSext", "propertyName": e.data.clicktype + "Type" }, { "node": "DCSext", "propertyName": e.data.clicktype + "Content"}]);
                that.clearWTValues([{ "node": "WT", "propertyName": "si_x" }, { "node": "WT", "propertyName": "si_n" }, { "node": "WT", "propertyName": "si_cs"}]); // clear scenario params
                that.clearWTValues(cleanUpParams);
                delete cleanUpParams;
            });
        });
    }
    else throw ("Missing Arguments require(nodes, name, value, type, option arguments) current:[" + arguments.length + "]");
}
//set webTrend values (WT or DCSext)
CSPReporting.prototype.setWTValue = function(name, property, value) {
    var obj = this._tag[name];
    if (typeof obj === undefined) log("WebTrend Object Name doesn't exist");
    else {
        if (typeof (obj[property]) != "undefined") {
            if (typeof (obj[property]) == "undefined") obj[property] = value;
            else if (obj[property] == null) obj[property] = value;
            else obj[property] = obj[property] + ";" + value;
        }
        else obj[property] = value;
    }
}
//set a custom value
CSPReporting.prototype.setValue = function(name, value) {
    if (typeof this.parameters[name] === "undefined") this.parameters[name] = value;
    else this.parameters[name] = ((this.parameters[name] != "") ? this.parameters[name] + ";" : "") + value;
}
CSPReporting.prototype.clearValues = function() {
    delete this.parameters;
    this.parameters = {};
}
//clean up WebTrend specific codes
CSPReporting.prototype.clearWTValues = function(node, propertyName) {
    if (typeof node === "string") {
        if (node == "WT") {
            if (typeof this._tag.WT[propertyName] !== undefined)
                delete this._tag.WT[propertyName];
        }
        else if (node == "DCSext") {
            if (typeof this._tag.DCSext[propertyName] !== undefined)
                delete this._tag.DCSext[propertyName];
        }
        else { this.log("Unnown Node Type ", node); }
    }
    else if (typeof node === "object") {
        if (node.length > 0)
            for (var i = 0; i < node.length; i++)
                this.clearWTValues(node[i].node, node[i].propertyName);
    }
    else { this.log("Option hasn't been implemented"); }
}
//collect data
CSPReporting.prototype.collectData = function() {
    //assuming wt object has been initialized
    this.setValue("csp_companyname", this.companyName);
    this.setValue("csp_companyId", this.companyId);
    this.setValue("csp_pageTitle", this.pageTitle);
    var tmp = [];
    var i = 0;
    //params
    for (var p in this.parameters) {
        if (p.indexOf("WT.") >= 0) this._tag.WT[p.substring(3)] = this.parameters[p]; //set WT.
        else if (p.indexOf("DCSext.") >= 0) {
            this._tag.DCSext[p.substring(7)] = this.parameters[p]; //set DCS
            tmp[i] = { "node": "DCSext", "propertyName": p.substring(7) };
            i = i + 1;
        }
        else if (p.indexOf("WTTag.") >= 0) this._tag[p.substring(6)] = this.parameters[p]; //set main tag
        else if (typeof (p) != "undefined") {
            this._tag.DCSext[p] = this.parameters[p]; // set DCSext.
            if (p != "csp_companyname" && p != "csp_companyId" && p != "csp_pageTitle") {
                tmp[i] = { "node": "DCSext", "propertyName": p };
                i = i + 1;
            }
        }
    }

    this._tag.dcsCollect();
    //this.clearWTValues([{ "node": "DCSext", "propertyName": "ConversionContent" }, { "node": "DCSext", "propertyName": "ConversionType" }, { "node": "DCSext", "propertyName": "ConversionShown" }, { "node": "WT", "propertyName": "si_n" }, { "node": "WT", "propertyName": "si_x" }, { "node": "WT", "propertyName": "si_cs" }, { "node": "DCSext", "propertyName": "ClickValue" }, { "node": "DCSext", "propertyName": "ClickType" }, { "node": "DCSext", "propertyName": "ClickContent"}]);
    this.clearWTValues([{ "node": "WT", "propertyName": "si_n" }, { "node": "WT", "propertyName": "si_x" }, { "node": "WT", "propertyName": "si_cs"}]);
    this.clearWTValues(tmp);
    delete tmp;
}
//collect scenario data
CSPReporting.prototype.scenario = function(name, step, isFinalStep) {
    this.setWTValue("WT", "si_n", name);
    this.setWTValue("WT", "si_x", step);
    if (isFinalStep) this.setValue("WT.si_cs", "1");
}
CSPReporting.prototype.getQueryValue = function(url, name, default_) {
    if (default_ == null) default_ = "";
    name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
    var qs = regex.exec(url);
    if (qs == null)
        return default_;
    else
        return qs[1];
}
CSPReporting.prototype.checkForEmailCampaign = function() {
    var url = document.location.search;
    var emailId = this.getQueryValue(url, "csp_emailid");
    emailId = emailId || "";
    if (emailId != "") {
        var emailLinkName = this.getQueryValue(url, "csp_emaillinkname");
        var emailClick = this.getQueryValue(url, "csp_emailclick");
        var vendorName = this.getQueryValue(url, "csp_vendorname");
        var vendorId = this.getQueryValue(url, "csp_vendorid");
        var vendorEmailClick = this.getQueryValue(url, "csp_vendoremailclick");
        var emailScenarioStep = this.getQueryValue(url, "csp_scenariostep");
        this.setValue("csp_emailid", emailId);
        if (emailLinkName != "") this.setValue("csp_emaillinkname", emailLinkName);
        if (emailClick != "") this.setValue("csp_emailclick", emailClick);
        if (vendorName != "") this.setValue("csp_vendorname", vendorName);
        if (vendorId != "") this.setValue("csp_vendorid", vendorId);
        if (vendorEmailClick != "") this.setValue("csp_vendoremailclick", vendorEmailClick);
        //store email id & track scenario?
        this.emailId = emailId;
        if (emailScenarioStep != "") {
            this.isTrackScenario = true;
            this.scenarioStep = emailScenarioStep;                        
        }
    }
    delete url;
    delete emailId;
}