1/** 2 * LeadSourceTrackingUtil.js 3 * lst_util 4 * 5 * v0.0.3 6 */ 7( function( root, doc, settings ) { 8 9 "use strict"; 10 11 // requirments 12 if ( !( settings && typeof settings == 'object' && ( function( k, o ) { 13 for ( var i = 0, r = 1; r && i < k.length; r = k[ i++ ] in o ); 14 return r; 15 } )( [ 'ajaxurl', 'cookiename', 'event' ], settings ) ) ) { 16 return; 17 } 18 19 // constants 20 const AJAXURL = settings.ajaxurl; 21 const COOKIENAME = settings.cookiename; 22 const ACTION = settings.event; 23 const SOURCE = settings.source; 24 const CONTENT = settings.content; 25 const CAMPAIGN = settings.campaign; 26 const TERM = settings.term; 27 const MEDIUM = settings.medium; 28 29 // methods 30 var ProcessLeadSourceTracking = function() { 31 var urlReferrer = ""; 32 if ( document.referrer != null ) { 33 urlReferrer = document.referrer; 34 } 35 if ( getDomain( urlReferrer ) !== getDomain( window.location.hostname ) ) { 36 SetTrackingParams( new QueryStrings(), getCookie( COOKIENAME ), urlReferrer ); 37 } 38 } 39 40 var SetTrackingParams = function( qs, cookie, referrer ) { 41 var Util = new LeadSourceTrackingUtil( { 42 referrer: referrer, 43 source: "", 44 ppc: false, 45 cookieUsed: false 46 } ); 47 var host = Util.GetHost(); 48 var searchEngineName = Util.GetSearchEngineName( host ); 49 var source = Util.GetSource( qs, cookie, host, searchEngineName ); 50 var medium = Util.GetMedium( qs, cookie, host, searchEngineName ); 51 var content = Util.GetContent( qs, cookie ); 52 var campaign = Util.GetCampaign( qs, cookie ); 53 var searchTerm = Util.GetSearchTerm( qs, cookie, searchEngineName ); 54 if ( !Util.cookieUsed && !Util.ppc ) { 55 var freshCookie = new Cookie( COOKIENAME ); 56 freshCookie.Add( SOURCE, source ); 57 freshCookie.Add( CONTENT, content ); 58 freshCookie.Add( CAMPAIGN, campaign ); 59 freshCookie.Add( TERM, searchTerm ); 60 freshCookie.Add( MEDIUM, medium ); 61 freshCookie.expires = 30; 62 freshCookie.Set(); 63 } 64 RequestSession( /*function( XHR ){console.log( XHR,Util )}*/ ); 65 } 66 67 var RequestSession = function( callback ) { 68 var XHR = new XMLHttpRequest(); 69 XHR.addEventListener( 'load', function( event ) { 70 event.response = JSON.parse( this.responseText ); 71 var evt = new ProgressEvent( ACTION, event ); 72 evt.originalEvent = event; 73 doc.dispatchEvent( evt ); 74 if ( callback && typeof callback == 'function' ) { 75 return callback( this.response ); 76 } 77 } ); 78 XHR.open( 'POST', AJAXURL ); 79 XHR.setRequestHeader( "Content-type", "application/x-www-form-urlencoded" ); 80 XHR.setRequestHeader( "X-Requested-With", "XMLHttpRequest" ); 81 XHR.send( "action=" + ACTION ); 82 } 83 84 // prototypes 85 function QueryStrings() { 86 try { 87 const a = window.location.search.split( /\?/ ).pop(); 88 const b = deserialize( a ); 89 for ( var c in b ) { 90 this[ c ] = b[ c ]; 91 } 92 } catch ( e ) { 93 console.log( e ); 94 } 95 } 96 97 function Cookies() { 98 var i, x, y, c = document.cookie.split( ";" ), 99 o = {}, 100 name; 101 if ( arguments && arguments.length == 1 && typeof arguments[ 0 ] == 'string' ) { 102 name = arguments[ 0 ]; 103 } 104 try { 105 for ( i = 0; i < c.length; i++ ) { 106 x = c[ i ].substr( 0, c[ i ].indexOf( "=" ) ); 107 y = deserialize( unescape( c[ i ].substr( c[ i ].indexOf( "=" ) + 1 ) ) ); 108 x = x.replace( /^\s+|\s+$/g, "" ); 109 if ( name ) { 110 if ( x == name ) { 111 o[ x ] = y; 112 break; 113 } 114 } else { 115 o[ x ] = y; 116 } 117 } 118 for ( var k in o ) { 119 this[ k ] = o[ k ]; 120 } 121 } catch ( e ) { 122 console.log( e ); 123 } 124 } 125 126 function Cookie( name ) { 127 Cookies.call( this, name ); 128 this.name = name; 129 this.expires = -1; 130 this.Add = function add() { 131 switch ( arguments.length ) { 132 case 2: 133 this[ this.name ] = typeof this[ this.name ] != 'object' ? {} : this[ this.name ]; 134 this[ this.name ][ arguments[ 0 ] ] = arguments[ 1 ]; 135 break; 136 case 1: 137 default: 138 this[ this.name ] = arguments[ 0 ]; 139 break; 140 } 141 } 142 this.Set = function set() { 143 try { 144 var exdate = new Date(); 145 exdate.setDate( exdate.getDate() + this.expires ); 146 var value = escape( serialize( this[ this.name ] ) ) + ( ( this.expires == -1 ) ? '' : '; expires=' + exdate.toUTCString() ); 147 document.cookie = this.name + '=' + value + '; path=/;'; 148 } catch ( e ) { 149 console.log( e ); 150 } 151 } 152 } 153 Cookie.prototype = Object.create( Cookies.prototype ); 154 155 function LeadSourceTrackingUtil( options ) { 156 this.referrer = document.referrer; 157 this.source = ""; 158 this.ppc = false;
159 this.cookieUsed = false; 160 if ( typeof options == 'object' ) { 161 for ( var k in options ) { 162 if ( this.hasOwnProperty( k ) ) { 163 this[ k ] = options[ k ]; 164 } 165 } 166 } 167 this.GetHost = function GetHost() { 168 // Remove the protocol and trailing values from the referrer 169 var host = this.referrer.replace( /^https?:\/\//, "" ).toLowerCase(); 170 var index = host.indexOf( "/" ); 171 if ( index > 0 ) { 172 host = host.substr( 0, index ); 173 } 174 return host; 175 } 176 this.GetSearchEngineName = function GetSearchEngineName( host ) { 177 // Remove the subdomain from the host 178 var domain = ""; 179 if ( host.indexOf( "." ) != host.lastIndexOf( "." ) ) { 180 var segments = host.split( '.' ); 181 var n = segments.length - 1; 182 domain = segments[ n - 1 ] + "." + segments[ n ]; 183 } else { 184 domain = host; 185 } 186 var searchEngineName = ""; 187 if ( domain.toLowerCase().indexOf( "eloqua" ) > -1 ) { 188 searchEngineName = ""; 189 } else if ( domain.toLowerCase().indexOf( "google" ) > -1 ) { 190 searchEngineName = "Google"; 191 } else if ( domain.toLowerCase().indexOf( "bing" ) > -1 ) { 192 searchEngineName = "Bing"; 193 } else if ( domain.toLowerCase().indexOf( "yahoo" ) > -1 ) { 194 searchEngineName = "Yahoo"; 195 } else { 196 var qsParams = this.referrer.split( '&' ); 197 var n = qsParams.Length; 198 for ( var i = 1; i < n; i++ ) { 199 if ( ( qsParams[ i ].startsWith( "p=" ) ) || ( qsParams[ i ].startsWith( "q=" ) ) ) { 200 searchEngineName = "SearchEng"; 201 break; 202 } 203 } 204 } 205 return searchEngineName; 206 } 207 this.GetSource = function GetSource( qs, cookie, host, searchEngineName ) { 208 // If ( utm_source, S, utm_content and utm_campaign are passed ) or ( utm_source is passed but S is not ) then 209 var source = ""; 210 if ( ( ( ( qs[ "utm_source" ] != null ) && ( qs[ "S" ] != null ) && ( qs[ "utm_content" ] != null ) && ( qs[ "utm_campaign" ] != null ) ) ) || ( ( ( qs[ "utm_source" ] != null ) && ( qs[ "S" ] == null ) ) ) ) { 211 source = qs[ "utm_source" ]; 212 } 213 // Else if utm_source and S are not passed then 214 else if ( ( qs[ "utm_source" ] == null ) && ( qs[ "S" ] == null ) ) { 215 // If a search engine was used then 216 if ( searchEngineName != null && searchEngineName != "" ) { 217 // Use the search engine name 218 source = searchEngineName; 219 } 220 // Else if an HTTP referrer was found then 221 else if ( host != null && host != "" && host.indexOf( "eloqua" ) == -1 ) { 222 // Use the referrer, leading www. 223 source = host.replace( "www.", "" ); 224 } 225 // Else if the cookie is not 30 days old then 226 else if ( cookie != false && cookie[ SOURCE ] != null ) { 227 this.cookieUsed = true; 228 source = cookie[ SOURCE ]; 229 } else { 230 // Return WI as this is a walk-in 231 source = "WI"; 232 } 233 } else { 234 // If this is a PPC link then 235 if ( ( qs[ "S" ].indexOf( "PPC_" ) > -1 ) || ( qs[ "S" ].indexOf( "GW_" ) > -1 ) ) { 236 this.ppc = true; 237 source = "Google"; 238 } else { 239 // Split the S parameter and return the middle values 240 var splits = qs[ "S" ].split( '_' ); 241 if ( splits[ 1 ] != null && splits[ 1 ] != "" ) { 242 source = splits[ 1 ]; 243 } 244 } 245 } 246 this.source = source; 247 return this.source; 248 } 249 this.GetMedium = function GetMedium( qs, cookie, host, searchEngineName ) { 250 var medium = ""; 251 // If utm_medium is passed then 252 if ( qs[ "utm_medium" ] != null ) { 253 medium = qs[ "utm_medium" ]; 254 } 255 // Else if S is passed then 256 else if ( qs[ "S" ] != null ) { 257 if ( this.ppc ) { 258 medium = "cpc"; 259 } 260 } 261 // Else if search engine was used then 262 else if ( searchEngineName != null && searchEngineName != "" ) { 263 medium = "organic"; 264 } 265 // Else if referrer used then 266 else if ( host != null && host != "" && host.indexOf( "eloqua" ) == -1 ) { 267 if ( host.toLowerCase().indexOf( "google" ) > -1 ) { 268 medium = "organic"; 269 } else { 270 medium = "referral"; 271 } 272 } 273 // Else if the cookie is not 30 days old then 274 else if ( cookie != false ) { 275 medium = cookie[ MEDIUM ]; 276 } else { 277 medium = "direct"; 278 } 279 return medium; 280 } 281 this.GetContent = function GetContent( qs, cookie ) { 282 var content = "";
283 // If ( utm_source, S, utm_content and utm_campaign are passed ) or ( utm_content is passed but S is not ) then 284 if ( ( ( ( qs[ "utm_source" ] != null ) && ( qs[ "S" ] != null ) && ( qs[ "utm_content" ] != null ) && ( qs[ "utm_campaign" ] != null ) ) ) || ( ( ( qs[ "utm_content" ] != null ) && ( qs[ "S" ] == null ) ) ) ) { 285 content = qs[ "utm_content" ]; 286 } 287 // Else if utm_content and S are not passed then 288 else if ( ( qs[ "utm_content" ] == null ) && ( qs[ "S" ] == null ) ) { 289 // If the cookie is not 30 days old and was used to retrieve the source then 290 if ( ( cookie != false ) && ( this.cookieUsed ) ) { 291 content = cookie[ CONTENT ]; 292 } else { 293 content = ""; 294 } 295 } else { 296 if ( qs[ "S" ] != null ) { 297 // Split the S parameter and return the first value 298 var splits = qs[ "S" ].split( '_' ); 299 content = splits[ 0 ]; 300 } 301 } 302 return content; 303 } 304 this.GetCampaign = function GetCampaign( qs, cookie ) { 305 var campaign = ""; 306 // If ( utm_source, S, utm_content and utm_campaign are passed ) or ( utm_campaign is passed but S is not ) then 307 if ( ( ( ( qs[ "utm_source" ] != null ) && ( qs[ "S" ] != null ) && ( qs[ "utm_content" ] != null ) && ( qs[ "utm_campaign" ] != null ) ) ) || ( ( ( qs[ "utm_campaign" ] != null ) && ( qs[ "S" ] == null ) ) ) ) { 308 campaign = qs[ "utm_campaign" ]; 309 } 310 // Else if utm_campaign and S are not passed then 311 else if ( ( qs[ "utm_campaign" ] == null ) && ( qs[ "S" ] == null ) ) { 312 // If the cookie is not 30 days old and was used to retrieve the source then 313 if ( ( cookie != false ) && ( this.cookieUsed ) ) { 314 campaign = cookie[ CAMPAIGN ]; 315 } else { 316 campaign = ""; 317 } 318 } else { 319 if ( qs[ "S" ] != null ) { 320 // Split the S parameter and return the third value 321 var splits = qs[ "S" ].split( '_' ); 322 campaign = splits[ 2 ]; 323 } 324 } 325 return campaign; 326 } 327 this.GetSearchTerm = function GetSearchTerm( qs, cookie, searchEngineName ) { 328 var searchTerm = ""; 329 // If utm_term is passed then 330 if ( qs[ "utm_term" ] != null ) { 331 searchTerm = qs[ "utm_term" ]; 332 } 333 // Else if S is passed then 334 else if ( qs[ "S" ] != null ) { 335 searchTerm = ""; 336 } 337 // Else if a search engine is used then 338 else if ( searchEngineName != null && searchEngineName != "" ) { 339 // If there is a keyword parameter then 340 var qsParams = this.referrer.split( '&' ); 341 var n = qsParams.length; 342 for ( var i = 1; i < n; i++ ) { 343 if ( ( qsParams[ i ].startsWith( "p=" ) ) || ( qsParams[ i ].startsWith( "q=" ) ) ) { 344 // Get the keyword( s ) 345 var param = qsParams[ i ].split( '=' ); 346 searchTerm = param[ 1 ]; 347 break; 348 } 349 } 350 } 351 // Else if the cookie is not 30 days old and was used to retrieve the source then 352 else if ( ( cookie != false ) && ( this.cookieUsed ) ) { 353 searchTerm = cookie[ TERM ]; 354 } else { 355 searchTerm = ""; 356 } 357 return searchTerm; 358 } 359 } 360 361 // helper functions 362 function getCookie( name ) { 363 var c = new Cookies( name ); 364 return ( name in c && c[ name ] ); 365 } 366 367 function getDomain( host ) { 368 var domain = host.replace( /^https?:\/\//, "" ).split( '/' ).shift().split( '.' ); 369 return [ domain[ domain.length - 2 ], domain[ domain.length - 1 ] ].join( '.' ).toLowerCase(); 370 } 371 372 function serialize( obj, prefix ) { 373 if ( typeof obj == "string" ) { 374 return obj; 375 } 376 var str = []; 377 for ( var p in obj ) { 378 if ( obj.hasOwnProperty( p ) ) { 379 var k = prefix ? prefix + "[" + p + "]" : p, 380 v = obj[ p ]; 381 str.push( ( v !== null && typeof v === "object" ) ? serialize( v, k ) : encodeURIComponent( k ) + "=" + encodeURIComponent( v !== null ? v : "" ) ); 382 } 383 } 384 return str.join( "&" ); 385 } 386 387 function deserialize( str ) { 388 var qso = {}; 389 // Check for an empty querystring 390 if ( str == "" ) { 391 return qso; 392 } 393 // Normalize the querystring 394 str = str.replace( /(^\?)/, '' ).replace( /;/g, '&' ); 395 while ( str.indexOf( "&&" ) != -1 ) { 396 str = str.replace( /&&/g, '&' ); 397 } 398 str = str.replace( /([\&]+$)/, '' ); 399 // Break the querystring into parts 400 var qs = str.split( "&" ); 401 // Build the querystring object 402 for ( var i = 0; i < qs.length; i++ ) { 403 var qi = qs[ i ].split( "=" ); 404 qi = [ decodeURIComponent( qi[ 0 ] ), decodeURIComponent( qi[ 1 ] ) ]; 405 if ( qso[ qi[ 0 ] ] != undefined ) { 406 // If a key already exists then make this an object 407 if ( typeof qso[ qi[ 0 ] ] == "string" ) { 408 var qt = qso[ qi[ 0 ] ]; 409 if ( qi[ 1 ] == "" || qi[ 1 ] == "undefined" ) { 410 qi[ 1 ] = null; 411 } 412 qso[ qi[ 0 ] ] = []; 413 qso[ qi[ 0 ] ].push( qt ); 414 qso[ qi[ 0 ] ].push( qi[ 1 ] ); 415 } else if ( typeof qso[ qi[ 0 ] ] == "object" ) { 416 if ( qi[ 1 ] == "" || qi[ 1 ] == "undefined" ) { 417 qi[ 1 ] = null; 418 } 419 qso[ qi[ 0 ] ].push( qi[ 1 ] ); 420 } 421 } else { 422 // If no key exists just set it as a string 423 if ( qi[ 1 ] == "" || qi[ 1 ] == "undefined" ) { 424 qi[ 1 ] = null; 425 } 426 qso[ qi[ 0 ] ] = qi[ 1 ]; 427 } 428 } 429 var nqso = {}, 430 a, j, k, o, p, q; 431 for ( var i in qso ) { 432 a = i.match( /([^\[\]]+)(\[[^\[\]]+[^\]])*?/g ); 433 p = qso[ i ]; 434 j = a && a.length; 435 while ( j-- ) { 436 q = {}; 437 q[ a[ j ] ] = p; 438 p = q; 439 } 440 // merge object 441 k = Object.keys( p )[ 0 ]; 442 o = nqso; 443 while ( k in o ) { 444 p = p[ k ]; 445 o = o[ k ]; 446 k = Object.keys( p )[ 0 ]; 447 } 448 o[ k ] = p[ k ]; 449 } 450 if ( Object.keys( nqso ).length === 1 && nqso[ Object.keys( nqso )[ 0 ] ] === "undefined" ) { 451 return Object.keys( nqso )[ 0 ]; 452 } 453 return nqso; 454 } 455 456 doc.addEventListener( ACTION, function( event ) { 457 console.log( event.originalEvent.response ); 458 } ); 459 460 // localize proccess method 461 root.ProcessLeadSourceTrackingUtil = { RequestSession: RequestSession, ProcessLeadSourceTracking: ProcessLeadSourceTracking }; 462 463 ProcessLeadSourceTracking(); 464 465} )( this, document, lst_util );
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.