Last active
August 26, 2020 04:16
-
-
Save billfitzgerald/ed45bc777b78fad5f9f18100f0c14e87 to your computer and use it in GitHub Desktop.
Javascript loaded on the College Board site 28 July 2020, referenced in this story: https://medium.com/cr-digital-lab/student-tracking-and-the-college-board-512a94d60ec3
This file has been truncated, but you can view the full file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * @license | |
| * Adobe Visitor API for JavaScript version: 4.6.0 | |
| * Copyright 2020 Adobe, Inc. All Rights Reserved | |
| * More info available at https://marketing.adobe.com/resources/help/en_US/mcvid/ | |
| */ | |
| var e=function(){"use strict";function e(t){"@babel/helpers - typeof";return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(t)}function t(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function n(){return{callbacks:{},add:function(e,t){this.callbacks[e]=this.callbacks[e]||[];var n=this.callbacks[e].push(t)-1,i=this;return function(){i.callbacks[e].splice(n,1)}},execute:function(e,t){if(this.callbacks[e]){t=void 0===t?[]:t,t=t instanceof Array?t:[t];try{for(;this.callbacks[e].length;){var n=this.callbacks[e].shift();"function"==typeof n?n.apply(null,t):n instanceof Array&&n[1].apply(n[0],t)}delete this.callbacks[e]}catch(e){}}},executeAll:function(e,t){(t||e&&!j.isObjectEmpty(e))&&Object.keys(this.callbacks).forEach(function(t){var n=void 0!==e[t]?e[t]:"";this.execute(t,n)},this)},hasCallbacks:function(){return Boolean(Object.keys(this.callbacks).length)}}}function i(e,t,n){var i=null==e?void 0:e[t];return void 0===i?n:i}function r(e){for(var t=/^\d+$/,n=0,i=e.length;n<i;n++)if(!t.test(e[n]))return!1;return!0}function a(e,t){for(;e.length<t.length;)e.push("0");for(;t.length<e.length;)t.push("0")}function o(e,t){for(var n=0;n<e.length;n++){var i=parseInt(e[n],10),r=parseInt(t[n],10);if(i>r)return 1;if(r>i)return-1}return 0}function s(e,t){if(e===t)return 0;var n=e.toString().split("."),i=t.toString().split(".");return r(n.concat(i))?(a(n,i),o(n,i)):NaN}function l(e){return e===Object(e)&&0===Object.keys(e).length}function c(e){return"function"==typeof e||e instanceof Array&&e.length}function u(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:function(){return!0};this.log=_e("log",e,t),this.warn=_e("warn",e,t),this.error=_e("error",e,t)}function d(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.isEnabled,n=e.cookieName,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=i.cookies;return t&&n&&r?{remove:function(){r.remove(n)},get:function(){var e=r.get(n),t={};try{t=JSON.parse(e)}catch(e){t={}}return t},set:function(e,t){t=t||{},r.set(n,JSON.stringify(e),{domain:t.optInCookieDomain||"",cookieLifetime:t.optInStorageExpiry||3419e4,expires:!0})}}:{get:Pe,set:Pe,remove:Pe}}function f(e){this.name=this.constructor.name,this.message=e,"function"==typeof Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=new Error(e).stack}function p(){function e(e,t){var n=De(e);return n.length?n.every(function(e){return!!t[e]}):Se(t)}function t(){M(b),O(ce.COMPLETE),_(h.status,h.permissions),m.set(h.permissions,{optInCookieDomain:l,optInStorageExpiry:c}),C.execute(xe)}function n(e){return function(n,i){if(!Ae(n))throw new Error("[OptIn] Invalid category(-ies). Please use the `OptIn.Categories` enum.");return O(ce.CHANGED),Object.assign(b,ye(De(n),e)),i||t(),h}}var i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=i.doesOptInApply,a=i.previousPermissions,o=i.preOptInApprovals,s=i.isOptInStorageEnabled,l=i.optInCookieDomain,c=i.optInStorageExpiry,u=i.isIabContext,f=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},p=f.cookies,g=Le(a);Re(g,"Invalid `previousPermissions`!"),Re(o,"Invalid `preOptInApprovals`!");var m=d({isEnabled:!!s,cookieName:"adobeujs-optin"},{cookies:p}),h=this,_=le(h),C=ge(),I=Me(g),v=Me(o),D=m.get(),S={},A=function(e,t){return ke(e)||t&&ke(t)?ce.COMPLETE:ce.PENDING}(I,D),y=function(e,t,n){var i=ye(pe,!r);return r?Object.assign({},i,e,t,n):i}(v,I,D),b=be(y),O=function(e){return A=e},M=function(e){return y=e};h.deny=n(!1),h.approve=n(!0),h.denyAll=h.deny.bind(h,pe),h.approveAll=h.approve.bind(h,pe),h.isApproved=function(t){return e(t,h.permissions)},h.isPreApproved=function(t){return e(t,v)},h.fetchPermissions=function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=t?h.on(ce.COMPLETE,e):Pe;return!r||r&&h.isComplete||!!o?e(h.permissions):t||C.add(xe,function(){return e(h.permissions)}),n},h.complete=function(){h.status===ce.CHANGED&&t()},h.registerPlugin=function(e){if(!e||!e.name||"function"!=typeof e.onRegister)throw new Error(je);S[e.name]||(S[e.name]=e,e.onRegister.call(e,h))},h.execute=Ne(S),Object.defineProperties(h,{permissions:{get:function(){return y}},status:{get:function(){return A}},Categories:{get:function(){return ue}},doesOptInApply:{get:function(){return!!r}},isPending:{get:function(){return h.status===ce.PENDING}},isComplete:{get:function(){return h.status===ce.COMPLETE}},__plugins:{get:function(){return Object.keys(S)}},isIabContext:{get:function(){return u}}})}function g(e,t){function n(){r=null,e.call(e,new f("The call took longer than you wanted!"))}function i(){r&&(clearTimeout(r),e.apply(e,arguments))}if(void 0===t)return e;var r=setTimeout(n,t);return i}function m(){if(window.__cmp)return window.__cmp;var e=window;if(e===window.top)return void Ie.error("__cmp not found");for(var t;!t;){e=e.parent;try{e.frames.__cmpLocator&&(t=e)}catch(e){}if(e===window.top)break}if(!t)return void Ie.error("__cmp not found");var n={};return window.__cmp=function(e,i,r){var a=Math.random()+"",o={__cmpCall:{command:e,parameter:i,callId:a}};n[a]=r,t.postMessage(o,"*")},window.addEventListener("message",function(e){var t=e.data;if("string"==typeof t)try{t=JSON.parse(e.data)}catch(e){}if(t.__cmpReturn){var i=t.__cmpReturn;n[i.callId]&&(n[i.callId](i.returnValue,i.success),delete n[i.callId])}},!1),window.__cmp}function h(){var e=this;e.name="iabPlugin",e.version="0.0.1";var t=ge(),n={allConsentData:null},i=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return n[e]=t};e.fetchConsentData=function(e){var t=e.callback,n=e.timeout,i=g(t,n);r({callback:i})},e.isApproved=function(e){var t=e.callback,i=e.category,a=e.timeout;if(n.allConsentData)return t(null,s(i,n.allConsentData.vendorConsents,n.allConsentData.purposeConsents));var o=g(function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=n.vendorConsents,a=n.purposeConsents;t(e,s(i,r,a))},a);r({category:i,callback:o})},e.onRegister=function(t){var n=Object.keys(de),i=function(e){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=i.purposeConsents,a=i.gdprApplies,o=i.vendorConsents;!e&&a&&o&&r&&(n.forEach(function(e){var n=s(e,o,r);t[n?"approve":"deny"](e,!0)}),t.complete())};e.fetchConsentData({callback:i})};var r=function(e){var r=e.callback;if(n.allConsentData)return r(null,n.allConsentData);t.add("FETCH_CONSENT_DATA",r);var s={};o(function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=e.purposeConsents,o=e.gdprApplies,l=e.vendorConsents;(arguments.length>1?arguments[1]:void 0)&&(s={purposeConsents:r,gdprApplies:o,vendorConsents:l},i("allConsentData",s)),a(function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};(arguments.length>1?arguments[1]:void 0)&&(s.consentString=e.consentData,i("allConsentData",s)),t.execute("FETCH_CONSENT_DATA",[null,n.allConsentData])})})},a=function(e){var t=m();t&&t("getConsentData",null,e)},o=function(e){var t=Fe(de),n=m();n&&n("getVendorConsents",t,e)},s=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},i=!!t[de[e]];return i&&function(){return fe[e].every(function(e){return n[e]})}()}}var _="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};Object.assign=Object.assign||function(e){for(var t,n,i=1;i<arguments.length;++i){n=arguments[i];for(t in n)Object.prototype.hasOwnProperty.call(n,t)&&(e[t]=n[t])}return e};var C,I,v={HANDSHAKE:"HANDSHAKE",GETSTATE:"GETSTATE",PARENTSTATE:"PARENTSTATE"},D={MCMID:"MCMID",MCAID:"MCAID",MCAAMB:"MCAAMB",MCAAMLH:"MCAAMLH",MCOPTOUT:"MCOPTOUT",CUSTOMERIDS:"CUSTOMERIDS"},S={MCMID:"getMarketingCloudVisitorID",MCAID:"getAnalyticsVisitorID",MCAAMB:"getAudienceManagerBlob",MCAAMLH:"getAudienceManagerLocationHint",MCOPTOUT:"isOptedOut",ALLFIELDS:"getVisitorValues"},A={CUSTOMERIDS:"getCustomerIDs"},y={MCMID:"getMarketingCloudVisitorID",MCAAMB:"getAudienceManagerBlob",MCAAMLH:"getAudienceManagerLocationHint",MCOPTOUT:"isOptedOut",MCAID:"getAnalyticsVisitorID",CUSTOMERIDS:"getCustomerIDs",ALLFIELDS:"getVisitorValues"},b={MC:"MCMID",A:"MCAID",AAM:"MCAAMB"},O={MCMID:"MCMID",MCOPTOUT:"MCOPTOUT",MCAID:"MCAID",MCAAMLH:"MCAAMLH",MCAAMB:"MCAAMB"},M={UNKNOWN:0,AUTHENTICATED:1,LOGGED_OUT:2},k={GLOBAL:"global"},E={MESSAGES:v,STATE_KEYS_MAP:D,ASYNC_API_MAP:S,SYNC_API_MAP:A,ALL_APIS:y,FIELDGROUP_TO_FIELD:b,FIELDS:O,AUTH_STATE:M,OPT_OUT:k},T=E.STATE_KEYS_MAP,P=function(e){function t(){}function n(t,n){var i=this;return function(){var r=e(0,t),a={};return a[t]=r,i.setStateAndPublish(a),n(r),r}}this.getMarketingCloudVisitorID=function(e){e=e||t;var i=this.findField(T.MCMID,e),r=n.call(this,T.MCMID,e);return void 0!==i?i:r()},this.getVisitorValues=function(e){this.getMarketingCloudVisitorID(function(t){e({MCMID:t})})}},L=E.MESSAGES,R=E.ASYNC_API_MAP,w=E.SYNC_API_MAP,F=function(){function e(){}function t(e,t){var n=this;return function(){return n.callbackRegistry.add(e,t),n.messageParent(L.GETSTATE),""}}function n(n){this[R[n]]=function(i){i=i||e;var r=this.findField(n,i),a=t.call(this,n,i);return void 0!==r?r:a()}}function i(t){this[w[t]]=function(){return this.findField(t,e)||{}}}Object.keys(R).forEach(n,this),Object.keys(w).forEach(i,this)},N=E.ASYNC_API_MAP,x=function(){Object.keys(N).forEach(function(e){this[N[e]]=function(t){this.callbackRegistry.add(e,t)}},this)},j=function(e,t){return t={exports:{}},e(t,t.exports),t.exports}(function(t,n){n.isObjectEmpty=function(e){return e===Object(e)&&0===Object.keys(e).length},n.isValueEmpty=function(e){return""===e||n.isObjectEmpty(e)};var i=function(){var e=navigator.appName,t=navigator.userAgent;return"Microsoft Internet Explorer"===e||t.indexOf("MSIE ")>=0||t.indexOf("Trident/")>=0&&t.indexOf("Windows NT 6")>=0};n.getIeVersion=function(){return document.documentMode?document.documentMode:i()?7:null},n.encodeAndBuildRequest=function(e,t){return e.map(encodeURIComponent).join(t)},n.isObject=function(t){return null!==t&&"object"===e(t)&&!1===Array.isArray(t)},n.defineGlobalNamespace=function(){return window.adobe=n.isObject(window.adobe)?window.adobe:{},window.adobe},n.pluck=function(e,t){return t.reduce(function(t,n){return e[n]&&(t[n]=e[n]),t},Object.create(null))},n.parseOptOut=function(e,t,n){t||(t=n,e.d_optout&&e.d_optout instanceof Array&&(t=e.d_optout.join(",")));var i=parseInt(e.d_ottl,10);return isNaN(i)&&(i=7200),{optOut:t,d_ottl:i}},n.normalizeBoolean=function(e){var t=e;return"true"===e?t=!0:"false"===e&&(t=!1),t}}),V=(j.isObjectEmpty,j.isValueEmpty,j.getIeVersion,j.encodeAndBuildRequest,j.isObject,j.defineGlobalNamespace,j.pluck,j.parseOptOut,j.normalizeBoolean,n),U=E.MESSAGES,H={0:"prefix",1:"orgID",2:"state"},B=function(e,t){this.parse=function(e){try{var t={};return e.data.split("|").forEach(function(e,n){if(void 0!==e){t[H[n]]=2!==n?e:JSON.parse(e)}}),t}catch(e){}},this.isInvalid=function(n){var i=this.parse(n);if(!i||Object.keys(i).length<2)return!0;var r=e!==i.orgID,a=!t||n.origin!==t,o=-1===Object.keys(U).indexOf(i.prefix);return r||a||o},this.send=function(n,i,r){var a=i+"|"+e;r&&r===Object(r)&&(a+="|"+JSON.stringify(r));try{n.postMessage(a,t)}catch(e){}}},G=E.MESSAGES,Y=function(e,t,n,i){function r(e){Object.assign(p,e)}function a(e){Object.assign(p.state,e),Object.assign(p.state.ALLFIELDS,e),p.callbackRegistry.executeAll(p.state)}function o(e){if(!h.isInvalid(e)){m=!1;var t=h.parse(e);p.setStateAndPublish(t.state)}}function s(e){!m&&g&&(m=!0,h.send(i,e))}function l(){r(new P(n._generateID)),p.getMarketingCloudVisitorID(),p.callbackRegistry.executeAll(p.state,!0),_.removeEventListener("message",c)}function c(e){if(!h.isInvalid(e)){var t=h.parse(e);m=!1,_.clearTimeout(p._handshakeTimeout),_.removeEventListener("message",c),r(new F(p)),_.addEventListener("message",o),p.setStateAndPublish(t.state),p.callbackRegistry.hasCallbacks()&&s(G.GETSTATE)}}function u(){g&&postMessage?(_.addEventListener("message",c),s(G.HANDSHAKE),p._handshakeTimeout=setTimeout(l,250)):l()}function d(){_.s_c_in||(_.s_c_il=[],_.s_c_in=0),p._c="Visitor",p._il=_.s_c_il,p._in=_.s_c_in,p._il[p._in]=p,_.s_c_in++}function f(){function e(e){0!==e.indexOf("_")&&"function"==typeof n[e]&&(p[e]=function(){})}Object.keys(n).forEach(e),p.getSupplementalDataID=n.getSupplementalDataID,p.isAllowed=function(){return!0}}var p=this,g=t.whitelistParentDomain;p.state={ALLFIELDS:{}},p.version=n.version,p.marketingCloudOrgID=e,p.cookieDomain=n.cookieDomain||"",p._instanceType="child";var m=!1,h=new B(e,g);p.callbackRegistry=V(),p.init=function(){d(),f(),r(new x(p)),u()},p.findField=function(e,t){if(void 0!==p.state[e])return t(p.state[e]),p.state[e]},p.messageParent=s,p.setStateAndPublish=a},q=E.MESSAGES,X=E.ALL_APIS,W=E.ASYNC_API_MAP,J=E.FIELDGROUP_TO_FIELD,K=function(e,t){function n(){var t={};return Object.keys(X).forEach(function(n){var i=X[n],r=e[i]();j.isValueEmpty(r)||(t[n]=r)}),t}function i(){var t=[];return e._loading&&Object.keys(e._loading).forEach(function(n){if(e._loading[n]){var i=J[n];t.push(i)}}),t.length?t:null}function r(t){return function n(r){var a=i();if(a){var o=W[a[0]];e[o](n,!0)}else t()}}function a(e,i){var r=n();t.send(e,i,r)}function o(e){l(e),a(e,q.HANDSHAKE)}function s(e){r(function(){a(e,q.PARENTSTATE)})()}function l(n){function i(i){r.call(e,i),t.send(n,q.PARENTSTATE,{CUSTOMERIDS:e.getCustomerIDs()})}var r=e.setCustomerIDs;e.setCustomerIDs=i}return function(e){if(!t.isInvalid(e)){(t.parse(e).prefix===q.HANDSHAKE?o:s)(e.source)}}},z=function(e,t){function n(e){return function(n){i[e]=n,r++,r===a&&t(i)}}var i={},r=0,a=Object.keys(e).length;Object.keys(e).forEach(function(t){var i=e[t];if(i.fn){var r=i.args||[];r.unshift(n(t)),i.fn.apply(i.context||null,r)}})},Q={get:function(e){e=encodeURIComponent(e);var t=(";"+document.cookie).split(" ").join(";"),n=t.indexOf(";"+e+"="),i=n<0?n:t.indexOf(";",n+1);return n<0?"":decodeURIComponent(t.substring(n+2+e.length,i<0?t.length:i))},set:function(e,t,n){var r=i(n,"cookieLifetime"),a=i(n,"expires"),o=i(n,"domain"),s=i(n,"secure"),l=s?"Secure":"";if(a&&"SESSION"!==r&&"NONE"!==r){var c=""!==t?parseInt(r||0,10):-60;if(c)a=new Date,a.setTime(a.getTime()+1e3*c);else if(1===a){a=new Date;var u=a.getYear();a.setYear(u+2+(u<1900?1900:0))}}else a=0;return e&&"NONE"!==r?(document.cookie=encodeURIComponent(e)+"="+encodeURIComponent(t)+"; path=/;"+(a?" expires="+a.toGMTString()+";":"")+(o?" domain="+o+";":"")+l,this.get(e)===t):0},remove:function(e,t){var n=i(t,"domain");n=n?" domain="+n+";":"",document.cookie=encodeURIComponent(e)+"=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;"+n}},$=function(e){var t;!e&&_.location&&(e=_.location.hostname),t=e;var n,i=t.split(".");for(n=i.length-2;n>=0;n--)if(t=i.slice(n).join("."),Q.set("test","cookie",{domain:t}))return Q.remove("test",{domain:t}),t;return""},Z={compare:s,isLessThan:function(e,t){return s(e,t)<0},areVersionsDifferent:function(e,t){return 0!==s(e,t)},isGreaterThan:function(e,t){return s(e,t)>0},isEqual:function(e,t){return 0===s(e,t)}},ee=!!_.postMessage,te={postMessage:function(e,t,n){var i=1;t&&(ee?n.postMessage(e,t.replace(/([^:]+:\/\/[^\/]+).*/,"$1")):t&&(n.location=t.replace(/#.*$/,"")+"#"+ +new Date+i+++"&"+e))},receiveMessage:function(e,t){var n;try{ee&&(e&&(n=function(n){if("string"==typeof t&&n.origin!==t||"[object Function]"===Object.prototype.toString.call(t)&&!1===t(n.origin))return!1;e(n)}),_.addEventListener?_[e?"addEventListener":"removeEventListener"]("message",n):_[e?"attachEvent":"detachEvent"]("onmessage",n))}catch(e){}}},ne=function(e){var t,n,i="0123456789",r="",a="",o=8,s=10,l=10;if(1==e){for(i+="ABCDEF",t=0;16>t;t++)n=Math.floor(Math.random()*o),r+=i.substring(n,n+1),n=Math.floor(Math.random()*o),a+=i.substring(n,n+1),o=16;return r+"-"+a}for(t=0;19>t;t++)n=Math.floor(Math.random()*s),r+=i.substring(n,n+1),0===t&&9==n?s=3:(1==t||2==t)&&10!=s&&2>n?s=10:2<t&&(s=10),n=Math.floor(Math.random()*l),a+=i.substring(n,n+1),0===t&&9==n?l=3:(1==t||2==t)&&10!=l&&2>n?l=10:2<t&&(l=10);return r+a},ie=function(e,t){return{corsMetadata:function(){var e="none",t=!0;return"undefined"!=typeof XMLHttpRequest&&XMLHttpRequest===Object(XMLHttpRequest)&&("withCredentials"in new XMLHttpRequest?e="XMLHttpRequest":"undefined"!=typeof XDomainRequest&&XDomainRequest===Object(XDomainRequest)&&(t=!1),Object.prototype.toString.call(_.HTMLElement).indexOf("Constructor")>0&&(t=!1)),{corsType:e,corsCookiesEnabled:t}}(),getCORSInstance:function(){return"none"===this.corsMetadata.corsType?null:new _[this.corsMetadata.corsType]},fireCORS:function(t,n,i){function r(e){var n;try{if((n=JSON.parse(e))!==Object(n))return void a.handleCORSError(t,null,"Response is not JSON")}catch(e){return void a.handleCORSError(t,e,"Error parsing response as JSON")}try{for(var i=t.callback,r=_,o=0;o<i.length;o++)r=r[i[o]];r(n)}catch(e){a.handleCORSError(t,e,"Error forming callback function")}}var a=this;n&&(t.loadErrorHandler=n);try{var o=this.getCORSInstance();o.open("get",t.corsUrl+"&ts="+(new Date).getTime(),!0),"XMLHttpRequest"===this.corsMetadata.corsType&&(o.withCredentials=!0,o.timeout=e.loadTimeout,o.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),o.onreadystatechange=function(){4===this.readyState&&200===this.status&&r(this.responseText)}),o.onerror=function(e){a.handleCORSError(t,e,"onerror")},o.ontimeout=function(e){a.handleCORSError(t,e,"ontimeout")},o.send(),e._log.requests.push(t.corsUrl)}catch(e){this.handleCORSError(t,e,"try-catch")}},handleCORSError:function(t,n,i){e.CORSErrors.push({corsData:t,error:n,description:i}),t.loadErrorHandler&&("ontimeout"===i?t.loadErrorHandler(!0):t.loadErrorHandler(!1))}}},re={POST_MESSAGE_ENABLED:!!_.postMessage,DAYS_BETWEEN_SYNC_ID_CALLS:1,MILLIS_PER_DAY:864e5,ADOBE_MC:"adobe_mc",ADOBE_MC_SDID:"adobe_mc_sdid",VALID_VISITOR_ID_REGEX:/^[0-9a-fA-F\-]+$/,ADOBE_MC_TTL_IN_MIN:5,VERSION_REGEX:/vVersion\|((\d+\.)?(\d+\.)?(\*|\d+))(?=$|\|)/,FIRST_PARTY_SERVER_COOKIE:"s_ecid"},ae=function(e,t){var n=_.document;return{THROTTLE_START:3e4,MAX_SYNCS_LENGTH:649,throttleTimerSet:!1,id:null,onPagePixels:[],iframeHost:null,getIframeHost:function(e){if("string"==typeof e){var t=e.split("/");return t[0]+"//"+t[2]}},subdomain:null,url:null,getUrl:function(){var t,i="http://fast.",r="?d_nsid="+e.idSyncContainerID+"#"+encodeURIComponent(n.location.origin);return this.subdomain||(this.subdomain="nosubdomainreturned"),e.loadSSL&&(i=e.idSyncSSLUseAkamai?"https://fast.":"https://"),t=i+this.subdomain+".demdex.net/dest5.html"+r,this.iframeHost=this.getIframeHost(t),this.id="destination_publishing_iframe_"+this.subdomain+"_"+e.idSyncContainerID,t},checkDPIframeSrc:function(){var t="?d_nsid="+e.idSyncContainerID+"#"+encodeURIComponent(n.location.href);"string"==typeof e.dpIframeSrc&&e.dpIframeSrc.length&&(this.id="destination_publishing_iframe_"+(e._subdomain||this.subdomain||(new Date).getTime())+"_"+e.idSyncContainerID,this.iframeHost=this.getIframeHost(e.dpIframeSrc),this.url=e.dpIframeSrc+t)},idCallNotProcesssed:null,doAttachIframe:!1,startedAttachingIframe:!1,iframeHasLoaded:null,iframeIdChanged:null,newIframeCreated:null,originalIframeHasLoadedAlready:null,iframeLoadedCallbacks:[],regionChanged:!1,timesRegionChanged:0,sendingMessages:!1,messages:[],messagesPosted:[],messagesReceived:[],messageSendingInterval:re.POST_MESSAGE_ENABLED?null:100,onPageDestinationsFired:[],jsonForComparison:[],jsonDuplicates:[],jsonWaiting:[],jsonProcessed:[],canSetThirdPartyCookies:!0,receivedThirdPartyCookiesNotification:!1,readyToAttachIframePreliminary:function(){return!(e.idSyncDisableSyncs||e.disableIdSyncs||e.idSyncDisable3rdPartySyncing||e.disableThirdPartyCookies||e.disableThirdPartyCalls)},readyToAttachIframe:function(){return this.readyToAttachIframePreliminary()&&(this.doAttachIframe||e._doAttachIframe)&&(this.subdomain&&"nosubdomainreturned"!==this.subdomain||e._subdomain)&&this.url&&!this.startedAttachingIframe},attachIframe:function(){function e(){r=n.createElement("iframe"),r.sandbox="allow-scripts allow-same-origin",r.title="Adobe ID Syncing iFrame",r.id=i.id,r.name=i.id+"_name",r.style.cssText="display: none; width: 0; height: 0;",r.src=i.url,i.newIframeCreated=!0,t(),n.body.appendChild(r)}function t(e){r.addEventListener("load",function(){r.className="aamIframeLoaded",i.iframeHasLoaded=!0,i.fireIframeLoadedCallbacks(e),i.requestToProcess()})}this.startedAttachingIframe=!0;var i=this,r=n.getElementById(this.id);r?"IFRAME"!==r.nodeName?(this.id+="_2",this.iframeIdChanged=!0,e()):(this.newIframeCreated=!1,"aamIframeLoaded"!==r.className?(this.originalIframeHasLoadedAlready=!1,t("The destination publishing iframe already exists from a different library, but hadn't loaded yet.")):(this.originalIframeHasLoadedAlready=!0,this.iframeHasLoaded=!0,this.iframe=r,this.fireIframeLoadedCallbacks("The destination publishing iframe already exists from a different library, and had loaded alresady."),this.requestToProcess())):e(),this.iframe=r},fireIframeLoadedCallbacks:function(e){this.iframeLoadedCallbacks.forEach(function(t){"function"==typeof t&&t({message:e||"The destination publishing iframe was attached and loaded successfully."})}),this.iframeLoadedCallbacks=[]},requestToProcess:function(t){function n(){r.jsonForComparison.push(t),r.jsonWaiting.push(t),r.processSyncOnPage(t)}var i,r=this;if(t===Object(t)&&t.ibs)if(i=JSON.stringify(t.ibs||[]),this.jsonForComparison.length){var a,o,s,l=!1;for(a=0,o=this.jsonForComparison.length;a<o;a++)if(s=this.jsonForComparison[a],i===JSON.stringify(s.ibs||[])){l=!0;break}l?this.jsonDuplicates.push(t):n()}else n();if((this.receivedThirdPartyCookiesNotification||!re.POST_MESSAGE_ENABLED||this.iframeHasLoaded)&&this.jsonWaiting.length){var c=this.jsonWaiting.shift();this.process(c),this.requestToProcess()}e.idSyncDisableSyncs||e.disableIdSyncs||!this.iframeHasLoaded||!this.messages.length||this.sendingMessages||(this.throttleTimerSet||(this.throttleTimerSet=!0,setTimeout(function(){r.messageSendingInterval=re.POST_MESSAGE_ENABLED?null:150},this.THROTTLE_START)),this.sendingMessages=!0,this.sendMessages())},getRegionAndCheckIfChanged:function(t,n){var i=e._getField("MCAAMLH"),r=t.d_region||t.dcs_region;return i?r&&(e._setFieldExpire("MCAAMLH",n),e._setField("MCAAMLH",r),parseInt(i,10)!==r&&(this.regionChanged=!0,this.timesRegionChanged++,e._setField("MCSYNCSOP",""),e._setField("MCSYNCS",""),i=r)):(i=r)&&(e._setFieldExpire("MCAAMLH",n),e._setField("MCAAMLH",i)),i||(i=""),i},processSyncOnPage:function(e){var t,n,i,r;if((t=e.ibs)&&t instanceof Array&&(n=t.length))for(i=0;i<n;i++)r=t[i],r.syncOnPage&&this.checkFirstPartyCookie(r,"","syncOnPage")},process:function(e){var t,n,i,r,a,o=encodeURIComponent,s=!1;if((t=e.ibs)&&t instanceof Array&&(n=t.length))for(s=!0,i=0;i<n;i++)r=t[i],a=[o("ibs"),o(r.id||""),o(r.tag||""),j.encodeAndBuildRequest(r.url||[],","),o(r.ttl||""),"","",r.fireURLSync?"true":"false"],r.syncOnPage||(this.canSetThirdPartyCookies?this.addMessage(a.join("|")):r.fireURLSync&&this.checkFirstPartyCookie(r,a.join("|")));s&&this.jsonProcessed.push(e)},checkFirstPartyCookie:function(t,n,i){var r="syncOnPage"===i,a=r?"MCSYNCSOP":"MCSYNCS";e._readVisitor();var o,s,l=e._getField(a),c=!1,u=!1,d=Math.ceil((new Date).getTime()/re.MILLIS_PER_DAY);l?(o=l.split("*"),s=this.pruneSyncData(o,t.id,d),c=s.dataPresent,u=s.dataValid,c&&u||this.fireSync(r,t,n,o,a,d)):(o=[],this.fireSync(r,t,n,o,a,d))},pruneSyncData:function(e,t,n){var i,r,a,o=!1,s=!1;for(r=0;r<e.length;r++)i=e[r],a=parseInt(i.split("-")[1],10),i.match("^"+t+"-")?(o=!0,n<a?s=!0:(e.splice(r,1),r--)):n>=a&&(e.splice(r,1),r--);return{dataPresent:o,dataValid:s}},manageSyncsSize:function(e){if(e.join("*").length>this.MAX_SYNCS_LENGTH)for(e.sort(function(e,t){return parseInt(e.split("-")[1],10)-parseInt(t.split("-")[1],10)});e.join("*").length>this.MAX_SYNCS_LENGTH;)e.shift()},fireSync:function(t,n,i,r,a,o){var s=this;if(t){if("img"===n.tag){var l,c,u,d,f=n.url,p=e.loadSSL?"https:":"http:";for(l=0,c=f.length;l<c;l++){u=f[l],d=/^\/\//.test(u);var g=new Image;g.addEventListener("load",function(t,n,i,r){return function(){s.onPagePixels[t]=null,e._readVisitor();var o,l=e._getField(a),c=[];if(l){o=l.split("*");var u,d,f;for(u=0,d=o.length;u<d;u++)f=o[u],f.match("^"+n.id+"-")||c.push(f)}s.setSyncTrackingData(c,n,i,r)}}(this.onPagePixels.length,n,a,o)),g.src=(d?p:"")+u,this.onPagePixels.push(g)}}}else this.addMessage(i),this.setSyncTrackingData(r,n,a,o)},addMessage:function(t){var n=encodeURIComponent,i=n(e._enableErrorReporting?"---destpub-debug---":"---destpub---");this.messages.push((re.POST_MESSAGE_ENABLED?"":i)+t)},setSyncTrackingData:function(t,n,i,r){t.push(n.id+"-"+(r+Math.ceil(n.ttl/60/24))),this.manageSyncsSize(t),e._setField(i,t.join("*"))},sendMessages:function(){var e,t=this,n="",i=encodeURIComponent;this.regionChanged&&(n=i("---destpub-clear-dextp---"),this.regionChanged=!1),this.messages.length?re.POST_MESSAGE_ENABLED?(e=n+i("---destpub-combined---")+this.messages.join("%01"),this.postMessage(e),this.messages=[],this.sendingMessages=!1):(e=this.messages.shift(),this.postMessage(n+e),setTimeout(function(){t.sendMessages()},this.messageSendingInterval)):this.sendingMessages=!1},postMessage:function(e){te.postMessage(e,this.url,this.iframe.contentWindow),this.messagesPosted.push(e)},receiveMessage:function(e){var t,n=/^---destpub-to-parent---/;"string"==typeof e&&n.test(e)&&(t=e.replace(n,"").split("|"),"canSetThirdPartyCookies"===t[0]&&(this.canSetThirdPartyCookies="true"===t[1],this.receivedThirdPartyCookiesNotification=!0,this.requestToProcess()),this.messagesReceived.push(e))},processIDCallData:function(i){(null==this.url||i.subdomain&&"nosubdomainreturned"===this.subdomain)&&("string"==typeof e._subdomain&&e._subdomain.length?this.subdomain=e._subdomain:this.subdomain=i.subdomain||"",this.url=this.getUrl()),i.ibs instanceof Array&&i.ibs.length&&(this.doAttachIframe=!0),this.readyToAttachIframe()&&(e.idSyncAttachIframeOnWindowLoad?(t.windowLoaded||"complete"===n.readyState||"loaded"===n.readyState)&&this.attachIframe():this.attachIframeASAP()),"function"==typeof e.idSyncIDCallResult?e.idSyncIDCallResult(i):this.requestToProcess(i),"function"==typeof e.idSyncAfterIDCallResult&&e.idSyncAfterIDCallResult(i)},canMakeSyncIDCall:function(t,n){return e._forceSyncIDCall||!t||n-t>re.DAYS_BETWEEN_SYNC_ID_CALLS},attachIframeASAP:function(){function e(){t.startedAttachingIframe||(n.body?t.attachIframe():setTimeout(e,30))}var t=this;e()}}},oe={audienceManagerServer:{},audienceManagerServerSecure:{},cookieDomain:{},cookieLifetime:{},cookieName:{},doesOptInApply:{},disableThirdPartyCalls:{},discardTrackingServerECID:{},idSyncAfterIDCallResult:{},idSyncAttachIframeOnWindowLoad:{},idSyncContainerID:{},idSyncDisable3rdPartySyncing:{},disableThirdPartyCookies:{},idSyncDisableSyncs:{},disableIdSyncs:{},idSyncIDCallResult:{},idSyncSSLUseAkamai:{},isCoopSafe:{},isIabContext:{},isOptInStorageEnabled:{},loadSSL:{},loadTimeout:{},marketingCloudServer:{},marketingCloudServerSecure:{},optInCookieDomain:{},optInStorageExpiry:{},overwriteCrossDomainMCIDAndAID:{},preOptInApprovals:{},previousPermissions:{},resetBeforeVersion:{},sdidParamExpiry:{},serverState:{},sessionCookieName:{},secureCookie:{},takeTimeoutMetrics:{},trackingServer:{},trackingServerSecure:{},whitelistIframeDomains:{},whitelistParentDomain:{}},se={getConfigNames:function(){return Object.keys(oe)},getConfigs:function(){return oe},normalizeConfig:function(e){return"function"!=typeof e?e:e()}},le=function(e){var t={};return e.on=function(e,n,i){if(!n||"function"!=typeof n)throw new Error("[ON] Callback should be a function.");t.hasOwnProperty(e)||(t[e]=[]);var r=t[e].push({callback:n,context:i})-1;return function(){t[e].splice(r,1),t[e].length||delete t[e]}},e.off=function(e,n){t.hasOwnProperty(e)&&(t[e]=t[e].filter(function(e){if(e.callback!==n)return e}))},e.publish=function(e){if(t.hasOwnProperty(e)){var n=[].slice.call(arguments,1);t[e].slice(0).forEach(function(e){e.callback.apply(e.context,n)})}},e.publish},ce={PENDING:"pending",CHANGED:"changed",COMPLETE:"complete"},ue={AAM:"aam",ADCLOUD:"adcloud",ANALYTICS:"aa",CAMPAIGN:"campaign",ECID:"ecid",LIVEFYRE:"livefyre",TARGET:"target",MEDIA_ANALYTICS:"mediaaa"},de=(C={},t(C,ue.AAM,565),t(C,ue.ECID,565),C),fe=(I={},t(I,ue.AAM,[1,2,5]),t(I,ue.ECID,[1,2,5]),I),pe=function(e){return Object.keys(e).map(function(t){return e[t]})}(ue),ge=function(){var e={};return e.callbacks=Object.create(null),e.add=function(t,n){if(!c(n))throw new Error("[callbackRegistryFactory] Make sure callback is a function or an array of functions.");e.callbacks[t]=e.callbacks[t]||[];var i=e.callbacks[t].push(n)-1;return function(){e.callbacks[t].splice(i,1)}},e.execute=function(t,n){if(e.callbacks[t]){n=void 0===n?[]:n,n=n instanceof Array?n:[n];try{for(;e.callbacks[t].length;){var i=e.callbacks[t].shift();"function"==typeof i?i.apply(null,n):i instanceof Array&&i[1].apply(i[0],n)}delete e.callbacks[t]}catch(e){}}},e.executeAll=function(t,n){(n||t&&!l(t))&&Object.keys(e.callbacks).forEach(function(n){var i=void 0!==t[n]?t[n]:"";e.execute(n,i)},e)},e.hasCallbacks=function(){return Boolean(Object.keys(e.callbacks).length)},e},me=function(){},he=function(e){var t=window,n=t.console;return!!n&&"function"==typeof n[e]},_e=function(e,t,n){return n()?function(){if(he(e)){for(var n=arguments.length,i=new Array(n),r=0;r<n;r++)i[r]=arguments[r];console[e].apply(console,[t].concat(i))}}:me},Ce=u,Ie=new Ce("[ADOBE OPT-IN]"),ve=function(t,n){return e(t)===n},De=function(e,t){return e instanceof Array?e:ve(e,"string")?[e]:t||[]},Se=function(e){var t=Object.keys(e);return!!t.length&&t.every(function(t){return!0===e[t]})},Ae=function(e){return!(!e||Oe(e))&&De(e).every(function(e){return pe.indexOf(e)>-1})},ye=function(e,t){return e.reduce(function(e,n){return e[n]=t,e},{})},be=function(e){return JSON.parse(JSON.stringify(e))},Oe=function(e){return"[object Array]"===Object.prototype.toString.call(e)&&!e.length},Me=function(e){if(Te(e))return e;try{return JSON.parse(e)}catch(e){return{}}},ke=function(e){return void 0===e||(Te(e)?Ae(Object.keys(e)):Ee(e))},Ee=function(e){try{var t=JSON.parse(e);return!!e&&ve(e,"string")&&Ae(Object.keys(t))}catch(e){return!1}},Te=function(e){return null!==e&&ve(e,"object")&&!1===Array.isArray(e)},Pe=function(){},Le=function(e){return ve(e,"function")?e():e},Re=function(e,t){ke(e)||Ie.error("".concat(t))},we=function(e){return Object.keys(e).map(function(t){return e[t]})},Fe=function(e){return we(e).filter(function(e,t,n){return n.indexOf(e)===t})},Ne=function(e){return function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=t.command,i=t.params,r=void 0===i?{}:i,a=t.callback,o=void 0===a?Pe:a;if(!n||-1===n.indexOf("."))throw new Error("[OptIn.execute] Please provide a valid command.");try{var s=n.split("."),l=e[s[0]],c=s[1];if(!l||"function"!=typeof l[c])throw new Error("Make sure the plugin and API name exist.");var u=Object.assign(r,{callback:o});l[c].call(l,u)}catch(e){Ie.error("[execute] Something went wrong: "+e.message)}}};f.prototype=Object.create(Error.prototype),f.prototype.constructor=f;var xe="fetchPermissions",je="[OptIn#registerPlugin] Plugin is invalid.";p.Categories=ue,p.TimeoutError=f;var Ve=Object.freeze({OptIn:p,IabPlugin:h}),Ue=function(e,t){e.publishDestinations=function(n){var i=arguments[1],r=arguments[2];try{r="function"==typeof r?r:n.callback}catch(e){r=function(){}}var a=t;if(!a.readyToAttachIframePreliminary())return void r({error:"The destination publishing iframe is disabled in the Visitor library."});if("string"==typeof n){if(!n.length)return void r({error:"subdomain is not a populated string."});if(!(i instanceof Array&&i.length))return void r({error:"messages is not a populated array."});var o=!1 | |
| ;if(i.forEach(function(e){"string"==typeof e&&e.length&&(a.addMessage(e),o=!0)}),!o)return void r({error:"None of the messages are populated strings."})}else{if(!j.isObject(n))return void r({error:"Invalid parameters passed."});var s=n;if("string"!=typeof(n=s.subdomain)||!n.length)return void r({error:"config.subdomain is not a populated string."});var l=s.urlDestinations;if(!(l instanceof Array&&l.length))return void r({error:"config.urlDestinations is not a populated array."});var c=[];l.forEach(function(e){j.isObject(e)&&(e.hideReferrer?e.message&&a.addMessage(e.message):c.push(e))});!function e(){c.length&&setTimeout(function(){var t=new Image,n=c.shift();t.src=n.url,a.onPageDestinationsFired.push(n),e()},100)}()}a.iframe?(r({message:"The destination publishing iframe is already attached and loaded."}),a.requestToProcess()):!e.subdomain&&e._getField("MCMID")?(a.subdomain=n,a.doAttachIframe=!0,a.url=a.getUrl(),a.readyToAttachIframe()?(a.iframeLoadedCallbacks.push(function(e){r({message:"Attempted to attach and load the destination publishing iframe through this API call. Result: "+(e.message||"no result")})}),a.attachIframe()):r({error:"Encountered a problem in attempting to attach and load the destination publishing iframe through this API call."})):a.iframeLoadedCallbacks.push(function(e){r({message:"Attempted to attach and load the destination publishing iframe through normal Visitor API processing. Result: "+(e.message||"no result")})})}},He=function e(t){function n(e,t){return e>>>t|e<<32-t}for(var i,r,a=Math.pow,o=a(2,32),s="",l=[],c=8*t.length,u=e.h=e.h||[],d=e.k=e.k||[],f=d.length,p={},g=2;f<64;g++)if(!p[g]){for(i=0;i<313;i+=g)p[i]=g;u[f]=a(g,.5)*o|0,d[f++]=a(g,1/3)*o|0}for(t+="รโฌ";t.length%64-56;)t+="\0";for(i=0;i<t.length;i++){if((r=t.charCodeAt(i))>>8)return;l[i>>2]|=r<<(3-i)%4*8}for(l[l.length]=c/o|0,l[l.length]=c,r=0;r<l.length;){var m=l.slice(r,r+=16),h=u;for(u=u.slice(0,8),i=0;i<64;i++){var _=m[i-15],C=m[i-2],I=u[0],v=u[4],D=u[7]+(n(v,6)^n(v,11)^n(v,25))+(v&u[5]^~v&u[6])+d[i]+(m[i]=i<16?m[i]:m[i-16]+(n(_,7)^n(_,18)^_>>>3)+m[i-7]+(n(C,17)^n(C,19)^C>>>10)|0);u=[D+((n(I,2)^n(I,13)^n(I,22))+(I&u[1]^I&u[2]^u[1]&u[2]))|0].concat(u),u[4]=u[4]+D|0}for(i=0;i<8;i++)u[i]=u[i]+h[i]|0}for(i=0;i<8;i++)for(r=3;r+1;r--){var S=u[i]>>8*r&255;s+=(S<16?0:"")+S.toString(16)}return s},Be=function(e,t){return"SHA-256"!==t&&"SHA256"!==t&&"sha256"!==t&&"sha-256"!==t||(e=He(e)),e},Ge=function(e){return String(e).trim().toLowerCase()},Ye=Ve.OptIn;j.defineGlobalNamespace(),window.adobe.OptInCategories=Ye.Categories;var qe=function(t,n,i){function r(e){var t=e;return function(e){var n=e||D.location.href;try{var i=m._extractParamFromUri(n,t);if(i)return N.parsePipeDelimetedKeyValues(i)}catch(e){}}}function a(e){function t(e,t,n){e&&e.match(re.VALID_VISITOR_ID_REGEX)&&(n===y&&(v=!0),t(e))}t(e[y],m.setMarketingCloudVisitorID,y),m._setFieldExpire(T,-1),t(e[M],m.setAnalyticsVisitorID)}function o(e){e=e||{},m._supplementalDataIDCurrent=e.supplementalDataIDCurrent||"",m._supplementalDataIDCurrentConsumed=e.supplementalDataIDCurrentConsumed||{},m._supplementalDataIDLast=e.supplementalDataIDLast||"",m._supplementalDataIDLastConsumed=e.supplementalDataIDLastConsumed||{}}function s(e){function t(e,t,n){return n=n?n+="|":n,n+=e+"="+encodeURIComponent(t)}function n(e,n){var i=n[0],r=n[1];return null!=r&&r!==P&&(e=t(i,r,e)),e}var i=e.reduce(n,"");return function(e){var t=N.getTimestampInSeconds();return e=e?e+="|":e,e+="TS="+t}(i)}function l(e){var t=e.minutesToLive,n="";return(m.idSyncDisableSyncs||m.disableIdSyncs)&&(n=n||"Error: id syncs have been disabled"),"string"==typeof e.dpid&&e.dpid.length||(n=n||"Error: config.dpid is empty"),"string"==typeof e.url&&e.url.length||(n=n||"Error: config.url is empty"),void 0===t?t=20160:(t=parseInt(t,10),(isNaN(t)||t<=0)&&(n=n||"Error: config.minutesToLive needs to be a positive number")),{error:n,ttl:t}}function c(){return!!m.configs.doesOptInApply&&!(h.optIn.isComplete&&u())}function u(){return m.configs.doesOptInApply&&m.configs.isIabContext?h.optIn.isApproved(h.optIn.Categories.ECID)&&I:h.optIn.isApproved(h.optIn.Categories.ECID)}function d(){[["getMarketingCloudVisitorID"],["setCustomerIDs",void 0],["getAnalyticsVisitorID"],["getAudienceManagerLocationHint"],["getLocationHint"],["getAudienceManagerBlob"]].forEach(function(e){var t=e[0],n=2===e.length?e[1]:"",i=m[t];m[t]=function(e){return u()&&m.isAllowed()?i.apply(m,arguments):("function"==typeof e&&m._callCallback(e,[n]),n)}})}function f(e,t){if(I=!0,e)throw new Error("[IAB plugin] : "+e);t.gdprApplies&&(C=t.consentString),m.init(),g()}function p(){h.optIn.isComplete&&(h.optIn.isApproved(h.optIn.Categories.ECID)?m.configs.isIabContext?h.optIn.execute({command:"iabPlugin.fetchConsentData",callback:f}):(m.init(),g()):(d(),g()))}function g(){h.optIn.off("complete",p)}if(!i||i.split("").reverse().join("")!==t)throw new Error("Please use `Visitor.getInstance` to instantiate Visitor.");var m=this,h=window.adobe,C="",I=!1,v=!1;m.version="4.6.0";var D=_,S=D.Visitor;S.version=m.version,S.AuthState=E.AUTH_STATE,S.OptOut=E.OPT_OUT,D.s_c_in||(D.s_c_il=[],D.s_c_in=0),m._c="Visitor",m._il=D.s_c_il,m._in=D.s_c_in,m._il[m._in]=m,D.s_c_in++,m._instanceType="regular",m._log={requests:[]},m.marketingCloudOrgID=t,m.cookieName="AMCV_"+t,m.sessionCookieName="AMCVS_"+t,m.cookieDomain=$(),m.loadSSL=!0,m.loadTimeout=3e4,m.CORSErrors=[],m.marketingCloudServer=m.audienceManagerServer="dpm.demdex.net",m.sdidParamExpiry=30;var A=null,y="MCMID",b="MCIDTS",O="A",M="MCAID",k="AAM",T="MCAAMB",P="NONE",L=function(e){return!Object.prototype[e]},R=ie(m);m.FIELDS=E.FIELDS,m.cookieRead=function(e){return Q.get(e)},m.cookieWrite=function(e,t,n){var i=m.cookieLifetime?(""+m.cookieLifetime).toUpperCase():"",r=!1;return m.configs&&m.configs.secureCookie&&"https:"===location.protocol&&(r=!0),Q.set(e,""+t,{expires:n,domain:m.cookieDomain,cookieLifetime:i,secure:r})},m.resetState=function(e){e?m._mergeServerState(e):o()},m._isAllowedDone=!1,m._isAllowedFlag=!1,m.isAllowed=function(){return m._isAllowedDone||(m._isAllowedDone=!0,(m.cookieRead(m.cookieName)||m.cookieWrite(m.cookieName,"T",1))&&(m._isAllowedFlag=!0)),"T"===m.cookieRead(m.cookieName)&&m._helpers.removeCookie(m.cookieName),m._isAllowedFlag},m.setMarketingCloudVisitorID=function(e){m._setMarketingCloudFields(e)},m._use1stPartyMarketingCloudServer=!1,m.getMarketingCloudVisitorID=function(e,t){m.marketingCloudServer&&m.marketingCloudServer.indexOf(".demdex.net")<0&&(m._use1stPartyMarketingCloudServer=!0);var n=m._getAudienceManagerURLData("_setMarketingCloudFields"),i=n.url;return m._getRemoteField(y,i,e,t,n)};var w=function(e,t){var n={};m.getMarketingCloudVisitorID(function(){t.forEach(function(e){n[e]=m._getField(e,!0)}),-1!==t.indexOf("MCOPTOUT")?m.isOptedOut(function(t){n.MCOPTOUT=t,e(n)},null,!0):e(n)},!0)};m.getVisitorValues=function(e,t){var n={MCMID:{fn:m.getMarketingCloudVisitorID,args:[!0],context:m},MCOPTOUT:{fn:m.isOptedOut,args:[void 0,!0],context:m},MCAID:{fn:m.getAnalyticsVisitorID,args:[!0],context:m},MCAAMLH:{fn:m.getAudienceManagerLocationHint,args:[!0],context:m},MCAAMB:{fn:m.getAudienceManagerBlob,args:[!0],context:m}},i=t&&t.length?j.pluck(n,t):n;t&&-1===t.indexOf("MCAID")?w(e,t):z(i,e)},m._currentCustomerIDs={},m._customerIDsHashChanged=!1,m._newCustomerIDsHash="",m.setCustomerIDs=function(t,n){function i(){m._customerIDsHashChanged=!1}if(!m.isOptedOut()&&t){if(!j.isObject(t)||j.isObjectEmpty(t))return!1;m._readVisitor();var r,a,o;for(r in t)if(L(r)&&(a=t[r],n=a.hasOwnProperty("hashType")?a.hashType:n,a))if("object"===e(a)){var s={};if(a.id){if(n){if(!(o=Be(Ge(a.id),n)))return;a.id=o,s.hashType=n}s.id=a.id}void 0!=a.authState&&(s.authState=a.authState),m._currentCustomerIDs[r]=s}else if(n){if(!(o=Be(Ge(a),n)))return;m._currentCustomerIDs[r]={id:o,hashType:n}}else m._currentCustomerIDs[r]={id:a};var l=m.getCustomerIDs(),c=m._getField("MCCIDH"),u="";c||(c=0);for(r in l)L(r)&&(a=l[r],u+=(u?"|":"")+r+"|"+(a.id?a.id:"")+(a.authState?a.authState:""));m._newCustomerIDsHash=String(m._hash(u)),m._newCustomerIDsHash!==c&&(m._customerIDsHashChanged=!0,m._mapCustomerIDs(i))}},m.getCustomerIDs=function(){m._readVisitor();var e,t,n={};for(e in m._currentCustomerIDs)L(e)&&(t=m._currentCustomerIDs[e],t.id&&(n[e]||(n[e]={}),n[e].id=t.id,void 0!=t.authState?n[e].authState=t.authState:n[e].authState=S.AuthState.UNKNOWN,t.hashType&&(n[e].hashType=t.hashType)));return n},m.setAnalyticsVisitorID=function(e){m._setAnalyticsFields(e)},m.getAnalyticsVisitorID=function(e,t,n){if(!N.isTrackingServerPopulated()&&!n)return m._callCallback(e,[""]),"";var i="";if(n||(i=m.getMarketingCloudVisitorID(function(t){m.getAnalyticsVisitorID(e,!0)})),i||n){var r=n?m.marketingCloudServer:m.trackingServer,a="";m.loadSSL&&(n?m.marketingCloudServerSecure&&(r=m.marketingCloudServerSecure):m.trackingServerSecure&&(r=m.trackingServerSecure));var o={};if(r){var s="http"+(m.loadSSL?"s":"")+"://"+r+"/id",l="d_visid_ver="+m.version+"&mcorgid="+encodeURIComponent(m.marketingCloudOrgID)+(i?"&mid="+encodeURIComponent(i):"")+(m.idSyncDisable3rdPartySyncing||m.disableThirdPartyCookies?"&d_coppa=true":""),c=["s_c_il",m._in,"_set"+(n?"MarketingCloud":"Analytics")+"Fields"];a=s+"?"+l+"&callback=s_c_il%5B"+m._in+"%5D._set"+(n?"MarketingCloud":"Analytics")+"Fields",o.corsUrl=s+"?"+l,o.callback=c}return o.url=a,m._getRemoteField(n?y:M,a,e,t,o)}return""},m.getAudienceManagerLocationHint=function(e,t){if(m.getMarketingCloudVisitorID(function(t){m.getAudienceManagerLocationHint(e,!0)})){var n=m._getField(M);if(!n&&N.isTrackingServerPopulated()&&(n=m.getAnalyticsVisitorID(function(t){m.getAudienceManagerLocationHint(e,!0)})),n||!N.isTrackingServerPopulated()){var i=m._getAudienceManagerURLData(),r=i.url;return m._getRemoteField("MCAAMLH",r,e,t,i)}}return""},m.getLocationHint=m.getAudienceManagerLocationHint,m.getAudienceManagerBlob=function(e,t){if(m.getMarketingCloudVisitorID(function(t){m.getAudienceManagerBlob(e,!0)})){var n=m._getField(M);if(!n&&N.isTrackingServerPopulated()&&(n=m.getAnalyticsVisitorID(function(t){m.getAudienceManagerBlob(e,!0)})),n||!N.isTrackingServerPopulated()){var i=m._getAudienceManagerURLData(),r=i.url;return m._customerIDsHashChanged&&m._setFieldExpire(T,-1),m._getRemoteField(T,r,e,t,i)}}return""},m._supplementalDataIDCurrent="",m._supplementalDataIDCurrentConsumed={},m._supplementalDataIDLast="",m._supplementalDataIDLastConsumed={},m.getSupplementalDataID=function(e,t){m._supplementalDataIDCurrent||t||(m._supplementalDataIDCurrent=m._generateID(1));var n=m._supplementalDataIDCurrent;return m._supplementalDataIDLast&&!m._supplementalDataIDLastConsumed[e]?(n=m._supplementalDataIDLast,m._supplementalDataIDLastConsumed[e]=!0):n&&(m._supplementalDataIDCurrentConsumed[e]&&(m._supplementalDataIDLast=m._supplementalDataIDCurrent,m._supplementalDataIDLastConsumed=m._supplementalDataIDCurrentConsumed,m._supplementalDataIDCurrent=n=t?"":m._generateID(1),m._supplementalDataIDCurrentConsumed={}),n&&(m._supplementalDataIDCurrentConsumed[e]=!0)),n};var F=!1;m._liberatedOptOut=null,m.getOptOut=function(e,t){var n=m._getAudienceManagerURLData("_setMarketingCloudFields"),i=n.url;if(u())return m._getRemoteField("MCOPTOUT",i,e,t,n);if(m._registerCallback("liberatedOptOut",e),null!==m._liberatedOptOut)return m._callAllCallbacks("liberatedOptOut",[m._liberatedOptOut]),F=!1,m._liberatedOptOut;if(F)return null;F=!0;var r="liberatedGetOptOut";return n.corsUrl=n.corsUrl.replace(/dpm\.demdex\.net\/id\?/,"dpm.demdex.net/optOutStatus?"),n.callback=[r],_[r]=function(e){if(e===Object(e)){var t,n,i=j.parseOptOut(e,t,P);t=i.optOut,n=1e3*i.d_ottl,m._liberatedOptOut=t,setTimeout(function(){m._liberatedOptOut=null},n)}m._callAllCallbacks("liberatedOptOut",[t]),F=!1},R.fireCORS(n),null},m.isOptedOut=function(e,t,n){t||(t=S.OptOut.GLOBAL);var i=m.getOptOut(function(n){var i=n===S.OptOut.GLOBAL||n.indexOf(t)>=0;m._callCallback(e,[i])},n);return i?i===S.OptOut.GLOBAL||i.indexOf(t)>=0:null},m._fields=null,m._fieldsExpired=null,m._hash=function(e){var t,n,i=0;if(e)for(t=0;t<e.length;t++)n=e.charCodeAt(t),i=(i<<5)-i+n,i&=i;return i},m._generateID=ne,m._generateLocalMID=function(){var e=m._generateID(0);return V.isClientSideMarketingCloudVisitorID=!0,e},m._callbackList=null,m._callCallback=function(e,t){try{"function"==typeof e?e.apply(D,t):e[1].apply(e[0],t)}catch(e){}},m._registerCallback=function(e,t){t&&(null==m._callbackList&&(m._callbackList={}),void 0==m._callbackList[e]&&(m._callbackList[e]=[]),m._callbackList[e].push(t))},m._callAllCallbacks=function(e,t){if(null!=m._callbackList){var n=m._callbackList[e];if(n)for(;n.length>0;)m._callCallback(n.shift(),t)}},m._addQuerystringParam=function(e,t,n,i){var r=encodeURIComponent(t)+"="+encodeURIComponent(n),a=N.parseHash(e),o=N.hashlessUrl(e);if(-1===o.indexOf("?"))return o+"?"+r+a;var s=o.split("?"),l=s[0]+"?",c=s[1];return l+N.addQueryParamAtLocation(c,r,i)+a},m._extractParamFromUri=function(e,t){var n=new RegExp("[\\?&#]"+t+"=([^&#]*)"),i=n.exec(e);if(i&&i.length)return decodeURIComponent(i[1])},m._parseAdobeMcFromUrl=r(re.ADOBE_MC),m._parseAdobeMcSdidFromUrl=r(re.ADOBE_MC_SDID),m._attemptToPopulateSdidFromUrl=function(e){var n=m._parseAdobeMcSdidFromUrl(e),i=1e9;n&&n.TS&&(i=N.getTimestampInSeconds()-n.TS),n&&n.SDID&&n.MCORGID===t&&i<m.sdidParamExpiry&&(m._supplementalDataIDCurrent=n.SDID,m._supplementalDataIDCurrentConsumed.SDID_URL_PARAM=!0)},m._attemptToPopulateIdsFromUrl=function(){var e=m._parseAdobeMcFromUrl();if(e&&e.TS){var n=N.getTimestampInSeconds(),i=n-e.TS;if(Math.floor(i/60)>re.ADOBE_MC_TTL_IN_MIN||e.MCORGID!==t)return;a(e)}},m._mergeServerState=function(e){if(e)try{if(e=function(e){return N.isObject(e)?e:JSON.parse(e)}(e),e[m.marketingCloudOrgID]){var t=e[m.marketingCloudOrgID];!function(e){N.isObject(e)&&m.setCustomerIDs(e)}(t.customerIDs),o(t.sdid)}}catch(e){throw new Error("`serverState` has an invalid format.")}},m._timeout=null,m._loadData=function(e,t,n,i){t=m._addQuerystringParam(t,"d_fieldgroup",e,1),i.url=m._addQuerystringParam(i.url,"d_fieldgroup",e,1),i.corsUrl=m._addQuerystringParam(i.corsUrl,"d_fieldgroup",e,1),V.fieldGroupObj[e]=!0,i===Object(i)&&i.corsUrl&&"XMLHttpRequest"===R.corsMetadata.corsType&&R.fireCORS(i,n,e)},m._clearTimeout=function(e){null!=m._timeout&&m._timeout[e]&&(clearTimeout(m._timeout[e]),m._timeout[e]=0)},m._settingsDigest=0,m._getSettingsDigest=function(){if(!m._settingsDigest){var e=m.version;m.audienceManagerServer&&(e+="|"+m.audienceManagerServer),m.audienceManagerServerSecure&&(e+="|"+m.audienceManagerServerSecure),m._settingsDigest=m._hash(e)}return m._settingsDigest},m._readVisitorDone=!1,m._readVisitor=function(){if(!m._readVisitorDone){m._readVisitorDone=!0;var e,t,n,i,r,a,o=m._getSettingsDigest(),s=!1,l=m.cookieRead(m.cookieName),c=new Date;if(l||v||m.discardTrackingServerECID||(l=m.cookieRead(re.FIRST_PARTY_SERVER_COOKIE)),null==m._fields&&(m._fields={}),l&&"T"!==l)for(l=l.split("|"),l[0].match(/^[\-0-9]+$/)&&(parseInt(l[0],10)!==o&&(s=!0),l.shift()),l.length%2==1&&l.pop(),e=0;e<l.length;e+=2)t=l[e].split("-"),n=t[0],i=l[e+1],t.length>1?(r=parseInt(t[1],10),a=t[1].indexOf("s")>0):(r=0,a=!1),s&&("MCCIDH"===n&&(i=""),r>0&&(r=c.getTime()/1e3-60)),n&&i&&(m._setField(n,i,1),r>0&&(m._fields["expire"+n]=r+(a?"s":""),(c.getTime()>=1e3*r||a&&!m.cookieRead(m.sessionCookieName))&&(m._fieldsExpired||(m._fieldsExpired={}),m._fieldsExpired[n]=!0)));!m._getField(M)&&N.isTrackingServerPopulated()&&(l=m.cookieRead("s_vi"))&&(l=l.split("|"),l.length>1&&l[0].indexOf("v1")>=0&&(i=l[1],e=i.indexOf("["),e>=0&&(i=i.substring(0,e)),i&&i.match(re.VALID_VISITOR_ID_REGEX)&&m._setField(M,i)))}},m._appendVersionTo=function(e){var t="vVersion|"+m.version,n=e?m._getCookieVersion(e):null;return n?Z.areVersionsDifferent(n,m.version)&&(e=e.replace(re.VERSION_REGEX,t)):e+=(e?"|":"")+t,e},m._writeVisitor=function(){var e,t,n=m._getSettingsDigest();for(e in m._fields)L(e)&&m._fields[e]&&"expire"!==e.substring(0,6)&&(t=m._fields[e],n+=(n?"|":"")+e+(m._fields["expire"+e]?"-"+m._fields["expire"+e]:"")+"|"+t);n=m._appendVersionTo(n),m.cookieWrite(m.cookieName,n,1)},m._getField=function(e,t){return null==m._fields||!t&&m._fieldsExpired&&m._fieldsExpired[e]?null:m._fields[e]},m._setField=function(e,t,n){null==m._fields&&(m._fields={}),m._fields[e]=t,n||m._writeVisitor()},m._getFieldList=function(e,t){var n=m._getField(e,t);return n?n.split("*"):null},m._setFieldList=function(e,t,n){m._setField(e,t?t.join("*"):"",n)},m._getFieldMap=function(e,t){var n=m._getFieldList(e,t);if(n){var i,r={};for(i=0;i<n.length;i+=2)r[n[i]]=n[i+1];return r}return null},m._setFieldMap=function(e,t,n){var i,r=null;if(t){r=[];for(i in t)L(i)&&(r.push(i),r.push(t[i]))}m._setFieldList(e,r,n)},m._setFieldExpire=function(e,t,n){var i=new Date;i.setTime(i.getTime()+1e3*t),null==m._fields&&(m._fields={}),m._fields["expire"+e]=Math.floor(i.getTime()/1e3)+(n?"s":""),t<0?(m._fieldsExpired||(m._fieldsExpired={}),m._fieldsExpired[e]=!0):m._fieldsExpired&&(m._fieldsExpired[e]=!1),n&&(m.cookieRead(m.sessionCookieName)||m.cookieWrite(m.sessionCookieName,"1"))},m._findVisitorID=function(t){return t&&("object"===e(t)&&(t=t.d_mid?t.d_mid:t.visitorID?t.visitorID:t.id?t.id:t.uuid?t.uuid:""+t),t&&"NOTARGET"===(t=t.toUpperCase())&&(t=P),t&&(t===P||t.match(re.VALID_VISITOR_ID_REGEX))||(t="")),t},m._setFields=function(t,n){if(m._clearTimeout(t),null!=m._loading&&(m._loading[t]=!1),V.fieldGroupObj[t]&&V.setState(t,!1),"MC"===t){!0!==V.isClientSideMarketingCloudVisitorID&&(V.isClientSideMarketingCloudVisitorID=!1);var i=m._getField(y);if(!i||m.overwriteCrossDomainMCIDAndAID){if(!(i="object"===e(n)&&n.mid?n.mid:m._findVisitorID(n))){if(m._use1stPartyMarketingCloudServer&&!m.tried1stPartyMarketingCloudServer)return m.tried1stPartyMarketingCloudServer=!0,void m.getAnalyticsVisitorID(null,!1,!0);i=m._generateLocalMID()}m._setField(y,i)}i&&i!==P||(i=""),"object"===e(n)&&((n.d_region||n.dcs_region||n.d_blob||n.blob)&&m._setFields(k,n),m._use1stPartyMarketingCloudServer&&n.mid&&m._setFields(O,{id:n.id})),m._callAllCallbacks(y,[i])}if(t===k&&"object"===e(n)){var r=604800;void 0!=n.id_sync_ttl&&n.id_sync_ttl&&(r=parseInt(n.id_sync_ttl,10));var a=x.getRegionAndCheckIfChanged(n,r);m._callAllCallbacks("MCAAMLH",[a]);var o=m._getField(T);(n.d_blob||n.blob)&&(o=n.d_blob,o||(o=n.blob),m._setFieldExpire(T,r),m._setField(T,o)),o||(o=""),m._callAllCallbacks(T,[o]),!n.error_msg&&m._newCustomerIDsHash&&m._setField("MCCIDH",m._newCustomerIDsHash)}if(t===O){var s=m._getField(M);s&&!m.overwriteCrossDomainMCIDAndAID||(s=m._findVisitorID(n),s?s!==P&&m._setFieldExpire(T,-1):s=P,m._setField(M,s)),s&&s!==P||(s=""),m._callAllCallbacks(M,[s])}if(m.idSyncDisableSyncs||m.disableIdSyncs)x.idCallNotProcesssed=!0;else{x.idCallNotProcesssed=!1;var l={};l.ibs=n.ibs,l.subdomain=n.subdomain,x.processIDCallData(l)}if(n===Object(n)){var c,d;u()&&m.isAllowed()&&(c=m._getField("MCOPTOUT"));var f=j.parseOptOut(n,c,P);c=f.optOut,d=f.d_ottl,m._setFieldExpire("MCOPTOUT",d,!0),m._setField("MCOPTOUT",c),m._callAllCallbacks("MCOPTOUT",[c])}},m._loading=null,m._getRemoteField=function(e,t,n,i,r){var a,o="",s=N.isFirstPartyAnalyticsVisitorIDCall(e),l={MCAAMLH:!0,MCAAMB:!0};if(u()&&m.isAllowed()){m._readVisitor(),o=m._getField(e,!0===l[e]);if(function(){return(!o||m._fieldsExpired&&m._fieldsExpired[e])&&(!m.disableThirdPartyCalls||s)}()){if(e===y||"MCOPTOUT"===e?a="MC":"MCAAMLH"===e||e===T?a=k:e===M&&(a=O),a)return!t||null!=m._loading&&m._loading[a]||(null==m._loading&&(m._loading={}),m._loading[a]=!0,m._loadData(a,t,function(t){if(!m._getField(e)){t&&V.setState(a,!0);var n="";e===y?n=m._generateLocalMID():a===k&&(n={error_msg:"timeout"}),m._setFields(a,n)}},r)),m._registerCallback(e,n),o||(t||m._setFields(a,{id:P}),"")}else o||(e===y?(m._registerCallback(e,n),o=m._generateLocalMID(),m.setMarketingCloudVisitorID(o)):e===M?(m._registerCallback(e,n),o="",m.setAnalyticsVisitorID(o)):(o="",i=!0))}return e!==y&&e!==M||o!==P||(o="",i=!0),n&&i&&m._callCallback(n,[o]),o},m._setMarketingCloudFields=function(e){m._readVisitor(),m._setFields("MC",e)},m._mapCustomerIDs=function(e){m.getAudienceManagerBlob(e,!0)},m._setAnalyticsFields=function(e){m._readVisitor(),m._setFields(O,e)},m._setAudienceManagerFields=function(e){m._readVisitor(),m._setFields(k,e)},m._getAudienceManagerURLData=function(e){var t=m.audienceManagerServer,n="",i=m._getField(y),r=m._getField(T,!0),a=m._getField(M),o=a&&a!==P?"&d_cid_ic=AVID%01"+encodeURIComponent(a):"";if(m.loadSSL&&m.audienceManagerServerSecure&&(t=m.audienceManagerServerSecure),t){var s,l,c=m.getCustomerIDs();if(c)for(s in c)L(s)&&(l=c[s],o+="&d_cid_ic="+encodeURIComponent(s)+"%01"+encodeURIComponent(l.id?l.id:"")+(l.authState?"%01"+l.authState:""));e||(e="_setAudienceManagerFields");var u="http"+(m.loadSSL?"s":"")+"://"+t+"/id",d="d_visid_ver="+m.version+(C&&-1!==u.indexOf("demdex.net")?"&gdpr=1&gdpr_force=1&gdpr_consent="+C:"")+"&d_rtbd=json&d_ver=2"+(!i&&m._use1stPartyMarketingCloudServer?"&d_verify=1":"")+"&d_orgid="+encodeURIComponent(m.marketingCloudOrgID)+"&d_nsid="+(m.idSyncContainerID||0)+(i?"&d_mid="+encodeURIComponent(i):"")+(m.idSyncDisable3rdPartySyncing||m.disableThirdPartyCookies?"&d_coppa=true":"")+(!0===A?"&d_coop_safe=1":!1===A?"&d_coop_unsafe=1":"")+(r?"&d_blob="+encodeURIComponent(r):"")+o,f=["s_c_il",m._in,e];return n=u+"?"+d+"&d_cb=s_c_il%5B"+m._in+"%5D."+e,{url:n,corsUrl:u+"?"+d,callback:f}}return{url:n}},m.appendVisitorIDsTo=function(e){try{var t=[[y,m._getField(y)],[M,m._getField(M)],["MCORGID",m.marketingCloudOrgID]];return m._addQuerystringParam(e,re.ADOBE_MC,s(t))}catch(t){return e}},m.appendSupplementalDataIDTo=function(e,t){if(!(t=t||m.getSupplementalDataID(N.generateRandomString(),!0)))return e;try{var n=s([["SDID",t],["MCORGID",m.marketingCloudOrgID]]);return m._addQuerystringParam(e,re.ADOBE_MC_SDID,n)}catch(t){return e}};var N={parseHash:function(e){var t=e.indexOf("#");return t>0?e.substr(t):""},hashlessUrl:function(e){var t=e.indexOf("#");return t>0?e.substr(0,t):e},addQueryParamAtLocation:function(e,t,n){var i=e.split("&");return n=null!=n?n:i.length,i.splice(n,0,t),i.join("&")},isFirstPartyAnalyticsVisitorIDCall:function(e,t,n){if(e!==M)return!1;var i;return t||(t=m.trackingServer),n||(n=m.trackingServerSecure),!("string"!=typeof(i=m.loadSSL?n:t)||!i.length)&&(i.indexOf("2o7.net")<0&&i.indexOf("omtrdc.net")<0)},isObject:function(e){return Boolean(e&&e===Object(e))},removeCookie:function(e){Q.remove(e,{domain:m.cookieDomain})},isTrackingServerPopulated:function(){return!!m.trackingServer||!!m.trackingServerSecure},getTimestampInSeconds:function(){return Math.round((new Date).getTime()/1e3)},parsePipeDelimetedKeyValues:function(e){return e.split("|").reduce(function(e,t){var n=t.split("=");return e[n[0]]=decodeURIComponent(n[1]),e},{})},generateRandomString:function(e){e=e||5;for(var t="",n="abcdefghijklmnopqrstuvwxyz0123456789";e--;)t+=n[Math.floor(Math.random()*n.length)];return t},normalizeBoolean:function(e){return"true"===e||"false"!==e&&e},parseBoolean:function(e){return"true"===e||"false"!==e&&null},replaceMethodsWithFunction:function(e,t){for(var n in e)e.hasOwnProperty(n)&&"function"==typeof e[n]&&(e[n]=t);return e}};m._helpers=N;var x=ae(m,S);m._destinationPublishing=x,m.timeoutMetricsLog=[];var V={isClientSideMarketingCloudVisitorID:null,MCIDCallTimedOut:null,AnalyticsIDCallTimedOut:null,AAMIDCallTimedOut:null,fieldGroupObj:{},setState:function(e,t){switch(e){case"MC":!1===t?!0!==this.MCIDCallTimedOut&&(this.MCIDCallTimedOut=!1):this.MCIDCallTimedOut=t;break;case O:!1===t?!0!==this.AnalyticsIDCallTimedOut&&(this.AnalyticsIDCallTimedOut=!1):this.AnalyticsIDCallTimedOut=t;break;case k:!1===t?!0!==this.AAMIDCallTimedOut&&(this.AAMIDCallTimedOut=!1):this.AAMIDCallTimedOut=t}}};m.isClientSideMarketingCloudVisitorID=function(){return V.isClientSideMarketingCloudVisitorID},m.MCIDCallTimedOut=function(){return V.MCIDCallTimedOut},m.AnalyticsIDCallTimedOut=function(){return V.AnalyticsIDCallTimedOut},m.AAMIDCallTimedOut=function(){return V.AAMIDCallTimedOut},m.idSyncGetOnPageSyncInfo=function(){return m._readVisitor(),m._getField("MCSYNCSOP")},m.idSyncByURL=function(e){if(!m.isOptedOut()){var t=l(e||{});if(t.error)return t.error;var n,i,r=e.url,a=encodeURIComponent,o=x;return r=r.replace(/^https:/,"").replace(/^http:/,""),n=j.encodeAndBuildRequest(["",e.dpid,e.dpuuid||""],","),i=["ibs",a(e.dpid),"img",a(r),t.ttl,"",n],o.addMessage(i.join("|")),o.requestToProcess(),"Successfully queued"}},m.idSyncByDataSource=function(e){if(!m.isOptedOut())return e===Object(e)&&"string"==typeof e.dpuuid&&e.dpuuid.length?(e.url="//dpm.demdex.net/ibs:dpid="+e.dpid+"&dpuuid="+e.dpuuid,m.idSyncByURL(e)):"Error: config or config.dpuuid is empty"},Ue(m,x),m._getCookieVersion=function(e){e=e||m.cookieRead(m.cookieName);var t=re.VERSION_REGEX.exec(e);return t&&t.length>1?t[1]:null},m._resetAmcvCookie=function(e){var t=m._getCookieVersion();t&&!Z.isLessThan(t,e)||N.removeCookie(m.cookieName)},m.setAsCoopSafe=function(){A=!0},m.setAsCoopUnsafe=function(){A=!1},function(){if(m.configs=Object.create(null),N.isObject(n))for(var e in n)L(e)&&(m[e]=n[e],m.configs[e]=n[e])}(),d();var U;m.init=function(){c()&&(h.optIn.fetchPermissions(p,!0),!h.optIn.isApproved(h.optIn.Categories.ECID))||U||(U=!0,function(){if(N.isObject(n)){m.idSyncContainerID=m.idSyncContainerID||0,A="boolean"==typeof m.isCoopSafe?m.isCoopSafe:N.parseBoolean(m.isCoopSafe),m.resetBeforeVersion&&m._resetAmcvCookie(m.resetBeforeVersion),m._attemptToPopulateIdsFromUrl(),m._attemptToPopulateSdidFromUrl(),m._readVisitor();var e=m._getField(b),t=Math.ceil((new Date).getTime()/re.MILLIS_PER_DAY);m.idSyncDisableSyncs||m.disableIdSyncs||!x.canMakeSyncIDCall(e,t)||(m._setFieldExpire(T,-1),m._setField(b,t)),m.getMarketingCloudVisitorID(),m.getAudienceManagerLocationHint(),m.getAudienceManagerBlob(),m._mergeServerState(m.serverState)}else m._attemptToPopulateIdsFromUrl(),m._attemptToPopulateSdidFromUrl()}(),function(){if(!m.idSyncDisableSyncs&&!m.disableIdSyncs){x.checkDPIframeSrc();var e=function(){var e=x;e.readyToAttachIframe()&&e.attachIframe()};D.addEventListener("load",function(){S.windowLoaded=!0,e()});try{te.receiveMessage(function(e){x.receiveMessage(e.data)},x.iframeHost)}catch(e){}}}(),function(){m.whitelistIframeDomains&&re.POST_MESSAGE_ENABLED&&(m.whitelistIframeDomains=m.whitelistIframeDomains instanceof Array?m.whitelistIframeDomains:[m.whitelistIframeDomains],m.whitelistIframeDomains.forEach(function(e){var n=new B(t,e),i=K(m,n);te.receiveMessage(i,e)}))}())}};qe.config=se,_.Visitor=qe;var Xe=qe,We=function(e){if(j.isObject(e))return Object.keys(e).filter(function(t){return""!==e[t]}).reduce(function(t,n){var i=se.normalizeConfig(e[n]),r=j.normalizeBoolean(i);return t[n]=r,t},Object.create(null))},Je=Ve.OptIn,Ke=Ve.IabPlugin;return Xe.getInstance=function(e,t){if(!e)throw new Error("Visitor requires Adobe Marketing Cloud Org ID.");e.indexOf("@")<0&&(e+="@AdobeOrg");var n=function(){var t=_.s_c_il;if(t)for(var n=0;n<t.length;n++){var i=t[n];if(i&&"Visitor"===i._c&&i.marketingCloudOrgID===e)return i}}();if(n)return n;var i=We(t);!function(e){_.adobe.optIn=_.adobe.optIn||function(){var t=j.pluck(e,["doesOptInApply","previousPermissions","preOptInApprovals","isOptInStorageEnabled","optInStorageExpiry","isIabContext"]),n=e.optInCookieDomain||e.cookieDomain;n=n||$(),n=n===window.location.hostname?"":n,t.optInCookieDomain=n;var i=new Je(t,{cookies:Q});if(t.isIabContext&&t.doesOptInApply){var r=new Ke(window.__cmp);i.registerPlugin(r)}return i}()}(i||{});var r=e,a=r.split("").reverse().join(""),o=new Xe(e,null,a);j.isObject(i)&&i.cookieDomain&&(o.cookieDomain=i.cookieDomain),function(){_.s_c_il.splice(--_.s_c_in,1)}();var s=j.getIeVersion();if("number"==typeof s&&s<10)return o._helpers.replaceMethodsWithFunction(o,function(){});var l=function(){try{return _.self!==_.parent}catch(e){return!0}}()&&!function(e){return e.cookieWrite("TEST_AMCV_COOKIE","T",1),"T"===e.cookieRead("TEST_AMCV_COOKIE")&&(e._helpers.removeCookie("TEST_AMCV_COOKIE"),!0)}(o)&&_.parent?new Y(e,i,o,_.parent):new Xe(e,i,a);return o=null,l.init(),l},function(){function e(){Xe.windowLoaded=!0}_.addEventListener?_.addEventListener("load",e):_.attachEvent&&_.attachEvent("onload",e),Xe.codeLoadEnd=(new Date).getTime()}(),Xe}();// Dynamic Tag Management Library | |
| // Property: DTM - 2.0 | |
| // All code and conventions are protected by copyright | |
| // Adobe Systems Incorporated | |
| (function(window, document, undefined) { | |
| // Satellite | |
| // ========= | |
| // | |
| // Satellite *core*. Yeah, you want it. | |
| // | |
| // In this first section, we have a some useful utility functions. | |
| var ToString = Object.prototype.toString | |
| var Overrides = window._satellite && window._satellite.override | |
| function assert(cond, msg){ | |
| if (!cond){ | |
| throw new Error(msg || "Assertion Failure") | |
| } | |
| } | |
| var SL = { | |
| initialized: false, | |
| // `$data(elm, prop, [val])` | |
| // ---------------------------- | |
| // | |
| // Our own `$data()` method, [a la jQuery](http://api.jquery.com/jQuery.data/) | |
| // , used to get or set | |
| // properties on DOM elements without going insane. | |
| // `uuid` and `dataCache` are used by `$data()` | |
| // | |
| // Parameters: | |
| // | |
| // - `elm` - the element to get or set a property to | |
| // - `prop` - the property name | |
| // - `val` - the value of the property, if omitted, the method will | |
| // return the existing value of the property, if any | |
| $data: function(elm, prop, val){ | |
| if (!elm) return; | |
| var __satellite__ = '__satellite__' | |
| var cache = SL.dataCache | |
| var uuid = elm[__satellite__] | |
| if (!uuid) uuid = elm[__satellite__] = SL.uuid++ | |
| var datas = cache[uuid] | |
| if (!datas) datas = cache[uuid] = {} | |
| if (val === undefined) | |
| return datas[prop] | |
| else | |
| datas[prop] = val | |
| }, | |
| uuid: 1, | |
| dataCache: {}, | |
| // `keys(object)` | |
| // -------------- | |
| // | |
| // Return all keys of an object in an array. | |
| keys: function(obj){ | |
| var ret = [] | |
| for (var key in obj) | |
| if (obj.hasOwnProperty(key)) | |
| ret.push(key) | |
| return ret | |
| }, | |
| // `values(object)` | |
| // ---------------- | |
| // | |
| // Return all values of an object in an array. | |
| values: function(obj){ | |
| var ret = [] | |
| for (var key in obj) | |
| if (obj.hasOwnProperty(key)) | |
| ret.push(obj[key]) | |
| return ret | |
| }, | |
| // `isArray(thing)` | |
| // -------------- | |
| // | |
| // Returns whether the given thing is an array. | |
| isArray: Array.isArray || function(thing){ | |
| return ToString.apply(thing) === "[object Array]" | |
| }, | |
| // `isObject(thing)` | |
| // ----------------- | |
| // | |
| // Returns whether the given thing is a plain object. | |
| isObject: function(thing){ | |
| return thing != null && !SL.isArray(thing) && | |
| typeof thing === 'object' | |
| }, | |
| // `isString(thing)` | |
| // ----------------- | |
| // | |
| // Returns whether thing is a string | |
| isString: function(thing){ | |
| return typeof thing === 'string' | |
| }, | |
| // `isNumber(thing)` | |
| // ----------------- | |
| // | |
| // Returns whether thing is a number | |
| isNumber: function(thing){ | |
| return ToString.apply(thing) === '[object Number]' && !SL.isNaN(thing) | |
| }, | |
| // `isNaN(thing)` | |
| // -------------- | |
| // | |
| // Return whether thing is NaN | |
| isNaN: function(thing){ | |
| return thing !== thing | |
| }, | |
| // `isRegex(thing)` | |
| // ---------------- | |
| // | |
| // Returns whether thing is a RegExp object | |
| isRegex: function(thing){ | |
| return thing instanceof RegExp | |
| }, | |
| // `isLinkTag(thing)` | |
| // ---------------- | |
| // | |
| // Returns whether thing is a DOM link element | |
| isLinkTag: function(thing){ | |
| return !!(thing && thing.nodeName && | |
| thing.nodeName.toLowerCase() === 'a') | |
| }, | |
| // `each(arr, func, [context])` | |
| // ------------------ | |
| // | |
| // A handy method for array iteration wo having to write a for-loop. | |
| // | |
| // Parameters: | |
| // | |
| // - `arr` - an array | |
| // - `func(item, index, arr)` - a function which accepts each item in the array | |
| // once. I takes these arguments | |
| // * `item` - an item | |
| // * `index` - the array index of said item | |
| // * `arr` - the array | |
| // - `context` - the context to be bound to `func` when it is invoked | |
| each: function(arr, func, context){ | |
| for (var i = 0, len = arr.length; i < len; i++) | |
| func.call(context, arr[i], i, arr) | |
| }, | |
| // `map(arr, func)` | |
| // ---------------- | |
| // | |
| // A handy method for mapping an array to another array using a 1-to-1 mapping | |
| // for each element | |
| // | |
| // Parameters: | |
| // | |
| // Parameters are the same as `SL.each`, except that `func` is expected to return | |
| // a the value you want in the corresponding index of the returned array. | |
| map: function(arr, func, context){ | |
| var ret = [] | |
| for (var i = 0, len = arr.length; i < len; i++) | |
| ret.push(func.call(context, arr[i], i, arr)) | |
| return ret | |
| }, | |
| // `filter(arr, cond)` | |
| // ------------------- | |
| // | |
| // Handy method for take an array and filtering down to a subset of the elements. | |
| // | |
| // Parameters: | |
| // | |
| // Parameters are the same as `SL.each` except the second argument is `cond` | |
| // instead of `func` and it is expected to return a truthy value respresenting | |
| // whether to include this item in the return array or not. | |
| filter: function(arr, cond, context){ | |
| var ret = [] | |
| for (var i = 0, len = arr.length; i < len; i++){ | |
| var item = arr[i] | |
| if (cond.call(context, item, i, arr)) | |
| ret.push(item) | |
| } | |
| return ret | |
| }, | |
| // `any(arr, cond, context)` | |
| // ------------------------- | |
| // | |
| // Another array helper function. Returns true if `cond(item)` returns true | |
| // for any item in the array. | |
| any: function(arr, cond, context){ | |
| for (var i = 0, len = arr.length; i < len; i++){ | |
| var item = arr[i] | |
| if (cond.call(context, item, i, arr)) | |
| return true | |
| } | |
| return false | |
| }, | |
| // `every(arr, cond, context)` | |
| // --------------------------- | |
| // | |
| // Another array helper function. Returns true if `cond(item)` returns true | |
| // for every item in the array. | |
| every: function(arr, cond, context){ | |
| var retval = true | |
| for (var i = 0, len = arr.length; i < len; i++){ | |
| var item = arr[i] | |
| retval = retval && cond.call(context, item, i, arr) | |
| } | |
| return retval | |
| }, | |
| // `contains(arr, obj)` | |
| // ----------------------- | |
| // | |
| // Tells you whether an array contains an object. | |
| // | |
| // Parameters: | |
| // | |
| // - `arr` - said array | |
| // - `obj` - said object | |
| contains: function(arr, obj){ | |
| return SL.indexOf(arr, obj) !== -1 | |
| }, | |
| // `indexOf(arr, obj)` | |
| // ------------------- | |
| // | |
| // Return the index of an object within an array. | |
| // | |
| // Parameters; | |
| // | |
| // - `arr` - said array | |
| // - `obj` - said object | |
| indexOf: function(arr, obj){ | |
| if (arr.indexOf) | |
| return arr.indexOf(obj) | |
| for (var i = arr.length; i--;) | |
| if (obj === arr[i]) | |
| return i | |
| return -1 | |
| }, | |
| // `find(arr, obj)` | |
| // ------------------- | |
| // | |
| // Return the index of an object within an array. | |
| // | |
| // Parameters; | |
| // | |
| // - `arr` - said array | |
| // - `obj` - said object | |
| find: function(arr, cond, context){ | |
| var ret = [] | |
| if (!arr) return null | |
| for (var i = 0, len = arr.length; i < len; i++){ | |
| var item = arr[i] | |
| if (cond.call(context, item, i, arr)) | |
| return item | |
| } | |
| return null | |
| }, | |
| // `textMatch(str, str_or_regex)` | |
| // ------------------------------ | |
| // | |
| // Perform a string match based on another string or a regex. | |
| // | |
| // Parameters: | |
| // | |
| // `str` - the input string to be matched | |
| // `str_or_regex` - the pattern to match against, if this is a string, it requires exact match, if | |
| // it's a regex, then it will do regex match | |
| textMatch: function(str, pattern){ | |
| if (pattern == null) throw new Error('Illegal Argument: Pattern is not present') | |
| if (str == null) return false | |
| if (typeof pattern === 'string') return str === pattern | |
| else if (pattern instanceof RegExp) return pattern.test(str) | |
| else return false | |
| }, | |
| // `stringify(obj, [seenValues])` | |
| // ------------------------------ | |
| // | |
| // Stringify any type of object. | |
| // | |
| // Parameters: | |
| // | |
| // `obj` - the object that needs to be stringified | |
| // `seenValues` - pool of parsed resources; used to avoid circular references; | |
| stringify: function(obj, seenValues){ | |
| seenValues = seenValues || []; | |
| if (SL.isObject(obj)) { | |
| if (SL.contains(seenValues, obj)) { | |
| return '<Cycle>'; | |
| } else { | |
| seenValues.push(obj); | |
| } | |
| } | |
| if (SL.isArray(obj)) { | |
| return '[' + SL.map(obj, function(value){ | |
| return SL.stringify(value, seenValues) | |
| }).join(',') + ']'; | |
| } else if (SL.isString(obj)) { | |
| return '"' + String(obj) + '"'; | |
| } if (SL.isObject(obj)) { | |
| var data = []; | |
| for (var prop in obj) { | |
| if (obj.hasOwnProperty(prop)) | |
| data.push(prop + ': ' + SL.stringify(obj[prop], seenValues)); | |
| } | |
| return '{' + data.join(', ') + '}'; | |
| } else { | |
| return String(obj); | |
| } | |
| }, | |
| // `trim(str)` | |
| // ----------- | |
| // | |
| // Trims a string. | |
| // | |
| // Parameters: | |
| // | |
| // `str` - the input string to be trimmed. | |
| trim: function(str){ | |
| if (str == null) return null | |
| if (str.trim){ | |
| return str.trim() | |
| }else{ | |
| return str.replace(/^ */, '').replace(/ *$/, '') | |
| } | |
| }, | |
| // `bind(func, context)` | |
| // --------------------- | |
| // | |
| // Binds a context permanently to a context. The returned function is a new function | |
| // which - when called - will call the passed in function with `context` bound to it. | |
| // | |
| // Parameters: | |
| // | |
| // `func` - a function | |
| // `context` - an object to be bound as the context of this function | |
| bind: function(func, context) { | |
| return function() { | |
| return func.apply(context, arguments) | |
| } | |
| }, | |
| // `throttle(fn, delay)` | |
| // --------------------- | |
| // | |
| // *Throttles* a function `fn` to be called no more than once during the interval | |
| // specified by `delay`. | |
| // | |
| // Parameters: | |
| // | |
| // - `fn` - a function | |
| // - `delay` - delay in milliseconds | |
| // | |
| // *Throttle function stolen from | |
| // <http://remysharp.com/2010/07/21/throttling-function-calls/>* | |
| throttle: function(fn, delay) { | |
| var timer = null; | |
| return function () { | |
| var context = this, args = arguments; | |
| clearTimeout(timer); | |
| timer = setTimeout(function () { | |
| fn.apply(context, args); | |
| }, delay); | |
| }; | |
| }, | |
| // `domReady(callback)` | |
| // -------------------- | |
| // | |
| // Registers a callback to be called when the DOM is fully parsed and loaded. | |
| // | |
| // Parameters: | |
| // | |
| // - `callback` - a function to be called at `domready` | |
| // | |
| // *domReady is borrowed from <https://github.com/ded/domready>* | |
| domReady: (function (ready) { | |
| var fns = [], fn, f = false | |
| , doc = document | |
| , testEl = doc.documentElement | |
| , hack = testEl.doScroll | |
| , domContentLoaded = 'DOMContentLoaded' | |
| , addEventListener = 'addEventListener' | |
| , onreadystatechange = 'onreadystatechange' | |
| , loaded = /^loade|^c/.test(doc.readyState) | |
| function flush(f) { | |
| loaded = 1 | |
| while (f = fns.shift()) f() | |
| } | |
| doc[addEventListener] && doc[addEventListener](domContentLoaded, fn = function () { | |
| doc.removeEventListener(domContentLoaded, fn, f) | |
| flush() | |
| }, f) | |
| hack && doc.attachEvent(onreadystatechange, (fn = function () { | |
| if (/^c/.test(doc.readyState)) { | |
| doc.detachEvent(onreadystatechange, fn) | |
| flush() | |
| } | |
| })) | |
| return (ready = hack ? | |
| function (fn) { | |
| self != top ? | |
| loaded ? fn() : fns.push(fn) : | |
| function () { | |
| try { | |
| testEl.doScroll('left') | |
| } catch (e) { | |
| return setTimeout(function() { ready(fn) }, 50) | |
| } | |
| fn() | |
| }() | |
| } : | |
| function (fn) { | |
| loaded ? fn() : fns.push(fn) | |
| }) | |
| }()), | |
| // `loadScript(url, [callback])` | |
| // ----------------------------- | |
| // | |
| // Load an external script. | |
| // | |
| // Parameters: | |
| // | |
| // - `url` - the URL of the script | |
| // - `callback`(optional) - the function to be called after the script has loaded. | |
| loadScript: function(url, callback){ | |
| var script = document.createElement('script') | |
| SL.scriptOnLoad(url, script, callback) | |
| script.src = url | |
| document.getElementsByTagName('head')[0] | |
| .appendChild(script) | |
| }, | |
| scriptOnLoad: function(url, script, callback){ | |
| function cb(err){ | |
| if (err) SL.logError(err) | |
| if (callback) callback(err) | |
| } | |
| if ('onload' in script){ | |
| script.onload = function(){ | |
| cb() | |
| } | |
| script.onerror = function(){ | |
| cb(new Error('Failed to load script ' + url)) | |
| } | |
| }else if ('readyState' in script){ | |
| script.onreadystatechange = function(){ | |
| var rs = script.readyState | |
| if (rs === 'loaded' || rs === 'complete'){ | |
| script.onreadystatechange = null | |
| cb() | |
| } | |
| } | |
| } | |
| }, | |
| // `loadScriptOnce(url, [callback])` | |
| // ----------------------------- | |
| // | |
| // Load an external script only if it hasn't been loaded until now. | |
| // | |
| // Parameters: | |
| // | |
| // - `url` - the URL of the script | |
| // - `callback`(optional) - the function to be called after the script has loaded. | |
| loadScriptOnce: function(url, callback){ | |
| if (SL.loadedScriptRegistry[url]) return | |
| SL.loadScript(url, function(err) { | |
| if (!err) { | |
| SL.loadedScriptRegistry[url] = true | |
| } | |
| if (callback) callback(err) | |
| }) | |
| }, | |
| loadedScriptRegistry: {}, | |
| // `loadScriptSync(url)` | |
| // ----------------------------- | |
| // | |
| // Load an external script using document.write. | |
| // | |
| // Parameters: | |
| // | |
| // - `url` - the URL of the script | |
| loadScriptSync: function(url){ | |
| if (!document.write) { | |
| SL.notify('Cannot load sync the "' + url + '" script because "document.write" is not available', 1) | |
| return | |
| } | |
| if (SL.domReadyFired){ | |
| SL.notify('Cannot load sync the "' + url + '" script after DOM Ready.', 1) | |
| return | |
| } | |
| // If the url contains a double quote, it could be someone trying to switch out of the | |
| // attribute to introduce an XSS hack. On the other hand, it could just be that the URL | |
| // was never escaped. We'll escape it to prevent the former while supporting the latter. | |
| if (url.indexOf('"') > -1) { | |
| url = encodeURI(url); | |
| } | |
| document.write('<script src="' + url + '"></scr' + 'ipt>'); | |
| }, | |
| // `pushAsyncScript(callback)` | |
| // ------------------- | |
| // | |
| // Called by an async custom user script. | |
| pushAsyncScript: function(cb){ | |
| SL.tools['default'].pushAsyncScript(cb) | |
| }, | |
| // `pushBlockingScript(callback)` | |
| // ------------------------------ | |
| // | |
| // Called by a blocking custom user script. | |
| pushBlockingScript: function(cb){ | |
| SL.tools['default'].pushBlockingScript(cb) | |
| }, | |
| // `addEventHandler(elm, evt, callback)` | |
| // ------------------------------------- | |
| // | |
| // Register an event handler for a element | |
| // | |
| // Parameters: | |
| // | |
| // - `elm` - the element in question | |
| // - `evt` - the event type to listen to | |
| // - `callback` - callback function | |
| addEventHandler: window.addEventListener ? | |
| function(node, evt, cb){ node.addEventListener(evt, cb, false) } : | |
| function(node, evt, cb){ node.attachEvent('on' + evt, cb) }, | |
| removeEventHandler: window.removeEventListener ? | |
| function(node, evt, cb){ node.removeEventListener(evt, cb, false) } : | |
| function(node, evt, cb){ node.detachEvent('on' + evt, cb) }, | |
| // `preventDefault(evt)` | |
| // --------------------- | |
| // | |
| // Prevent the default browser behavior for this event | |
| // | |
| // Parameters: | |
| // | |
| // `evt` - the event triggered | |
| preventDefault: window.addEventListener ? | |
| function(e){ e.preventDefault() } : | |
| function(e){ e.returnValue = false }, | |
| // `stopPropagation(evt)` | |
| // ---------------------- | |
| // | |
| // Cross-browser `stopPropagation` | |
| // | |
| // Parameters: | |
| // | |
| // `evt` - the event triggered | |
| stopPropagation: function(e){ | |
| e.cancelBubble = true | |
| if (e.stopPropagation) e.stopPropagation() | |
| }, | |
| // `containsElement(container, elm)` | |
| // ---------------------- | |
| // | |
| // Given DOM elements `container` and `elm`, returns whether `container` contains `elm`. | |
| // | |
| // Parameters: | |
| // | |
| // `elm1` - the possible parent | |
| // `elm2` - the possible child | |
| containsElement: function(container, elm) { | |
| return container.contains ? container.contains(elm) : | |
| !!(container.compareDocumentPosition(elm) & 16); | |
| }, | |
| // `matchesCss(css, elm)` | |
| // ---------------------- | |
| // | |
| // Returns whether a DOM element matches a given css selector | |
| // | |
| // Parameters: | |
| // | |
| // - `css` - the CSS selector | |
| // - `elm` - the element | |
| matchesCss: (function(docEl){ | |
| function simpleTagMatch(selector, elm){ | |
| var tagName = elm.tagName | |
| if (!tagName) return false | |
| return selector.toLowerCase() === tagName.toLowerCase() | |
| } | |
| var matches = | |
| docEl.matchesSelector || | |
| docEl.mozMatchesSelector || | |
| docEl.webkitMatchesSelector || | |
| docEl.oMatchesSelector || | |
| docEl.msMatchesSelector | |
| if (matches) { | |
| return function(selector, elm){ | |
| if (elm === document || elm === window) return false | |
| try{ | |
| return matches.call(elm, selector) | |
| }catch(e){ | |
| return false | |
| } | |
| } | |
| } else if(docEl.querySelectorAll) { | |
| return function(selector, elm) { | |
| var parent = elm.parentNode | |
| if (!parent) return false | |
| if (selector.match(/^[a-z]+$/i)){ | |
| return simpleTagMatch(selector, elm) | |
| } | |
| try{ | |
| var nodeList = elm.parentNode.querySelectorAll(selector) | |
| for (var i = nodeList.length; i--;) | |
| if (nodeList[i] === elm) return true | |
| }catch(e){ | |
| // | |
| } | |
| return false | |
| } | |
| }else{ | |
| return function(selector, elm){ | |
| if (selector.match(/^[a-z]+$/i)){ | |
| return simpleTagMatch(selector, elm) | |
| } | |
| try{ | |
| return SL.Sizzle.matches(selector, [elm]).length > 0 | |
| }catch(e){ | |
| return false | |
| } | |
| } | |
| } | |
| }(document.documentElement)), | |
| // `cssQuery(css)` | |
| // --------------- | |
| // | |
| // Return a list of element matching the given css selector | |
| // | |
| // Parameters: | |
| // | |
| // - `css` - the CSS selector | |
| cssQuery: (function(doc){ | |
| if (doc.querySelectorAll) { | |
| return function(css, cb){ | |
| var results | |
| try{ | |
| results = doc.querySelectorAll(css) | |
| }catch(e){ | |
| results = [] | |
| } | |
| cb(results) | |
| } | |
| }else{ | |
| return function(css, cb){ | |
| if (SL.Sizzle){ | |
| var results | |
| try{ | |
| results = SL.Sizzle(css) | |
| }catch(e){ | |
| results = [] | |
| } | |
| cb(results) | |
| }else | |
| SL.sizzleQueue.push([css, cb]) | |
| } | |
| } | |
| })(document), | |
| // `hasAttr(elem, attrName)` | |
| // --------------- | |
| // | |
| // Check if attribute is defined on element | |
| // | |
| // Parameters: | |
| // | |
| // - `elem` - the DOM element | |
| // - `attrName` - attribute name | |
| hasAttr: function(elem, attrName) { | |
| return elem.hasAttribute ? elem.hasAttribute(attrName) : elem[attrName] !== undefined; | |
| }, | |
| // `inherit(subClass, superClass)` | |
| // ------------------------------- | |
| // | |
| // Make `subClass` inherit `superClass`. | |
| // | |
| // Parameters: | |
| // | |
| // - `subClass` - a Javascript function representing a constructor - the inheritor | |
| // - `superClass` - another constructor - the one to inherit from | |
| inherit: function(subClass, superClass){ | |
| var f = function() {} | |
| f.prototype = superClass.prototype | |
| subClass.prototype = new f() | |
| subClass.prototype.constructor = subClass | |
| }, | |
| // `extend(dst, src)` | |
| // ---------------- | |
| // | |
| // Extend an object with the properties of another. | |
| // | |
| // Parameters: | |
| // | |
| // - `dst` - object to copy to | |
| // - `src` - object to copy from | |
| extend: function(dst, src){ | |
| for (var prop in src) | |
| if (src.hasOwnProperty(prop)) | |
| dst[prop] = src[prop] | |
| }, | |
| // `toArray(arrayLike)` | |
| // -------------------- | |
| // | |
| // Converts an array-like object to an array. | |
| // | |
| // Parameters: | |
| // | |
| // - `arrayLike` - an array-like object, meaning it has a length property | |
| // which is a number | |
| toArray: (function(){ | |
| try { | |
| var slice = Array.prototype.slice | |
| slice.call( document.documentElement.childNodes, 0 )[0].nodeType; | |
| return function(thing){ | |
| return slice.call(thing, 0) | |
| } | |
| // Provide a fallback method if it does not work | |
| } catch( e ) { | |
| return function(thing){ | |
| var ret = [] | |
| for (var i = 0, len = thing.length; i < len; i++) | |
| ret.push(thing[i]) | |
| return ret | |
| } | |
| } | |
| })(), | |
| // `equalsIgnoreCase(str1, str2)` | |
| // ------------------------------ | |
| // | |
| // Returns true iff str1 and str2 are equal ignoring case. | |
| // | |
| // Parameters: | |
| // | |
| // * `str1` - the first string | |
| // * `str2` - the second string | |
| equalsIgnoreCase: function(str1, str2){ | |
| if (str1 == null) return str2 == null | |
| if (str2 == null) return false | |
| return String(str1).toLowerCase() === String(str2).toLowerCase() | |
| }, | |
| // `poll(fn, [freq], [max_retries])` | |
| // ------------------ | |
| // | |
| // Runs `fn` for every `freq` ms. `freq` defaults to 1000. If any | |
| // invocation of `fn()` returns true, polling will stop. | |
| // The polling will stop if the number or retries exceeds the | |
| // provided `max_retries`. | |
| // | |
| // Parameters: | |
| // | |
| // * `fn` - function to be called repeatedly | |
| // * `freq` - frequency to call the function | |
| // * `max_retries` - number of times to retry | |
| poll: function(fn, freq, max_retries){ | |
| var retries = 0 | |
| freq = freq || 1000 | |
| check() | |
| function check(){ | |
| if (SL.isNumber(max_retries) && retries++ >= max_retries) { | |
| return; | |
| } | |
| if (!fn()){ | |
| setTimeout(check, freq) | |
| } | |
| } | |
| }, | |
| // ``Html(str)` | |
| // -------------------- | |
| // | |
| // Escapes a string for being used in an HTML context. Returns | |
| // the escaped version of the string. Replaces the characters | |
| // `&` `<` `>` `"` `'` and `/`. | |
| // | |
| // Parameters: | |
| // | |
| // * `str` - the string to be escaped | |
| escapeForHtml: function(str){ | |
| if (!str) return str | |
| return String(str) | |
| .replace(/\&/g, '&') | |
| .replace(/\</g, '<') | |
| .replace(/\>/g, '>') | |
| .replace(/\"/g, '"') | |
| .replace(/\'/g, ''') | |
| .replace(/\//g, '/') | |
| } | |
| } | |
| // The available tools to use. | |
| SL.availableTools = {} | |
| // The avaliable event emitters to use. | |
| SL.availableEventEmitters = [] | |
| // The names of the events which can only fire once. | |
| SL.fireOnceEvents = ['condition', 'elementexists'] | |
| // Initialize all event emitters. | |
| SL.initEventEmitters = function(){ | |
| SL.eventEmitters = SL.map(SL.availableEventEmitters, function(ee){ | |
| return new ee() | |
| }) | |
| } | |
| // Call `registerElements` on all event emitters. | |
| SL.eventEmitterBackgroundTasks = function(){ | |
| SL.each(SL.eventEmitters, function(ee){ | |
| if ('backgroundTasks' in ee) | |
| ee.backgroundTasks() | |
| }) | |
| } | |
| // Initialize all tools. | |
| SL.initTools = function(toolSpecs){ | |
| var tools = { 'default': new DefaultTool() } | |
| var euCookieName = SL.settings.euCookieName || 'sat_track' | |
| for (var id in toolSpecs){ | |
| if(toolSpecs.hasOwnProperty(id)) { | |
| var toolSpec, ctr, tool | |
| toolSpec = toolSpecs[id] | |
| if (toolSpec.euCookie){ | |
| var cookieSet = SL.readCookie(euCookieName) !== 'true' | |
| if (cookieSet) continue | |
| } | |
| ctr = SL.availableTools[toolSpec.engine] | |
| if (!ctr){ | |
| var available = [] | |
| for (var key in SL.availableTools){ | |
| if (SL.availableTools.hasOwnProperty(key)) { | |
| available.push(key) | |
| } | |
| } | |
| throw new Error('No tool engine named ' + toolSpec.engine + | |
| ', available: ' + available.join(',') + '.') | |
| } | |
| tool = new ctr(toolSpec) | |
| tool.id = id | |
| tools[id] = tool | |
| } | |
| } | |
| return tools | |
| } | |
| // Pre-process arguments (variable substitutions and lower-casing) before | |
| // feeding them to the tools. | |
| SL.preprocessArguments = function(args, elm, evt, forceLowerCase, escapeHtml){ | |
| if (!args) return args | |
| return preprocessArray(args, forceLowerCase) | |
| function forceLowerCaseIfNeeded(value) { | |
| return forceLowerCase && SL.isString(value) ? value.toLowerCase() : value | |
| } | |
| function preprocessObject(obj){ | |
| var ret = {} | |
| for (var key in obj){ | |
| if (obj.hasOwnProperty(key)){ | |
| var value = obj[key] | |
| if (SL.isObject(value)){ | |
| ret[key] = preprocessObject(value) | |
| }else if (SL.isArray(value)){ | |
| ret[key] = preprocessArray(value, forceLowerCase) | |
| }else{ | |
| ret[key] = forceLowerCaseIfNeeded(SL.replace(value, elm, evt, escapeHtml)) | |
| } | |
| } | |
| } | |
| return ret | |
| } | |
| function preprocessArray(args, forceLowerCase){ | |
| var ret = [] | |
| for (var i = 0, len = args.length; i < len; i++){ | |
| var value = args[i] | |
| if (SL.isString(value)){ | |
| value = forceLowerCaseIfNeeded(SL.replace(value, elm, evt)) | |
| }else if (value && value.constructor === Object){ | |
| value = preprocessObject(value) | |
| } | |
| ret.push(value) | |
| } | |
| return ret | |
| } | |
| } | |
| // Execute a command. | |
| SL.execute = function(trig, elm, evt, tools){ | |
| if (_satellite.settings.hideActivity) return | |
| tools = tools || SL.tools | |
| function doit(toolName){ | |
| var tool = tools[toolName || 'default'] | |
| if (!tool) | |
| return | |
| try{ | |
| tool.triggerCommand(trig, elm, evt) | |
| }catch(e){ | |
| SL.logError(e) | |
| } | |
| } | |
| if (trig.engine){ | |
| var engine = trig.engine | |
| for (var toolName in tools){ | |
| if (tools.hasOwnProperty(toolName)) { | |
| var tool = tools[toolName] | |
| if (tool.settings && tool.settings.engine === engine) | |
| doit(toolName) | |
| } | |
| } | |
| }else if (trig.tool instanceof Array) | |
| SL.each(trig.tool, function(toolName){ | |
| doit(toolName) | |
| }) | |
| else | |
| doit(trig.tool) | |
| } | |
| // Wrapper object that handles Satellite internal logging. | |
| // | |
| // It saves all messages for future reference (up to `keepLimit`, default 100) and | |
| // outputs to browser's console if `_satellite.settings.notifications` is `true`. | |
| // ----------------------------------------------------- | |
| SL.Logger = { | |
| outputEnabled: false, | |
| messages: [], | |
| keepLimit: 100, | |
| flushed: false, | |
| // @fixme: remove first 2 items when legacy code is updated | |
| LEVELS: [null, null, 'log', 'info', 'warn', 'error'], | |
| // `lvl` should be the index of a level defined in `LEVELS` | |
| message: function(msg, lvl) { | |
| var level = this.LEVELS[lvl] || 'log'; | |
| this.messages.push([level, msg]); | |
| if (this.messages.length > this.keepLimit) { | |
| this.messages.shift(); | |
| } | |
| if (this.outputEnabled) { | |
| this.echo(level, msg) | |
| } | |
| }, | |
| getHistory: function() { | |
| return this.messages; | |
| }, | |
| clearHistory: function() { | |
| this.messages = []; | |
| }, | |
| setOutputState: function(state) { | |
| if (this.outputEnabled == state) return; | |
| this.outputEnabled = state; | |
| if (state) { | |
| this.flush(); | |
| } else { | |
| this.flushed = false; | |
| } | |
| }, | |
| // Private | |
| // ---------------------------------------- | |
| echo: function(func, msg) { | |
| if (!window.console) return; | |
| window.console[func]("SATELLITE: " + msg); | |
| }, | |
| flush: function() { | |
| if (this.flushed) return; | |
| SL.each(this.messages, function(item) { | |
| if (item[2] === true) return; // message already flushed | |
| this.echo(item[0], item[1]); | |
| item[2] = true; | |
| }, this); | |
| this.flushed = true; | |
| } | |
| }; | |
| // `notify(msg, pty)` | |
| // ------------------ | |
| // | |
| // Notify the user of things happening in Satellite using `console.log` | |
| // | |
| // - msg - message to print | |
| // - pty - priority | |
| SL.notify = SL.bind(SL.Logger.message, SL.Logger); | |
| // `cleanText(str)` | |
| // ================ | |
| // | |
| // "Cleans" the text from an element's innerText. This is used directly by the | |
| // @cleanText special property. | |
| SL.cleanText = function(str){ | |
| if (str == null) return null | |
| return SL.trim(str).replace(/\s+/g, ' ') | |
| } | |
| SL.cleanText.legacy = function(str){ | |
| if (str == null) return null | |
| return SL.trim(str).replace(/\s{2,}/g, ' ') | |
| .replace(/[^\000-\177]*/g, '') | |
| } | |
| SL.text = function(obj){ | |
| return obj.textContent || obj.innerText | |
| } | |
| // Special Properties for DOM elements. You use special properties using | |
| // the @ prefix. Example: | |
| // | |
| // this.@text | |
| SL.specialProperties = { | |
| text: SL.text, | |
| cleanText: function(obj){ | |
| return SL.cleanText(SL.text(obj)) | |
| } | |
| } | |
| // `getObjectProperty(obj, property)` | |
| // ============================ | |
| // | |
| // Get property(potentially nested) from an object. | |
| SL.getObjectProperty = function(obj, property, supportSpecial){ | |
| var propChain = property.split('.') | |
| var currValue = obj | |
| var special = SL.specialProperties | |
| var attrMatch | |
| for (var i = 0, len = propChain.length; i < len; i++){ | |
| if (currValue == null) return undefined | |
| var prop = propChain[i] | |
| if (supportSpecial && prop.charAt(0) === '@'){ | |
| var specialProp = prop.slice(1) | |
| currValue = special[specialProp](currValue) | |
| continue | |
| } | |
| if (currValue.getAttribute && | |
| (attrMatch = prop.match(/^getAttribute\((.+)\)$/))){ | |
| var attr = attrMatch[1] | |
| currValue = currValue.getAttribute(attr) | |
| continue | |
| } | |
| currValue = currValue[prop] | |
| } | |
| return currValue | |
| } | |
| // `getToolsByType(type)` | |
| // ------------------------------------------------ | |
| // | |
| // Returns an array containing all the tools whose engine property match | |
| // the provided type. | |
| // | |
| // - `type` - The searched tool type | |
| SL.getToolsByType = function(type){ | |
| if (!type) { | |
| throw new Error('Tool type is missing') | |
| } | |
| var result = [] | |
| for (var t in SL.tools) { | |
| if (SL.tools.hasOwnProperty(t)) { | |
| var tool = SL.tools[t] | |
| if (tool.settings && tool.settings.engine === type) { | |
| result.push(tool) | |
| } | |
| } | |
| } | |
| return result | |
| } | |
| // `setVar(name, value)` or `setVar(mapping)` | |
| // ========================================== | |
| // | |
| // Set a customer variable. Can be either called like this | |
| // | |
| // _satellite.setVar('name', 'value') | |
| // | |
| // Or by passing in a mapping(object literall) which allows setting multiple variables at | |
| // the same time. | |
| // | |
| // _satellite.setVar({name: 'value', foo: 'bar'}) | |
| SL.setVar = function(){ | |
| var customVars = SL.data.customVars | |
| if(customVars == null) SL.data.customVars = {}, customVars = SL.data.customVars | |
| if (typeof arguments[0] === 'string'){ | |
| var prop = arguments[0] | |
| customVars[prop] = arguments[1] | |
| }else if (arguments[0]){ // assume an object literal | |
| var mapping = arguments[0] | |
| for (var key in mapping) | |
| if (mapping.hasOwnProperty(key)) | |
| customVars[key] = mapping[key] | |
| } | |
| } | |
| SL.dataElementSafe = function(key, length){ | |
| if (arguments.length > 2){ | |
| // setter | |
| var value = arguments[2] | |
| if (length === 'pageview'){ | |
| SL.dataElementSafe.pageviewCache[key] = value | |
| }else if (length === 'session'){ | |
| SL.setCookie('_sdsat_' + key, value) | |
| }else if (length === 'visitor') { | |
| SL.setCookie('_sdsat_' + key, value, 365 * 2) | |
| } | |
| }else{ | |
| // getter | |
| if (length === 'pageview'){ | |
| return SL.dataElementSafe.pageviewCache[key] | |
| }else if (length === 'session' || length === 'visitor'){ | |
| return SL.readCookie('_sdsat_' + key) | |
| } | |
| } | |
| } | |
| SL.dataElementSafe.pageviewCache = {} | |
| SL.realGetDataElement = function(dataDef){ | |
| var ret | |
| if (dataDef.selector) { | |
| if (SL.hasSelector) { | |
| SL.cssQuery(dataDef.selector, function(elms) { | |
| if (elms.length > 0) { | |
| var elm = elms[0] | |
| if (dataDef.property === 'text') { | |
| ret = elm.innerText || elm.textContent | |
| }else if (dataDef.property in elm){ | |
| ret = elm[dataDef.property] | |
| }else if (SL.hasAttr(elm, dataDef.property)){ | |
| ret = elm.getAttribute(dataDef.property) | |
| } | |
| } | |
| }) | |
| } | |
| }else if (dataDef.queryParam) { | |
| if (dataDef.ignoreCase){ | |
| ret = SL.getQueryParamCaseInsensitive(dataDef.queryParam) | |
| }else{ | |
| ret = SL.getQueryParam(dataDef.queryParam) | |
| } | |
| }else if (dataDef.cookie) { | |
| ret = SL.readCookie(dataDef.cookie) | |
| }else if (dataDef.jsVariable) { | |
| ret = SL.getObjectProperty(window, dataDef.jsVariable) | |
| }else if (dataDef.customJS) { | |
| ret = dataDef.customJS() | |
| }else if (dataDef.contextHub) { | |
| ret = dataDef.contextHub() | |
| } | |
| if (SL.isString(ret) && dataDef.cleanText){ | |
| ret = SL.cleanText(ret) | |
| } | |
| return ret | |
| } | |
| SL.getDataElement = function(variable, suppressDefault, dataDef) { | |
| dataDef = dataDef || SL.dataElements[variable] | |
| if (dataDef == null) { | |
| return SL.settings.undefinedVarsReturnEmpty ? '' : null; | |
| } | |
| var ret = SL.realGetDataElement(dataDef) | |
| if (ret === undefined && dataDef.storeLength) { | |
| ret = SL.dataElementSafe(variable, dataDef.storeLength) | |
| }else if (ret !== undefined && dataDef.storeLength) { | |
| SL.dataElementSafe(variable, dataDef.storeLength, ret) | |
| } | |
| if (!ret && !suppressDefault) { | |
| ret = dataDef['default'] || '' | |
| } | |
| if (SL.isString(ret) && dataDef.forceLowerCase) { | |
| ret = ret.toLowerCase() | |
| } | |
| return ret | |
| } | |
| // getVar(variable, elm, evt) | |
| // ========================== | |
| // | |
| // Return the value of a variable, where the variable | |
| // can be a data element, defined in the "data" section | |
| // of the initial settings, or reference properties on | |
| // an element, event, or target of the event in question, | |
| // a query parameter, or a random number. | |
| // | |
| // - `variable` - the name of the variable to get | |
| // - `[elm]` - the associated element, if any | |
| // - `[evt]` - the associated event, if any | |
| SL.getVar = function(variable, elm, evt){ | |
| var custVars = SL.data.customVars | |
| , target = evt ? (evt.target || evt.srcElement) : null | |
| , randMatch | |
| , value | |
| var map = { | |
| uri: SL.URI(), | |
| protocol: document.location.protocol, | |
| hostname: document.location.hostname | |
| } | |
| if (SL.dataElements && variable in SL.dataElements){ | |
| return SL.getDataElement(variable) | |
| } | |
| value = map[variable.toLowerCase()] | |
| if (value === undefined){ | |
| if (variable.substring(0, 5) === 'this.'){ | |
| variable = variable.slice(5) | |
| value = SL.getObjectProperty(elm, variable, true) | |
| }else if(variable.substring(0, 6) === 'event.'){ | |
| variable = variable.slice(6) | |
| value = SL.getObjectProperty(evt, variable) | |
| }else if(variable.substring(0, 7) === 'target.'){ | |
| variable = variable.slice(7) | |
| value = SL.getObjectProperty(target, variable) | |
| }else if(variable.substring(0, 7) === 'window.'){ | |
| variable = variable.slice(7) | |
| value = SL.getObjectProperty(window, variable) | |
| }else if (variable.substring(0, 6) === 'param.'){ | |
| variable = variable.slice(6) | |
| value = SL.getQueryParam(variable) | |
| }else if(randMatch = variable.match(/^rand([0-9]+)$/)){ | |
| var len = Number(randMatch[1]) | |
| , s = (Math.random() * (Math.pow(10, len) - 1)).toFixed(0) | |
| value = Array(len - s.length + 1).join('0') + s | |
| }else{ | |
| value = SL.getObjectProperty(custVars, variable) | |
| } | |
| } | |
| return value | |
| } | |
| SL.getVars = function(variables, elm, evt){ | |
| var ret = {} | |
| SL.each(variables, function(variable){ | |
| ret[variable] = SL.getVar(variable, elm, evt) | |
| }) | |
| return ret | |
| } | |
| // `replace(str, [elm], [target])` | |
| // --------------------- | |
| // | |
| // Perform variable subtitutions substitute to a string where subtitions are | |
| // specified in the form `"%foo%"`. Variables are lookup either in `SL.data.customVars`, or | |
| // if the `elm` parameter is passed it, and the variable spec is of the form `"%this.tagName%"`, it | |
| // is subsituted with the properties on `elm`, *i.e. `elm.tagName`. | |
| // | |
| // Parameters: | |
| // | |
| // - `str` - string to apply substitutions to | |
| // - `elm`(optional) - object or element to use for substitutions of the form `%this.property%` | |
| // - `target`(optional) - element to use for subsitution of the form `%target.property%` | |
| // - `escapeHtml` (optional) - whether or not to escape substitutions for embedding in HTML | |
| SL.replace = function(str, elm, evt, escapeHtml) { | |
| if (typeof str !== 'string') return str | |
| return str | |
| .replace(/%(.*?)%/g, function(m, variable){ | |
| var val = SL.getVar(variable, elm, evt) | |
| if (val == null) { | |
| return SL.settings.undefinedVarsReturnEmpty ? '' : m; | |
| } else { | |
| if (escapeHtml) { | |
| return SL.escapeForHtml(val); | |
| } else { | |
| return val; | |
| } | |
| } | |
| }); | |
| } | |
| SL.escapeHtmlParams = function(fn){ | |
| fn.escapeHtml = true | |
| return fn | |
| } | |
| // From a object literal of variable, generate a query string. | |
| SL.searchVariables = function(vars, elm, evt){ | |
| if (!vars || vars.length === 0) return '' | |
| var qsParts = [] | |
| for (var i = 0, len = vars.length; i < len; i++){ | |
| var varr = vars[i] | |
| , value = SL.getVar(varr, elm, evt) | |
| qsParts.push(varr + '=' + escape(value)) | |
| } | |
| return '?' + qsParts.join('&') | |
| } | |
| // Fire all the trigger actions associated with a rule. | |
| SL.fireRule = function(rule, elm, evt){ | |
| var triggers = rule.trigger | |
| if (!triggers) return | |
| for (var i = 0, len = triggers.length; i < len; i++){ | |
| var trig = triggers[i] | |
| SL.execute(trig, elm, evt) | |
| } | |
| if (SL.contains(SL.fireOnceEvents, rule.event)) | |
| rule.expired = true | |
| } | |
| // `isLinked(elm)` | |
| // --------------- | |
| // | |
| // Returns whether the element is either an anchor or a descendant of an anchor or contains an anchor. | |
| // | |
| // `elm` - the element to test | |
| SL.isLinked = function(elm){ | |
| for (var cur = elm; cur; cur = cur.parentNode) { | |
| if (SL.isLinkTag(cur)) | |
| return true | |
| } | |
| return false | |
| } | |
| // Fire a page load event. `type` is one of `pagetop`, `pagebottom`, `domready` and | |
| // `windowload`. | |
| SL.firePageLoadEvent = function(type) { | |
| var location = document.location | |
| var evt = {type: type, target: location} | |
| var rules = SL.pageLoadRules | |
| var handlers = SL.evtHandlers[evt.type]; | |
| for (var i = rules.length; i--;){ | |
| var rule = rules[i] | |
| if (SL.ruleMatches(rule, evt, location)){ | |
| SL.notify('Rule "' + rule.name + '" fired.', 1) | |
| SL.fireRule(rule, location, evt) | |
| } | |
| } | |
| for (var id in SL.tools){ | |
| if (SL.tools.hasOwnProperty(id)) { | |
| var tool = SL.tools[id] | |
| if (tool.endPLPhase) { | |
| tool.endPLPhase(type) | |
| } | |
| } | |
| } | |
| if (handlers){ | |
| SL.each(handlers, function(cb){ | |
| cb(evt) | |
| }) | |
| } | |
| } | |
| // `track(id)` | |
| // ----------- | |
| // | |
| // Directly fire a direct call rule by id. | |
| SL.track = function(ruleName) { | |
| // trim extra spaces that may exist at beginning or end of string | |
| ruleName = ruleName.replace(/^\s*/,"").replace(/\s*$/,"") | |
| for (var i = 0; i < SL.directCallRules.length; i++){ | |
| var rule = SL.directCallRules[i] | |
| if (rule.name === ruleName){ | |
| SL.notify('Direct call Rule "' + ruleName + '" fired.', 1) | |
| SL.fireRule(rule, location, {type: ruleName}) | |
| return | |
| } | |
| } | |
| SL.notify('Direct call Rule "' + ruleName + '" not found.', 1) | |
| } | |
| // `basePath()` | |
| // ------------ | |
| // | |
| // Returns the base path of all Satellite generated assets. | |
| SL.basePath = function(){ | |
| if (SL.data.host) | |
| return (document.location.protocol === 'https:' ? | |
| 'https://' + SL.data.host.https : | |
| 'http://' + SL.data.host.http) + '/' | |
| else | |
| return this.settings.basePath | |
| } | |
| // `setLocation(url)` | |
| // ------------------ | |
| // | |
| // Set the current URL | |
| // | |
| // - `url` - the URL to set to | |
| SL.setLocation = function(url){ | |
| window.location = url | |
| } | |
| SL.parseQueryParams = function(str){ | |
| var URIDecode = function (str) { | |
| var result = str | |
| try { | |
| result = decodeURIComponent(str) | |
| } catch(err) {} | |
| return result | |
| } | |
| if (str === '' || SL.isString(str) === false) return {} | |
| if (str.indexOf('?') === 0) { | |
| str = str.substring(1) | |
| } | |
| var ret = {} | |
| , pairs = str.split('&') | |
| SL.each(pairs, function(pair){ | |
| pair = pair.split('=') | |
| if (!pair[1]) { | |
| return | |
| } | |
| ret[URIDecode(pair[0])] = URIDecode(pair[1]) | |
| }) | |
| return ret | |
| } | |
| SL.getCaseSensitivityQueryParamsMap = function (str) { | |
| var normal = SL.parseQueryParams(str) | |
| var insensitive = {} | |
| for (var prop in normal) | |
| if (normal.hasOwnProperty(prop)) | |
| insensitive[prop.toLowerCase()] = normal[prop] | |
| return { | |
| normal: normal, | |
| caseInsensitive: insensitive | |
| } | |
| } | |
| SL.updateQueryParams = function(){ | |
| SL.QueryParams = SL.getCaseSensitivityQueryParamsMap(window.location.search) | |
| } | |
| SL.updateQueryParams() | |
| SL.getQueryParam = function(key){ | |
| return SL.QueryParams.normal[key] | |
| } | |
| SL.getQueryParamCaseInsensitive = function(key){ | |
| return SL.QueryParams.caseInsensitive[key.toLowerCase()] | |
| } | |
| SL.encodeObjectToURI = function(obj) { | |
| if (SL.isObject(obj) === false) { | |
| return '' | |
| } | |
| var uri = [] | |
| for (var key in obj) { | |
| if (obj.hasOwnProperty(key)) { | |
| uri.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key])) | |
| } | |
| } | |
| return uri.join('&') | |
| } | |
| SL.readCookie = function(name) { | |
| var nameEQ = name + "=" | |
| var parts = document.cookie.split(';') | |
| for(var i=0;i < parts.length;i++) { | |
| var c = parts[i] | |
| while (c.charAt(0)==' '){ | |
| c = c.substring(1,c.length) | |
| } | |
| if (c.indexOf(nameEQ) === 0){ | |
| return c.substring(nameEQ.length,c.length) | |
| } | |
| } | |
| return undefined | |
| } | |
| SL.setCookie = function(name,value,days) { | |
| var expires | |
| if (days) { | |
| var date = new Date() | |
| date.setTime(date.getTime()+(days*24*60*60*1000)) | |
| expires = "; expires="+date.toGMTString() | |
| } | |
| else{ | |
| expires = "" | |
| } | |
| document.cookie = name+"="+value+expires+"; path=/" | |
| } | |
| SL.removeCookie = function(name) { | |
| SL.setCookie(name,"",-1); | |
| } | |
| SL.getElementProperty = function(elm, prop){ | |
| if (prop.charAt(0) === '@'){ | |
| var special = SL.specialProperties[prop.substring(1)] | |
| if (special){ | |
| return special(elm) | |
| } | |
| } | |
| if (prop === 'innerText'){ | |
| return SL.text(elm) | |
| } | |
| if (prop in elm) | |
| return elm[prop] | |
| return elm.getAttribute ? elm.getAttribute(prop) : undefined | |
| } | |
| SL.propertiesMatch = function(property, elm){ | |
| if (property){ | |
| for (var prop in property){ | |
| if (property.hasOwnProperty(prop)) { | |
| var target = property[prop] | |
| var value = SL.getElementProperty(elm, prop) | |
| if (typeof target === 'string' && target !== value) return false | |
| if (target instanceof RegExp && !target.test(value)) return false | |
| } | |
| } | |
| } | |
| return true | |
| } | |
| // from http://www.quirksmode.org/js/events_properties.html | |
| SL.isRightClick = function(e){ | |
| var ret | |
| if (e.which){ | |
| ret = e.which == 3 | |
| }else if (e.button){ | |
| ret = e.button == 2 | |
| } | |
| return ret | |
| } | |
| // `ruleMatches(rule, evt, elm, eventEntriesFound)` | |
| // ------------------------------------------------ | |
| // | |
| // - `rule` - the rules to match | |
| // - `evt` - the event triggered | |
| // - `elm` - the element the event was on | |
| // - `eventEntriesFound` - number of rules matched so far | |
| SL.ruleMatches = function(rule, evt, elm, eventEntriesFound){ | |
| var cnd = rule.condition | |
| var cnds = rule.conditions | |
| var property = rule.property | |
| var eventType = evt.type | |
| var matchValue = rule.value | |
| var target = evt.target || evt.srcElement | |
| var initialTarget = elm === target | |
| if (rule.event !== eventType && (rule.event !== 'custom' || rule.customEvent !== eventType)) return false | |
| if (!SL.ruleInScope(rule)) return false | |
| // ignore all right-clicks | |
| if (rule.event === 'click' && SL.isRightClick(evt)){ | |
| return false | |
| } | |
| if (rule.isDefault && eventEntriesFound > 0) | |
| return false | |
| if (rule.expired) return false | |
| if (eventType === 'inview' && evt.inviewDelay !== rule.inviewDelay){ | |
| return false | |
| } | |
| if (!(initialTarget || | |
| ((rule.bubbleFireIfParent !== false) && (eventEntriesFound === 0 || (rule.bubbleFireIfChildFired !== false))))) return false | |
| if (rule.selector && !SL.matchesCss(rule.selector, elm)) return false | |
| if (!SL.propertiesMatch(property, elm)) return false | |
| if (matchValue != null){ | |
| if (typeof matchValue === 'string'){ | |
| if (matchValue !== elm.value) | |
| return false | |
| }else if (!matchValue.test(elm.value)) | |
| return false | |
| } | |
| if (cnd){ | |
| try{ | |
| if (!cnd.call(elm, evt, target)){ | |
| SL.notify('Condition for rule "' + rule.name + '" not met.', 1) | |
| return false | |
| } | |
| }catch(e){ | |
| SL.notify('Condition for rule "' + rule.name + '" not met. Error: ' + e.message, 1) | |
| return false | |
| } | |
| } | |
| if (cnds){ | |
| var failed = SL.find(cnds, function(cnd){ | |
| try{ | |
| return !cnd.call(elm, evt, target) | |
| }catch(e){ | |
| SL.notify('Condition for rule "' + rule.name + '" not met. Error: ' + e.message, 1) | |
| return true | |
| } | |
| }) | |
| if (failed){ | |
| SL.notify('Condition ' + failed.toString() + ' for rule "' + rule.name + '" not met.', 1) | |
| return false | |
| } | |
| } | |
| return true | |
| } | |
| SL.evtHandlers = {} | |
| // `bindEvent(evtName, callback)` | |
| // ------------------------------ | |
| // | |
| // Register for an event by name. Alias: `whenEvent`. | |
| // | |
| // `evtName` - the name of the event | |
| // `callback` - the function to be called when even fires | |
| SL.bindEvent = function(evtName, callback){ | |
| var handlers = SL.evtHandlers | |
| if (!handlers[evtName]) | |
| handlers[evtName] = [] | |
| handlers[evtName].push(callback) | |
| } | |
| SL.whenEvent = SL.bindEvent | |
| // `unbindEvent(evtName, callback) | |
| // ------------------------------- | |
| // | |
| // Unregister for an event by name. | |
| // | |
| // `evtName` - the name of the event | |
| // `callback` - the function to unregister | |
| SL.unbindEvent = function(evtName, callback){ | |
| var handlers = SL.evtHandlers | |
| if (!handlers[evtName]) return | |
| var idx = SL.indexOf(handlers[evtName], callback) | |
| handlers[evtName].splice(idx, 1) | |
| } | |
| SL.bindEventOnce = function(evtName, callback){ | |
| var wrapped = function(){ | |
| SL.unbindEvent(evtName, wrapped) | |
| callback.apply(null, arguments) | |
| } | |
| SL.bindEvent(evtName, wrapped) | |
| } | |
| // See <http://tobyho.com/2014/02/26/attribute-only-valid-on-v-image/> | |
| SL.isVMLPoisoned = function(elm){ | |
| if (!elm) return false | |
| try{ | |
| elm.nodeName | |
| }catch(e){ | |
| if (e.message === 'Attribute only valid on v:image'){ | |
| return true | |
| } | |
| } | |
| return false | |
| } | |
| SL.handleEvent = function(evt) { | |
| // Don't process an event twice. | |
| if (SL.$data(evt, 'eventProcessed')) return | |
| var eventType = evt.type.toLowerCase() | |
| , target = evt.target || evt.srcElement | |
| , rulesMatched = 0 | |
| , rules = SL.rules | |
| , tools = SL.tools | |
| , handlers = SL.evtHandlers[evt.type] | |
| if (SL.isVMLPoisoned(target)){ | |
| SL.notify('detected ' + eventType + ' on poisoned VML element, skipping.', 1) | |
| return | |
| } | |
| if (handlers){ | |
| SL.each(handlers, function(cb){ | |
| cb(evt) | |
| }) | |
| } | |
| var nodeName = target && target.nodeName; | |
| if (nodeName) | |
| SL.notify("detected " + eventType + " on " + target.nodeName, 1) | |
| else | |
| SL.notify("detected " + eventType, 1) | |
| for (var curr = target; curr; curr = curr.parentNode) { | |
| var bubbleStop = false | |
| SL.each(rules, function(rule){ | |
| if (SL.ruleMatches(rule, evt, curr, rulesMatched)){ | |
| SL.notify('Rule "' + rule.name + '" fired.', 1) | |
| SL.fireRule(rule, curr, evt) | |
| rulesMatched++ | |
| if (rule.bubbleStop) | |
| bubbleStop = true | |
| } | |
| }) | |
| if (bubbleStop) break | |
| } | |
| SL.$data(evt, 'eventProcessed', true) | |
| } | |
| // `onEvent(evt)` | |
| // ------------ | |
| // | |
| // Handle an event, whether it is a DOM event or a synthetic event. | |
| // | |
| // - `evt` - the event triggered | |
| SL.onEvent = document.querySelectorAll ? | |
| function(evt){ SL.handleEvent(evt) } : | |
| (function(){ | |
| var q = [] | |
| var onEvent = function(evt) { | |
| if (evt.selector) | |
| q.push(evt) | |
| else | |
| SL.handleEvent(evt) | |
| } | |
| onEvent.pendingEvents = q | |
| return onEvent | |
| })() | |
| // `fireEvent(eventType, eventTarget)` | |
| // ------------ | |
| // | |
| // Conviniently programmatically fire an event. | |
| // | |
| // - `eventType` - the type of event | |
| // - `eventTarget` - the target object that fired the event | |
| SL.fireEvent = function(type, target){ | |
| SL.onEvent({type: type, target: target}) | |
| } | |
| // `registerEvents(elm, events)` | |
| // ----------------------------- | |
| // | |
| // Register events for an element using `track` as the callback | |
| // | |
| // - `elm` - the element to listen for events on | |
| // - `events` - an array of event types (strings) | |
| SL.registerEvents = function(elm, events){ | |
| for (var i = events.length - 1; i >= 0; i--){ | |
| var event = events[i] | |
| if (!SL.$data(elm, event + '.tracked')){ | |
| SL.addEventHandler(elm, event, SL.onEvent) | |
| SL.$data(elm, event + '.tracked', true) | |
| } | |
| } | |
| } | |
| // `registerEventsForTags(tags, events)` | |
| // ------------------------------------- | |
| // | |
| // Register events for all element that have the specified tags | |
| // | |
| // - `tags` - an array of tags to match for (strings) | |
| // - `events` - an array of event types (strings) | |
| SL.registerEventsForTags = function(tags, events){ | |
| for (var i = tags.length - 1; i >= 0; i--){ | |
| var tag = tags[i] | |
| var elms = document.getElementsByTagName(tag); | |
| for (var j = elms.length - 1; j >= 0; j--) | |
| SL.registerEvents(elms[j], events) | |
| } | |
| } | |
| // `setListeners()` | |
| // ---------------- | |
| // | |
| // Set events for `document` | |
| SL.setListeners = function() { | |
| var events = ['click', 'submit']; | |
| SL.each(SL.rules, function(rule) { | |
| if (rule.event === 'custom' && | |
| rule.hasOwnProperty('customEvent') && | |
| !SL.contains(events, rule.customEvent)) { | |
| events.push(rule.customEvent); | |
| } | |
| }); | |
| SL.registerEvents(document, events); | |
| }; | |
| // `getUniqueRuleEvents()` | |
| // ----------------------- | |
| // | |
| // Returns an array of unique event types for which event-based rules | |
| // have been configured. | |
| SL.getUniqueRuleEvents = function() { | |
| if (!SL._uniqueRuleEvents) { | |
| SL._uniqueRuleEvents = []; | |
| SL.each(SL.rules, function(rule) { | |
| if (SL.indexOf(SL._uniqueRuleEvents, rule.event) === -1) { | |
| SL._uniqueRuleEvents.push(rule.event); | |
| } | |
| }); | |
| } | |
| return SL._uniqueRuleEvents; | |
| }; | |
| // `setFormListeners()` | |
| // -------------------- | |
| // | |
| // Listen for events on form elements. Listeners for these events are added directly to form | |
| // elements since they don't bubble (though some do in modern browsers). | |
| SL.setFormListeners = function() { | |
| if (!SL._relevantFormEvents) { | |
| var formEvents = [ | |
| "change", | |
| "focus", | |
| "blur", | |
| // Why do we add event listeners directly to form elements for the keypress event? The | |
| // keypress event bubbles so we could add it directly to document. Note that keypress | |
| // events can be triggered when any element has focus which means that by adding the event | |
| // listener directly to form elements we're filtering any keypress events from other elements. | |
| // Is this the intention? If so, we could still add a single listener directly to document | |
| // and filter on event.target.nodeName. | |
| "keypress" | |
| ]; | |
| SL._relevantFormEvents = SL.filter(SL.getUniqueRuleEvents(), function(event) { | |
| return SL.indexOf(formEvents, event) !== -1; | |
| }); | |
| } | |
| if (SL._relevantFormEvents.length) { | |
| SL.registerEventsForTags(['input', 'select', 'textarea', 'button'], SL._relevantFormEvents); | |
| } | |
| }; | |
| // `setVideoListeners()` | |
| // --------------------- | |
| // | |
| // Listen for events on video elements. Listeners for these events are added directly to form | |
| // elements since they don't bubble. | |
| SL.setVideoListeners = function() { | |
| if (!SL._relevantVideoEvents) { | |
| var videoEvents = [ | |
| "play", | |
| "pause", | |
| "ended", | |
| "volumechange", | |
| "stalled", | |
| "loadeddata" | |
| ]; | |
| SL._relevantVideoEvents = SL.filter(SL.getUniqueRuleEvents(), function(event) { | |
| return SL.indexOf(videoEvents, event) !== -1; | |
| }); | |
| } | |
| if (SL._relevantVideoEvents.length) { | |
| SL.registerEventsForTags(['video'], SL._relevantVideoEvents); | |
| } | |
| }; | |
| // `readStoredSetting(name)` | |
| // ================== | |
| // | |
| // Reads the cookie of the given name. | |
| // Stolen from <http://www.quirksmode.org/js/cookies.html> | |
| SL.readStoredSetting = function(name) { | |
| // When local storage is disabled on Safari, the mere act of referencing window.localStorage | |
| // throws an error. For this reason, referencing window.localStorage without being inside | |
| // a try-catch should be avoided. | |
| try{ | |
| name = 'sdsat_' + name | |
| return window.localStorage.getItem(name) | |
| }catch(e){ | |
| SL.notify('Cannot read stored setting from localStorage: ' + e.message, 2) | |
| return null | |
| } | |
| } | |
| // Read satelliteUtilsCookie values to see about getting bookmarklet running / settings | |
| SL.loadStoredSettings = function () { | |
| var debug = SL.readStoredSetting('debug') | |
| , hideActivity = SL.readStoredSetting('hide_activity') | |
| if (debug) | |
| SL.settings.notifications = debug === 'true' | |
| if (hideActivity) | |
| SL.settings.hideActivity = hideActivity === 'true' | |
| } | |
| SL.isRuleActive = function(rule, date){ | |
| var schd = rule.schedule | |
| if (!schd) return true | |
| var utc = schd.utc | |
| , getDate = utc ? 'getUTCDate' : 'getDate' | |
| , getDay = utc ? 'getUTCDay' : 'getDay' | |
| , getFullYear = utc ? 'getUTCFullYear' : 'getFullYear' | |
| , getMonth = utc ? 'getUTCMonth' : 'getMonth' | |
| , getHours = utc ? 'getUTCHours' : 'getHours' | |
| , getMinutes = utc ? 'getUTCMinutes' : 'getMinutes' | |
| , setHours = utc ? 'setUTCHours' : 'setHours' | |
| , setMinutes = utc ? 'setUTCMinutes' : 'setMinutes' | |
| , setDate = utc ? 'setUTCDate' : 'setDate' | |
| date = date || new Date() | |
| function dayDiff(one, other){ | |
| other = modifyDate(other, { | |
| hour: one[getHours](), | |
| minute: one[getMinutes]() | |
| }) | |
| return Math.floor(Math.abs((one.getTime() - other.getTime()) / (1000 * 60 * 60 * 24))) | |
| } | |
| function monthDiff(one, other){ | |
| function months(date){ | |
| return date[getFullYear]() * 12 + date[getMonth]() | |
| } | |
| return Math.abs(months(one) - months(other)) | |
| } | |
| function modifyDate(date, fields){ | |
| var retval = new Date(date.getTime()) | |
| for (var field in fields){ | |
| if (fields.hasOwnProperty(field)) { | |
| var val = fields[field] | |
| switch(field){ | |
| case 'hour': | |
| retval[setHours](val) | |
| break | |
| case 'minute': | |
| retval[setMinutes](val) | |
| break | |
| case 'date': | |
| retval[setDate](val) | |
| break | |
| } | |
| } | |
| } | |
| return retval | |
| } | |
| function timeGreaterThan(one, other){ | |
| var h1 = one[getHours]() | |
| , m1 = one[getMinutes]() | |
| , h2 = other[getHours]() | |
| , m2 = other[getMinutes]() | |
| return (h1 * 60 + m1) > (h2 * 60 + m2) | |
| } | |
| function timeLessThan(one, other){ | |
| var h1 = one[getHours]() | |
| , m1 = one[getMinutes]() | |
| , h2 = other[getHours]() | |
| , m2 = other[getMinutes]() | |
| return (h1 * 60 + m1) < (h2 * 60 + m2) | |
| } | |
| if (schd.repeat){ | |
| if (timeGreaterThan(schd.start, date)) return false | |
| if (timeLessThan(schd.end, date)) return false | |
| if (date < schd.start) return false | |
| if (schd.endRepeat && date >= schd.endRepeat) return false | |
| if (schd.repeat === 'daily'){ | |
| if (schd.repeatEvery){ | |
| var dd = dayDiff(schd.start, date) | |
| if (dd % schd.repeatEvery !== 0) return false | |
| } | |
| }else if (schd.repeat === 'weekly'){ | |
| if (schd.days){ | |
| if (!SL.contains(schd.days, date[getDay]())) return false | |
| }else | |
| if (schd.start[getDay]() !== date[getDay]()) return false | |
| if (schd.repeatEvery){ | |
| var diff = dayDiff(schd.start, date) | |
| if (diff % (7 * schd.repeatEvery) !== 0) | |
| return false | |
| } | |
| }else if (schd.repeat === 'monthly'){ | |
| if (schd.repeatEvery){ | |
| var md = monthDiff(schd.start, date) | |
| if (md % schd.repeatEvery !== 0) return false | |
| } | |
| if (schd.nthWeek && schd.mthDay){ | |
| if (schd.mthDay !== date[getDay]()) return false | |
| var nthWeek = Math.floor((date[getDate]() - date[getDay]() + 1) / 7) | |
| if (schd.nthWeek !== nthWeek) return false | |
| }else | |
| if (schd.start[getDate]() !== date[getDate]()) return false | |
| }else if (schd.repeat === 'yearly'){ | |
| if (schd.start[getMonth]() !== date[getMonth]()) return false | |
| if (schd.start[getDate]() !== date[getDate]()) return false | |
| if (schd.repeatEvery){ | |
| var diff = Math.abs(schd.start[getFullYear]() - date[getFullYear]()) | |
| if (diff % schd.repeatEvery !== 0) return false | |
| } | |
| } | |
| }else{ | |
| if (schd.start > date) return false | |
| if (schd.end < date) return false | |
| } | |
| return true | |
| } | |
| SL.isOutboundLink = function(elm){ | |
| if (!elm.getAttribute('href')) return false | |
| var hostname = elm.hostname | |
| var href = elm.href | |
| var protocol = elm.protocol | |
| if (protocol !== 'http:' && protocol !== 'https:') return false | |
| var isMyDomain = SL.any(SL.settings.domainList, function(domain){ | |
| return SL.isSubdomainOf(hostname, domain) | |
| }) | |
| if (isMyDomain) return false | |
| return hostname !== location.hostname | |
| } | |
| SL.isLinkerLink = function(elm){ | |
| if (!elm.getAttribute || !elm.getAttribute('href')) return false | |
| return SL.hasMultipleDomains() && | |
| elm.hostname != location.hostname && | |
| !elm.href.match(/^javascript/i) && | |
| !SL.isOutboundLink(elm) | |
| } | |
| SL.isSubdomainOf = function(sub, root){ | |
| if (sub === root) return true | |
| var idx = sub.length - root.length | |
| if (idx > 0) | |
| return SL.equalsIgnoreCase(sub.substring(idx), root) | |
| return false | |
| } | |
| // `getVisitorId()` | |
| // ------------------------------------------------ | |
| // | |
| // Returns the library instance associated to a VisitorId tool if the tool exists | |
| // | |
| SL.getVisitorId = function(){ | |
| var visitorIdTools = SL.getToolsByType('visitor_id') | |
| if (visitorIdTools.length === 0) { | |
| return null; | |
| } | |
| return visitorIdTools[0].getInstance() | |
| } | |
| SL.URI = function(){ | |
| var ret = document.location.pathname + document.location.search | |
| if (SL.settings.forceLowerCase){ | |
| ret = ret.toLowerCase() | |
| } | |
| return ret | |
| } | |
| SL.URL = function(){ | |
| var ret = document.location.href | |
| if (SL.settings.forceLowerCase){ | |
| ret = ret.toLowerCase() | |
| } | |
| return ret | |
| } | |
| // Filter `SL.rules` down to only the once relevant for the current page. | |
| SL.filterRules = function(){ | |
| function matches(rule){ | |
| if (!SL.isRuleActive(rule)) return false | |
| return true | |
| } | |
| SL.rules = SL.filter(SL.rules, matches) | |
| SL.pageLoadRules = SL.filter(SL.pageLoadRules, matches) | |
| } | |
| SL.ruleInScope = function(rule, location){ | |
| location = location || document.location | |
| var scope = rule.scope | |
| if (!scope) return true | |
| var URI = scope.URI | |
| var subdomains = scope.subdomains | |
| var domains = scope.domains | |
| var protocols = scope.protocols | |
| var hashes = scope.hashes | |
| if (URI && includeExcludeFails(URI, location.pathname + location.search)) return false | |
| if (subdomains && includeExcludeFails(subdomains, location.hostname)) return false | |
| if (domains && matchFails(domains, location.hostname)) return false | |
| if (protocols && matchFails(protocols, location.protocol)) return false | |
| if (hashes && includeExcludeFails(hashes, location.hash)) return false | |
| function includeExcludeFails(matcher, matchee){ | |
| var include = matcher.include | |
| var exclude = matcher.exclude | |
| if (include && matchFails(include, matchee)) return true | |
| if (exclude){ | |
| if (SL.isString(exclude) && exclude === matchee) | |
| return true | |
| if (SL.isArray(exclude) && SL.any(exclude, matches)) | |
| return true | |
| if (SL.isRegex(exclude) && matches(exclude)) | |
| return true | |
| } | |
| return false | |
| function matches(regex){ | |
| return matchee.match(regex) | |
| } | |
| } | |
| function matchFails(matcher, matchee){ | |
| if (SL.isString(matcher) && matcher !== matchee) | |
| return true | |
| if (SL.isArray(matcher) && !SL.any(matcher, matches)) | |
| return true | |
| if (SL.isRegex(matcher) && !matches(matcher)) | |
| return true | |
| return false | |
| function matches(regex){ | |
| return matchee.match(regex) | |
| } | |
| } | |
| return true | |
| } | |
| // Run background tasks once. This will get invoked periodically. | |
| SL.backgroundTasks = function(){ | |
| var start = +new Date() | |
| SL.setFormListeners() | |
| SL.setVideoListeners() | |
| SL.loadStoredSettings() | |
| SL.registerNewElementsForDynamicRules() | |
| SL.eventEmitterBackgroundTasks() | |
| // Trigger condition events | |
| //SL.onEvent({type: 'condition', target: 'document'}) | |
| var end = +new Date() | |
| // We want to keep an eye on the execution time here. | |
| // If it gets to around 50ms for any customer site, | |
| // we want to either optimize or start using a task queue | |
| //SL.notify('Background tasks executed in ' + (end - start) + 'ms', 3) | |
| } | |
| // For rules that poll for dynamically injected elements on the page, | |
| // find them and register events for them. | |
| SL.registerNewElementsForDynamicRules = function(){ | |
| function cssQuery(selector, callback){ | |
| var hit = cssQuery.cache[selector] | |
| if (hit){ | |
| return callback(hit) | |
| }else{ | |
| SL.cssQuery(selector, function(elms){ | |
| cssQuery.cache[selector] = elms | |
| callback(elms) | |
| }) | |
| } | |
| } | |
| cssQuery.cache = {} | |
| SL.each(SL.dynamicRules, function(rule){ | |
| cssQuery(rule.selector, function(elms){ | |
| SL.each(elms, function(elm){ | |
| var event = rule.event === 'custom' ? rule.customEvent : rule.event; | |
| if (SL.$data(elm, 'dynamicRules.seen.' + event)) return | |
| SL.$data(elm, 'dynamicRules.seen.' + event, true) | |
| if (SL.propertiesMatch(rule.property, elm)){ | |
| SL.registerEvents(elm, [event]) | |
| } | |
| }) | |
| }) | |
| }) | |
| } | |
| // If the browser doesn't support CSS selector queries, we have to include one. | |
| SL.ensureCSSSelector = function(){ | |
| if (document.querySelectorAll){ | |
| SL.hasSelector = true | |
| return | |
| } | |
| SL.loadingSizzle = true | |
| SL.sizzleQueue = [] | |
| SL.loadScript(SL.basePath() + 'selector.js', function(){ | |
| if (!SL.Sizzle){ | |
| SL.logError(new Error('Failed to load selector.js')) | |
| return | |
| } | |
| var pending = SL.onEvent.pendingEvents | |
| SL.each(pending, function(evt){ | |
| SL.handleEvent(evt) | |
| }, this) | |
| SL.onEvent = SL.handleEvent | |
| SL.hasSelector = true | |
| ;delete SL.loadingSizzle | |
| SL.each(SL.sizzleQueue, function(item){ | |
| SL.cssQuery(item[0], item[1]) | |
| }) | |
| ;delete SL.sizzleQueue | |
| }) | |
| } | |
| // Error Handling | |
| SL.errors = [] | |
| SL.logError = function(err){ | |
| SL.errors.push(err) | |
| SL.notify(err.name + ' - ' + err.message, 5) | |
| } | |
| // `pageBottom()` | |
| // -------------- | |
| // | |
| // The function is to be called by the web page using an script tag like so: | |
| // | |
| // <script>_satellite.pageBottom()</script> | |
| // | |
| // just before the `</body>` tag. | |
| SL.pageBottom = function(){ | |
| if (!SL.initialized) return | |
| SL.pageBottomFired = true | |
| SL.firePageLoadEvent('pagebottom') | |
| } | |
| // This allows Rover to configure the browser to use the staging library instead. | |
| SL.stagingLibraryOverride = function(){ | |
| /*jshint evil:true */ | |
| var libraryOverride = SL.readStoredSetting('stagingLibrary') === 'true' | |
| if (libraryOverride){ // allow Rover to override the library to staging | |
| var scripts = document.getElementsByTagName('script') | |
| , regex = /^(.*)satelliteLib-([a-f0-9]{40})\.js$/ | |
| , regexStaging = /^(.*)satelliteLib-([a-f0-9]{40})-staging\.js$/ | |
| , match | |
| , matchStaging | |
| , src | |
| for (var i = 0, len = scripts.length; i < len; i++){ | |
| src = scripts[i].getAttribute('src') | |
| if (!src) continue | |
| if (!match) match = src.match(regex) | |
| if (!matchStaging) matchStaging = src.match(regexStaging) | |
| if (matchStaging) break | |
| } | |
| if (match && !matchStaging){ | |
| var stagingURL = match[1] + 'satelliteLib-' + match[2] + '-staging.js' | |
| if (document.write) { | |
| document.write('<script src="' + stagingURL + '"></script>') | |
| } else { | |
| var s = document.createElement('script') | |
| s.src = stagingURL | |
| document.head.appendChild(s) | |
| } | |
| return true | |
| } | |
| } | |
| return false | |
| } | |
| SL.checkAsyncInclude = function(){ | |
| if (window.satellite_asyncLoad) | |
| SL.notify('You may be using the async installation of Satellite. In-page HTML and the "pagebottom" event will not work. Please update your Satellite installation for these features.', 5) | |
| } | |
| SL.hasMultipleDomains = function(){ | |
| return !!SL.settings.domainList && SL.settings.domainList.length > 1 | |
| } | |
| SL.handleOverrides = function(){ | |
| if (Overrides){ | |
| for (var key in Overrides){ | |
| if (Overrides.hasOwnProperty(key)){ | |
| SL.data[key] = Overrides[key] | |
| } | |
| } | |
| } | |
| } | |
| SL.privacyManagerParams = function(){ | |
| var params = {} | |
| SL.extend(params, SL.settings.privacyManagement) | |
| var analyticsTools = [] | |
| for (var key in SL.tools){ | |
| if (SL.tools.hasOwnProperty(key)) { | |
| var tool = SL.tools[key] | |
| var settings = tool.settings | |
| if (!settings) continue | |
| if (settings.engine === 'sc'){ | |
| analyticsTools.push(tool) | |
| } | |
| } | |
| } | |
| var analyticsTrackingServers = SL.filter(SL.map(analyticsTools, function(tool){ | |
| return tool.getTrackingServer() | |
| }), function(s){ return s != null }) | |
| params.adobeAnalyticsTrackingServers = analyticsTrackingServers | |
| var substitutable = [ | |
| 'bannerText', | |
| 'headline', | |
| 'introductoryText', | |
| 'customCSS' | |
| ] | |
| for (var i = 0; i < substitutable.length; i++){ | |
| var prop = substitutable[i] | |
| var spec = params[prop] | |
| if (!spec) continue | |
| if (spec.type === 'text'){ | |
| params[prop] = spec.value | |
| }else if (spec.type === 'data'){ | |
| params[prop] = SL.getVar(spec.value) | |
| }else{ | |
| throw new Error('Invalid type: ' + spec.type) | |
| } | |
| } | |
| return params | |
| } | |
| SL.prepareLoadPrivacyManager = function(){ | |
| SL.addEventHandler(window, 'load', function(){ | |
| loadWhenAllSCToolsLoaded(SL.loadPrivacyManager) | |
| }) | |
| function loadWhenAllSCToolsLoaded(callback){ | |
| var scTools = SL.filter(SL.values(SL.tools), function(tool){ | |
| return tool.settings && tool.settings.engine === 'sc' | |
| }) | |
| if (scTools.length === 0){ | |
| return callback() | |
| } | |
| var numLoaded = 0 | |
| SL.each(scTools, function(tool){ | |
| SL.bindEvent(tool.id + '.load', onLoad) | |
| }) | |
| var tid = setTimeout(onTimeout, 5000) | |
| function onLoad(){ | |
| numLoaded++ | |
| if (numLoaded === scTools.length){ | |
| cleanUp() | |
| clearTimeout(tid) | |
| callback() | |
| } | |
| } | |
| function cleanUp(){ | |
| SL.each(scTools, function(tool){ | |
| SL.unbindEvent(tool.id + '.load', onLoad) | |
| }) | |
| } | |
| function onTimeout(){ | |
| cleanUp() | |
| callback() | |
| } | |
| } | |
| } | |
| // `loadPrivacyManager()` | |
| // ---------------------- | |
| // | |
| // Initialize privacy manager | |
| SL.loadPrivacyManager = function(){ | |
| var scriptUrl = SL.basePath() + 'privacy_manager.js' | |
| SL.loadScript(scriptUrl, function(){ | |
| var pm = SL.privacyManager | |
| pm.configure(SL.privacyManagerParams()) | |
| pm.openIfRequired() | |
| }) | |
| } | |
| // `init()` | |
| // -------- | |
| // | |
| // Initialize Satellite. | |
| // | |
| // - `settings` - all the settings that comprising a library. | |
| SL.init = function(settings) { | |
| if (SL.stagingLibraryOverride()) | |
| return | |
| SL.configurationSettings = settings | |
| var tools = settings.tools | |
| ;delete settings.tools | |
| for (var key in settings){ | |
| if (settings.hasOwnProperty(key)){ | |
| SL[key] = settings[key] | |
| } | |
| } | |
| if(SL.data.customVars === undefined) | |
| SL.data.customVars = {} | |
| SL.data.queryParams = SL.QueryParams.normal | |
| SL.handleOverrides() | |
| SL.detectBrowserInfo() | |
| if (SL.trackVisitorInfo) | |
| SL.trackVisitorInfo() | |
| SL.loadStoredSettings() | |
| SL.Logger.setOutputState(SL.settings.notifications) | |
| SL.checkAsyncInclude() | |
| SL.ensureCSSSelector() | |
| SL.filterRules() | |
| SL.dynamicRules = SL.filter(SL.rules, function(rule){ | |
| return rule.eventHandlerOnElement | |
| }) | |
| SL.tools = SL.initTools(tools) | |
| SL.initEventEmitters() | |
| SL.firePageLoadEvent('aftertoolinit') | |
| if (SL.settings.privacyManagement){ | |
| SL.prepareLoadPrivacyManager() | |
| } | |
| if (SL.hasSelector) | |
| SL.domReady(SL.eventEmitterBackgroundTasks) | |
| SL.setListeners() | |
| // Setup background tasks | |
| SL.domReady(function() { | |
| SL.poll( | |
| function() { SL.backgroundTasks() }, | |
| SL.settings.recheckEvery || 3000 | |
| ) | |
| }) | |
| // Setup page load events | |
| SL.domReady(function(){ | |
| SL.domReadyFired = true | |
| if (!SL.pageBottomFired) | |
| SL.pageBottom() | |
| SL.firePageLoadEvent('domready') | |
| }) | |
| SL.addEventHandler(window, 'load', function(){ | |
| SL.firePageLoadEvent('windowload') | |
| }) | |
| SL.firePageLoadEvent('pagetop') | |
| SL.initialized = true | |
| } | |
| SL.pageLoadPhases = ['aftertoolinit', 'pagetop', 'pagebottom', 'domready', 'windowload'] | |
| SL.loadEventBefore = function(one, other){ | |
| return SL.indexOf(SL.pageLoadPhases, one) <= SL.indexOf(SL.pageLoadPhases, other) | |
| } | |
| SL.flushPendingCalls = function(tool){ | |
| if (tool.pending){ | |
| SL.each(tool.pending, function(call){ | |
| var cmd = call[0] | |
| , elm = call[1] | |
| , evt = call[2] | |
| , args = call[3] | |
| if (cmd in tool) | |
| tool[cmd].apply(tool, [elm, evt].concat(args)) | |
| else if (tool.emit) | |
| tool.emit(cmd, elm, evt, args) | |
| else | |
| SL.notify('Failed to trigger ' + cmd + | |
| ' for tool ' + tool.id, 1) | |
| }) | |
| ;delete tool.pending | |
| } | |
| } | |
| // setDebug(debug) | |
| // -------------- | |
| // | |
| // Activate or deactivate debug mode - within which | |
| // log statements will be printed to the JS console. | |
| // | |
| // - `debug` - a boolean indicating whether debug mode | |
| // should be turned on. | |
| SL.setDebug = function(debug){ | |
| // When local storage is disabled on Safari, the mere act of referencing window.localStorage | |
| // throws an error. For this reason, referencing window.localStorage without being inside | |
| // a try-catch should be avoided. | |
| try { | |
| window.localStorage.setItem('sdsat_debug', debug) | |
| } catch (e) { | |
| SL.notify('Cannot set debug mode: ' + e.message, 2) | |
| }; | |
| } | |
| SL.getUserAgent = function() { | |
| return navigator.userAgent; | |
| }; | |
| SL.detectBrowserInfo = function(){ | |
| // Based on <http://jsbin.com/inubez/3/> | |
| function matcher(regexs){ | |
| return function(userAgent){ | |
| for (var key in regexs){ | |
| if (regexs.hasOwnProperty(key)) { | |
| var regex = regexs[key]; | |
| var match = regex.test(userAgent); | |
| if (match) return key; | |
| } | |
| } | |
| return "Unknown"; | |
| }; | |
| } | |
| // The order in which these regular expressions are evaluated is important. | |
| var getBrowser = matcher({ | |
| "IE Edge Mobile": /Windows Phone.*Edge/, | |
| "IE Edge": /Edge/, | |
| OmniWeb: /OmniWeb/, | |
| "Opera Mini": /Opera Mini/, | |
| "Opera Mobile": /Opera Mobi/, | |
| Opera: /Opera/, | |
| Chrome: /Chrome|CriOS|CrMo/, | |
| Firefox: /Firefox|FxiOS/, | |
| "IE Mobile": /IEMobile/, | |
| IE: /MSIE|Trident/, | |
| "Mobile Safari": /Mobile(\/[0-9A-z]+)? Safari/, | |
| Safari: /Safari/ | |
| }); | |
| var getOS = matcher({ | |
| Blackberry: /BlackBerry|BB10/, | |
| "Symbian OS": /Symbian|SymbOS/, | |
| Maemo: /Maemo/, | |
| Android: /Android/, | |
| Linux: / Linux /, | |
| Unix: /FreeBSD|OpenBSD|CrOS/, | |
| Windows: /[\( ]Windows /, | |
| iOS: /iPhone|iPad|iPod/, | |
| MacOS: /Macintosh;/ | |
| }); | |
| var getDeviceType = matcher({ | |
| // This is not entirely accurate. A few old Samsung, Motorola, and Sony Ericsson phones | |
| // will match but the majority and best guess is Nokia. Also, Nokia makes Windows phones and | |
| // for those we will make it match Windows Phone and not Nokia. | |
| Nokia: /Symbian|SymbOS|Maemo/, | |
| "Windows Phone": /Windows Phone/, | |
| Blackberry: /BlackBerry|BB10/, | |
| Android: /Android/, | |
| iPad: /iPad/, | |
| iPod: /iPod/, | |
| iPhone: /iPhone/, | |
| Desktop: /.*/ | |
| }); | |
| var userAgent = SL.getUserAgent(); | |
| SL.browserInfo = { | |
| browser: getBrowser(userAgent) | |
| , os: getOS(userAgent) | |
| , deviceType: getDeviceType(userAgent) | |
| } | |
| } | |
| SL.isHttps = function(){ | |
| return 'https:' == document.location.protocol | |
| } | |
| SL.BaseTool = function(settings){ | |
| this.settings = settings || {} | |
| this.forceLowerCase = SL.settings.forceLowerCase | |
| if ('forceLowerCase' in this.settings){ | |
| this.forceLowerCase = this.settings.forceLowerCase | |
| } | |
| } | |
| SL.BaseTool.prototype = { | |
| triggerCommand: function(trig, elm, evt){ | |
| var settings = this.settings || {} | |
| if (this.initialize && this.isQueueAvailable()){ | |
| if (this.isQueueable(trig) && evt && SL.loadEventBefore(evt.type, settings.loadOn)){ | |
| this.queueCommand(trig, elm, evt) | |
| return | |
| } | |
| } | |
| var cmd = trig.command | |
| var method = this['$' + cmd] | |
| var escapeHtml = method ? method.escapeHtml : false | |
| var args = SL.preprocessArguments( | |
| trig['arguments'], | |
| elm, | |
| evt, | |
| this.forceLowerCase, | |
| escapeHtml) | |
| if (method){ | |
| method.apply(this, [elm, evt].concat(args)) | |
| }else if (this.$missing$){ | |
| this.$missing$(cmd, elm, evt, args) | |
| }else | |
| SL.notify('Failed to trigger ' + cmd + | |
| ' for tool ' + this.id, 1) | |
| }, | |
| endPLPhase: function(pageLoadEvent){ | |
| // override to handle end initialization | |
| }, | |
| isQueueable: function(trig){ | |
| // everything is queueable except `cancelToolInit` | |
| return trig.command !== 'cancelToolInit' | |
| }, | |
| isQueueAvailable: function(){ | |
| return !this.initialized && !this.initializing | |
| }, | |
| flushQueue: function(){ | |
| if (this.pending){ | |
| SL.each(this.pending, function(args){ | |
| this.triggerCommand.apply(this, args) | |
| }, this) | |
| this.pending = [] | |
| } | |
| }, | |
| queueCommand: function(trig, elm, evt){ | |
| if (!this.pending) | |
| this.pending = [] | |
| this.pending.push([trig, elm, evt]) | |
| }, | |
| $cancelToolInit: function(){ | |
| this._cancelToolInit = true | |
| } | |
| } | |
| // Set Satellite to the global variable `_satellite`. | |
| window._satellite = SL | |
| // ElementExistsEventEmitter | |
| // ================== | |
| // | |
| // Emits the `elementexists` event. The `elementexists` event fires when an element | |
| // of a specified selector becomes into existance - either because it's in the page | |
| // markup or dynamically injected later on. *Each rule only fires once.* | |
| function ElementExistsEventEmitter() { | |
| this.rules = SL.filter(SL.rules, function(rule) { | |
| return rule.event === 'elementexists'; | |
| }); | |
| } | |
| ElementExistsEventEmitter.prototype.backgroundTasks = function() { | |
| SL.each(this.rules, function(rule) { | |
| SL.cssQuery(rule.selector, function(elms) { | |
| if (elms.length > 0){ | |
| // This results in a bug: https://jira.corp.adobe.com/browse/DTM-6681 | |
| // The fix was reverted due to: https://jira.corp.adobe.com/browse/DTM-7377 | |
| var elm = elms[0]; | |
| if (SL.$data(elm, 'elementexists.seen')) return; | |
| SL.$data(elm, 'elementexists.seen', true); | |
| SL.onEvent({type: 'elementexists', target: elm}); | |
| } | |
| }) | |
| }) | |
| } | |
| SL.availableEventEmitters.push(ElementExistsEventEmitter); | |
| // Leave Event Emitter | |
| // ============================ | |
| // | |
| // The page leave is an event that is used to detect the moment when the | |
| // browser's tab gets closed. | |
| // | |
| function LeaveEventEmitter() { | |
| if (SL.getToolsByType('nielsen').length > 0) { | |
| SL.domReady(SL.bind(this.initialize, this)); | |
| } | |
| } | |
| LeaveEventEmitter.prototype = { | |
| obue: false, | |
| initialize: function() { | |
| this.attachCloseListeners(); | |
| }, | |
| obuePrevUnload: function() {}, | |
| obuePrevBeforeUnload: function() {}, | |
| newObueListener: function() { | |
| if (!this.obue) { | |
| this.obue = true; | |
| this.triggerBeacons(); | |
| } | |
| }, | |
| attachCloseListeners: function() { | |
| this.prevUnload = window.onunload; | |
| this.prevBeforeUnload = window.onbeforeunload; | |
| window.onunload = SL.bind(function(e) { | |
| if (this.prevUnload) { | |
| setTimeout(SL.bind(function() { | |
| this.prevUnload.call(window, e); | |
| }, this), 1); | |
| } | |
| this.newObueListener(); | |
| }, this); | |
| window.onbeforeunload = SL.bind(function(e) { | |
| if (this.prevBeforeUnload) { | |
| setTimeout(SL.bind(function() { | |
| this.prevBeforeUnload.call(window, e); | |
| }, this), 1); | |
| } | |
| this.newObueListener(); | |
| }, this); | |
| }, | |
| triggerBeacons: function() { | |
| SL.fireEvent('leave', document); | |
| } | |
| } | |
| SL.availableEventEmitters.push(LeaveEventEmitter); | |
| // Orientation Change Event Emitter | |
| // ================================ | |
| // | |
| // The `orientationchange` event on mobile devices fire when the devices switchs between | |
| // portrait and landscape modes. You can use `%event.orientation%` in your command arguments | |
| // to evaluate to either `portrait` or `landscape`. | |
| function OrientationChangeEventEmitter(){ | |
| SL.addEventHandler(window, "orientationchange", OrientationChangeEventEmitter.orientationChange) | |
| } | |
| OrientationChangeEventEmitter.orientationChange = function (e) { | |
| var orientation = window.orientation === 0 ? | |
| 'portrait' : | |
| 'landscape' | |
| e.orientation = orientation | |
| SL.onEvent(e) | |
| } | |
| SL.availableEventEmitters.push(OrientationChangeEventEmitter) | |
| // Hover Event Emitter | |
| // ===================== | |
| // | |
| // Emits the `hover` event in the event. This is better than `mouseover` because you can introduce a certain delay. | |
| // | |
| // { | |
| // name: "Hover for 1 second" | |
| // event: "hover(1000)", | |
| // ... | |
| // } | |
| function HoverEventEmitter(){ | |
| var eventRegex = this.eventRegex = /^hover\(([0-9]+)\)$/ | |
| var rules = this.rules = [] | |
| SL.each(SL.rules, function(rule){ | |
| var m = rule.event.match(eventRegex) | |
| if (m){ | |
| rules.push([ | |
| Number(rule.event.match(eventRegex)[1]), | |
| rule.selector | |
| ]) | |
| } | |
| }) | |
| } | |
| HoverEventEmitter.prototype = { | |
| backgroundTasks: function(){ | |
| var self = this | |
| SL.each(this.rules, function(rule){ | |
| var selector = rule[1] | |
| , delay = rule[0] | |
| SL.cssQuery(selector, function(newElms){ | |
| SL.each(newElms, function(elm){ | |
| self.trackElement(elm, delay) | |
| }) | |
| }) | |
| }, this) | |
| }, | |
| trackElement: function(elm, delay){ | |
| var self = this | |
| , trackDelays = SL.$data(elm, 'hover.delays') | |
| if (!trackDelays){ | |
| SL.addEventHandler(elm, 'mouseover', function(e){ | |
| self.onMouseOver(e, elm) | |
| }) | |
| SL.addEventHandler(elm, 'mouseout', function(e){ | |
| self.onMouseOut(e, elm) | |
| }) | |
| SL.$data(elm, 'hover.delays', [delay]) | |
| } | |
| else if (!SL.contains(trackDelays, delay)){ | |
| trackDelays.push(delay) | |
| } | |
| }, | |
| onMouseOver: function(e, elem){ | |
| var target = e.target || e.srcElement | |
| , related = e.relatedTarget || e.fromElement | |
| , hit = (elem === target || SL.containsElement(elem, target)) && | |
| !SL.containsElement(elem, related) | |
| if (hit) | |
| this.onMouseEnter(elem) | |
| }, | |
| onMouseEnter: function(elm){ | |
| var delays = SL.$data(elm, 'hover.delays') | |
| var delayTimers = SL.map(delays, function(delay){ | |
| return setTimeout(function(){ | |
| SL.onEvent({type: 'hover(' + delay + ')', target: elm}) | |
| }, delay) | |
| }) | |
| SL.$data(elm, 'hover.delayTimers', delayTimers) | |
| }, | |
| onMouseOut: function(e, elem){ | |
| var target = e.target || e.srcElement | |
| , related = e.relatedTarget || e.toElement | |
| , hit = (elem === target || SL.containsElement(elem, target)) && | |
| !SL.containsElement(elem, related) | |
| if (hit) | |
| this.onMouseLeave(elem) | |
| }, | |
| onMouseLeave: function(elm){ | |
| var delayTimers = SL.$data(elm, 'hover.delayTimers') | |
| if (delayTimers) | |
| SL.each(delayTimers, function(timer){ | |
| clearTimeout(timer) | |
| }) | |
| } | |
| } | |
| SL.availableEventEmitters.push(HoverEventEmitter) | |
| // Visibility API Event Emitter | |
| // ============================ | |
| // | |
| // The `visibility API` is used when the browser's tab gets hidden because | |
| // another tab now is visible. For more information see Mozilla's [Page Visibility API](https://developer.mozilla.org/en-US/docs/Web/Guide/User_experience/Using_the_Page_Visibility_API) | |
| function VisibilityEventEmitter() { | |
| this.defineEvents(); | |
| this.visibilityApiHasPriority = true; | |
| if (!document.addEventListener) { // Older browers (e.g.: IE8) | |
| this.attachDetachOlderEventListeners(true, document, 'focusout'); | |
| } else { | |
| this.setVisibilityApiPriority(false); | |
| } | |
| var context = this; | |
| SL.bindEvent('aftertoolinit', function() { | |
| SL.fireEvent(SL.visibility.isHidden() ? 'tabblur' : 'tabfocus'); | |
| }); | |
| } | |
| VisibilityEventEmitter.prototype = { | |
| defineEvents: function() { | |
| this.oldBlurClosure = function() { | |
| SL.fireEvent('tabblur', document) | |
| }; | |
| this.oldFocusClosure = SL.bind(function() { | |
| if (this.visibilityApiHasPriority) { | |
| SL.fireEvent('tabfocus', document); | |
| } else { | |
| if (SL.visibility.getHiddenProperty() != null) { | |
| if(!SL.visibility.isHidden()) { | |
| SL.fireEvent('tabfocus', document); | |
| } | |
| } else { | |
| SL.fireEvent('tabfocus', document); | |
| } | |
| } | |
| }, this); | |
| }, | |
| attachDetachModernEventListeners: function(add) { | |
| var method = (add == false ? 'removeEventHandler' : 'addEventHandler'); | |
| SL[method](document, | |
| SL.visibility.getVisibilityEvent(), | |
| this.handleVisibilityChange | |
| ); | |
| }, | |
| attachDetachOlderEventListeners: function(add, blurTarget, blurEventName) { | |
| var method = (add == false ? 'removeEventHandler' : 'addEventHandler'); | |
| SL[method](blurTarget, blurEventName, this.oldBlurClosure); | |
| SL[method](window, 'focus', this.oldFocusClosure); | |
| }, | |
| handleVisibilityChange: function() { | |
| if (SL.visibility.isHidden()) { | |
| SL.fireEvent('tabblur', document); | |
| } else { | |
| SL.fireEvent('tabfocus', document); | |
| } | |
| }, | |
| setVisibilityApiPriority: function(visibilityApiHasPriority) { | |
| this.visibilityApiHasPriority = visibilityApiHasPriority; | |
| this.attachDetachOlderEventListeners(false, window, 'blur'); | |
| this.attachDetachModernEventListeners(false); | |
| if (visibilityApiHasPriority) { | |
| if (SL.visibility.getHiddenProperty() != null) { // Modern browsers | |
| this.attachDetachModernEventListeners(true); | |
| } else { | |
| this.attachDetachOlderEventListeners(true, window, 'blur'); | |
| } | |
| } else { | |
| this.attachDetachOlderEventListeners(true, window, 'blur'); | |
| if (SL.visibility.getHiddenProperty() != null) { // Modern browsers | |
| this.attachDetachModernEventListeners(true); | |
| } | |
| } | |
| }, | |
| oldBlurClosure: null, | |
| oldFocusClosure: null, | |
| visibilityApiHasPriority: true | |
| }; | |
| SL.availableEventEmitters.push(VisibilityEventEmitter); | |
| // Location Change Event Emitter | |
| // ============================= | |
| // | |
| // Will fire `locationchange` event whenever the browser location | |
| // changes due to `hashchange`, `popstate`, `history.pushState()`, | |
| // or `history.replaceState()`. | |
| function LocationChangeEventEmitter(){ | |
| this.lastURL = SL.URL() | |
| this._fireIfURIChanged = SL.bind(this.fireIfURIChanged, this) | |
| this._onPopState = SL.bind(this.onPopState, this) | |
| this._onHashChange = SL.bind(this.onHashChange, this) | |
| this._pushState = SL.bind(this.pushState, this) | |
| this._replaceState = SL.bind(this.replaceState, this) | |
| this.initialize() | |
| } | |
| LocationChangeEventEmitter.prototype = { | |
| initialize: function(){ | |
| this.setupHistoryAPI() | |
| this.setupHashChange() | |
| }, | |
| fireIfURIChanged: function(){ | |
| var URL = SL.URL() | |
| if (this.lastURL !== URL){ | |
| this.fireEvent() | |
| this.lastURL = URL | |
| } | |
| }, | |
| fireEvent: function(){ | |
| SL.updateQueryParams() | |
| SL.onEvent({ type: 'locationchange', target: document }) | |
| }, | |
| setupSPASupport: function(){ | |
| this.setupHistoryAPI() | |
| this.setupHashChange() | |
| }, | |
| setupHistoryAPI: function(){ | |
| var history = window.history | |
| if (history){ | |
| if (history.pushState){ | |
| this.originalPushState = history.pushState | |
| history.pushState = this._pushState | |
| } | |
| if (history.replaceState){ | |
| this.originalReplaceState = history.replaceState | |
| history.replaceState = this._replaceState | |
| } | |
| } | |
| SL.addEventHandler(window, 'popstate', this._onPopState) | |
| }, | |
| pushState: function(){ | |
| var ret = this.originalPushState.apply(history, arguments) | |
| this.onPushState() | |
| return ret | |
| }, | |
| replaceState: function(){ | |
| var ret = this.originalReplaceState.apply(history, arguments) | |
| this.onReplaceState() | |
| return ret | |
| }, | |
| setupHashChange: function(){ | |
| SL.addEventHandler(window, 'hashchange', this._onHashChange) | |
| }, | |
| onReplaceState: function(){ | |
| setTimeout(this._fireIfURIChanged, 0) | |
| }, | |
| onPushState: function(){ | |
| setTimeout(this._fireIfURIChanged, 0) | |
| }, | |
| onPopState: function(){ | |
| setTimeout(this._fireIfURIChanged, 0) | |
| }, | |
| onHashChange: function(){ | |
| setTimeout(this._fireIfURIChanged, 0) | |
| }, | |
| uninitialize: function(){ | |
| this.cleanUpHistoryAPI() | |
| this.cleanUpHashChange() | |
| }, | |
| cleanUpHistoryAPI: function(){ | |
| if (history.pushState === this._pushState){ | |
| history.pushState = this.originalPushState | |
| } | |
| if (history.replaceState === this._replaceState){ | |
| history.replaceState = this.originalReplaceState | |
| } | |
| SL.removeEventHandler(window, 'popstate', this._onPopState) | |
| }, | |
| cleanUpHashChange: function(){ | |
| SL.removeEventHandler(window, 'hashchange', this._onHashChange) | |
| } | |
| } | |
| SL.availableEventEmitters.push(LocationChangeEventEmitter); | |
| // VideoPlayedEventEmitter | |
| // ======================= | |
| // | |
| // Emits the `videoplayed` event, given a specified percentage or duration, i.e. `videoplayed` | |
| // is a parameterized event. A rule looks like this | |
| // | |
| // { | |
| // name: "Video 10% complete", | |
| // event: "videoplayed(10%)", | |
| // selector: "#video", | |
| // trigger: [ | |
| // { | |
| // tool: "ga", | |
| // command: "trackEvent", | |
| // arguments: [ | |
| // "video", | |
| // "video 10% complete", | |
| // "from: %URI%" | |
| // ] | |
| // } | |
| // ] | |
| // } | |
| // | |
| // `10%` is in the paranthesis which indicates this rule will only fire when the 10% | |
| // of the total length of the video has been played. | |
| // You can also specifiy a duration in seconds, which looks like `videoplayed(8s)` - which | |
| // stands for 8 seconds. | |
| function VideoPlayedEventEmitter(){ | |
| this.rules = SL.filter(SL.rules, function(rule){ | |
| return rule.event.substring(0, 11) === 'videoplayed' | |
| }) | |
| this.eventHandler = SL.bind(this.onUpdateTime, this) | |
| } | |
| VideoPlayedEventEmitter.prototype = { | |
| backgroundTasks: function(){ | |
| var eventHandler = this.eventHandler | |
| SL.each(this.rules, function(rule){ | |
| SL.cssQuery(rule.selector || 'video', function(elms){ | |
| SL.each(elms, function(elm){ | |
| if (SL.$data(elm, 'videoplayed.tracked')) return | |
| SL.addEventHandler(elm, 'timeupdate', SL.throttle(eventHandler, 100)) | |
| SL.$data(elm, 'videoplayed.tracked', true) | |
| }) | |
| }) | |
| }) | |
| }, | |
| evalRule: function(elm, rule){ | |
| var eventType = rule.event | |
| , seekable = elm.seekable | |
| , startTime = seekable.start(0) | |
| , endTime = seekable.end(0) | |
| , currentTime = elm.currentTime | |
| , m = rule.event.match(/^videoplayed\(([0-9]+)([s%])\)$/) | |
| if (!m) return | |
| var unit = m[2] | |
| , amount = Number(m[1]) | |
| var func = unit === '%' ? | |
| function(){ | |
| return amount <= | |
| 100 * (currentTime - startTime) / (endTime - startTime) | |
| } : | |
| function(){ | |
| return amount <= currentTime - startTime | |
| } | |
| if (!SL.$data(elm, eventType) && func()){ | |
| SL.$data(elm, eventType, true) | |
| SL.onEvent({type: eventType, target: elm}) | |
| } | |
| }, | |
| onUpdateTime: function(e){ | |
| var rules = this.rules | |
| , elm = e.target | |
| if (!elm.seekable || elm.seekable.length === 0) return | |
| for (var i = 0, len = rules.length; i < len; i++) | |
| this.evalRule(elm, rules[i]) | |
| } | |
| } | |
| SL.availableEventEmitters.push(VideoPlayedEventEmitter) | |
| // Facebook Event Emitter | |
| // ====================== | |
| // | |
| // Will track `edge.create`, `edge.remove` and `message.send` events from the Facebook | |
| // Javascript API and emit `facebook.like`, `facebook.unlike` and `facebook.send` events | |
| // respectively. | |
| function FacebookEventEmitter(FB){ | |
| this.delay = 250; | |
| this.FB = FB; | |
| SL.domReady(SL.bind(function () { | |
| SL.poll(SL.bind(this.initialize, this), this.delay, 8); | |
| }, this)); | |
| } | |
| FacebookEventEmitter.prototype = { | |
| initialize: function() { | |
| this.FB = this.FB || window.FB; | |
| if (this.FB && this.FB.Event && this.FB.Event.subscribe) { | |
| this.bind(); | |
| return true; | |
| } | |
| }, | |
| bind: function(){ | |
| this.FB.Event.subscribe('edge.create', function() { | |
| SL.notify("tracking a facebook like", 1) | |
| SL.onEvent({type: 'facebook.like', target: document}) | |
| }); | |
| this.FB.Event.subscribe('edge.remove', function() { | |
| SL.notify("tracking a facebook unlike", 1) | |
| SL.onEvent({type: 'facebook.unlike', target: document}) | |
| }); | |
| this.FB.Event.subscribe('message.send', function() { | |
| SL.notify("tracking a facebook share", 1) | |
| SL.onEvent({type: 'facebook.send', target: document}) | |
| }); | |
| } | |
| } | |
| SL.availableEventEmitters.push(FacebookEventEmitter); | |
| // Twitter Event Emitter | |
| // ===================== | |
| // | |
| // Emits the `twitter.tweet` event in the event a user tweets from the site. | |
| function TwitterEventEmitter(twttr){ | |
| SL.domReady(SL.bind(function () { | |
| this.twttr = twttr || window.twttr; | |
| this.initialize(); | |
| }, this)); | |
| } | |
| TwitterEventEmitter.prototype = { | |
| initialize: function(){ | |
| var twttr = this.twttr; | |
| if (twttr && typeof twttr.ready === 'function') { | |
| twttr.ready(SL.bind(this.bind, this)); | |
| } | |
| }, | |
| bind: function(){ | |
| this.twttr.events.bind('tweet', function(event) { | |
| if (event) { | |
| SL.notify("tracking a tweet button", 1); | |
| SL.onEvent({type: 'twitter.tweet', target: document}); | |
| } | |
| }); | |
| } | |
| } | |
| SL.availableEventEmitters.push(TwitterEventEmitter) | |
| // InviewEventEmitter | |
| // ================== | |
| // | |
| // Emits the `inview` event. The `inview` event fires on an element when the element | |
| // first comes into the view of the user. If the element is in view immediately upon page | |
| // load, it will be fired right away, if it only comes in view after some scrolling, it | |
| // will fire then. An optional delay interval `inviewDelay` can be specified in the rule | |
| // which determine how long the element has to be in view for before the event fires, | |
| // of which the default value is 1 second. | |
| function InViewEventEmitter(rules){ | |
| rules = rules || SL.rules | |
| this.rules = SL.filter(rules, function(rule){ | |
| return rule.event === 'inview' | |
| }) | |
| this.elements = [] | |
| this.eventHandler = SL.bind(this.track, this) | |
| SL.addEventHandler(window, 'scroll', this.eventHandler) | |
| SL.addEventHandler(window, 'load', this.eventHandler) | |
| } | |
| // Util functions needed by `InViewEventEmitter` | |
| InViewEventEmitter.offset = function(elem) { | |
| var top = null, left = null; | |
| try { | |
| var box = elem.getBoundingClientRect(), | |
| doc = document, | |
| docElem = doc.documentElement, | |
| body = doc.body, | |
| win = window, | |
| clientTop = docElem.clientTop || body.clientTop || 0, | |
| clientLeft = docElem.clientLeft || body.clientLeft || 0, | |
| scrollTop = win.pageYOffset || docElem.scrollTop || body.scrollTop, | |
| scrollLeft = win.pageXOffset || docElem.scrollLeft || body.scrollLeft; | |
| top = box.top + scrollTop - clientTop; | |
| left = box.left + scrollLeft - clientLeft; | |
| } catch(e) { | |
| } | |
| return { top: top, left: left } | |
| } | |
| InViewEventEmitter.getViewportHeight = function() { | |
| var height = window.innerHeight // Safari, Opera | |
| var mode = document.compatMode | |
| if (mode) { // IE, Gecko | |
| height = (mode == 'CSS1Compat') ? | |
| document.documentElement.clientHeight : // Standards | |
| document.body.clientHeight // Quirks | |
| } | |
| return height | |
| } | |
| InViewEventEmitter.getScrollTop = function(){ | |
| return (document.documentElement.scrollTop ? | |
| document.documentElement.scrollTop : | |
| document.body.scrollTop) | |
| } | |
| InViewEventEmitter.isElementInDocument = function(el) { | |
| return document.body.contains(el); | |
| } | |
| InViewEventEmitter.isElementInView = function(el) { | |
| if (!InViewEventEmitter.isElementInDocument(el)) { | |
| return false; | |
| } | |
| var vpH = InViewEventEmitter.getViewportHeight() | |
| , scrolltop = InViewEventEmitter.getScrollTop() | |
| , top = InViewEventEmitter.offset(el).top | |
| , height = el.offsetHeight; | |
| if (top !== null) { | |
| return !(scrolltop > (top + height) || scrolltop + vpH < top) | |
| } | |
| return false; | |
| } | |
| InViewEventEmitter.prototype = { | |
| backgroundTasks: function(){ | |
| var elements = this.elements | |
| SL.each(this.rules, function(rule){ | |
| SL.cssQuery(rule.selector, function(elms){ | |
| var addCount = 0 | |
| SL.each(elms, function(elm){ | |
| if (!SL.contains(elements, elm)){ | |
| elements.push(elm) | |
| addCount++ | |
| } | |
| }) | |
| if (addCount){ | |
| SL.notify(rule.selector + ' added ' + addCount + ' elements.', 1) | |
| } | |
| }) | |
| }) | |
| this.track() | |
| }, | |
| checkInView: function(el, recheck, delay){ | |
| var inview = SL.$data(el, 'inview'); | |
| if (InViewEventEmitter.isElementInView(el)) { | |
| // it is in view now | |
| if (!inview) | |
| SL.$data(el, 'inview', true) | |
| var self = this | |
| this.processRules(el, function(rule, viewedProp, timeoutIdProp){ | |
| if (recheck || !rule.inviewDelay){ | |
| SL.$data(el, viewedProp, true) | |
| SL.onEvent({type: 'inview', target: el, inviewDelay: rule.inviewDelay}) | |
| }else if(rule.inviewDelay){ | |
| var timeout = SL.$data(el, timeoutIdProp) | |
| if (!timeout) { | |
| timeout = setTimeout(function(){ | |
| self.checkInView(el, true, rule.inviewDelay) | |
| }, rule.inviewDelay) | |
| SL.$data(el, timeoutIdProp, timeout) | |
| } | |
| } | |
| }, delay) | |
| } else { | |
| if (!InViewEventEmitter.isElementInDocument(el)) { | |
| var idx = SL.indexOf(this.elements, el); | |
| this.elements.splice(idx, 1) | |
| } | |
| // it is not in view now | |
| if (inview) | |
| SL.$data(el, 'inview', false) | |
| this.processRules(el, function(rule, viewedProp, timeoutIdProp){ | |
| var timeout = SL.$data(el, timeoutIdProp) | |
| if (timeout){ | |
| clearTimeout(timeout) | |
| } | |
| }, delay) | |
| } | |
| }, | |
| track: function(){ | |
| // We are not using SL.each here because we might do a splice inisde | |
| // `checkInView` method. | |
| for (var i = this.elements.length - 1; i >=0; i--) { | |
| this.checkInView(this.elements[i]); | |
| } | |
| }, | |
| processRules: function(elm, callback, delay){ | |
| var filteredRules = this.rules; | |
| if (delay) { | |
| filteredRules = SL.filter(this.rules, function(e){ | |
| return e.inviewDelay == delay; | |
| }); | |
| } | |
| SL.each(filteredRules, function(rule, i){ | |
| // viewedProp: for rules that has a timeout, the definition for | |
| // "viewed" is rule dependent. But for all rules that do not have | |
| // a timeout, it is independent. | |
| var viewedProp = rule.inviewDelay ? 'viewed_' + rule.inviewDelay : 'viewed' | |
| var timeoutIdProp = 'inview_timeout_id_' + i | |
| if (SL.$data(elm, viewedProp)) return | |
| if (SL.matchesCss(rule.selector, elm)){ | |
| callback(rule, viewedProp, timeoutIdProp) | |
| } | |
| }) | |
| } | |
| } | |
| SL.availableEventEmitters.push(InViewEventEmitter) | |
| function DataElementChangeEmitter() { | |
| var rules = SL.filter(SL.rules, function(rule) { | |
| return rule.event.indexOf('dataelementchange') === 0; | |
| }); | |
| this.dataElementsNames = SL.map(rules, function(rule) { | |
| var matchedSubstrings = rule.event.match(/dataelementchange\((.*)\)/i); | |
| return matchedSubstrings[1]; | |
| }, this); | |
| this.initPolling(); | |
| } | |
| // SL.stringify is not 100% compatible with JSON.stringify (for example JSON.stringify breaks | |
| // whenever it encounters a cyclic reference). Since this check might become intensive, | |
| // only for this case we would prefer using JSON.stringify whenever that's available. | |
| DataElementChangeEmitter.prototype.getStringifiedValue = | |
| (window.JSON && window.JSON.stringify) || SL.stringify; | |
| DataElementChangeEmitter.prototype.initPolling = function() { | |
| if (this.dataElementsNames.length === 0) { | |
| return; | |
| } | |
| this.dataElementsStore = this.getDataElementsValues(); | |
| SL.poll(SL.bind(this.checkDataElementValues, this), 1000); | |
| }; | |
| DataElementChangeEmitter.prototype.getDataElementsValues = function() { | |
| var values = {}; | |
| SL.each(this.dataElementsNames, function(dataElementName) { | |
| var value = SL.getVar(dataElementName); | |
| values[dataElementName] = this.getStringifiedValue(value); | |
| }, this); | |
| return values; | |
| }; | |
| DataElementChangeEmitter.prototype.checkDataElementValues = function() { | |
| SL.each(this.dataElementsNames, SL.bind(function(dataElementName) { | |
| var currentStringifiedValue = this.getStringifiedValue(SL.getVar(dataElementName)); | |
| var previousStringifiedValue = this.dataElementsStore[dataElementName]; | |
| if (currentStringifiedValue !== previousStringifiedValue) { | |
| this.dataElementsStore[dataElementName] = currentStringifiedValue; | |
| SL.onEvent({ | |
| type: 'dataelementchange(' + dataElementName + ')', | |
| target: document | |
| }); | |
| } | |
| }, this)); | |
| }; | |
| SL.availableEventEmitters.push(DataElementChangeEmitter); | |
| // Visibility API Event Emitter | |
| // ============================ | |
| // | |
| // The `visibility API` is used when the browser's tab gets hidden because | |
| // another tab now is visible. For more information see Mozilla's [Page Visibility API](https://developer.mozilla.org/en-US/docs/Web/Guide/User_experience/Using_the_Page_Visibility_API) | |
| SL.visibility = { | |
| // Public | |
| // ------------------------------------------------ | |
| // `isHidden()` | |
| // | |
| // The method returns true if the tab is hidden, otherwise false. | |
| isHidden: function() { | |
| var prop = this.getHiddenProperty(); | |
| if (!prop) return false; | |
| return document[prop]; | |
| }, | |
| // `isVisible()` | |
| // | |
| // The method is an alias for the `!isHidden`. | |
| isVisible: function() { | |
| return !this.isHidden(); | |
| }, | |
| // Private | |
| // ------------------------------------------------ | |
| getHiddenProperty: function() { | |
| var prefixes = ['webkit', 'moz', 'ms', 'o']; | |
| if ('hidden' in document) return 'hidden'; | |
| // otherwise loop over all the known prefixes until we find one | |
| for (var i = 0; i < prefixes.length; i++) { | |
| if ((prefixes[i] + 'Hidden') in document) | |
| return prefixes[i] + 'Hidden'; | |
| } | |
| // otherwise it's not supported | |
| return null; | |
| }, | |
| getVisibilityEvent: function() { | |
| var ve = this.getHiddenProperty(); | |
| if (!ve) return null; | |
| return ve.replace(/[H|h]idden/,'') + 'visibilitychange'; | |
| } | |
| }; | |
| // E-Commerce APIs | |
| // --------------- | |
| // | |
| // The ecommerce API allows web admins to integrate e-commerce tracking with Satellite. | |
| // More details on the [GA E-Commerce API's](http://code.google.com/apis/analytics/docs/gaJS/gaJSApiEcommerce.html). | |
| // Upon any of the methods on the API being called, they will fire an event, which | |
| // in turn can be handled by a rule in the library. | |
| SL.ecommerce = { | |
| // `addItem(orderId, sku, name, category, price, quantity)` | |
| // ------------------------------------- | |
| // | |
| // Add an item to the transaction. | |
| addItem: function(){ | |
| var args = [].slice.call(arguments) | |
| SL.onEvent({type: 'ecommerce.additem', target: args}) | |
| }, | |
| // `addTrans(orderId, affiliation, total, tax, shipping, city, state, country)` | |
| // ---------------------------------------------------------------------------- | |
| // | |
| // Add a new transaction. | |
| addTrans: function(){ | |
| var args = [].slice.call(arguments) | |
| SL.data.saleData.sale = { | |
| orderId: args[0], | |
| revenue: args[2] | |
| } | |
| SL.onEvent({type: 'ecommerce.addtrans', target: args}) | |
| }, | |
| // `trackTrans()` | |
| // -------------- | |
| // | |
| // Send the transaction data that's been set up using `addItem()` and `addTrans()` | |
| // to GA to be tracked. | |
| trackTrans: function(){ | |
| SL.onEvent({type: 'ecommerce.tracktrans', target: []}) | |
| } | |
| } | |
| // The Marketing Cloud Visitor ID Service Tool | |
| // ================ | |
| // | |
| // This tool interacts with the [Visitor ID library](https://git.corp.adobe.com/mc-visitor/VisitorAPI/tree/master/js/src). | |
| // The tool initilizes the Visitor ID library as soon as the tool itself is | |
| // created, by calling the `initialize` method. Find out more info about the | |
| // initializing sequence by clicking [here](#-initialize-). | |
| // | |
| // The tool accepts the following settings: | |
| // | |
| // - `mcOrgId` - The Adobe Marketing Cloud Organization ID (Required) | |
| // - `initVars` - Map containing properties that can be set on the Visitor ID | |
| // instance. The following keys can be set here: | |
| // * `trackingServer`, | |
| // * `trackingServerSecure`, | |
| // * `marketingCloudServer` | |
| // * `marketingCloudServerSecure` | |
| // - `customerIDs` - Map containing Customer IDs values that will be set on the | |
| // instance | |
| // - `autoRequest` - Flag that will read the Marketing Cloud Visitor ID by | |
| // calling `getMarketingCloudVisitorID` method | |
| function VisitorIdTool(settings) { | |
| SL.BaseTool.call(this, settings); | |
| this.name = settings.name || 'VisitorID'; | |
| this.initialize(); | |
| } | |
| SL.extend(VisitorIdTool.prototype, { | |
| // Public | |
| // ------------------------------------------------ | |
| // | |
| // `getInstance()` | |
| // ------------------------------------------------ | |
| // | |
| // Returns the Visitor ID instance that was created when the tool was | |
| // initialized. | |
| getInstance: function() { | |
| return this.instance; | |
| }, | |
| // Private | |
| // ------------------------------------------------ | |
| // | |
| // `initialize()` | |
| // ------------------------------------------------ | |
| // | |
| // The method creates a Visitor ID instance if all the data provided is valid. | |
| // The instance will contain all the keys defined in the `initVar` setting. | |
| // Any `dataElement` present as a value in the initVars map will be replaced | |
| // with the correct value. | |
| // | |
| // It applies then a the map of Customer IDs by calling the `setCustomerIDs` | |
| // method from the newly created instance. Any `dataElement` present as a | |
| // value in the Customer IDs map will be replaced with the correct value. | |
| // | |
| // After that, the `getMarketingCloudVisitorID` method from the newly created | |
| // instance is called, provided that the `autoRequest` settings is set to true. | |
| initialize: function() { | |
| var settings = this.settings, visitor; | |
| SL.notify('Visitor ID: Initializing tool', 1); | |
| visitor = this.createInstance( | |
| settings.mcOrgId, | |
| settings.initVars | |
| ); | |
| if (visitor === null) { | |
| return; | |
| } | |
| if (settings.customerIDs) { | |
| this.applyCustomerIDs(visitor, settings.customerIDs); | |
| } | |
| if (settings.autoRequest) { | |
| visitor.getMarketingCloudVisitorID(); | |
| } | |
| this.instance = visitor; | |
| }, | |
| createInstance: function(mcOrgId, initVars) { | |
| if(!SL.isString(mcOrgId)) { | |
| SL.notify( | |
| 'Visitor ID: Cannot create instance using mcOrgId: "' + mcOrgId + '"', 4); | |
| return null; | |
| } | |
| mcOrgId = SL.replace(mcOrgId); | |
| SL.notify( | |
| 'Visitor ID: Create instance using mcOrgId: "' + mcOrgId + '"', 1); | |
| initVars = this.parseValues(initVars); | |
| var instance = Visitor.getInstance(mcOrgId, initVars); | |
| SL.notify('Visitor ID: Set variables: ' + SL.stringify(initVars), 1); | |
| return instance; | |
| }, | |
| applyCustomerIDs: function(instance, ids) { | |
| var parsedIds = this.parseIds(ids); | |
| instance.setCustomerIDs(parsedIds); | |
| SL.notify('Visitor ID: Set Customer IDs: ' + SL.stringify(parsedIds), 1); | |
| }, | |
| parseValues: function(hash) { | |
| if (SL.isObject(hash) === false) { | |
| return {}; | |
| } | |
| var obj = {}; | |
| for (var v in hash) { | |
| if (hash.hasOwnProperty(v)) { | |
| obj[v] = SL.replace(hash[v]); | |
| } | |
| } | |
| return obj; | |
| }, | |
| parseIds: function(hash) { | |
| var parsedIds = {}; | |
| if (SL.isObject(hash) === false) { | |
| return {}; | |
| } | |
| for (var v in hash) { | |
| if (hash.hasOwnProperty(v)) { | |
| var id = SL.replace(hash[v]['id']); | |
| // All IDs should be data elements. If no replacement has taken place, | |
| // then we can conclude that the data element doesn't exists. | |
| // Also we should ignore existing data elements that are empty. | |
| if (id !== hash[v]['id'] && id) { | |
| parsedIds[v] = {}; | |
| parsedIds[v]['id'] = id; | |
| parsedIds[v]['authState'] = Visitor.AuthState[hash[v]['authState']]; | |
| } | |
| } | |
| } | |
| return parsedIds; | |
| } | |
| }); | |
| SL.availableTools.visitor_id = VisitorIdTool; | |
| // Basic Tool | |
| // ------------ | |
| // | |
| // This is a generic tool that allows integrating with | |
| // various simple tools. | |
| // | |
| function BasicTool(settings){ | |
| SL.BaseTool.call(this, settings) | |
| this.name = settings.name || 'Basic' | |
| } | |
| SL.inherit(BasicTool, SL.BaseTool) | |
| SL.extend(BasicTool.prototype, { | |
| initialize: function(){ | |
| var settings = this.settings | |
| if (this.settings.initTool !== false){ | |
| var url = settings.url | |
| if (typeof url === 'string'){ | |
| url = SL.basePath() + url | |
| }else{ | |
| url = SL.isHttps() ? url.https : url.http | |
| } | |
| SL.loadScript(url, SL.bind(this.onLoad, this)) | |
| this.initializing = true | |
| }else{ | |
| this.initialized = true | |
| } | |
| }, | |
| isQueueAvailable: function(){ | |
| return !this.initialized | |
| }, | |
| onLoad: function(){ | |
| this.initialized = true | |
| this.initializing = false | |
| if (this.settings.initialBeacon){ | |
| this.settings.initialBeacon() | |
| } | |
| this.flushQueue() | |
| }, | |
| endPLPhase: function(pageLoadEvent){ | |
| var loadOn = this.settings.loadOn | |
| if (pageLoadEvent === loadOn){ | |
| SL.notify(this.name + ': Initializing at ' + pageLoadEvent, 1) | |
| this.initialize() | |
| } | |
| }, | |
| $fire: function(elm, evt, fun){ | |
| if (this.initializing){ | |
| this.queueCommand({ | |
| command: 'fire', | |
| arguments: [fun] | |
| }, elm, evt) | |
| return | |
| } | |
| fun.call(this.settings, elm, evt) | |
| } | |
| }) | |
| SL.availableTools.am = BasicTool | |
| SL.availableTools.adlens = BasicTool | |
| SL.availableTools.aem = BasicTool | |
| SL.availableTools.__basic = BasicTool | |
| // The Adobe Target Tool | |
| // ================== | |
| // | |
| // This tool interacts with [Adobe Target library](https://git.corp.adobe.com/mc-visitor/VisitorAPI). | |
| // | |
| // The tool accepts the following settings: | |
| // | |
| // - `engine` - The engine identifier (tnt) | |
| // - `mboxURL` - The URL where the mbox can be found | |
| // - `loadSync` - Specifies how the mbox should be loaded. A true value means | |
| // that it should be loaded in a synchronous mode. | |
| // - `pageParams` - Object containing key/value pairs used in the mbox retrieval | |
| // call. The pairs are merged onto the `targetPageParams` property of | |
| // Target Javascript library. For more information click | |
| // [here](https://marketing.adobe.com/resources/help/en_US/target/target/c_pass_parameters_to_global_mbox.html). | |
| function Tnt(settings){ | |
| SL.BaseTool.call(this, settings) | |
| this.styleElements = {} | |
| this.targetPageParamsStore = {} | |
| } | |
| SL.inherit(Tnt, SL.BaseTool) | |
| SL.extend(Tnt.prototype, { | |
| // Public | |
| // ------------------------------------------------ | |
| name: 'tnt', | |
| // `endPLPhase()` | |
| // ------------------------------------------------ | |
| // | |
| // Method that starts the tool initialization when the page load phase is | |
| // matched and only if the tool initialization has not been previously | |
| // cancelled. | |
| // | |
| // When the tool is initialized the global `targetPageParams` are updated with | |
| // the parameters provided in the settings. | |
| // | |
| // It is important to know that the `targetPageParams` property is not | |
| // overwritten instead a merging process is taking place. If a key is already | |
| // present then its value is updated. | |
| // | |
| // The last step is the loading of the mbox where the `mboxURL` is used. | |
| endPLPhase: function(pageLoadEvent) { | |
| if (pageLoadEvent === 'aftertoolinit') { | |
| this.initialize(); | |
| } | |
| }, | |
| // Private | |
| // ------------------------------------------------ | |
| initialize: function() { | |
| SL.notify('Test & Target: Initializing', 1) | |
| this.initializeTargetPageParams() | |
| this.load() | |
| }, | |
| initializeTargetPageParams: function() { | |
| if (window.targetPageParams) { | |
| this.updateTargetPageParams( | |
| this.parseTargetPageParamsResult( | |
| window.targetPageParams() | |
| ) | |
| ) | |
| } | |
| this.updateTargetPageParams(this.settings.pageParams) | |
| this.setTargetPageParamsFunction() | |
| }, | |
| load: function(){ | |
| var url = this.getMboxURL(this.settings.mboxURL) | |
| if (this.settings.initTool !== false){ | |
| if (this.settings.loadSync) { | |
| SL.loadScriptSync(url) | |
| this.onScriptLoaded() | |
| } else { | |
| SL.loadScript(url, SL.bind(this.onScriptLoaded, this)) | |
| this.initializing = true | |
| } | |
| } else { | |
| this.initialized = true | |
| } | |
| }, | |
| getMboxURL: function(urlData) { | |
| var url = urlData | |
| if (SL.isObject(urlData)) { | |
| if (window.location.protocol === 'https:') | |
| url = urlData.https | |
| else | |
| url = urlData.http | |
| } | |
| if (!url.match(/^https?:/)) | |
| return SL.basePath() + url | |
| else | |
| return url | |
| }, | |
| onScriptLoaded: function(){ | |
| SL.notify('Test & Target: loaded.', 1) | |
| this.flushQueue() | |
| this.initialized = true | |
| this.initializing = false | |
| }, | |
| $addMbox: function(elm, evt, settings){ | |
| var mboxGoesAround = settings.mboxGoesAround | |
| var styleText = mboxGoesAround + '{visibility: hidden;}' | |
| var styleElm = this.appendStyle(styleText) | |
| if (!(mboxGoesAround in this.styleElements)){ | |
| this.styleElements[mboxGoesAround] = styleElm | |
| } | |
| if (this.initialized){ | |
| this.$addMBoxStep2(null, null, settings) | |
| }else if (this.initializing){ | |
| this.queueCommand({ | |
| command: 'addMBoxStep2' | |
| , "arguments": [settings] | |
| }, elm, evt) | |
| } | |
| }, | |
| $addMBoxStep2: function(elm, evt, settings){ | |
| var mboxID = this.generateID() | |
| var self = this | |
| SL.addEventHandler(window, 'load', SL.bind(function(){ | |
| SL.cssQuery(settings.mboxGoesAround, function(elms){ | |
| var elem = elms[0] | |
| if (!elem) return | |
| var newDiv = document.createElement("div") | |
| newDiv.id = mboxID | |
| elem.parentNode.replaceChild(newDiv, elem) | |
| newDiv.appendChild(elem) | |
| window.mboxDefine(mboxID, settings.mboxName) | |
| var args = [settings.mboxName] | |
| if (settings.arguments){ | |
| args = args.concat(settings.arguments) | |
| } | |
| window.mboxUpdate.apply(null, args) | |
| self.reappearWhenCallComesBack(elem, mboxID, settings.timeout, settings) | |
| }); | |
| }, this)) | |
| this.lastMboxID = mboxID // leave this here for easier testing | |
| }, | |
| $addTargetPageParams: function(elm, evt, pageParams) { | |
| this.updateTargetPageParams(pageParams) | |
| }, | |
| generateID: function(){ | |
| var id = '_sdsat_mbox_' + String(Math.random()).substring(2) + '_' | |
| return id | |
| }, | |
| appendStyle: function(css){ | |
| var head = document.getElementsByTagName('head')[0], | |
| style = document.createElement('style'); | |
| style.type = 'text/css'; | |
| if(style.styleSheet){ | |
| style.styleSheet.cssText = css; | |
| } else { | |
| style.appendChild(document.createTextNode(css)); | |
| } | |
| head.appendChild(style); | |
| return style; | |
| }, | |
| reappearWhenCallComesBack: function(elmGoesAround, mboxID, timeout, settings){ | |
| var self = this | |
| function reappear(){ | |
| var styleElm = self.styleElements[settings.mboxGoesAround] | |
| if (styleElm){ | |
| styleElm.parentNode.removeChild(styleElm) | |
| ;delete self.styleElements[settings.mboxGoesAround] | |
| } | |
| } | |
| SL.cssQuery('script[src*="omtrdc.net"]', function(results){ | |
| var script = results[0] | |
| if (script){ | |
| SL.scriptOnLoad(script.src, script, function(){ | |
| SL.notify('Test & Target: request complete', 1) | |
| reappear() | |
| clearTimeout(timeoutID) | |
| }) | |
| var timeoutID = setTimeout(function(){ | |
| SL.notify('Test & Target: bailing after ' + timeout + 'ms', 1) | |
| reappear() | |
| }, timeout) | |
| }else{ | |
| SL.notify('Test & Target: failed to find T&T ajax call, bailing', 1) | |
| reappear() | |
| } | |
| }) | |
| }, | |
| updateTargetPageParams: function(obj) { | |
| var o = {} | |
| for (var key in obj) { | |
| if (obj.hasOwnProperty(key)) { | |
| o[SL.replace(key)] = SL.replace(obj[key]) | |
| } | |
| } | |
| SL.extend( | |
| this.targetPageParamsStore, | |
| o | |
| ) | |
| }, | |
| getTargetPageParams: function() { | |
| return this.targetPageParamsStore | |
| }, | |
| setTargetPageParamsFunction: function() { | |
| window.targetPageParams = SL.bind(this.getTargetPageParams, this) | |
| }, | |
| parseTargetPageParamsResult: function(data) { | |
| var result = data | |
| if(SL.isArray(data)) { | |
| data = data.join('&') | |
| } | |
| if (SL.isString(data)) { | |
| result = SL.parseQueryParams(data) | |
| } | |
| return result | |
| } | |
| }) | |
| SL.availableTools.tnt = Tnt | |
| var GAUtils = { | |
| allowLinker: function() { | |
| return SL.hasMultipleDomains(); | |
| }, | |
| cookieDomain: function() { | |
| var domainList = SL.settings.domainList; | |
| var domainName = SL.find(domainList, function(domain) { | |
| var hostname = window.location.hostname; | |
| return SL.equalsIgnoreCase( | |
| hostname.slice(hostname.length - domain.length), | |
| domain); | |
| }); | |
| var cookieDomain = domainName ? ('.' + domainName) : 'auto'; | |
| return cookieDomain; | |
| } | |
| }; | |
| // The Google Analytics Universal Tool | |
| // ================ | |
| // | |
| // This tool interacts with the [GAU library](https://developers.google.com/analytics/devguides/collection/analyticsjs/). | |
| // | |
| // From a high end perspective the following steps will happen. A `ga` dummy | |
| // object will be initialized. Until the `analytics.js` file will be loaded in | |
| // the browser, any triggered command will be queued in the `ga` object. Once | |
| // the `analytics.js` will finish to load, all the queued commands will be | |
| // executed. | |
| // | |
| // The tool is initialized during one of the following page load phases: | |
| // top, bottom. Find out more info about the initializing sequence by clicking | |
| // [here](#-endplphase-). | |
| // | |
| // Data elements are replaced when the tracker is created and on the commands | |
| // from `initCommands` array. For the other situations, the data elements are | |
| // replaced in the `triggerCommand` method from BaseTool. | |
| // | |
| // Beside the settings that are processed by the BaseTool code, this tool uses | |
| // the following extra settings: | |
| // | |
| // - `engine` - The engine identifier (ga_universal) | |
| // - `loadOn` - The PL phase when this tool will be initialized (top | bottom) | |
| // - `url` - Custom URL of the `analytics.js` URL location. If none is provided | |
| // the Google default URL will be used. | |
| // - `initTool` - Boolean flag that can suppress the tool initialization phase. | |
| // When set to `false` no JS library will be loaded and no initial command | |
| // will be executed. All the later commands triggered by this tool will | |
| // piggy back on any availble `ga` function from the page. | |
| // - `trackerSettings` - Object containing properties that will be added on the | |
| // command that will create the GAU tracker. For a list of all supported | |
| // properties please click [here](https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#create) | |
| // - `initCommands` - It's an array containing commands. A command example: | |
| // `["set", "anonymizeIp", true]`. For a list of all supported commands | |
| // please click [here](https://developers.google.com/analytics/devguides/collection/analyticsjs/method-reference#tracker) | |
| // The commands defined here will be executed after the tracker is created. | |
| // - `allowLinker` - Flag that will make the GAU library load the cross domain | |
| // linking plugin. | |
| // - `customInit` - JS code that will be executed immediately after the tool is | |
| // initialized. The boolean result from `customInit` will affect the | |
| // initial page view call. | |
| function GAUniversalTool(settings) { | |
| SL.BaseTool.call(this, settings) | |
| } | |
| SL.inherit(GAUniversalTool, SL.BaseTool); | |
| SL.extend(GAUniversalTool.prototype, { | |
| // Public | |
| // ------------------------------------------------ | |
| name: 'GAUniversal', | |
| // `endPLPhase()` | |
| // ------------------------------------------------ | |
| // | |
| // Method that starts the tool initialization when the page load phase is | |
| // matched and only if the tool initialization has not been previously | |
| // cancelled. Find out more info about the initializing sequence by clicking | |
| // [here](#-initialize-). | |
| // | |
| // After the tool is initialized a page view call is triggered if | |
| // `suppressInitialPageView` flag is not set to `true`. | |
| endPLPhase: function(pageLoadEvent) { | |
| var settings = this.settings; | |
| var loadOn = settings.loadOn; | |
| if (pageLoadEvent === loadOn) { | |
| SL.notify('GAU: Initializing at ' + pageLoadEvent, 1); | |
| this.initialize(); | |
| this.flushQueue(); | |
| this.trackInitialPageView(); | |
| } | |
| }, | |
| // `getTrackerName()` | |
| // ------------------------------------------------ | |
| // | |
| // Returns the name of the GA tracker initialized by this tool. | |
| getTrackerName: function () { | |
| return this.settings.trackerSettings.name || ''; | |
| }, | |
| // Private | |
| // ------------------------------------------------ | |
| isPageCodeLoadSuppressed: function() { | |
| return this.settings.initTool === false || this._cancelToolInit === true; | |
| }, | |
| // `initialize()` | |
| // ------------------------------------------------ | |
| // | |
| // The method first creates the GA scaffolding objects (the `ga` object and | |
| // the `GoogleAnalyticsObject` object. | |
| // | |
| // Then it loads the `analytics.js` library and append the command that will | |
| // create the GAU tracker object to the `ga` object. | |
| // | |
| // Next, the commands from the `initCommands` array will be appended to | |
| // the `ga` object. Finally the JS code defined in the `customInit` setting | |
| // variable will be called. | |
| initialize: function() { | |
| if (this.isPageCodeLoadSuppressed()) { | |
| this.initialized = true; | |
| SL.notify('GAU: Page code not loaded (suppressed).', 1); | |
| return; | |
| } | |
| var gaName = 'ga'; | |
| window[gaName] = window[gaName] || this.createGAObject(); | |
| window.GoogleAnalyticsObject = gaName; | |
| SL.notify('GAU: Page code loaded.', 1); | |
| SL.loadScriptOnce(this.getToolUrl()); | |
| var settings = this.settings; | |
| if (GAUtils.allowLinker() && settings.allowLinker !== false) { | |
| this.createAccountForLinker(); | |
| } else { | |
| this.createAccount(); | |
| } | |
| this.executeInitCommands(); | |
| if (settings.customInit){ | |
| var customInit = settings.customInit | |
| var result = customInit(window[gaName], this.getTrackerName()) | |
| if (result === false){ | |
| this.suppressInitialPageView = true; | |
| } | |
| } | |
| this.initialized = true; | |
| }, | |
| createGAObject: function() { | |
| var ga = function() { | |
| ga.q.push(arguments); | |
| }; | |
| ga.q = []; | |
| ga.l = 1 * new Date(); | |
| return ga; | |
| }, | |
| createAccount: function() { | |
| this.create(); | |
| }, | |
| createAccountForLinker: function() { | |
| var options = {}; | |
| if (GAUtils.allowLinker()) | |
| options.allowLinker = true; | |
| this.create(options); | |
| this.call('require', 'linker'); | |
| this.call('linker:autoLink', this.autoLinkDomains(), false, true); | |
| }, | |
| create: function(extra){ | |
| var options = this.settings.trackerSettings; | |
| options = | |
| SL.preprocessArguments([options], location, null, this.forceLowerCase)[0]; | |
| options.trackingId = | |
| SL.replace(this.settings.trackerSettings.trackingId, location); | |
| if (!options.cookieDomain) { | |
| options.cookieDomain = GAUtils.cookieDomain(); | |
| } | |
| SL.extend(options, extra || {}); | |
| this.call('create', options); | |
| }, | |
| autoLinkDomains: function() { | |
| var ourDomain = location.hostname; | |
| return SL.filter(SL.settings.domainList, function(domain) { | |
| return domain !== ourDomain; | |
| }); | |
| }, | |
| executeInitCommands: function() { | |
| var settings = this.settings; | |
| if (settings.initCommands) { | |
| SL.each(settings.initCommands, function(command) { | |
| var args = command.splice(2, command.length - 2); | |
| command = command.concat( | |
| SL.preprocessArguments(args, location, null, this.forceLowerCase) | |
| ); | |
| this.call.apply(this, command); | |
| }, this); | |
| } | |
| }, | |
| trackInitialPageView: function(){ | |
| if (this.suppressInitialPageView || this.isPageCodeLoadSuppressed()) { | |
| return; | |
| } | |
| this.call('send', 'pageview'); | |
| }, | |
| call: function() { | |
| if (typeof ga !== 'function') { | |
| SL.notify('GA Universal function not found!', 4); | |
| return; | |
| } | |
| if (this.isCallSuppressed()) { | |
| return; | |
| } | |
| arguments[0] = this.cmd(arguments[0]); | |
| this.log(SL.toArray(arguments)); | |
| ga.apply(window, arguments); | |
| }, | |
| isCallSuppressed: function() { | |
| return this._cancelToolInit === true; | |
| }, | |
| $missing$: function(command, elm, evt, args) { | |
| args = args || []; | |
| args = [command].concat(args); | |
| this.call.apply(this, args); | |
| }, | |
| getToolUrl: function() { | |
| var settings = this.settings; | |
| var isHttps = SL.isHttps(); | |
| if (settings.url) { | |
| return isHttps ? settings.url.https : settings.url.http; | |
| } | |
| return (isHttps ? 'https://ssl' : 'http://www') + '.google-analytics.com/analytics.js'; | |
| }, | |
| cmd: function(command) { | |
| var trackerCommands = ['send', 'set', 'get']; | |
| var trackerName = this.getTrackerName(); | |
| if (!trackerName || SL.indexOf(trackerCommands, command) === -1) { | |
| return command; | |
| } | |
| return trackerName + '.' + command; | |
| }, | |
| log: function(args) { | |
| var cmd = args[0]; | |
| var tracker = this.getTrackerName() || 'default'; | |
| var msg = 'GA Universal: sent command ' + cmd + ' to tracker ' + tracker; | |
| if (args.length > 1) { | |
| var parameters = SL.stringify(args.slice(1)); | |
| msg += ' with parameters ' + SL.stringify(args.slice(1)); | |
| } | |
| msg += '.'; | |
| SL.notify(msg, 1); | |
| } | |
| }); | |
| SL.availableTools.ga_universal = GAUniversalTool; | |
| // Google Analytics Tool | |
| // --------------------- | |
| // | |
| // The GATool allows you to use any Google Analytics command. | |
| // Example: | |
| // | |
| // trigger: [ | |
| // { | |
| // tool: "ga", | |
| // command: "trackEvent", | |
| // arguments: [ | |
| // "video", | |
| // "video 10% complete" | |
| // ] | |
| // } | |
| // ] | |
| // | |
| // This trigger will call the `trackEvent` method, which is equivalent to | |
| // | |
| // _gaq.push(['_trackEvent', 'video', 'video 10% complete']) | |
| function GATool(settings){ | |
| SL.BaseTool.call(this, settings) | |
| } | |
| SL.inherit(GATool, SL.BaseTool) | |
| SL.extend(GATool.prototype, { | |
| name: 'GA', | |
| initialize: function(){ | |
| var settings = this.settings | |
| var before = window._gaq | |
| , initCommands = settings.initCommands || [] | |
| , customInit = settings.customInit | |
| if (!before){ | |
| // And yes, I *do* mean to set a global variable | |
| // of `_gaq` here | |
| _gaq = [] | |
| } | |
| if (!this.isSuppressed()){ | |
| if (!before && !GATool.scriptLoaded){ | |
| var https = SL.isHttps() | |
| var url = | |
| (https ? 'https://ssl' : 'http://www') + | |
| '.google-analytics.com/ga.js' | |
| if (settings.url){ | |
| url = https ? settings.url.https : settings.url.http | |
| } | |
| SL.loadScript(url) | |
| GATool.scriptLoaded = true | |
| SL.notify('GA: page code loaded.', 1) | |
| } | |
| var domain = settings.domain | |
| , trackerName = settings.trackerName | |
| , allowLinker = GAUtils.allowLinker() | |
| , account = SL.replace(settings.account, location) | |
| , domainList = SL.settings.domainList || [] | |
| _gaq.push([this.cmd('setAccount'), account]) | |
| if (allowLinker) | |
| _gaq.push([this.cmd('setAllowLinker'), allowLinker]) | |
| _gaq.push([this.cmd('setDomainName'), GAUtils.cookieDomain()]) | |
| SL.each(initCommands, function(cmd){ | |
| var arr = [this.cmd(cmd[0])].concat(SL.preprocessArguments(cmd.slice(1), location, null, this.forceLowerCase)) | |
| _gaq.push(arr) | |
| }, this) | |
| if (customInit) | |
| this.suppressInitialPageView = false === customInit(_gaq, trackerName) | |
| if (settings.pageName) | |
| this.$overrideInitialPageView(null, null, settings.pageName) | |
| }else{ | |
| SL.notify('GA: page code not loaded(suppressed).', 1) | |
| } | |
| this.initialized = true | |
| SL.fireEvent(this.id + '.configure', _gaq, trackerName) | |
| }, | |
| isSuppressed: function(){ | |
| return this._cancelToolInit || this.settings.initTool === false | |
| }, | |
| tracker: function(){ | |
| return this.settings.trackerName | |
| }, | |
| cmd: function(cmd){ | |
| var tracker = this.tracker() | |
| return tracker ? tracker + '._' + cmd : '_' + cmd | |
| }, | |
| $overrideInitialPageView: function(elm, evt, url){ | |
| this.urlOverride = url | |
| }, | |
| trackInitialPageView: function(){ | |
| if (this.isSuppressed()) return | |
| if (this.suppressInitialPageView) return | |
| if (this.urlOverride){ | |
| var args = SL.preprocessArguments([this.urlOverride], location, null, this.forceLowerCase) | |
| this.$missing$('trackPageview', null, null, args) | |
| }else{ | |
| this.$missing$('trackPageview') | |
| } | |
| }, | |
| endPLPhase: function(pageLoadEvent){ | |
| var loadOn = this.settings.loadOn | |
| if (pageLoadEvent === loadOn){ | |
| SL.notify('GA: Initializing at ' + pageLoadEvent, 1) | |
| this.initialize() | |
| this.flushQueue() | |
| this.trackInitialPageView() | |
| } | |
| }, | |
| call: function(cmd, elm, evt, args){ | |
| if (this._cancelToolInit) return | |
| var settings = this.settings | |
| , tracker = this.tracker() | |
| , fullCmd = this.cmd(cmd) | |
| , args = args ? [fullCmd].concat(args) : [fullCmd] | |
| _gaq.push(args) | |
| if (tracker) | |
| SL.notify("GA: sent command " + cmd + " to tracker " + tracker + | |
| (args.length > 1 ? | |
| " with parameters [" + args.slice(1).join(', ') + "]" : | |
| '') + ".", 1) | |
| else | |
| SL.notify("GA: sent command " + cmd + | |
| (args.length > 1 ? | |
| " with parameters [" + args.slice(1).join(', ') + "]": | |
| '') + ".", 1) | |
| }, | |
| $missing$: function(cmd, elm, evt, args){ | |
| this.call(cmd, elm, evt, args) | |
| }, | |
| // individual command methods | |
| $postTransaction: function(elm, evt, varname){ | |
| var trans = SL.data.customVars.transaction = window[varname] | |
| this.call('addTrans', elm, evt, [ | |
| trans.orderID, | |
| trans.affiliation, | |
| trans.total, | |
| trans.tax, | |
| trans.shipping, | |
| trans.city, | |
| trans.state, | |
| trans.country | |
| ]) | |
| SL.each(trans.items, function(item){ | |
| this.call('addItem', elm, evt, [ | |
| item.orderID, | |
| item.sku, | |
| item.product, | |
| item.category, | |
| item.unitPrice, | |
| item.quantity | |
| ]) | |
| }, this) | |
| this.call('trackTrans', elm, evt) | |
| }, | |
| delayLink: function(elm, evt){ | |
| var ga = this | |
| if (!GAUtils.allowLinker()) return | |
| if (!elm.hostname.match(this.settings.linkerDomains)) return | |
| if (SL.isSubdomainOf(elm.hostname, location.hostname)) return | |
| SL.preventDefault(evt) | |
| var linkDelay = SL.settings.linkDelay || 100 | |
| setTimeout(function(){ | |
| ga.call('link', elm, evt, [elm.href]) | |
| }, linkDelay) | |
| }, | |
| popupLink: function(elm, evt){ | |
| if (!window._gat) return | |
| SL.preventDefault(evt) | |
| var account = this.settings.account | |
| var tracker = window._gat._createTracker(account) | |
| var url = tracker._getLinkerUrl(elm.href) | |
| window.open(url) | |
| }, | |
| $link: function(elm, evt){ | |
| if (elm.getAttribute('target') === '_blank'){ | |
| this.popupLink(elm, evt) | |
| }else{ | |
| this.delayLink(elm, evt) | |
| } | |
| }, | |
| $trackEvent: function(elm, evt){ | |
| var args = Array.prototype.slice.call(arguments, 2) | |
| if (args.length >= 4 && args[3] != null){ | |
| // acertain that the 4th element is a number, falling back to 1 | |
| var value = parseInt(args[3], 10) | |
| if (SL.isNaN(value)){ | |
| value = 1 | |
| } | |
| args[3] = value | |
| } | |
| this.call('trackEvent', elm, evt, args) | |
| } | |
| }) | |
| SL.availableTools.ga = GATool | |
| // Adobe Analytics Tool | |
| // ================ | |
| // | |
| // This tool interacts with the [AppMeasurement library](http://microsite.omniture.com/t2/help/en_US/sc/appmeasurement/release/c_release_notes_mjs.html) | |
| // | |
| // Beside the settings that are processed by the BaseTool code, this tool uses | |
| // the following extra settings: | |
| // | |
| // - `engine` - The engine identifier (sc) | |
| // - `initVars` - It's an array containing key/value pair of AppMeasurement's | |
| // properties that are used in tracking and for settings. An example of | |
| // such pair would be: `{ eVar6: "6", server: "tracking.server"}`. For a | |
| // list of all supported properties please consult the [AppMeasurement's | |
| // documentation](http://microsite.omniture.com/t2/help/en_US/sc/implement/sc_variables.html). | |
| // - `initTool` - Boolean flag that can suppress the tool initialization phase. | |
| // When set to `false` no JS library will be loaded and no initial command | |
| // will be executed. All the later commands triggered by this tool will | |
| // piggy back on any availble `ga` function from the page. | |
| // - `sCodeURL` - Custom URL of the AppMeasurement Javascript library URL | |
| // location. | |
| // - `loadOn` - The PL phase when this tool will be initialized (top | bottom) | |
| // - `account` - String containing the report suite ID to track to. | |
| // - `skipSetAccount` - Boolean value that when true disables setting | |
| // of the `account` with the value provided in settings. Default value | |
| // is no being set. | |
| // - `euCookie' - Please see the description on SL (core.js) code | |
| // - `renameS` - String specifying the name of the global AppMeasurement | |
| // instance. If no provided `s` is implied. | |
| // - `executeCustomPageCodeFirst` - Boolean flag that lets the custom | |
| // initialization code be executed before or after the `initVars` method | |
| // call. Default value is not set which means false. | |
| // - `customInit` - JS code that will be executed immediately after the tool is | |
| // initialized. The boolean result from `customInit` will affect the | |
| // initial page view call. A false value results in disabling the initial | |
| // page view tracking call. | |
| // | |
| // The SiteCatalystTool allows to set variables, add events, track link, etc. | |
| // Example: | |
| // | |
| // trigger: [ | |
| // { | |
| // tool: "sc", | |
| // command: "trackLink" | |
| // } | |
| // ] | |
| // | |
| function SiteCatalystTool(settings){ | |
| SL.BaseTool.call(this, settings) | |
| this.varBindings = {} | |
| this.events = [] | |
| this.products = [] | |
| this.customSetupFuns = [] | |
| } | |
| SL.inherit(SiteCatalystTool, SL.BaseTool) | |
| SL.extend(SiteCatalystTool.prototype, { | |
| // Public | |
| // ------------------------------------------------ | |
| name: 'SC', | |
| // `endPLPhase()` | |
| // ------------------------------------------------ | |
| // | |
| // Method that starts the tool initialization when the page load phase is | |
| // matched and only if the tool initialization has not been previously | |
| // cancelled. Find out more info about the initializing sequence by clicking | |
| // [here](#-initialize-). | |
| // | |
| // After the tool is initialized a page view call is triggered if | |
| // `suppressInitialPageView` flag is not set to `true`. | |
| endPLPhase: function(pageLoadEvent){ | |
| var loadOn = this.settings.loadOn | |
| if (pageLoadEvent === loadOn){ | |
| this.initialize(pageLoadEvent) | |
| } | |
| }, | |
| // Private | |
| // ------------------------------------------------ | |
| // `initialize()` | |
| // ------------------------------------------------ | |
| // | |
| // The method first check to see if the default initialization is specifically | |
| // canceled. | |
| // | |
| // Then it sets an event listener on `pageLoadeEvent` to update the tracking | |
| // variables with the ones provided in `initVars` setting object. | |
| // | |
| // In case that the user chosen to provide the Javascript code for | |
| // AppMeasurement by himself instead of using the automatic management | |
| // then we wait for the library to load. | |
| // | |
| // Otherwise we load the AppMeasurement from the storage and then set the | |
| // setup variables on the tracker object. | |
| initialize: function(pageLoadEvent){ | |
| if (this._cancelToolInit) return | |
| this.settings.initVars = this.substituteVariables( | |
| this.settings.initVars, { type: pageLoadEvent } | |
| ) | |
| if (this.settings.initTool !== false){ | |
| var url = this.settings.sCodeURL || SL.basePath() + 's_code.js' | |
| if (typeof url === 'object'){ | |
| if (window.location.protocol === 'https:') | |
| url = url.https | |
| else | |
| url = url.http | |
| } | |
| if (!url.match(/^https?:/)) | |
| url = SL.basePath() + url | |
| if (this.settings.initVars){ | |
| this.$setVars(null, null, this.settings.initVars) | |
| } | |
| SL.loadScript(url, SL.bind(this.onSCodeLoaded, this)) | |
| this.initializing = true | |
| }else{ | |
| // Set to initializing because we are | |
| // waiting on the AppMeasurement/s_code library to be loaded by | |
| // the site and we'll detect the completion of the load | |
| // in a background task. | |
| this.initializing = true | |
| this.pollForSC() | |
| } | |
| }, | |
| // `getS(s, options)` | |
| // ------------------------------------------------ | |
| // | |
| // The method initializes the `s` object. | |
| // | |
| // A notificaiton is given and `null` is returned in case of not finding | |
| // the account/RSID. | |
| // | |
| // If Marketing Cloud Visitor ID Service is used that instance is linked | |
| // with the instatiated `s` object. | |
| getS: function(s, options){ | |
| var hostname = options && options.hostname || window.location.hostname | |
| var varBindings = this.concatWithToolVarBindings( | |
| options && options.setVars || this.varBindings | |
| ) | |
| var events = options && options.addEvent || this.events | |
| var acct = this.getAccount(hostname) | |
| var s_gi = window.s_gi | |
| if (!s_gi) return null | |
| if (!this.isValidSCInstance(s)) s = null | |
| if (!acct && !s) { | |
| SL.notify('Adobe Analytics: tracker not initialized because account was not found', 1) | |
| return null | |
| } | |
| var s = s || s_gi(acct) | |
| var DTMversion = 'D' + SL.appVersion; | |
| if(typeof s.tagContainerMarker !== 'undefined') { | |
| s.tagContainerMarker = DTMversion | |
| } else { | |
| if (typeof s.version === 'string' && | |
| s.version.substring(s.version.length - 5) !== | |
| ('-' + DTMversion)){ | |
| s.version += '-' + DTMversion | |
| } | |
| } | |
| if (s.sa && this.settings.skipSetAccount !== true && this.settings.initTool !== false) s.sa(this.settings.account) | |
| this.applyVarBindingsOnTracker(s, varBindings) | |
| if (events.length > 0) | |
| s.events = events.join(',') | |
| var visitorIdInstance = SL.getVisitorId() | |
| if (visitorIdInstance) { | |
| s.visitor = SL.getVisitorId() | |
| } | |
| return s | |
| }, | |
| // `onSCodeLoaded()` | |
| // ------------------------------------------------ | |
| // | |
| // The method triggers load event on Analytics tool so all subsequent and | |
| // listening methods would be properly triggered. | |
| // | |
| // Before cleaning up the queue the tracking beacon call is made. | |
| onSCodeLoaded: function(loaded_manually){ | |
| this.initialized = true | |
| this.initializing = false | |
| var msg = [ | |
| 'Adobe Analytics: loaded', | |
| loaded_manually ? ' (manual)' : '', | |
| '.' | |
| ] | |
| SL.notify(msg.join(''), 1) | |
| SL.fireEvent(this.id + '.load', this.getS()) | |
| if (!loaded_manually) { | |
| this.flushQueueExceptTrackLink() | |
| this.sendBeacon() | |
| } | |
| this.flushQueue() | |
| }, | |
| // `getAccount(hostname)` | |
| // ------------------------------------------------ | |
| // | |
| // The returns the `s_account` for a specified `hostname` | |
| // | |
| // TODO: need to be refactored because `accountByHost` is no longer used. | |
| getAccount: function(hostname){ | |
| if (window.s_account){ | |
| return window.s_account | |
| } | |
| if (hostname && this.settings.accountByHost){ | |
| return this.settings.accountByHost[hostname] || this.settings.account | |
| }else{ | |
| return this.settings.account | |
| } | |
| }, | |
| // `getTrackingServer()` | |
| // ------------------------------------------------ | |
| // | |
| // The method tries to retrieve the tracking server from the `s` object | |
| // otherwise falls back on generating one based on the `account`. | |
| // | |
| // If neither `account` or `trackingServer` are availalble, `null` is | |
| // returned. | |
| // | |
| // TODO: need to be refactored to remove the tracking server generate method | |
| // as Analytics now offers a central point to shoot to. | |
| getTrackingServer: function(){ | |
| var tool = this | |
| var s = tool.getS() | |
| if (s) { | |
| if (s.ssl && s.trackingServerSecure) { | |
| return s.trackingServerSecure | |
| } | |
| else if (s.trackingServer) { | |
| return s.trackingServer | |
| } | |
| } | |
| var account = tool.getAccount(window.location.hostname) | |
| if (!account) return null | |
| // Based on code in app measurement. | |
| var w | |
| var c = '' | |
| var d = s && s.dc | |
| var e | |
| var f | |
| w = account | |
| e = w.indexOf(",") | |
| e >= 0 && (w = w.gb(0, e)) | |
| w = w.replace(/[^A-Za-z0-9]/g, "") | |
| c || (c = "2o7.net") | |
| d = d ? ("" + d).toLowerCase() : "d1" | |
| c == "2o7.net" && (d == "d1" ? d = "112" : d == "d2" && (d = "122"), f = "") | |
| e = w + "." + d + "." + f + c | |
| return e | |
| }, | |
| // `sendBeacon()` | |
| // ------------------------------------------------ | |
| // | |
| // The method triggers the tracking call. | |
| // | |
| // If custom initialization is used the beacon is supressed. Also, if custom | |
| // code is provided and specifically stated that it should be executed first | |
| // (`executeCustomPageCodeFirst`) the tracker get updated with the result of | |
| // the code. | |
| sendBeacon: function(){ | |
| var s = this.getS(window[this.settings.renameS || 's']) | |
| if (!s){ | |
| SL.notify('Adobe Analytics: page code not loaded', 1) | |
| return | |
| } | |
| if (this.settings.customInit){ | |
| if (this.settings.customInit(s) === false){ | |
| SL.notify("Adobe Analytics: custom init suppressed beacon", 1) | |
| return | |
| } | |
| } | |
| if (this.settings.executeCustomPageCodeFirst) { | |
| this.applyVarBindingsOnTracker(s, this.varBindings) | |
| } | |
| this.executeCustomSetupFuns(s) | |
| s.t() | |
| this.clearVarBindings() | |
| this.clearCustomSetup() | |
| SL.notify("Adobe Analytics: tracked page view", 1) | |
| }, | |
| pollForSC: function(){ | |
| SL.poll(SL.bind(function(){ | |
| if (typeof window.s_gi === 'function'){ | |
| this.onSCodeLoaded(true) | |
| return true | |
| } | |
| }, this)) | |
| }, | |
| flushQueueExceptTrackLink: function(){ | |
| // Because we always s.tl() after the first s.t() | |
| // that way the variables set by s.tl() will not | |
| // contaminate the s.t() call. | |
| if (!this.pending) return | |
| var left = [] | |
| for (var i = 0; i < this.pending.length; i++){ | |
| var args = this.pending[i] | |
| var trig = args[0] | |
| if (trig.command === 'trackLink'){ | |
| left.push(args) | |
| }else{ | |
| this.triggerCommand.apply(this, args) | |
| } | |
| } | |
| this.pending = left | |
| }, | |
| isQueueAvailable: function(){ | |
| return !this.initialized | |
| }, | |
| substituteVariables: function(obj, evt){ | |
| var ret = {} | |
| for (var key in obj){ | |
| if (obj.hasOwnProperty(key)) { | |
| var value = obj[key] | |
| ret[key] = SL.replace(value, location, evt) | |
| } | |
| } | |
| return ret | |
| }, | |
| $setVars: function(elm, evt, vars){ | |
| for (var v in vars){ | |
| if (vars.hasOwnProperty(v)) { | |
| var val = vars[v] | |
| if (typeof val === 'function') | |
| val = val() | |
| this.varBindings[v] = val | |
| } | |
| } | |
| SL.notify('Adobe Analytics: set variables.', 2) | |
| }, | |
| $customSetup: function(elm, evt, setup){ | |
| this.customSetupFuns.push(function(s){ | |
| setup.call(elm, evt, s) | |
| }) | |
| }, | |
| isValidSCInstance: function(s) { | |
| return !!s && typeof s.t === 'function' && typeof s.tl === 'function' | |
| }, | |
| concatWithToolVarBindings: function(varBindings){ | |
| var settingsInitVars = this.settings.initVars || {} | |
| SL.map(['trackingServer', 'trackingServerSecure'], function (item) { | |
| if (settingsInitVars[item] && !varBindings[item]) { | |
| varBindings[item] = settingsInitVars[item] | |
| } | |
| }); | |
| return varBindings | |
| }, | |
| applyVarBindingsOnTracker: function (s, varBindings) { | |
| for (var v in varBindings){ | |
| if (varBindings.hasOwnProperty(v)) { | |
| s[v] = varBindings[v] | |
| } | |
| } | |
| }, | |
| clearVarBindings: function(){ | |
| this.varBindings = {} | |
| }, | |
| clearCustomSetup: function(){ | |
| this.customSetupFuns = [] | |
| }, | |
| executeCustomSetupFuns: function(s){ | |
| SL.each(this.customSetupFuns, function(fun){ | |
| fun.call(window, s) | |
| }) | |
| }, | |
| $trackLink: function(elm, evt, params){ | |
| params = params || {} | |
| var type = params.type | |
| var linkName = params.linkName | |
| if (!linkName && | |
| elm && | |
| elm.nodeName && | |
| elm.nodeName.toLowerCase() === 'a'){ | |
| linkName = elm.innerHTML | |
| } | |
| if (!linkName){ | |
| linkName = 'link clicked' | |
| } | |
| var vars = params && params.setVars | |
| var events = (params && params.addEvent) || [] | |
| var s = this.getS(null, { | |
| setVars: vars, | |
| addEvent: events | |
| }) | |
| if (!s){ | |
| SL.notify('Adobe Analytics: page code not loaded', 1) | |
| return | |
| } | |
| var orgLinkTrackVars = s.linkTrackVars | |
| var orgLinkTrackEvents = s.linkTrackEvents | |
| var definedVarNames = this.definedVarNames(vars) | |
| if (params && params.customSetup){ | |
| params.customSetup.call(elm, evt, s) | |
| } | |
| if (events.length > 0) | |
| definedVarNames.push('events') | |
| if (s.products) | |
| definedVarNames.push('products') | |
| // add back the vars from s | |
| definedVarNames = this.mergeTrackLinkVars(s.linkTrackVars, definedVarNames) | |
| // add back events from s | |
| events = this.mergeTrackLinkVars(s.linkTrackEvents, events) | |
| s.linkTrackVars = this.getCustomLinkVarsList(definedVarNames) | |
| var eventsKeys = SL.map(events, function(item) { | |
| return item.split(':')[0] | |
| }); | |
| s.linkTrackEvents = this.getCustomLinkVarsList(eventsKeys) | |
| s.tl(true, type || 'o', linkName) | |
| SL.notify([ | |
| 'Adobe Analytics: tracked link ', | |
| 'using: linkTrackVars=', | |
| SL.stringify(s.linkTrackVars), | |
| '; linkTrackEvents=', | |
| SL.stringify(s.linkTrackEvents) | |
| ].join(''), 1) | |
| s.linkTrackVars = orgLinkTrackVars | |
| s.linkTrackEvents = orgLinkTrackEvents | |
| }, | |
| mergeTrackLinkVars: function(newVarsStr, varsArr){ | |
| if (newVarsStr) { | |
| varsArr = newVarsStr.split(',').concat(varsArr) | |
| } | |
| return varsArr | |
| }, | |
| getCustomLinkVarsList: function (keysArr) { | |
| var noneIndex = SL.indexOf(keysArr, 'None'); | |
| if (noneIndex > -1 && keysArr.length > 1) { | |
| keysArr.splice(noneIndex, 1) | |
| } | |
| return keysArr.join(','); | |
| }, | |
| definedVarNames: function(vars){ | |
| vars = vars || this.varBindings | |
| var ret = [] | |
| for (var varname in vars){ | |
| if (vars.hasOwnProperty(varname) && /^(eVar[0-9]+)|(prop[0-9]+)|(hier[0-9]+)|campaign|purchaseID|channel|server|state|zip|pageType$/.test(varname)) | |
| ret.push(varname) | |
| } | |
| return ret | |
| }, | |
| $trackPageView: function(elm, evt, params){ | |
| var vars = params && params.setVars | |
| var events = (params && params.addEvent) || [] | |
| var s = this.getS(null, { | |
| setVars: vars, | |
| addEvent: events | |
| }) | |
| if (!s){ | |
| SL.notify('Adobe Analytics: page code not loaded', 1) | |
| return | |
| } | |
| s.linkTrackVars = '' | |
| s.linkTrackEvents = '' | |
| this.executeCustomSetupFuns(s) | |
| if (params && params.customSetup){ | |
| params.customSetup.call(elm, evt, s) | |
| } | |
| s.t() | |
| this.clearVarBindings() | |
| this.clearCustomSetup() | |
| SL.notify("Adobe Analytics: tracked page view", 1) | |
| }, | |
| $postTransaction: function(elm, evt, varname){ | |
| var trans = SL.data.transaction = window[varname] | |
| , s = this.varBindings | |
| , mapping = this.settings.fieldVarMapping | |
| SL.each(trans.items, function(item){ | |
| this.products.push(item) | |
| }, this) | |
| s.products = SL.map(this.products, function(item){ | |
| var vars = [] | |
| if (mapping && mapping.item){ | |
| for (var field in mapping.item){ | |
| if (mapping.item.hasOwnProperty(field)) { | |
| var varname = mapping.item[field] | |
| vars.push(varname + '=' + item[field]) | |
| if (varname.substring(0, 5) === 'event') | |
| this.events.push(varname) | |
| } | |
| } | |
| } | |
| var arr = ['', item.product, item.quantity, item.unitPrice * item.quantity] | |
| if (vars.length > 0) | |
| arr.push(vars.join('|')) | |
| return arr.join(';') | |
| }, this).join(',') | |
| if (mapping && mapping.transaction){ | |
| // Add top-level events/eVars to products string. | |
| var topLevelVars = [] | |
| for (var field in mapping.transaction){ | |
| if (mapping.transaction.hasOwnProperty(field)) { | |
| var varname = mapping.transaction[field] | |
| topLevelVars.push(varname + '=' + trans[field]) | |
| if (varname.substring(0, 5) === 'event') | |
| this.events.push(varname) | |
| } | |
| } | |
| if (s.products.length > 0) | |
| s.products += ',' | |
| s.products += ';;;;' + topLevelVars.join('|') | |
| } | |
| }, | |
| $addEvent: function(elm, evt){ | |
| for (var i = 2, len = arguments.length; i < len; i++){ | |
| this.events.push(arguments[i]) | |
| } | |
| }, | |
| $addProduct: function(elm, evt){ | |
| for (var i = 2, len = arguments.length; i < len; i++){ | |
| this.products.push(arguments[i]) | |
| } | |
| } | |
| }) | |
| SL.availableTools.sc = SiteCatalystTool | |
| // The Default Tool | |
| // ================ | |
| // | |
| // The default tool comes with several handy utilities. | |
| function DefaultTool(){ | |
| SL.BaseTool.call(this) | |
| this.asyncScriptCallbackQueue = [] | |
| this.argsForBlockingScripts = [] | |
| } | |
| SL.inherit(DefaultTool, SL.BaseTool) | |
| SL.extend(DefaultTool.prototype, { | |
| name: 'Default', | |
| // `loadIframe(src, variables)` | |
| // ---------------------------- | |
| // | |
| // Dynamically create an iframe to load a URL. | |
| // | |
| // - src - the URL to load | |
| // - variables - an object literal of which the key/value pairs will be used | |
| // to create the query string to use in the src URL | |
| $loadIframe: function(elm, evt, options){ | |
| var pages = options.pages | |
| , loadOn = options.loadOn | |
| var doit = SL.bind(function(){ | |
| SL.each(pages, function(page){ | |
| this.loadIframe(elm, evt, page) | |
| }, this) | |
| }, this) | |
| if (!loadOn) doit() | |
| if (loadOn === 'domready') SL.domReady(doit) | |
| if (loadOn === 'load') SL.addEventHandler(window, 'load', doit) | |
| }, | |
| loadIframe: function(elm, evt, page){ | |
| var iframe = document.createElement('iframe') | |
| iframe.style.display = 'none' | |
| var host = SL.data.host | |
| , data = page.data | |
| , src = this.scriptURL(page.src) | |
| , search = SL.searchVariables(data, elm, evt) | |
| if (host) | |
| src = SL.basePath() + src | |
| src += search | |
| iframe.src = src | |
| var body = document.getElementsByTagName('body')[0] | |
| if (body) | |
| body.appendChild(iframe) | |
| else | |
| SL.domReady(function(){ | |
| document.getElementsByTagName('body')[0].appendChild(iframe) | |
| }) | |
| }, | |
| scriptURL: function(url){ | |
| var scriptDir = SL.settings.scriptDir || '' | |
| return scriptDir + url | |
| }, | |
| // `loadScript(options) | |
| // ------------------------------ | |
| // | |
| // Load any number of Javascript files using dynamically generated script tags. | |
| // If you provide multiple file URLs, they will be loaded sequentially. | |
| $loadScript: function(elm, evt, options){ | |
| var scripts = options.scripts | |
| , sequential = options.sequential | |
| , loadOn = options.loadOn | |
| var doit = SL.bind(function(){ | |
| if (sequential){ | |
| this.loadScripts(elm, evt, scripts) | |
| }else{ | |
| SL.each(scripts, function(script){ | |
| this.loadScripts(elm, evt, [script]) | |
| }, this) | |
| } | |
| }, this) | |
| if (!loadOn) doit() | |
| else if (loadOn === 'domready') SL.domReady(doit) | |
| else if (loadOn === 'load') SL.addEventHandler(window, 'load', doit) | |
| }, | |
| loadScripts: function(elm, evt, scripts) { | |
| try{ | |
| var scripts = scripts.slice(0) | |
| , q = this.asyncScriptCallbackQueue | |
| , lastScript | |
| , target = evt.target || evt.srcElement | |
| , self = this | |
| }catch(e){ | |
| console.error('scripts is', SL.stringify(scripts)) | |
| } | |
| function loadNext(){ | |
| if (q.length > 0 && lastScript){ | |
| var callback = q.shift() | |
| callback.call(elm, evt, target) | |
| } | |
| var script = scripts.shift() | |
| if (script){ | |
| var host = SL.data.host | |
| , src = self.scriptURL(script.src) | |
| if (host) | |
| src = SL.basePath() + src | |
| lastScript = script | |
| SL.loadScript(src, loadNext) | |
| } | |
| } | |
| loadNext() | |
| }, | |
| $loadBlockingScript: function(elm, evt, options){ | |
| var scripts = options.scripts | |
| , loadOn = options.loadOn | |
| var doit = SL.bind(function(){ | |
| SL.each(scripts, function(script){ | |
| this.loadBlockingScript(elm, evt, script) | |
| }, this) | |
| }, this) | |
| //if (!loadOn || loadOn === evt.type) doit() | |
| doit() | |
| }, | |
| loadBlockingScript: function(elm, evt, script){ | |
| /*jshint evil:true */ | |
| var src = this.scriptURL(script.src) | |
| , host = SL.data.host | |
| , target = evt.target || evt.srcElement | |
| if (host) | |
| src = SL.basePath() + src | |
| this.argsForBlockingScripts.push([elm, evt, target]) | |
| SL.loadScriptSync(src) | |
| }, | |
| pushAsyncScript: function(callback){ | |
| this.asyncScriptCallbackQueue.push(callback) | |
| }, | |
| pushBlockingScript: function(callback){ | |
| var args = this.argsForBlockingScripts.shift() | |
| var element = args[0] | |
| callback.apply(element, args.slice(1)) | |
| }, | |
| // `writeHTML(html)` | |
| // ----------------- | |
| // | |
| // Write an HTML fragment onto the page using `document.write()`. | |
| // | |
| // - `html` - the HTML fragment | |
| $writeHTML: SL.escapeHtmlParams(function(elm, evt){ | |
| /*jshint evil:true */ | |
| if (SL.domReadyFired || !document.write){ | |
| SL.notify('Command writeHTML failed. You should try appending HTML using the async option.', 1) | |
| return | |
| } | |
| if (evt.type !== 'pagebottom' && evt.type !== 'pagetop'){ | |
| SL.notify('You can only use writeHTML on the `pagetop` and `pagebottom` events.', 1) | |
| return | |
| } | |
| for (var i = 2, len = arguments.length; i < len; i++){ | |
| var html = arguments[i].html | |
| html = SL.replace(html, elm, evt) | |
| document.write(html) | |
| } | |
| }), | |
| linkNeedsDelayActivate: function(a, win){ | |
| win = win || window | |
| var tagName = a.tagName | |
| , target = a.getAttribute('target') | |
| , location = a.getAttribute('href') | |
| if (tagName && tagName.toLowerCase() !== 'a') | |
| return false | |
| if (!location) | |
| return false | |
| else if (!target) | |
| return true | |
| else if (target === '_blank') | |
| return false | |
| else if (target === '_top') | |
| return win.top === win | |
| else if (target === '_parent') | |
| return false | |
| else if (target === '_self') | |
| return true | |
| else if (win.name) | |
| return target === win.name | |
| else | |
| return true | |
| }, | |
| // `delayActivateLink()` | |
| // --------------------- | |
| // | |
| // Delay the activation of an anchor link by first using `evt.preventDefault()` on | |
| // the click event, and then setting the window location to the destination after | |
| // a small delay. The default delay is 100 milliseconds, which can be configured in | |
| // `_satellite.settings.linkDelay` | |
| $delayActivateLink: function(elm, evt){ | |
| if (!this.linkNeedsDelayActivate(elm)) return | |
| SL.preventDefault(evt) | |
| var linkDelay = SL.settings.linkDelay || 100 | |
| setTimeout(function(){ | |
| SL.setLocation(elm.href) | |
| }, linkDelay) | |
| }, | |
| isQueueable: function(trig){ | |
| return trig.command !== 'writeHTML' | |
| } | |
| }) | |
| SL.availableTools['default'] = DefaultTool | |
| // The Nielsen Tool | |
| // ================ | |
| // | |
| // This tool provides the means to make Nielsen tracking possible. | |
| // | |
| // The tool accepts the following settings: | |
| // | |
| // - `collectionServer` - The collection server to be used. The variable | |
| // specifies the nearest collection server. | |
| // - `clientId` - The client identifier. A unique Nielsen supplied ID that | |
| // should be alphanumeric and lowercase. A dash (-) character is allowed. | |
| // - `contentGroup` - The content group. A historical variable used for | |
| // grouping/aggregating content into channels. Currently the | |
| // default value is "0". | |
| function NielsenTool(settings) { | |
| SL.BaseTool.call(this, settings); | |
| this.defineListeners(); | |
| this.beaconMethod = 'plainBeacon'; | |
| this.adapt = new NielsenTool.DataAdapters(); | |
| this.dataProvider = new NielsenTool.DataProvider.Aggregate(); | |
| } | |
| SL.inherit(NielsenTool, SL.BaseTool); | |
| SL.extend(NielsenTool.prototype, { | |
| // Public | |
| // ------------------------------------------------ | |
| name: 'Nielsen', | |
| // Private | |
| // ------------------------------------------------ | |
| // `endPLPhase()` | |
| // ------------------------------------------------ | |
| // | |
| // Method that starts the tool initialization when the page load phase is | |
| // matched and only if the tool initialization has not been previously | |
| // cancelled. | |
| // | |
| // This is needed in order to be able to properly hook the needed events. | |
| endPLPhase: function(pageLoadEvent) { | |
| switch (pageLoadEvent) { | |
| case 'pagetop': | |
| this.initialize(); | |
| break; | |
| case 'pagebottom': | |
| if (this.enableTracking) { | |
| this.queueCommand({ command: 'sendFirstBeacon', "arguments": [] }); | |
| this.flushQueueWhenReady(); | |
| } | |
| break; | |
| } | |
| }, | |
| defineListeners: function() { | |
| this.onTabFocus = SL.bind(function() { | |
| this.notify('Tab visible, sending view beacon when ready', 1); | |
| this.tabEverVisible = true; | |
| this.flushQueueWhenReady(); | |
| }, this); | |
| this.onPageLeave = SL.bind(function() { | |
| this.notify('isHuman? : '+ this.isHuman(), 1); | |
| if (this.isHuman()) { | |
| this.sendDurationBeacon(); // track page leave | |
| } | |
| }, this); | |
| this.onHumanDetectionChange = SL.bind(function(e) { | |
| if (this == e.target.target) this.human = e.target.isHuman; | |
| }, this); | |
| }, | |
| initialize: function() { | |
| this.initializeTracking(); | |
| this.initializeDataProviders(); | |
| this.initializeNonHumanDetection(); | |
| this.tabEverVisible = SL.visibility.isVisible(); | |
| if (!this.tabEverVisible) { | |
| SL.bindEventOnce('tabfocus', this.onTabFocus); | |
| } | |
| else { | |
| this.notify('Tab visible, sending view beacon when ready', 1); | |
| } | |
| this.initialized = true; | |
| }, | |
| // `initializeTracking()` | |
| // ------------------------------------------------ | |
| // | |
| // The method starts the time tracking and hooks on the leave event. | |
| initializeTracking: function() { | |
| if (this.initialized) return; | |
| this.notify('Initializing tracking', 1); | |
| this.addRemovePageLeaveEvent(this.enableTracking); | |
| this.addRemoveHumanDetectionChangeEvent(this.enableTracking); | |
| this.initialized = true; | |
| }, | |
| // `initializeDataProviders()` | |
| // ------------------------------------------------ | |
| // | |
| // The method initializes default data providers for: | |
| // - Analytics Report Suite ID, if Analytics account is linked | |
| // - Marketing Cloud Visitor ID, with fallback to auto-generated UUID | |
| initializeDataProviders: function() { | |
| var analytics = this.getAnalyticsTool(), rsid; | |
| this.dataProvider.register( | |
| new NielsenTool.DataProvider.VisitorID( | |
| SL.getVisitorId() | |
| ) | |
| ); | |
| if (analytics) { | |
| rsid = new NielsenTool.DataProvider.Generic('rsid', function() { | |
| return analytics.settings.account; | |
| }); | |
| this.dataProvider.register(rsid); | |
| } | |
| else { | |
| this.notify('Missing integration with Analytics: rsid will not be sent.'); | |
| } | |
| }, | |
| initializeNonHumanDetection: function() { | |
| if (SL.nonhumandetection) { | |
| SL.nonhumandetection.init(); | |
| this.setEnableNonHumanDetection( | |
| this.settings.enableNonHumanDetection == false ? false : true); | |
| if (this.settings.nonHumanDetectionDelay > 0) { | |
| this.setNonHumanDetectionDelay( | |
| parseInt(this.settings.nonHumanDetectionDelay) * 1000); | |
| } | |
| } else { | |
| this.notify('NHDM is not available.'); | |
| } | |
| }, | |
| // `getAnalyticsTool()` | |
| // ------------------------------------------------ | |
| // | |
| // If integration is defined, this method returns the tool instance of | |
| // the linked Analytics account | |
| getAnalyticsTool: function() { | |
| if (this.settings.integratesWith) { | |
| return SL.tools[this.settings.integratesWith]; | |
| } | |
| }, | |
| flushQueueWhenReady: function() { | |
| if (!this.enableTracking || !this.tabEverVisible) return; | |
| SL.poll(SL.bind(function() { | |
| if (this.isReadyToTrack()) { | |
| this.flushQueue(); | |
| return true; | |
| } | |
| }, this), 100, 20); | |
| }, | |
| isReadyToTrack: function() { | |
| return this.tabEverVisible && this.dataProvider.isReady(); | |
| }, | |
| // `setVars(vars)` | |
| // ------------------------------------------------ | |
| // | |
| // The method is used to set variables on the tool | |
| $setVars: function(elm, evt, vars) { | |
| for (var v in vars) { | |
| var val = vars[v]; | |
| if (typeof val === 'function') | |
| val = val(); | |
| this.settings[v] = val; | |
| } | |
| this.notify('Set variables done', 2); | |
| this.prepareContextData(); | |
| }, | |
| // `setEnableTracking()` | |
| // ------------------------------------------------ | |
| // | |
| // The method triggers the view tracking call. | |
| $setEnableTracking: function(elm, evt, bool) { | |
| this.notify('Will' + (!bool ? ' not' : '') + ' track time on page', 1); | |
| if (this.enableTracking != bool) { | |
| this.addRemovePageLeaveEvent(bool); | |
| this.addRemoveHumanDetectionChangeEvent(bool); | |
| this.enableTracking = bool; | |
| } | |
| }, | |
| // `sendFirstBeacon()` | |
| // ------------------------------------------------ | |
| // | |
| // The method is called as soon as everything is in place. | |
| $sendFirstBeacon: function(elm, evt, settings) { | |
| this.sendViewBeacon(); | |
| }, | |
| // `setEnableNonHumanDetection()` | |
| // ------------------------------------------------ | |
| // | |
| // The method enables/disables the human detection mechanism. | |
| setEnableNonHumanDetection: function(bool) { | |
| if (bool) { | |
| SL.nonhumandetection.register(this); | |
| } else { | |
| SL.nonhumandetection.unregister(this); | |
| } | |
| }, | |
| // `setNonHumanDetectionDelay()` | |
| // ------------------------------------------------ | |
| // | |
| // The method set the timeout for entering in non human state. | |
| setNonHumanDetectionDelay: function(delay) { | |
| SL.nonhumandetection.register(this, delay); | |
| }, | |
| addRemovePageLeaveEvent: function(add) { | |
| this.notify((add ? 'Attach onto' : 'Detach from') + ' page leave event', 1); | |
| var method = (add == false ? 'unbindEvent' : 'bindEvent'); | |
| SL[method]('leave', this.onPageLeave); | |
| }, | |
| addRemoveHumanDetectionChangeEvent: function(add) { | |
| this.notify((add ? 'Attach onto' : 'Detach from') + ' human detection change event', 1); | |
| var method = (add == false ? 'unbindEvent' : 'bindEvent'); | |
| SL[method]('humandetection.change', this.onHumanDetectionChange); | |
| }, | |
| // `sendViewBeacon()` | |
| // ------------------------------------------------ | |
| // | |
| // The method triggers the view tracking call. | |
| sendViewBeacon: function() { | |
| this.notify('Tracked page view.', 1); | |
| this.sendBeaconWith(); | |
| }, | |
| // `sendDurationBeacon()` | |
| // ------------------------------------------------ | |
| // | |
| // The method triggers the duration tracking call. This adds the time | |
| // spent on the page to the call and is triggered when the user leaves | |
| // the current web page. | |
| sendDurationBeacon: function() { | |
| if ( | |
| !SL.timetracking || | |
| typeof SL.timetracking.timeOnPage != 'function' || | |
| SL.timetracking.timeOnPage() == null | |
| ) { | |
| this.notify('Could not track close due missing time on page', 5); | |
| return; | |
| } | |
| this.notify('Tracked close', 1); | |
| this.sendBeaconWith({ | |
| timeOnPage: Math.round(SL.timetracking.timeOnPage() / 1000), | |
| duration: 'D', | |
| timer: 'timer' | |
| }); | |
| // a bit of delay to let the network thread finish sending data | |
| var i,s='';for(i=0;i<this.magicConst;i++){s+='0'}; | |
| }, | |
| // `sendBeaconWith(obj)` | |
| // ------------------------------------------------ | |
| // | |
| // The method builds the tracking call based on provided settings and | |
| // parameters. | |
| sendBeaconWith: function(params) { | |
| if (this.enableTracking) { | |
| this[this.beaconMethod].call(this, this.prepareUrl(params)); | |
| } | |
| }, | |
| plainBeacon: function(url) { | |
| var img = new Image(); | |
| img.src = url; | |
| img.width = 1; | |
| img.height = 1; | |
| img.alt = ''; | |
| }, | |
| navigatorSendBeacon: function(url) { | |
| navigator.sendBeacon(url); | |
| }, | |
| prepareUrl: function(params) { | |
| var obj = this.settings; | |
| SL.extend(obj, this.dataProvider.provide()); | |
| SL.extend(obj, params); | |
| return this.preparePrefix(this.settings.collectionServer) + | |
| this.adapt.convertToURI( | |
| this.adapt.toNielsen( | |
| this.substituteVariables(obj))); | |
| }, | |
| preparePrefix: function(server) { | |
| return '//' + encodeURIComponent(server) + '.imrworldwide.com/cgi-bin/gn?'; | |
| }, | |
| substituteVariables: function(hash){ | |
| var obj = {}; | |
| for (var v in hash) { | |
| if (hash.hasOwnProperty(v)) { | |
| obj[v] = SL.replace(hash[v]); | |
| } | |
| } | |
| return obj; | |
| }, | |
| prepareContextData: function() { | |
| if (!this.getAnalyticsTool()) { | |
| this.notify('Adobe Analytics missing.'); | |
| return; | |
| } | |
| var obj = this.settings; | |
| obj.sdkVersion =_satellite.publishDate; | |
| this.getAnalyticsTool().$setVars(null, null, { | |
| contextData: this.adapt.toAnalytics( | |
| this.substituteVariables(obj)) | |
| }); | |
| }, | |
| isHuman: function() { | |
| return this.human; | |
| }, | |
| onTabFocus: function() {}, | |
| onPageLeave: function() {}, | |
| onHumanDetectionChange: function() {}, | |
| notify: function(msg, lvl) { | |
| SL.notify(this.logPrefix + msg, lvl); | |
| }, | |
| beaconMethod: 'plainBeacon', | |
| adapt: null, | |
| enableTracking: false, | |
| logPrefix: "Nielsen: ", | |
| tabEverVisible: false, | |
| human: true, | |
| magicConst: 0x1e8480 | |
| }); | |
| // `NielsenTool.DataProvider` | |
| // ========================== | |
| // | |
| // The following components handle the task of providing extra information | |
| // for the Nielsen beacon, with support for asynchronous data | |
| // | |
| NielsenTool.DataProvider = {}; | |
| NielsenTool.DataProvider.Generic = function(key, valueFn) { | |
| this.key = key; | |
| this.valueFn = valueFn; | |
| }; | |
| SL.extend(NielsenTool.DataProvider.Generic.prototype, { | |
| isReady: function() { | |
| return true; | |
| }, | |
| getValue: function() { | |
| return this.valueFn(); | |
| }, | |
| provide: function() { | |
| if (!this.isReady()) { | |
| NielsenTool.prototype.notify('Not yet ready to provide value for: ' + this.key, 5) | |
| } | |
| var data = {}; | |
| data[this.key] = this.getValue(); | |
| return data; | |
| } | |
| }); | |
| // `NielsenTool.DataProvider.VisitorID` | |
| // ==================================== | |
| // | |
| // Gets and optionally waits for Marketing Cloud ID to be loaded. | |
| // If no visitor instance is provided, then it falls-back to generated UUID. | |
| // | |
| NielsenTool.DataProvider.VisitorID = function(visitorInstance, key, fallbackProvider) { | |
| this.key = key || 'uuid'; | |
| this.visitorInstance = visitorInstance; | |
| if (this.visitorInstance) { | |
| this.visitorId = visitorInstance.getMarketingCloudVisitorID([this, this._visitorIdCallback]); | |
| } | |
| this.fallbackProvider = fallbackProvider || new NielsenTool.UUID(); | |
| }; | |
| SL.inherit(NielsenTool.DataProvider.VisitorID, NielsenTool.DataProvider.Generic); | |
| SL.extend(NielsenTool.DataProvider.VisitorID.prototype, { | |
| isReady: function() { | |
| if (this.visitorInstance === null) { | |
| return true; | |
| } | |
| return !!this.visitorId; | |
| }, | |
| getValue: function() { | |
| return this.visitorId || this.fallbackProvider.get(); | |
| }, | |
| _visitorIdCallback: function(id) { | |
| this.visitorId = id; | |
| } | |
| }); | |
| // `NielsenTool.DataProvider.Aggregate` | |
| // ==================================== | |
| // | |
| // Aggregates data from multiple providers, being aware of their ready-state. | |
| // | |
| NielsenTool.DataProvider.Aggregate = function() { | |
| this.providers = []; | |
| for (var i=0; i<arguments.length; i++) { | |
| this.register(arguments[i]); | |
| } | |
| }; | |
| SL.extend(NielsenTool.DataProvider.Aggregate.prototype, { | |
| register: function(provider) { | |
| this.providers.push(provider); | |
| }, | |
| isReady: function() { | |
| return SL.every(this.providers, function(provider) { | |
| return provider.isReady(); | |
| }); | |
| }, | |
| provide: function() { | |
| var data = {}; | |
| SL.each(this.providers, function(provider) { | |
| SL.extend(data, provider.provide()); | |
| }); | |
| return data; | |
| } | |
| }); | |
| // `UUID` | |
| // =============== | |
| // | |
| // The follwing generates an [RFC 4122 version 4](https://www.ietf.org/rfc/rfc4122.txt) | |
| // uinique ID and stores it in a cookie. | |
| NielsenTool.UUID = function() {}; | |
| SL.extend(NielsenTool.UUID.prototype, { | |
| // `generate()` | |
| // ------------------------------------------------ | |
| // | |
| // Method that generates an [RFC 4122 version 4](https://www.ietf.org/rfc/rfc4122.txt) | |
| // compliant unique ID. | |
| // | |
| // This is needed in for Nielsen tracking w/o Analytics integration. | |
| generate: function() { | |
| return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { | |
| var r = Math.random() * 16 | 0, | |
| v = c == 'x' ? r : (r & 0x3 | 0x8); | |
| return v.toString(16); | |
| }); | |
| }, | |
| get: function() { | |
| var cookieUUID = SL.readCookie(this.key('uuid')); | |
| if (cookieUUID) return cookieUUID; | |
| cookieUUID = this.generate(); | |
| SL.setCookie(this.key('uuid'), cookieUUID); | |
| return cookieUUID; | |
| }, | |
| key: function(name) { | |
| return '_dtm_nielsen_' + name; | |
| } | |
| }); | |
| // `Data Adapters` | |
| // =============== | |
| // | |
| // The follwing adapters are used to adapt the settings to the proper format | |
| // for both Nielsen tracking call and AA tracking calls | |
| NielsenTool.DataAdapters = function() {}; | |
| SL.extend(NielsenTool.DataAdapters.prototype, { | |
| toNielsen: function(settings) { | |
| var cdate = new Date().getTime(), | |
| nielsenPrefixes = { | |
| c6: 'vc,', | |
| c13: 'asid,', | |
| c15: 'apn,', | |
| c27: 'cln,', | |
| c32: 'segA,', | |
| c33: 'segB,', | |
| c34: 'segC,', | |
| c35: 'adrsid,', | |
| c29: 'plid,', | |
| c30: 'bldv,', | |
| c40: 'adbid,' | |
| }, | |
| nielsenObj = { | |
| ci: settings.clientId, | |
| c6: settings.vcid, | |
| c13: settings.appId, | |
| c15: settings.appName, | |
| prv: 1, | |
| forward: 0, | |
| ad: 0, | |
| cr: settings.duration || 'V', // [V|D], default V | |
| rt: 'text', | |
| st: 'dcr', | |
| prd: 'dcr', | |
| r: cdate, | |
| at: settings.timer || 'view', // [view|timer], default view | |
| c16: settings.sdkVersion, | |
| c27: settings.timeOnPage || 0, | |
| c40: settings.uuid, | |
| c35: settings.rsid, | |
| ti: cdate, | |
| sup: 0, | |
| c32: settings.segmentA, | |
| c33: settings.segmentB, | |
| c34: settings.segmentC, | |
| asn: settings.assetName, | |
| c29: settings.playerID, | |
| c30: settings.buildVersion | |
| }; | |
| for (key in nielsenObj) { | |
| if (nielsenObj[key] !== undefined && nielsenObj[key] != null) { | |
| if (nielsenObj[key] !== undefined && nielsenObj != null && nielsenObj != '') { | |
| var val = encodeURIComponent(nielsenObj[key]); | |
| if (nielsenPrefixes.hasOwnProperty(key) && val) { | |
| val = nielsenPrefixes[key] + val; | |
| } | |
| nielsenObj[key] = val; | |
| } | |
| } | |
| } | |
| return this.filterObject(nielsenObj); | |
| }, | |
| toAnalytics: function(settings) { | |
| return this.filterObject({ | |
| 'a.nielsen.clientid': settings.clientId, | |
| 'a.nielsen.vcid': settings.vcid, | |
| 'a.nielsen.appid': settings.appId, | |
| 'a.nielsen.appname': settings.appName, | |
| 'a.nielsen.accmethod': "0", | |
| 'a.nielsen.ctype': "text", | |
| 'a.nielsen.sega': settings.segmentA, | |
| 'a.nielsen.segb': settings.segmentB, | |
| 'a.nielsen.segc': settings.segmentC, | |
| 'a.nielsen.asset': settings.assetName | |
| }); | |
| }, | |
| convertToURI: function(obj) { | |
| if (SL.isObject(obj) === false) return ''; | |
| var uri = [] | |
| for (var key in obj) { | |
| if (obj.hasOwnProperty(key)) uri.push(key + '=' + obj[key]); | |
| } | |
| return uri.join('&') | |
| }, | |
| filterObject: function(obj) { | |
| for (var k in obj) { | |
| if (obj.hasOwnProperty(k) && | |
| (obj[k] == null || obj[k] === undefined)) { | |
| delete obj[k]; | |
| } | |
| } | |
| return obj; | |
| } | |
| }); | |
| SL.availableTools.nielsen = NielsenTool; | |
| _satellite.init({ | |
| "tools": { | |
| "21d4da84002970ac77af10cdabc32f20": { | |
| "engine": "sc", | |
| "loadOn": "pagebottom", | |
| "account": "clgbcollegeboardcomprod", | |
| "euCookie": false, | |
| "sCodeURL": "7a8a98de0363fbed05b98da851d6b23866ffa7cc/s-code-contents-55dc9cec4faa6cdfed0976f767868b7bcd08c911.js", | |
| "initVars": { | |
| "charSet": "UTF-8", | |
| "currencyCode": "USD", | |
| "trackingServer": "track.collegeboard.org", | |
| "trackingServerSecure": "strack.collegeboard.org", | |
| "trackInlineStats": true, | |
| "trackDownloadLinks": false, | |
| "trackExternalLinks": false, | |
| "linkLeaveQueryString": false, | |
| "dynamicVariablePrefix": "D=" | |
| }, | |
| "customInit": function(s){ | |
| /* global Visitor, SatReg */ | |
| /** | |
| * Configured by jbeach on 2016-07-20 | |
| * Updated by jbeach on 2020-07-08 | |
| */ | |
| kiwi = window.kiwi || {}; | |
| kiwi.util = kiwi.util || _satellite.getVar('Kiwi Utility Functions') || {}; | |
| var ruleName='KIWI: Tool > Analytics > Custom JS'; | |
| /********************* Global Vars Init SECTION *********************/ | |
| //_satellite.notify(ruleName+' > Global Vars Section'); | |
| // DDL | |
| digitalData = window.digitalData || {}; | |
| digitalData.page = digitalData.page || {}; | |
| digitalData.page.pageInfo = digitalData.page.pageInfo || {}; | |
| digitalData.page.category = digitalData.page.category || {}; | |
| digitalData.page.attributes = digitalData.page.attributes || {}; | |
| digitalData.page.attributes.targetModsComplete = digitalData.page.attributes.targetModsComplete || 0; | |
| digitalData.user = digitalData.user || [ {profile: {} } ]; | |
| // CB Track Data | |
| cbTrackData = window.cbTrackData || {}; | |
| /************************** CONFIGURATIONS SECTION ***************/ | |
| //_satellite.notify('KIWI: Tool > Analytics > Custom JS > CONFIGURATIONS SECTION'); | |
| s.usePlugins=true; | |
| s.visitor = Visitor.getInstance('5E1B123F5245B29B0A490D45@AdobeOrg'); | |
| s.linkDownloadFileTypes='.arf,.avi,.css,.csv,.dmg,.doc,.docx,.dotx,.eps,.exe,.ics,.js,.m4v,.mov,.mp3,.mp4,.mpg,.pages,.pdf,.ppt,.pptx,.rar,.rm,.rtf,.swf,.tab,.txt,.vsd,.vxd,.wav,.wma,.wmv,.xls,.xlsx,.xml,.zip'; | |
| s.linkInternalFilters='javascript:,acquia-sites.com,apscore.org,cbapis.org,collegeboard.com,collegeboard.org,springboardonline.com,springboardonline.org'; | |
| s.ActionDepthTest=true; // Depth1: Landing Page and Depth2: Second Page Events | |
| /* Time Parting Config */ | |
| //time parting configuration | |
| //US | |
| s._tpDST = { | |
| 2012:'3/11,11/4', | |
| 2013:'3/10,11/3', | |
| 2014:'3/9,11/2', | |
| 2015:'3/8,11/1', | |
| 2016:'3/13,11/6', | |
| 2017:'3/12,11/5', | |
| 2018:'3/11,11/4', | |
| 2019:'3/10,11/3', | |
| 2020:'3/8,11/1', | |
| 2021:'3/14,11/7', | |
| 2022:'3/13,11/6', | |
| 2023:'3/12,11/5'}; | |
| /* end Time Parting Config */ | |
| /** end Configurations Section **/ | |
| /*********Media Module Calls**************/ | |
| /***** MEDIA MODULE CONFIGURATION FOR MILESTONE TRACKING START*****/ | |
| s.loadModule('Media'); | |
| s.Media.onLoad = function(s) { | |
| s.Media.autoTrack= false; | |
| /*Track Milestone 10%, 25%, 50%, 75%, 95% | |
| * Delete unwanted milestone if necessary | |
| */ | |
| s.Media.trackMilestones='25,50,75,100'; //10,25,50,75,95 | |
| s.Media.playerName='default-video-player-name'; //_satellite.getVar('Video Player Name') || ; | |
| s.Media.segmentByMilestones = true; | |
| s.Media.trackUsingContextData = true; | |
| /* Add reserved context data variables as needed to populate default metrics | |
| * a.media.progress10, a.media.progress25, a.media.progress50 ,a.media.progress75, a.media.progress95 | |
| * a.media.friendlyname --> to populate Video Name report | |
| */ | |
| s.Media.trackVars='contextData.a.media.progress10,contextData.a.media.progress25,contextData.a.media.progress50,contextData.a.media.progress75,contextData.a.media.progress95,contextData.a.media.friendlyname'; | |
| }; | |
| /* | |
| * USE MEDIA MONITOR TO SEND THE ADDITIONAL a.media.progressXX variables: needed as no processing rules are created by default to handle media.milestone | |
| */ | |
| s.Media.monitor = function (s,media) { | |
| //Reset Variables | |
| s.contextData['a.media.progress10'] = s.contextData['a.media.progress25'] = s.contextData['a.media.progress50'] = s.contextData['a.media.progress75'] = s.contextData['a.media.progress95'] = s.contextData['a.media.friendlyname'] = ''; | |
| s.contextData['a.media.friendlyname'] = _satellite.getVar('Video Media Name'); //assign custom friendly name if needed | |
| //if no custom friendly name | |
| if(!s.contextData['a.media.friendlyname']){ | |
| //default to media.name | |
| s.contextData['a.media.friendlyname'] = media.name; | |
| } | |
| //If MILESTONE EVENT | |
| if(media.event=='MILESTONE') { | |
| //Check which milestone has been reached: media.milestone | |
| switch (media.milestone) { | |
| case 10: | |
| //When the 10% milestone is reached add a.media.progress10 to the Adobe Analytics request | |
| s.contextData['a.media.progress10'] = true; | |
| s.Media.track(media.name); | |
| break; | |
| case 25: | |
| //When the 25% milestone is reached add a.media.progress25 to the Adobe Analytics request | |
| s.contextData['a.media.progress25'] = true; | |
| s.Media.track(media.name); | |
| break; | |
| case 50: | |
| //When the 50% milestone is reached add a.media.progress50 to the Adobe Analytics request | |
| s.contextData['a.media.progress50'] = true; | |
| s.Media.track(media.name); | |
| break; | |
| case 75: | |
| //When the 75% milestone is reached add a.media.progress75 to the Adobe Analytics request | |
| s.contextData['a.media.progress75'] = true; | |
| s.Media.track(media.name); | |
| break; | |
| case 95: | |
| //When the 95% milestone is reached add a.media.progress95 to the Adobe Analytics request | |
| s.contextData['a.media.progress95'] = true; | |
| s.Media.track(media.name); | |
| break; | |
| default: | |
| //When any other % milestone is reached do nothing | |
| break; | |
| } | |
| } | |
| }; | |
| /***** MEDIA MODULE CONFIGURATION FOR MILESTONE TRACKING END*****/ | |
| /*********end Media Module Calls**************/ | |
| /************************** DO PLUGINS SECTION ***********************/ | |
| s.doPlugins=function(s) { | |
| //_satellite.notify('KIWI: Tool > Analytics > Custom JS > DO PLUGINS SECTION (begin)'); | |
| //track times through do plugins | |
| if (typeof kiwi._timesThruDoPlugins != 'undefined') kiwi._timesThruDoPlugins++; | |
| else kiwi._timesThruDoPlugins = 0; | |
| _satellite.notify('KIWI: Tool > Analytics > Custom JS > kiwi._timesThruDoPlugins = '+ kiwi._timesThruDoPlugins.toString()); | |
| //start fresh | |
| s.clearVars(); | |
| s.linkTrackVars = 'channel,server,prop1,prop5,prop6,prop7,prop9,prop11,prop12,prop13,prop14,prop17,prop18,prop19,prop20,prop21,' + | |
| 'prop25,prop32,prop57,prop59,eVar5,eVar8,eVar17,eVar21,eVar22,eVar23,eVar24,eVar25,eVar67'; //send with all link tracking TODO: prop50,prop51 | |
| s.linkTrackEvents = ''; | |
| /* Legacy Analytics Overrides */ | |
| var ruleName='KIWI: Tool > Analytics > Custom JS > Legacy Analytics Overrides > NSAT'; | |
| if (kiwi._thisPage.siteCode == 'nsat') { | |
| _satellite.notify(ruleName); | |
| /* NSAT analytics overrides */ | |
| if ((!cbTrackData.flowCode && !cbTrackData.pageCode) || | |
| (cbTrackData.pageCode.match(/(satprofile:coursework[1-6]|:confirmationpopup|:printadmissionticket)/i))) { | |
| var s_pageName = _satellite.getVar('SCode Page Name'); | |
| if(s_pageName) { | |
| if (s_pageName.match(/:/i)) { | |
| //parse it | |
| var arr_s_pageName = s_pageName.split(':'); | |
| cbTrackData.flowCode = arr_s_pageName[0]; | |
| cbTrackData.pageCode = arr_s_pageName[1]; | |
| } | |
| } | |
| } | |
| // NSAT Page Name fixing HACKERY :(, 8/21/2017 | |
| var my_pageName = s_pageName || cbTrackData.flowCode + ':' +cbTrackData.pageCode, | |
| hack_pageName = '', | |
| my_prevPage = decodeURIComponent(_satellite.readCookie('gpv_pn')); | |
| if (my_pageName == 'satregistration:photo-flash' && document.location.href.match(/\/managereg\//i)) { | |
| hack_pageName = 'changesat:photo-flash'; | |
| } | |
| if (my_pageName == 'satregistration:confirmationpopup') { | |
| if (my_prevPage == 'satregistration:reviewpurchase') hack_pageName = 'satregistration:purchaseconfirmpopup'; | |
| else if (my_prevPage == 'scorechoice:satregrevieworderpage') hack_pageName = 'scorechoice:confirmpopup'; | |
| } else if (my_pageName == 'changesat:confirmationpopup' && my_prevPage == 'changesat:reviewpurchase') hack_pageName = 'changesat:purchaseconfirmpopup'; | |
| if (hack_pageName) { | |
| _satellite.setVar('Page Name Override', hack_pageName); | |
| my_pageName = hack_pageName; | |
| } | |
| //map pagenames to steps, set current flowsteps | |
| var pageToStepsArray = [ | |
| ['satregistration:getstarted', ['begin']], | |
| ['satregistration:getstarted-orf1', ['begin']], | |
| ['satregistration:reviewpersonalprofile', ['profile-pi']], | |
| ['satregistration:demographics', ['profile-dg']], | |
| ['satregistration:contractoptinpage', ['contract-optin']], | |
| ['satprofile:cbprograms', ['sdq-cbprograms']], | |
| ['satprofile:gparank', ['sdq-gparank']], | |
| ['satprofile:coursework1', ['sdq-cw-math']], | |
| ['satprofile:coursework2', ['sdq-cw-english']], | |
| ['satprofile:coursework3', ['sdq-cw-science']], | |
| ['satprofile:coursework4', ['sdq-cw-socialstudies']], | |
| ['satprofile:coursework5', ['sdq-cw-languages']], | |
| ['satprofile:coursework6', ['sdq-cw-artsmusic']], | |
| ['satprofile:hsactivities', ['sdq-hsactivities']], | |
| ['satprofile:collegeplans', ['sdq-collegeplans']], | |
| ['satregistration:termsandconditions', ['terms']], | |
| ['satregistration:choosetestanddate', ['choose-test']], | |
| ['satregistration:choosetestcenter', ['choose-center']], | |
| ['satregistration:photo-flash', ['photo']], | |
| ['satregistration:facebookphotopage', ['photo-facebook']], | |
| ['satregistration:crosssell', ['crosssell']], | |
| ['satregistration:reviewpurchase', ['purchase-review']], | |
| ['satregistration:purchaseconfirmpopup', ['purchase-accept']], | |
| ['satregistration:purchaseconfirmation', ['purchase-complete']], | |
| ['satregistration:revieworder', ['reg-review']], | |
| ['satregistration:confirmationpopup', ['reg-accept']], | |
| ['satregistration:confirmation', ['reg-complete']], | |
| ['satregistration:printadmissionticket', ['ticket']], | |
| ['changesat:changeregistration', ['change-begin']], | |
| ['changesat:reviewpersonalprofile', ['change-profile-pi']], | |
| ['changesat:choosetestanddate', ['change-test']], | |
| ['changesat:choosetestcenter', ['change-center']], | |
| ['changesat:photo-flash', ['change-photo']], | |
| ['changesat:crosssell', ['change-crosssell']], | |
| ['changesat:revieworder', ['change-review']], | |
| ['changesat:confirmationpopup', ['change-accept']], | |
| ['changesat:confirmationpage', ['change-complete']], | |
| ['changesat:printadmissionticket', ['change-ticket']] | |
| ]; | |
| //NOT ENOUGH BROWSER SUPPORT YET for "Map" | |
| //var pageToStepsMap = new Map(pageToStepsArray); | |
| //cbTrackData.flowSteps = pageToStepsMap.get(cbTrackData.pageCode); | |
| for (var i = 0; i < pageToStepsArray.length; i++) { | |
| var pageKey = pageToStepsArray[i][0], | |
| arrSteps = pageToStepsArray[i][1]; | |
| if (pageKey == my_pageName) cbTrackData.flowSteps = arrSteps; | |
| } | |
| //get at SAT regNo | |
| if (_satellite.getVar('SCode Events Data')) { | |
| var arrSEvents = _satellite.getVar('SCode Events Data').split(','); | |
| (function(){ | |
| for (var i = 0; i < arrSEvents.length; i++) { | |
| if (arrSEvents[i].match(/event(2|71|72|73|74|75):/i)) { | |
| cbTrackData.satRegNo = arrSEvents[i].split(':')[1]; | |
| if (cbTrackData.satRegNo == 'regNo' && | |
| typeof SatReg != 'undefined' && | |
| typeof SatReg.FtlVars != 'undefined' && | |
| typeof SatReg.FtlVars.regNo != 'undefined') cbTrackData.satRegNo = window.SatReg.FtlVars.regNo; //fixes bug in Print Ticket event tracking on Next Steps button | |
| } | |
| } | |
| })(); | |
| } | |
| //get at Test Type | |
| if (cbTrackData.pageCode == 'choosetestcenter' && _satellite.getVar('DOM nsat TestTypeId')) { | |
| // sat subject tests open info box ... OR sat open info box ... OR sat with essay open info box... | |
| if (_satellite.getVar('DOM nsat TestTypeId').match(/sat subject tests/i)) {s.eVar26 = 'SAT Subject';} | |
| else s.eVar26 = 'SAT'; | |
| } | |
| /* end NSAT analytics overrides */ | |
| } | |
| /* end Legacy Analytics Overrides */ | |
| /* Basic Var settings */ | |
| s.events = s.apl(s.events, 'event7', ',', 2); //Page View | |
| s.hier1 = 'D=g'; | |
| s.prop58 = _satellite.getVar('protocol'); | |
| s.server = _satellite.getVar('Domain'); | |
| s.prop20 = _satellite.getVar('Subdomain'); | |
| s.prop32 = _satellite.getVar('Site Code'); | |
| cbTrackData.flowCode = _satellite.getVar('AppData Flow Code'); | |
| s.prop1 = 'D=pageName'; | |
| //s.pageName = _satellite.getVar('Page Name'); //Page | |
| //Page Track Object | |
| (function(oData){ | |
| s.prop8 = oData.source || 'undefined'; //Page Track Source | |
| s.pageName = oData.pageName || _satellite.getVar('Page Name'); //Page | |
| })(_satellite.getVar('Data - Page Track')); | |
| s.prop1 = 'PAGE|'+s.pageName; | |
| /*s.eVar87 = _satellite.getVar('Page Property - AP Classroom - Application ID'); //AP Classroom Page Application ID | |
| s.eVar88 = _satellite.getVar('Page Property - AP Classroom - Student ID'); //AP Classroom Page Student ID | |
| s.eVar89 = _satellite.getVar('Page Property - AP Classroom - Unit ID'); //AP Classroom Page Unit ID */ | |
| s.prop7 = _satellite.readCookie('gpv_c32') || ''; //Previous Site Code | |
| s.prop52 = _satellite.readCookie('gpv_pn') || ''; //Previous Page | |
| s.prop18 = s.getTimeParting('n', '-5'); //Hour of Day, Day of Week, Weekend/Weekday | |
| s.eVar20 = s.getDaysSinceLastVisit('s_lastvisit'); //Days Since Last Visit | |
| if (kiwi._pageLoadTime) { | |
| s.events = s.apl(s.events, 'event86=' + kiwi._pageLoadTime, ',', 2); //Page Load Time | |
| s.prop61 = kiwi._pageLoadTime; //Page Load Time | |
| } | |
| if (s.ActionDepthTest) { | |
| s.pdvalue = s.getActionDepth('s_depth'); | |
| if (s.pdvalue == 1) {s.events = s.apl(s.events, 'event38', ',', 2);} // Depth1: Landing Page | |
| if (s.pdvalue == 2) {s.events = s.apl(s.events, 'event39', ',', 2);} // Depth2: Second Page | |
| } | |
| s.ActionDepthTest = false; | |
| //s.prop50 = _satellite.getVar('Kiwi MCIDS Present'); //MCIDS Present | |
| //s.prop51 = _satellite.getVar('Kiwi MC Visitor ID'); //Marketing Cloud Visitor ID | |
| s.prop6 = _satellite.getVar('Kiwi Version'); //Kiwi Version | |
| s.prop35 = _satellite.getVar('Enterprise Widgets Version'); //Enterprise Widgets Version | |
| s.prop36 = _satellite.getVar('Apricot Version'); //Apricot Version | |
| s.prop57 = _satellite.getVar('DOM Browser Width'); //Browser Width | |
| s.prop74 = _satellite.getVar('Report Load Speed'); //BI Report Load Speed | |
| s.prop5 = _satellite.getVar('Derived Education Period Code'); //Education Period Code | |
| s.eVar7 = _satellite.getVar('DDL - User - LIFW Status'); //LIFW Status | |
| s.eVar8 = _satellite.getVar('AppData App User Org ID'); //App User Org ID (e.g. app-specific AI Code, DI Code) | |
| s.prop19 = _satellite.getVar('DDL - User Role'); //App User Role | |
| s.prop21 = _satellite.getVar('AppData App Pilot'); //'channels-20180103-01'; //App Pilot | |
| s.prop14 = _satellite.getVar('AppData AP Student Grade Level'); //AP Student Grade Level | |
| s.prop33 = _satellite.getVar('AppData AP Course ID'); //AP Course ID | |
| s.prop39 = _satellite.getVar('AA - App Data Custom 1'); //App Data Custom 1 | |
| s.prop40 = _satellite.getVar('AA - App Data Custom 2'); //App Data Custom 2 | |
| s.prop41 = _satellite.getVar('AA - App Data Custom 3'); //App Data Custom 3 | |
| s.prop42 = _satellite.getVar('AA - App Data Custom 4'); //App Data Custom 4 | |
| //clear the App Data Custom vars | |
| _satellite.setVar('AA - App Data Custom 1', ''); | |
| _satellite.setVar('AA - App Data Custom 2', ''); | |
| _satellite.setVar('AA - App Data Custom 3', ''); | |
| _satellite.setVar('AA - App Data Custom 4', ''); | |
| s.prop31 = _satellite.getVar('SKU'); | |
| s.prop70 = _satellite.getVar('AppData DI Code'); //DI Code | |
| s.eVar67 = _satellite.getVar('Apricot - User Input Method'); //User Input Method | |
| if (kiwi._thisPage.siteCode === 'hedr') { | |
| s.prop70 = s.eVar8; //DI Code | |
| s.prop71 = s.prop19; //HED Reporting App Role TODO: switch reports to use prop19 and disable prop71 | |
| } | |
| if (kiwi._thisPage.siteCode === 'springboarddigital') { | |
| s.prop62 = s.prop19; //Springboard Digital Audience TODO: switch reports to use prop19 and disable prop62 | |
| s.prop63 = _satellite.getVar('AppData User District'); //TODO: switch to "AppData App User Org ID" | |
| } | |
| if((_satellite.getVar('AppData User Type')=='a2o')) s.prop72 = 'a2o'; //A2O Segment //TODO: deprecate switch this to "AppData App User Role" | |
| /* end Basic Var settings */ | |
| /* CB Web (IAM) */ | |
| kiwi.userIsLoggedIn = (_satellite.readCookie('cb_login')) || false; | |
| /* CB Web Login Tracking */ | |
| (function(oData, sPageName) { | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: Data - CB Web Data found: ' + JSON.stringify(oData)); | |
| if (oData.events) { | |
| if (oData.events.match(/event(9|14|21)/i)) { | |
| s.eVar19 = oData.appId || ''; // CB Application ID | |
| } | |
| if (oData.events.match(/event9/i) && !s.prop52.match(/(securitycheck-)/i)) { | |
| if (oData.interim) { | |
| s.events = s.apl(s.events, 'event198', ',', 2); //CB Web AP Interim Logins | |
| //accommodate for when page after interim account create is reminder message, WAP-2908 | |
| if (sPageName.match(/^iam:/i)) { | |
| s.events = s.apl(s.events, 'event197:' + oData.id, ',', 2); //CB Web AP Interim Registrations | |
| } | |
| } else { | |
| s.events = s.apl(s.events, 'event9', ',', 2); //CB Web Logins | |
| } | |
| } | |
| if (oData.events.match(/event14/i)) { | |
| if (oData.interim) { | |
| s.events = s.apl(s.events, 'event197:' + oData.id, ',', 2); //CB Web AP Interim Registrations | |
| } else { | |
| s.events = s.apl(s.events, 'event14:' + oData.id, ',', 2); //CB Web ECL Registrations | |
| } | |
| } | |
| if (oData.events.match(/event21/i)) { | |
| s.events = s.apl(s.events, 'event21:' + oData.id, ',', 2); //CB Web EPL Registrations | |
| } | |
| } | |
| //accommodate for when WEP doesn't include event14/event197 but new account is created! | |
| if (sPageName.match(/^(iam:registrationconfirmationpage|iam:interimaccount:create:success)-/i)) { | |
| if (oData.interim) { | |
| s.events = s.apl(s.events, 'event197:' + oData.id, ',', 2); //CB Web AP Interim Registrations | |
| } else { | |
| s.events = s.apl(s.events, 'event14:' + oData.id, ',', 2); //CB Web ECL Registrations | |
| } | |
| kiwi.util.fireCustomEvent('ECL Account Created'); | |
| } | |
| //new prof account creation doesn't currently get event21 in WEP cookie! so we test for scode event21 next | |
| var sEvents = _satellite.getVar('SCode Events Data'); | |
| if (sEvents.match(/event21/i)) { | |
| s.events = s.apl(s.events, 'event21:' + oData.id, ',', 2); //CB Web EPL Registrations | |
| } | |
| //derive Interim Account Merge scenario (page name not currently working for this) | |
| var iamPageClasses = _satellite.getVar('DOM - iam-page Node'); | |
| if (iamPageClasses.match(/(^| )iam-merged($| )/i)) { | |
| s.events = s.apl(s.events, 'event199', ',', 2); //CB Web AP Interim Account Merges | |
| } | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| //stop interim account events from firing on random Custom Links, e.g. on Big Future, WAP-2908, WAP2916 | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event9,event14,event21', ',', 2); | |
| //s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event9,event14,event21,event197,event198,event199', ',', 2); | |
| //Expire WAP_EXTERNAL_PROPERTIES cookie after track | |
| _satellite.notify('WAP_EXTERNAL_PROPERTIES='+ _satellite.getVar('IAM Cookie - WAP_EXTERNAL_PROPERTIES')) | |
| document.cookie = 'WAP_EXTERNAL_PROPERTIES=;expires=-1;path=/ ;domain=collegeboard.org'; | |
| //update kiwi.user vals | |
| kiwi.user = { | |
| interim: oData.interim, | |
| type: oData.type, | |
| cbId: oData.id, | |
| orgId: oData.orgId, | |
| gender: oData.gender, | |
| gradeLevel: oData.gradeLevel, | |
| gradYear: oData.gradYear, | |
| jobTitle: oData.jobTitle | |
| }; | |
| //signal kiwi.cookie.user updates | |
| kiwi._sessCookieMod = true; | |
| kiwi.cookie.sess.user = kiwi.user; | |
| } | |
| })(_satellite.getVar('Data - CB Web Login'), _satellite.getVar('SCode Page Name')); | |
| /* end CB Web Login Tracking */ | |
| /* CB Web Account Creation Custom Events */ | |
| //if (s.pageName.match(/^iam:registrationpage2-/i)) {} | |
| /* end CB Web Account Creation Custom Events */ | |
| s.prop9 = _satellite.getVar('CB Web - Logged In State'); //CB Web Logged In State | |
| s.eVar22 = _satellite.getVar('CB Web - Account Type'); //CB Web Account Type | |
| s.eVar17 = _satellite.getVar('CB Web - Account ID'); //CB Web Account ID | |
| s.eVar5 = _satellite.getVar('CB Web - Org ID'); //CB Web Org ID | |
| s.eVar24 = _satellite.getVar('CB Web - Gender'); //CB Web Gender | |
| s.eVar23 = _satellite.getVar('CB Web - Grad Year'); //CB Web Grad Year | |
| s.eVar21 = _satellite.getVar('CB Web - Grade Level'); //CB Web Grade Level | |
| s.eVar25 = _satellite.getVar('CB Web - Job Title Code'); //CB Web Job Title Code | |
| //_satellite.notify('KIWI: CB Web Data tracked: ' + JSON.stringify(kiwi.user)); | |
| /* end CB Web (IAM) */ | |
| /* Special IAM Page Name */ | |
| var arrMatchCurr = s.pageName.match(/^iam:default:lockedout-(.*)$/i), | |
| arrMatchPrev = s.prop52.match(/(login|securitycheck)/i); | |
| if (arrMatchCurr !== null && arrMatchPrev !== null) { | |
| s.pageName = 'iam:'+arrMatchPrev[1]+':lockedout-' + arrMatchCurr[1]; | |
| } | |
| var arrMatchCurr = s.pageName.match(/^iam:login:error:password-(.*)$/i), | |
| lockoutWarnModal = document.getElementById('lockout'), | |
| pageModalOpen = document.querySelector('[iam-spa].modal-open'); | |
| if (arrMatchCurr !== null && lockoutWarnModal && pageModalOpen) { | |
| s.pageName = 'iam:login:lockoutwarning-' + arrMatchCurr[1]; | |
| } | |
| /* end Special IAM Page Name */ | |
| /* Error Page Tracking */ | |
| var result = s.pageName.match(/:(404errorpage|500errorpage|downpage|highvolume|403forbidden)/i); | |
| if (result !== null) { | |
| //s.pageName=''; | |
| //s.pageType='errorPage'; | |
| s.prop11 = 'server'; | |
| s.prop12 = result[1]; | |
| s.prop13 = 'D=g'; //URL Attempted | |
| } | |
| if (s.linkType === 'o') { | |
| if (s.linkName == 'ajax error tracking') { | |
| var oData = _satellite.getVar('Ajax Error Data'); | |
| if (oData) { | |
| s.prop11 = oData.type; | |
| s.prop12 = oData.code; | |
| s.prop13 = 'D=pageName'; | |
| } | |
| //reset data | |
| _satellite.setVar('Ajax Error Data', ''); | |
| } | |
| } | |
| /* end Error Page Tracking */ | |
| /* App Error on Page */ | |
| (function(){ | |
| var warningAlertText = _satellite.getVar('DOM - Alert Text - Warning'), | |
| dangerAlertText = _satellite.getVar('DOM - Alert Text - Danger'); | |
| if (dangerAlertText || warningAlertText) { | |
| s.prop11 = 'on-page-alert'; | |
| s.prop12 = dangerAlertText?'on-page-alert (danger): '+dangerAlertText:'on-page-alert (warning): '+warningAlertText; | |
| s.prop13 = 'D=pageName'; | |
| } | |
| })(); | |
| /* end App Error on Page */ | |
| /* Legacy Internal Campaign Clicks */ | |
| //TODO: Deprecate after Target Late coming links tracking is fixed | |
| var sIntCmp = _satellite.getVar('Legacy Internal Campaign Clicked'); | |
| if (sIntCmp) { | |
| s.eVar2 = sIntCmp; //Internal Campaign Clicks (legacy) | |
| s.eVar2 = s.getValOnce(s.eVar2, 's_v2', 30); //Internal Campaign Clicks (legacy), deduped | |
| if (s.eVar2.length) { | |
| //_satellite.notify('KIWI: Legacy Internal Campaign Tracked: ' + sIntCmp); | |
| s.events = s.apl(s.events, 'event13', ',', 2); //Internal Campaign Clicks (legacy) | |
| //reset appdata, cookie after track | |
| //_satellite.setVar('Legacy Internal Campaign Clicked', ''); | |
| document.cookie = 'cb_intcmp=; expires=-1; path=/; domain=.collegeboard.org'; | |
| } | |
| } | |
| /* end Legacy Internal Campaign Clicks */ | |
| /* Promo/Nav Track Goals Setup */ | |
| kiwi._promoTrackGoals = kiwi._promoTrackGoals || ''; | |
| kiwi._navTrackGoals = kiwi._navTrackGoals || ''; | |
| //page load or click track via JS | |
| if (s.linkType) { | |
| //click track via JS - check link type | |
| if (s.linkType === 'o' && (s.linkName === 'Widget Display Change')) { | |
| //widget state change - collect promo views on widget | |
| kiwi._promoTrackGoals = 'views'; | |
| kiwi._navTrackGoals = 'both'; | |
| _satellite.notify('KIWI: Promo/Nav Track Goals //widget state change - collect promo views on widget'); | |
| } else { | |
| //check for nav/promo clicks | |
| if (s.linkType === 'e' || | |
| s.linkType === 'd' || | |
| (s.linkType === 'o' && (s.linkName === 'Dynamic Download Link' || | |
| s.linkName.match(/Promo Link/i) || | |
| s.linkName === 'Nav Link' || | |
| s.linkName === 'Site Search Link'))) { | |
| kiwi._promoTrackGoals = 'clicks'; | |
| kiwi._navTrackGoals = 'clicks'; | |
| if (s.linkName.match(/Promo Link/i)) kiwi._navTrackGoals = 'none'; | |
| if (s.linkName === 'Nav Link') kiwi._promoTrackGoals = 'none'; | |
| _satellite.notify('KIWI: Promo/Nav Track Goals //click track - link type: '+ s.linkType + ', '+ s.linkName); | |
| } | |
| } | |
| } else { | |
| //page load track - collect promo views on page (e.g. SSR but also BF First Level Tabs, also Modals as pages) | |
| kiwi.util.fireCustomEvent('Page View'); | |
| kiwi._promoTrackGoals = 'views'; | |
| kiwi._navTrackGoals = 'both'; | |
| _satellite.notify('KIWI: Promo/Nav Track Goals //page load track - collect promo views on page'); | |
| } | |
| if (s.linkName && (s.linkName === 'Widgets Ready' || | |
| s.linkName.match(/Feature Clicks - /i) || | |
| s.linkName.match(/Feature Used - /i))) { | |
| //widget state change or feature click | |
| kiwi._promoTrackGoals = ''; | |
| kiwi._navTrackGoals = ''; | |
| //_satellite.notify('KIWI: Promo/Nav Track Goals = NONE//atlas widget or feature clicks - track in a new way'); | |
| } | |
| /* end Promo/Nav Track Goals Setup */ | |
| /* Promo Views/Clicks */ | |
| if (kiwi._promoTrackGoals === 'clicks') { | |
| //_satellite.notify('KIWI: Promo Track Goals = clicks'); | |
| /* Promo Clicks */ | |
| var sPromoClicked2017 = _satellite.getVar('Promo - Clicked'), | |
| sPromoClicked2019 = _satellite.getVar('Promo - Clicked 2019'); | |
| if (sPromoClicked2017 || sPromoClicked2019) { | |
| //merge promos clicked | |
| //sPromoClicked = kiwi.util.mergeLists(sPromoClicked2017, sPromoClicked2019); | |
| //track 2017 promos | |
| if (sPromoClicked2017 && kiwi._thisPage.siteSettings.use2017promos) { | |
| s.list1 = sPromoClicked2017; //Promos (CTR) | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'list1', ',', 2); | |
| s.list2 = sPromoClicked2017; //Promos (Conv) | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'list2', ',', 2); | |
| s.events = s.apl(s.events, 'event99', ',', 2); //Promo Clicks | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event99', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events', ',', 2); | |
| } | |
| //track 2019 promos | |
| if (sPromoClicked2019) { | |
| s.list3 = sPromoClicked2019; //Promos (CTR) 2019 | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'list3', ',', 2); | |
| s.eVar18 = sPromoClicked2019; //Promos (Conv) 2019 | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'eVar18', ',', 2); | |
| s.events = s.apl(s.events, 'event57', ',', 2); //Promo Clicks 2019 | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event57', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events', ',', 2); | |
| } | |
| } | |
| _satellite.notify('KIWI: Promo 2017 Tracked: ' + sPromoClicked2017); | |
| _satellite.notify('KIWI: Promo 2019 Tracked: ' + sPromoClicked2019); | |
| var sPromoClickedTnT = _satellite.getVar('Promo - Clicked TnT'); | |
| if (sPromoClickedTnT) { | |
| //track tnt promos | |
| s.list3 = sPromoClickedTnT; //Promos (CTR) 2019 | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'list3', ',', 2); | |
| s.eVar18 = sPromoClickedTnT; //Promos (Conv) 2019 | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'eVar18', ',', 2); | |
| s.events = s.apl(s.events, 'event57', ',', 2); //Promo Clicks 2019 | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event57', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events', ',', 2); | |
| } | |
| _satellite.notify('KIWI: Promo TnT Tracked: ' + sPromoClickedTnT); | |
| /* SSS Opt-Ins/re-Opt-Ins */ | |
| var promoWasOptin = sPromoClicked2017.match(/widget-sssoptin:optin\|yes/i) || false, | |
| sEvent = '', | |
| sEventDedupeString = '', | |
| sEventFriendlyName = ''; | |
| if (promoWasOptin) { | |
| sEvent = 'event59'; | |
| sEventFriendlyName = 'SSS Opt Ins'; | |
| } else { | |
| promoWasOptin = sPromoClicked2017.match(/widget-sssoptin:reoptin\|yes/i) || false; | |
| if (promoWasOptin) { | |
| sEvent = 'event196'; | |
| sEventFriendlyName = 'SSS re-Opt Ins'; | |
| } | |
| } | |
| if (promoWasOptin) { | |
| sEventDedupeString = sEvent + ':' + kiwi.cookie.sess.user.cbId; | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, sEvent, ',', 2); | |
| s.events = s.apl(s.events, sEventDedupeString, ',', 2); //SSS Opt-Ins, SSS re-Opt-Ins | |
| _satellite.notify('KIWI: Custom Event Tracked: ' + sEventFriendlyName + ': ' + sEventDedupeString); | |
| } | |
| /* endSSS Opt-Ins/re-Opt-Ins */ | |
| /* end Promo Clicks */ | |
| } else if (kiwi._promoTrackGoals === 'views') { | |
| _satellite.notify('KIWI: Promo Track Goals = views'); | |
| /* Promo Views */ | |
| var sPromoViews2017 = _satellite.getVar('Promo - Views'), | |
| sPromoViews2019 = _satellite.getVar('Promo - Views 2019'), | |
| sTntPromoViews = _satellite.getVar('Promo - Views TnT'); | |
| if (sPromoViews2017 || sPromoViews2019) { | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events,list1,list3', ',', 2); | |
| s.linkTrackEvents = s.apl(s.linkTrackEvents, 'event98,event12,event56', ',', 2); | |
| //merge promo views lists | |
| //sPromoViews = kiwi.util.mergeLists(sPromoViews2017, sPromoViews2019); | |
| //track 2017 promos | |
| if (sPromoViews2017 && kiwi._thisPage.siteSettings.use2017promos) { | |
| var arrPromoViews2017 = sPromoViews2017.split(','); | |
| for (var iPv17 = 0; iPv17 < arrPromoViews2017.length; iPv17++) { | |
| s.list1 = s.apl(s.list1, arrPromoViews2017[iPv17], ',', 2); //Promos (CTR) | |
| } | |
| s.events = s.apl(s.events, 'event98', ',', 2); //Promo Views | |
| s.events = s.apl(s.events, 'event12', ',', 2); //Internal Campaign Views (legacy) | |
| } | |
| //track 2019 promos | |
| if (sPromoViews2019) { | |
| var arrPromoViews2019 = sPromoViews2019.split(','); | |
| for (var iPv19 = 0; iPv19 < arrPromoViews2019.length; iPv19++) { | |
| s.list3 = s.apl(s.list3, arrPromoViews2019[iPv19], ',', 2); //Promos (CTR) 2019 | |
| } | |
| s.events = s.apl(s.events, 'event56', ',', 2); //Promo Views 2019 | |
| } | |
| } | |
| if (sTntPromoViews) { | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events,list3', ',', 2); | |
| s.linkTrackEvents = s.apl(s.linkTrackEvents, 'event56', ',', 2); | |
| //track tnt promos | |
| if (sTntPromoViews) { | |
| var arrTnTPromoViews = sTntPromoViews.split(','); | |
| for (var iPvTnt = 0; iPvTnt < arrTnTPromoViews.length; iPvTnt++) { | |
| s.list3 = s.apl(s.list3, arrTnTPromoViews[iPvTnt], ',', 2); //Promos (CTR) 2019 | |
| } | |
| s.events = s.apl(s.events, 'event56', ',', 2); //Promo Views 2019 | |
| } | |
| } | |
| /* end Promo Views */ | |
| } | |
| /* end Promo Views/Clicks */ | |
| /* Nav Views/Clicks */ | |
| /* Global Nav Clicks - legacy method */ | |
| s.prop49 = _satellite.getVar('Global Nav ID'); | |
| s.prop49 = s.getValOnce(s.prop49, 'gvo_c49', 0); //Global Nav ID | |
| if (s.prop49) { | |
| s.events = s.apl(s.events, 'event70', ',', 2); //Global Nav Clicks | |
| } | |
| /* end Global Nav Clicks */ | |
| if (kiwi._navTrackGoals === 'both' || kiwi._navTrackGoals === 'views') { | |
| _satellite.notify('KIWI: Nav Track Goals = both/views'); | |
| /* Nav Views */ | |
| var sNavViewEvents = _satellite.getVar('Nav - Views'); | |
| if (sNavViewEvents) { | |
| //for CTR Tracking: | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, sNavViewEvents, ',', 2); | |
| s.events = s.apl(s.events, sNavViewEvents, ',', 2); //[xyz] Nav Views | |
| } | |
| /* end Nav Views */ | |
| } | |
| if (kiwi._navTrackGoals === 'both' || kiwi._navTrackGoals === 'clicks') { | |
| _satellite.notify('KIWI: Nav Track Goals = both/clicks'); | |
| /* Nav Clicks */ | |
| if (kiwi._skipTrackNav) kiwi._skipTrackNav = false; | |
| else { | |
| var sNavClicked = _satellite.getVar('Nav - Clicked'); | |
| if (sNavClicked) { | |
| var sArrNavClicked = sNavClicked.split('|'), | |
| oNav = { //e.g. event221|global|gh|Skip to content|#main-content, event229|local|program-band|Major & Career Search | |
| clickEvent: sArrNavClicked[0] || '', | |
| type: sArrNavClicked[1], | |
| key: sArrNavClicked[2], | |
| subNav: sArrNavClicked[3] || '', | |
| text: sArrNavClicked[4] || '', | |
| hash: sArrNavClicked[5] || '' | |
| }, | |
| sNavTracked = oNav.key + ':' + oNav.subNav+ ':' + oNav.text; | |
| sNavTracked = oNav.hash?'nav-toggle:' + sNavTracked:'nav-click:' + sNavTracked; | |
| if (oNav.hash) { | |
| 'nav-toggle:' + sNavTracked; | |
| } | |
| s.prop43 = sNavTracked; | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop43,', ',', 2); | |
| if (oNav.clickEvent) { | |
| s.events = s.apl(s.events, oNav.clickEvent, ',', 2); //[xyz] Nav Clicks | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, oNav.clickEvent, ',', 2); | |
| switch (oNav.type) { | |
| case 'global': | |
| s.events = s.apl(s.events, 'event70', ',', 2); //Global Nav Clicks | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event70', ',', 2); | |
| break; | |
| case 'local': | |
| s.events = s.apl(s.events, 'event95', ',', 2); //Local Nav Clicks | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event95', ',', 2); | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| //Reset Vars after track | |
| document.cookie = 'cbtrack_nav=; expires=-1; path=/; domain=.collegeboard.org'; | |
| if (cbTrackData.localNavItemClicked) {//from SSR | |
| _satellite.notify('KIWI: cbTrackData.localNavItemClicked = ' + cbTrackData.localNavItemClicked); | |
| cbTrackData.localNavItemClicked = ''; | |
| } | |
| _satellite.notify('KIWI: Nav Tracked: ' + sNavClicked); | |
| } | |
| } | |
| /* end Nav Clicks */ | |
| } | |
| /* end Nav Views/Clicks */ | |
| /* College Lists */ | |
| // College List Starts/Saves | |
| (function(oData, deduper){ | |
| if (oData && oData.hasData) { | |
| // - Set on Page Track in BF React | |
| _satellite.notify('KIWI: College List Data found!: ' + JSON.stringify(oData)); | |
| s.events = s.apl(s.events, 'event190:' + deduper, ',', 2); //College List Saves, Deduped | |
| if (oData.rmsListStarted) { | |
| s.events = s.apl(s.events, 'event202:' + deduper, ',', 2); //RMS College List Started, Deduped | |
| } | |
| if (oData.rmsListFulfilled) { | |
| s.events = s.apl(s.events, 'event203:' + deduper, ',', 2); //RMS College List Fullfilled, Deduped | |
| } | |
| } | |
| })(_satellite.getVar('Data - College List'), kiwi.user.cbId); //oData, deduper | |
| //College List Adds | |
| (function(oData, deduper){ | |
| // - Set on Link Track (DCR) in BF React | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: College Added!: ' + JSON.stringify(oData)); | |
| //first derive legacy isFirstCollege | |
| if (oData.addSource.match(/^(BF GWT|BF Mobile)$/i)) { | |
| var sCollegeListCreated='true'; | |
| sCollegeListCreated=s.getValOnce(sCollegeListCreated,'s_collegeListCreated', 99999); | |
| if(sCollegeListCreated) { | |
| oData.isFirstCollege = true; | |
| } | |
| } | |
| s.events = s.apl(s.events, 'event66', ',', 2); //College List Adds | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event66', ',', 2); | |
| s.eVar60 = oData.addMethod; | |
| s.eVar11 = oData.collegeAdded; | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'eVar60', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'eVar11', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| if (oData.isFirstCollege) { | |
| _satellite.notify('KIWI: New College List!: ' + JSON.stringify(oData)); | |
| s.events = s.apl(s.events, 'event67', ',', 2); //College Lists Created (legacy metric, not deduped) | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event67', ',', 2); | |
| if (deduper) { | |
| s.events = s.apl(s.events, 'event190:' + deduper, ',', 2); //College List Saves, Deduped | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event190', ',', 2); | |
| kiwi.util.fireCustomEvent('College List Saved'); | |
| if (oData.isRmsCollege) { | |
| s.events = s.apl(s.events, 'event202:' + deduper, ',', 2); //RMS College List Started, Deduped | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event202', ',', 2); | |
| } | |
| } | |
| } | |
| } else { | |
| //Abort Link Track if no Data to Capture | |
| if (s.linkType === 'o' && s.linkName === 'College Add') { | |
| _satellite.notify('College Add Link Track: No data to capture, aborting tracking call.') | |
| s.abort = true; | |
| } | |
| } | |
| })(_satellite.getVar('Data - College List Add'), kiwi.user.cbId); //oData, deduper | |
| //RMS Score Changes | |
| (function(oData){ | |
| // - Set on Link Track (DCR) in BF React | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: RMS Score Changed!: ' + JSON.stringify(oData)); | |
| s.events = s.apl(s.events, 'event204', ',', 2); //RMS Score Changes | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event204', ',', 2); | |
| s.eVar6 = oData.scoreType; | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'eVar6', ',', 2); | |
| } else { | |
| if (s.linkType === 'o' && s.linkName === 'RMS Score Change') { | |
| s.abort = true; | |
| } | |
| } | |
| })(_satellite.getVar('Data - RMS Score Change')); //oData | |
| /* end College Lists */ | |
| /* CB Opportunity Scholarships Events */ | |
| //many of these are also set on Link Track (DCR) but deduped through serialization | |
| (function(oData){ | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: CBOS Events Data Found: ' + JSON.stringify(oData)); | |
| var serializeVal = kiwi.user.cbId+'-'+kiwi.user.gradYear; | |
| //"Build" | |
| if (oData.build) s.events = s.apl(s.events, 'event136:'+serializeVal, ',', 2); //CBOS Students - Build College List | |
| //"Practice" | |
| if (oData.practice) s.events = s.apl(s.events, 'event137:'+serializeVal, ',', 2); //CBOS Students - Practice SAT | |
| //"Improve" | |
| if (oData.improve) s.events = s.apl(s.events, 'event138:'+serializeVal, ',', 2); //CBOS Students - Improve Score | |
| //"Strengthen" | |
| if (oData.strengthen) s.events = s.apl(s.events, 'event139:'+serializeVal, ',', 2); //CBOS Students - Strengthen List | |
| //"Complete" | |
| if (oData.complete) s.events = s.apl(s.events, 'event132:'+serializeVal, ',', 2); //CBOS Students - Complete FAFSA | |
| //"Apply" | |
| if (oData.apply) s.events = s.apl(s.events, 'event133:'+serializeVal, ',', 2); //CBOS Students - Apply to Colleges | |
| //"Complete Your Journey" | |
| if (oData.cyj) s.events = s.apl(s.events, 'event135:'+serializeVal, ',', 2); //CBOS Students - Complete Journey | |
| } | |
| })(_satellite.getVar('Data - CBOS')); //oData | |
| /* end CB Opportunity Scholarships Events */ | |
| /* Score View Tracking */ | |
| (function(oData){ | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: Data - Score View found: ' + JSON.stringify(oData)); | |
| if (oData.sat.adminCode) { | |
| s.eVar51 = oData.sat.adminType + '-' + oData.sat.adminCode; //SAT Score View Admin | |
| s.eVar51 = s.eVar51.toLowerCase(); | |
| var satSVEventDedupeKey = oData.sat.adminRegId; | |
| satSVEventDedupeKey = satSVEventDedupeKey.toUpperCase(); //set it this way to match NSAT | |
| var satSVEvent = 'event24:' + satSVEventDedupeKey; | |
| s.events = s.apl(s.events, satSVEvent, ',', 2); //SAT Score Views | |
| var satSVEventDedupeKey2 = kiwi.user.cbId + '-' + s.eVar51; | |
| satSVEventDedupeKey2 = satSVEventDedupeKey2.toLowerCase(); | |
| s.events = s.apl(s.events, 'event116:'+satSVEventDedupeKey2, ',', 2); //SAT Multiple Choice Score Views | |
| if (s.pageName.match(/^ssr:score-(report|overview):/i)) { //score report page only | |
| s.events = s.apl(s.events, 'event118:' + satSVEventDedupeKey2, ',', 2); //SAT Score Report Views | |
| } | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'eVar51', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event24', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event116', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event118', ',', 2); | |
| if (kiwi._thisPage.siteCode === 'ssr' && kiwi._thisPage.pageCode.match(/^dashboard/i)) { //dashboard page only | |
| kiwi.util.fireCustomEvent( | |
| 'SAT Score Viewed', { | |
| adminType: oData.sat.adminType, | |
| adminDate: oData.sat.adminCode, | |
| registrantType: oData.sat.registrantType, | |
| fwStatus: oData.sat.fwStatus, | |
| scoreBand: oData.sat.scoreBand | |
| }); | |
| } | |
| } | |
| if (oData.psat.adminCode) { | |
| s.eVar72 = oData.psat.adminType + '-' + oData.psat.adminCode; //PSAT Score View Admin | |
| s.eVar72 = s.eVar72.toLowerCase(); | |
| var psatSVEventDedupeKey = kiwi.user.cbId + '-' + s.eVar72; | |
| var psatSVEvent = 'event88:' + psatSVEventDedupeKey; | |
| s.events = s.apl(s.events, psatSVEvent, ',', 2); //PSAT Score Views | |
| if (s.pageName.match(/^ssr:score-(report|overview):/i)) { //score report page only | |
| s.events = s.apl(s.events, 'event119:'+psatSVEventDedupeKey, ',', 2); //PSAT Score Report Views | |
| } | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'eVar72', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event88', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event119', ',', 2); | |
| if (kiwi._thisPage.siteCode === 'ssr' && kiwi._thisPage.pageCode.match(/^dashboard/i)) { //dashboard page only | |
| kiwi.util.fireCustomEvent( | |
| 'PSAT Score Viewed', { | |
| adminType: oData.psat.adminType, | |
| adminDate: oData.psat.adminCode, | |
| registrantType: oData.psat.registrantType, | |
| fwStatus: oData.psat.fwStatus, | |
| scoreBand: oData.psat.scoreBand | |
| }); | |
| } | |
| } | |
| if (kiwi._thisPage.siteCode === 'ssr' && kiwi._thisPage.pageCode.match(/dashboard/i)) { //dashboard pages only | |
| s.eVar64 = _satellite.getVar('AppData Score Status'); | |
| } | |
| } else { | |
| if (s.prop32 === 'ssr' && cbTrackData.pageCode && cbTrackData.pageCode.match(/sat-essays:/i)) {//TODO: get SAT Essay score view reporing working via DDL instead of in this brittle way | |
| if (!s.prop12 || (s.prop12 && !(s.prop12.match(/on-page-alert (warning): Your SAT Essay scores/i)))) { | |
| var arrPageCode = cbTrackData.pageCode.split(':'); | |
| s.eVar51 = arrPageCode[1] + '-' + arrPageCode[2]; //SAT Score View Admin | |
| s.eVar51 = s.eVar51.toLowerCase(); | |
| var satSVEventDedupeKey3 = kiwi.user.cbId + '-' + s.eVar51; | |
| satSVEventDedupeKey3 = satSVEventDedupeKey3.toLowerCase(); | |
| s.events = s.apl(s.events, 'event58:'+satSVEventDedupeKey3, ',', 2); //SAT Essay Score Views | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'eVar51,events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event58', ',', 2); | |
| } | |
| } | |
| } | |
| //Mark DDL as tracked! | |
| kiwi.ddl.aaTracked.scoreView = true; | |
| })(_satellite.getVar('Data - Score View')); | |
| /* end Score View Tracking */ | |
| /* Features Used - Legacy Method */ | |
| (function(sFeatureUsed){ | |
| _satellite.notify('KIWI: Feature Used found: ' + sFeatureUsed); | |
| if (sFeatureUsed) { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop43', ',', 2); | |
| s.prop43 = s.apl(s.prop43, sFeatureUsed, '^', 2); //Features Used | |
| if (kiwi._timesThruDoPlugins) { | |
| //clear out page-tracked feature used... | |
| if (cbTrackData.featureUsed) cbTrackData.featureUsed = ''; | |
| if (cbTrackData.user && cbTrackData.user.featureUsed) cbTrackData.user.featureUsed = ''; //legacy DDL settings by BF Mobile | |
| var ddlEvents = _satellite.getVar('DDL Events'); | |
| if (ddlEvents && ddlEvents.length) { | |
| var deleteIdx = 0; | |
| for (var i = 1; i < ddlEvents.length + 1; i++) { | |
| var e = ddlEvents[i-1]; | |
| if ( | |
| typeof e.eventInfo !== 'undefined' | |
| && typeof e.eventInfo.eventName !== 'undefined' | |
| && e.eventInfo.eventName == 'Feature Used' | |
| ) { | |
| deleteIdx = i-1; | |
| break; | |
| } | |
| } | |
| ddlEvents[deleteIdx] = {}; | |
| } | |
| } | |
| } | |
| })(_satellite.getVar('Feature Used')); | |
| /* end Features Used - Legacy Method */ | |
| /* Feature Views */ | |
| kiwi.trackFeatureViews = function(featData, featId) { | |
| ruleName = 'KIWI: kiwi.trackFeatureViews'; | |
| //var featData = _satellite.getVar(featDataName); | |
| if (featData && featData.hasData) { | |
| _satellite.notify(ruleName + ': ' + featId + ' found: ' + JSON.stringify(featData)); | |
| kiwi.cookie.sess.features[featId] = kiwi.cookie.sess.features[featId] || {}; | |
| for (var i = 0; i < featData.featureNames.length; i++) { | |
| var featureName = featData.featureNames[i], | |
| bAlreadyInSess = (kiwi.cookie.sess.features[featId][kiwi._thisPage.siteCode] && | |
| kiwi.cookie.sess.features[featId][kiwi._thisPage.siteCode].hasOwnProperty(featureName)); | |
| //report these things only once per session cookie + featureName instance | |
| if(!bAlreadyInSess && !featData.wireUpOnly) { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'eVar34', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop43', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event242', ',', 2); | |
| s.eVar34 = 'D=pageName'; //Feature Page | |
| s.prop43 = s.apl(s.prop43, featData.featureType + ':' + featureName, '^', 2); //Features Used | |
| s.events = s.apl(s.events, 'event242', ',', 2); //Feature Views | |
| switch (featId) { | |
| case 'filters': | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event240', ',', 2); | |
| s.events = s.apl(s.events, 'event240', ',', 2); //Filter Views | |
| break; | |
| default: | |
| break; | |
| } | |
| kiwi._sessCookieMod = true; | |
| kiwi.cookie.sess.features[featId][kiwi._thisPage.siteCode] = kiwi.cookie.sess.features[featId][kiwi._thisPage.siteCode] || {}; | |
| kiwi.cookie.sess.features[featId][kiwi._thisPage.siteCode][featureName] = 0; | |
| } | |
| //report these things regardless of featureName instance | |
| switch (featId) { | |
| /*case 'lnavtop': | |
| //s.linkTrackVars=s.apl(s.linkTrackEvents, 'event220', ',', 2); | |
| //s.events = s.apl(s.events, 'event220', ',', 2); //Global Header Nav Views | |
| break;*/ | |
| case 'widget': | |
| switch (featureName) { | |
| case 'header': | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event220', ',', 2); | |
| s.events = s.apl(s.events, 'event220', ',', 2); //Global Header Nav Views | |
| break; | |
| case 'footer': | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event222', ',', 2); | |
| s.events = s.apl(s.events, 'event222', ',', 2); //Global Footer Nav Views | |
| break; | |
| case 'identity': | |
| if (kiwi.userIsLoggedIn) { | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event232', ',', 2); | |
| s.events = s.apl(s.events, 'event232', ',', 2); //Global Login Nav Views | |
| } else { | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event230', ',', 2); | |
| s.events = s.apl(s.events, 'event230', ',', 2); //Global Student/Prof Nav Views | |
| } | |
| break; | |
| case 'bfcl': | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'prop34', ',', 2); | |
| s.prop34 = 'bfcl:bar'; //Widget Screen | |
| break; | |
| default: | |
| break; | |
| } | |
| break; | |
| default: | |
| break; | |
| } | |
| //indicate auto-sugg term results in DOM | |
| if (kiwi.cookie.sess.prev['isQuick']) { | |
| var elSS = document.querySelector('[data-cbtrack-widget="sitesearch"], .lv-search-widget'); | |
| if (elSS) {elSS.setAttribute('data-cbtrack-autosuggtermused','');} | |
| } | |
| //check for site search promo views | |
| var ssBannerViews = [], | |
| bannerAreas = document.querySelectorAll('[data-cbtrack-searchbanner], #sitesearch .lv-banner, #sitesearch .lv-no-results'); | |
| for (var m = 0; m < bannerAreas.length; m++) { | |
| var oPromoPrefixMap = {'trustee_search':'feat','related_search':'rel','noresults':'noresults'}, | |
| myBanner = bannerAreas[m], | |
| myBannerType = myBanner.getAttribute('data-cbtrack-searchbanner') || '', | |
| myBannerArea = myBannerType?oPromoPrefixMap[myBannerType]:''; | |
| if (!myBannerArea) {//legacy site search widget banner elements | |
| myBannerArea = myBanner.classList.contains('lv-banner-type-related_search')?'rel':myBannerArea; | |
| myBannerArea = myBanner.classList.contains('lv-banner-type-trustee_search')?'feat':myBannerArea; | |
| myBannerArea = myBanner.classList.contains('lv-no-results')?'noresults':myBannerArea; | |
| } | |
| var myBannerEls = myBanner.querySelectorAll('a'); | |
| for (var n = 0; n < myBannerEls.length; n++) { | |
| var bannerPromoView = 'ss:'+myBannerArea+':', | |
| myBannerEl = myBannerEls[n], | |
| myBannerViewAlreadyTracked = (!!myBannerEl.hasAttribute('data-kiwi-promo-view')), | |
| myBannerLinkAlreadyTracked = (!!myBannerEl.hasAttribute('data-kiwi-promo-link')); | |
| //track view | |
| if (!myBannerViewAlreadyTracked) { | |
| bannerPromoView += myBannerEl.getAttribute('data-cbtrack-label') || kiwi.util.getFeatureText(myBannerEl); | |
| ssBannerViews.push(bannerPromoView); | |
| myBannerEl.setAttribute('data-kiwi-promo-view', ''); | |
| } | |
| //track link | |
| if (!myBannerLinkAlreadyTracked) { | |
| _satellite.notify(ruleName+': wiring up site search promo/banner links'); | |
| var alreadyWired = false; | |
| if ((myBannerEl.hasAttribute('data-kiwi-sspromo-link'))) {alreadyWired = true;} | |
| if (!alreadyWired) {myBannerEl.setAttribute('data-kiwi-sspromo-link', bannerPromoView);} | |
| //prevent tracking by legacy promo 2019 code | |
| myBannerEl.setAttribute('data-kiwi-promo-link', ''); | |
| myBannerEl.removeAttribute('data-cb-adcode', ''); | |
| myBannerEl.removeAttribute('trackclickvalue', ''); | |
| } | |
| } | |
| } | |
| if (ssBannerViews.length) { | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event56', ',', 2); | |
| s.events = s.apl(s.events, 'event56', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'list3', ',', 2); | |
| for (var ssb = 0; ssb < ssBannerViews.length; ssb++) { | |
| s.list3 = s.apl(s.list3, ssBannerViews[ssb], ',', 2); //Promos (CTR) 2019 | |
| } | |
| } | |
| //check for other promo views | |
| var promoViews = [], | |
| els = {}, | |
| promoViewPrefix = ''; | |
| //Widget Screen Els vs. Other Feature Els | |
| if (featData.widgetName) { | |
| promoViewPrefix = 'widget:'+ featData.widgetName + ':' + featureName + ':'; | |
| els = document.querySelectorAll('[data-cbtrack-widget="'+featData.widgetName+'"] [data-cbtrack-linkgroup="'+featureName+'"]'); | |
| } else { | |
| promoViewPrefix = kiwi._thisPage.siteCode + ':' + featData.featureType + ':' + featureName + ':'; | |
| els = document.querySelectorAll('[data-cbtrack-'+ featId +'="'+featureName+'"]'); | |
| } | |
| for (var j = 0; j < els.length; j++) { | |
| var promoEls = els[j].querySelectorAll('[data-cbtrack-promo], [data-cbtrack-linktype*="promo"]'); | |
| for (var k = 0; k < promoEls.length; k++) { | |
| function isHidden(el) { | |
| var isHidden = false, | |
| style = window.getComputedStyle(el); | |
| isHidden = ((style.display === 'none') || (style.visibility === 'hidden')); | |
| if (!isHidden && kiwi.util.getClosest) { | |
| isHidden = !!(kiwi.util.getClosest(el, '[aria-hidden="true"]')); | |
| } | |
| return isHidden; | |
| } | |
| if (!isHidden(promoEls[k])) { | |
| var promoView = promoViewPrefix; | |
| promoView += kiwi.util.getFeatureText(promoEls[k]); | |
| promoViews.push(promoView); | |
| //prevent tracking by promo 2019 code | |
| promoEls[k].setAttribute('data-kiwi-promo-link', ''); | |
| if (featData.widgetScreenName) {promoEls[k].setAttribute('data-kiwi-widgetscreenname', featData.widgetScreenName);} | |
| } | |
| } | |
| } | |
| if (promoViews.length) { | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event56', ',', 2); | |
| if (kiwi._thisPage.siteSettings.use2017promos) { | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event98', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event12', ',', 2); | |
| s.events = s.apl(s.events, 'event98', ',', 2); | |
| s.events = s.apl(s.events, 'event12', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'list1', ',', 2); | |
| } | |
| s.events = s.apl(s.events, 'event56', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'list3', ',', 2); | |
| for (var iPv = 0; iPv < promoViews.length; iPv++) { | |
| if (kiwi._thisPage.siteSettings.use2017promos) { | |
| s.list1 = s.apl(s.list1, promoViews[iPv], ',', 2); //Promos (CTR) | |
| } | |
| s.list3 = s.apl(s.list3, promoViews[iPv], ',', 2); //Promos (CTR) 2019 | |
| } | |
| } | |
| } | |
| } | |
| }; | |
| if (!cbTrackData || !cbTrackData.siteCode || cbTrackData.siteCode !== 'bfm') { | |
| kiwi.trackFeatureViews(_satellite.getVar('Feature Views - Accordions'), 'accordion'); | |
| kiwi.trackFeatureViews(_satellite.getVar('Feature Views - Crosslinks'), 'crosslink'); | |
| kiwi.trackFeatureViews(_satellite.getVar('Feature Views - CTA Cards'), 'ctacard'); | |
| kiwi.trackFeatureViews(_satellite.getVar('Feature Views - Event Cards'), 'ec'); | |
| kiwi.trackFeatureViews(_satellite.getVar('Feature Views - Filters'), 'filter'); | |
| kiwi.trackFeatureViews(_satellite.getVar('Feature Views - Jump Links'), 'jumplinks'); | |
| kiwi.trackFeatureViews(_satellite.getVar('Feature Views - Key Benefits'), 'keybenefits'); | |
| kiwi.trackFeatureViews(_satellite.getVar('Feature Views - Layout Panels'), 'layp'); | |
| //kiwi.trackFeatureViews(_satellite.getVar('Feature Views - Local Nav Top'), 'lnavtop'); | |
| kiwi.trackFeatureViews(_satellite.getVar('Feature Views - Custom'), 'custom'); | |
| kiwi.trackFeatureViews(_satellite.getVar('Feature Views - Features'), 'feature'); | |
| } | |
| if (kiwi.widgetTrack) kiwi.trackFeatureViews(_satellite.getVar('Feature Views - Widgets'), 'widget'); | |
| /* end Feature Views */ | |
| /* Feature Clicks */ | |
| kiwi.trackFeatureClicks = function(featData, featId) { | |
| ruleName = 'KIWI: kiwi.trackFeatureClicks'; | |
| //var featData = _satellite.getVar(featDataName); | |
| if (featData && featData.hasData) { | |
| _satellite.notify(ruleName + ': ' + featId + ' found: ' + JSON.stringify(featData)); | |
| s.eVar34 = 'D=c25'; //Feature Page | |
| s.prop43 = featData.featureType + ':' + featData.featureName; //Features Used | |
| s.prop29 = featData.featureOptions; //Feature Options Used | |
| var usageCount = 0; | |
| try {usageCount = kiwi.cookie.sess.features[featId][kiwi._thisPage.siteCode][featData.featureName];} | |
| catch(e) {_satellite.notify('Kiwi: ' + featId + ' cookie issue for Usage Count');} | |
| if (parseInt(usageCount, 10)) { | |
| //track additional usage as additional views, to keep CTR in good shape | |
| s.events = s.apl(s.events, 'event242', ',', 2); //Feature Views | |
| switch (featId) { | |
| case 'filter': | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event240', ',', 2); | |
| s.events = s.apl(s.events, 'event240', ',', 2); //Filter Views | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| usageCount += 1; | |
| s.events = s.apl(s.events, 'event243', ',', 2); //Feature Clicks | |
| s.prop30 = usageCount; //Feature Used Count | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'eVar34', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop43', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop29', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop30', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event242', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event243', ',', 2); | |
| kiwi._sessCookieMod = true; | |
| kiwi.cookie.sess.features[featId][kiwi._thisPage.siteCode] = kiwi.cookie.sess.features[featId][kiwi._thisPage.siteCode] || {}; | |
| kiwi.cookie.sess.features[featId][kiwi._thisPage.siteCode][featData.featureName] = usageCount; | |
| //track additional things by feature type | |
| switch (featId) { | |
| case 'filter': | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event241', ',', 2); | |
| s.events = s.apl(s.events, 'event241', ',', 2); //Filter Applies | |
| break; | |
| case 'widget': | |
| //check for widgetScreen | |
| if (featData.widgetScreenName) { | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'prop34', ',', 2); | |
| s.prop34 = featData.widgetScreenName; //Widget Screen | |
| } | |
| break; | |
| default: | |
| break; | |
| } | |
| //check for nav clicks | |
| if (featData.linkTypes.match(/(^|,)nav(,|$)/i)) { | |
| switch (featData.featureName) { | |
| case 'header': | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event221', ',', 2); | |
| s.events = s.apl(s.events, 'event221', ',', 2); //Global Header Nav Clicks | |
| s.eVar61 = kiwi._thisPage.siteCode + ':' + featData.featureOptions; | |
| s.eVar61 = s.getValOnce(s.eVar61, 'gvo_v61', 0); //Global Nav ID 2019 | |
| if (s.eVar61) { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'eVar61', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event70', ',', 2); | |
| s.events = s.apl(s.events, 'event70', ',', 2); //Global Nav Clicks | |
| } | |
| break; | |
| case 'footer': | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event223', ',', 2); | |
| s.events = s.apl(s.events, 'event223', ',', 2); //Global Footer Nav Clicks | |
| s.eVar61 = kiwi._thisPage.siteCode + ':' + featData.featureOptions; | |
| s.eVar61 = s.getValOnce(s.eVar61, 'gvo_v61', 0); //Global Nav ID 2019 | |
| if (s.eVar61) { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'eVar61', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event70', ',', 2); | |
| s.events = s.apl(s.events, 'event70', ',', 2); //Global Nav Clicks | |
| } | |
| break; | |
| case 'identity': | |
| if (kiwi.userIsLoggedIn) { | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event233', ',', 2); | |
| s.events = s.apl(s.events, 'event233', ',', 2); //Student/Prof Nav Clicks | |
| s.eVar61 = kiwi._thisPage.siteCode + ':' + featData.featureOptions; | |
| s.eVar61 = s.getValOnce(s.eVar61, 'gvo_v61', 0); //Global Nav ID 2019 | |
| if (s.eVar61) { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'eVar61', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event70', ',', 2); | |
| s.events = s.apl(s.events, 'event70', ',', 2); //Global Nav Clicks | |
| } | |
| } else { | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event231', ',', 2); | |
| s.events = s.apl(s.events, 'event231', ',', 2); //Identity Pre-Auth Clicks | |
| s.eVar61 = kiwi._thisPage.siteCode + ':' + featData.featureOptions; | |
| s.eVar61 = s.getValOnce(s.eVar61, 'gvo_v61', 0); //Global Nav ID 2019 | |
| if (s.eVar61) { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'eVar61', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event70', ',', 2); | |
| s.events = s.apl(s.events, 'event70', ',', 2); //Global Nav Clicks | |
| } | |
| } | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| var promoName = '', | |
| blnTrack2017 = blnTrack2019 = true; | |
| //check for sspromo clicks | |
| if (featData.ssPromoName) { | |
| promoName = featData.ssPromoName; | |
| blnTrack2017 = false; | |
| } else if (featData.linkTypes.match(/(^|,)promo(,|$)/i)) { | |
| //check for other promo clicks | |
| if (featId==='widget') { | |
| promoName = featData.featureType + ':' + featData.featureName + ':' + featData.featureOptions; | |
| } else { | |
| promoName = kiwi._thisPage.siteCode + ':' + featData.featureType + ':' + featData.featureName + ':' + featData.featureOptions; | |
| } | |
| } | |
| //track promo clicks | |
| if (promoName) { | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events', ',', 2); | |
| if (blnTrack2017 && kiwi._thisPage.siteSettings.use2017promos) { | |
| s.events=s.apl(s.events, 'event99', ',', 2); //Promo Clicks | |
| s.list1 = promoName; //Promos (CTR) | |
| s.list2 = promoName; //Promos (Conv) | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event99', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'list1', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'list2', ',', 2); | |
| _satellite.notify('KIWI: Promo 2017 Tracked: ' + promoName); | |
| } | |
| if (blnTrack2019) { | |
| s.events=s.apl(s.events, 'event57', ',', 2); //Promo Clicks 2019 | |
| s.list3 = promoName; //Promos (CTR) 2019 | |
| s.eVar18 = promoName; //Promos (Conv) 2019 | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event57', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'list3', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'eVar18', ',', 2); | |
| _satellite.notify('KIWI: Promo 2019 Tracked: ' + promoName); | |
| } | |
| } | |
| } | |
| }; | |
| if (s.linkType === 'o') { | |
| if (s.linkName === 'Feature Used - Accordion') kiwi.trackFeatureClicks(_satellite.getVar('Feature Clicks - Accordion'), 'accordion'); | |
| if (s.linkName === 'Feature Used - Crosslink') kiwi.trackFeatureClicks(_satellite.getVar('Feature Clicks - Crosslink'), 'crosslink'); | |
| if (s.linkName === 'Feature Used - CTA Card') kiwi.trackFeatureClicks(_satellite.getVar('Feature Clicks - CTA Card'), 'ctacard'); | |
| if (s.linkName === 'Feature Used - Event Card') kiwi.trackFeatureClicks(_satellite.getVar('Feature Clicks - Event Card'), 'ec'); | |
| if (s.linkName === 'Feature Used - Filter') kiwi.trackFeatureClicks(_satellite.getVar('Feature Clicks - Filter'), 'filter'); | |
| if (s.linkName === 'Feature Used - Jump Link') kiwi.trackFeatureClicks(_satellite.getVar('Feature Clicks - Jump Link'), 'jumplinks'); | |
| if (s.linkName === 'Feature Used - Key Benefit') kiwi.trackFeatureClicks(_satellite.getVar('Feature Clicks - Key Benefits'), 'keybenefits'); | |
| if (s.linkName === 'Feature Used - Layout Panel') kiwi.trackFeatureClicks(_satellite.getVar('Feature Clicks - Layout Panel'), 'layp'); | |
| //if (s.linkName === 'Feature Used - Local Nav Top') kiwi.trackFeatureClicks(_satellite.getVar('Feature Clicks - Local Nav Top'), 'lnavtop'); | |
| if (s.linkName === 'Feature Used - Widget') kiwi.trackFeatureClicks(_satellite.getVar('Feature Clicks - Widget'), 'widget'); | |
| if (s.linkName === 'Feature Used - Custom') kiwi.trackFeatureClicks(_satellite.getVar('Feature Clicks - Custom'), 'custom'); | |
| if (s.linkName === 'Feature Used - Feature') kiwi.trackFeatureClicks(_satellite.getVar('Feature Clicks - Feature'), 'feature'); | |
| } | |
| /* end Feature Clicks */ | |
| /* Atlas Widgets */ | |
| kiwi.trackWidgetScreenView = function(widgetName, widgetScreenName, blnTrackFeatureViews) { | |
| ruleName = 'kiwi.trackWidgetScreenView'; | |
| widgetName = widgetName || ''; | |
| widgetScreenName = widgetScreenName || ''; | |
| blnTrackFeatureViews = blnTrackFeatureViews || true; | |
| var widgetScreen = widgetScreenName?widgetScreenName:'no-screen-found'; | |
| widgetScreen = widgetName+':'+widgetScreen; | |
| if (kiwi._autoshown) {widgetScreen += ':autoshown';} | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'prop34', ',', 2); | |
| s.prop34 = widgetScreen; //Widget Screen | |
| _satellite.notify(ruleName+ ': ' + widgetScreen); | |
| //Feature Clicks, if not page track | |
| if (s.linkType) { | |
| kiwi.trackFeatureClicks({ | |
| hasData: true, | |
| featureType: 'widget', | |
| featureName: widgetName, | |
| featureOptions: [widgetScreenName], | |
| linkTypes: '', | |
| widgetScreen: widgetScreen | |
| }, 'widget'); | |
| } | |
| if (blnTrackFeatureViews) { | |
| //Feature Views (and Promos) | |
| kiwi.trackFeatureViews({ | |
| hasData: true, | |
| featureType: 'widget:'+widgetName, | |
| featureNames: [widgetScreenName], | |
| widgetName: widgetName, | |
| widgetScreen: widgetScreen, | |
| wireUpOnly: true | |
| }, 'widget:'+widgetName); | |
| } | |
| //reset | |
| kiwi._autoshown = false; | |
| }; | |
| if (kiwi.widgetTrack) {//ensure only reporting on widgets ready call | |
| (function(oData) { | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: Atlas Widgets Data processed: ' + 'JSON.stringify(oData)'); | |
| var linkTrackVars = 'events,prop26', | |
| linkTrackEvents = 'event194'; | |
| linkTrackVars += oData.widgetLoads?',prop27':''; | |
| linkTrackVars += oData.widgetFails?',prop28':''; | |
| linkTrackVars += oData.widgetServices?',prop23':''; | |
| linkTrackVars += oData.loadSpeed?',eVar91':''; | |
| linkTrackVars += oData.errorType?',prop11,prop12,prop13':''; | |
| linkTrackEvents += oData.widgetServices?',event195':''; | |
| s.linkTrackVars=s.apl(s.linkTrackVars, linkTrackVars, ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, linkTrackEvents, ',', 2); | |
| s.events = s.apl(s.events, linkTrackEvents, ',', 2); //Atlas Widget Ready Calls, Atlas Widget with Service Ready Calls | |
| s.prop26 = oData.widgets; //Atlas Widgets Attempted | |
| s.prop27 = oData.widgetLoads; //Atlas Widgets Loaded | |
| s.prop28 = oData.widgetFails; //Atlas Widgets Failed | |
| s.prop23 = oData.widgetServices; //Atlas Widget Services Requested | |
| if (oData.loadSpeed) s.eVar91 = oData.loadSpeed; //Service Backed Element Load Speed | |
| if (oData.errorType) { | |
| s.prop11 = oData.errorType; //Error Type | |
| s.prop12 = oData.errorCode; //Error Code | |
| s.prop13 = 'D=pageName'; //Page with Error | |
| } | |
| if (oData.widgets.match(/(^|\^)bfcl($|\^)/i)) { | |
| kiwi.trackWidgetScreenView('bfcl','bar', false); | |
| } | |
| } | |
| })(_satellite.getVar('Feature Views - Widgets')); | |
| //update ddl reported flags | |
| Object.keys(kiwi.ddl.atlas).forEach(function (widget) { | |
| this[widget].isNew = false; | |
| if (this[widget].components && typeof this[widget].components === 'object') { | |
| Object.keys(this[widget].components).forEach(function (component) { | |
| this[component].isNew = false; | |
| this[component].serviceStartIndex += this[component].totalNewServices; | |
| this[component].totalNewServices = 0; | |
| //this[component].services = {}; //remove prior reported services so repeat calls get reported | |
| if(this[component].services && typeof this[component].services === 'object') { | |
| Object.keys(this[component].services).forEach(function (service) { | |
| this[service].isNew = false; | |
| }, this[component].services); | |
| } | |
| }, this[widget].components); | |
| } | |
| }, kiwi.ddl.atlas); | |
| } | |
| /* end Atlas Widgets */ | |
| /* Internal Searches */ | |
| (function(oData){ | |
| if (oData && oData.hasData) { | |
| //de-dupe page refreshes | |
| kiwi.util = kiwi.util || {}; | |
| var searchDataPersist = {term: oData.term, type: oData.type, facet: oData.facet}, | |
| cv = JSON.stringify(searchDataPersist), | |
| pv = kiwi.util.previousValue(cv, 'searchData') || ''; | |
| if (cv !== pv) { | |
| s.events = s.apl(s.events, 'event1', ',', 2); //Internal Searches | |
| s.eVar1 = oData.term; //Internal Search Term | |
| s.eVar3 = oData.type; //Internal Search Type | |
| s.prop2 = oData.count; //Total Search Results | |
| s.prop73 = oData.speed; //Search Results Speed | |
| s.eVar52 = oData.facet; //Search Results Facet | |
| if (oData.isQuick) { | |
| s.events = s.apl(s.events, 'event117', ',', 2); //Auto-Suggested Term Searches | |
| s.eVar9 = oData.term; //Auto-Suggested Search Term | |
| } | |
| var oSearchTypes = _satellite.getVar('Kiwi Config - Search Types'), | |
| mySearchTypeEvent = oSearchTypes[oData.type] || oSearchTypes['generic-site']; | |
| if (mySearchTypeEvent) { | |
| s.events = s.apl(s.events, mySearchTypeEvent, ',', 2); //...Various Search Types... | |
| } else if (mySearchTypeEvent.match(/site/i)) { | |
| //generic "site" search | |
| s.events = s.apl(s.events, 'event3', ',', 2); //Site Searches | |
| } | |
| if (s.events.match(/(,|^)event3(,|$)/i)) { | |
| s.eVar35 = 'D=c52'; //Site Search Origin Page | |
| } | |
| } | |
| //Feature Views (and Promos) | |
| kiwi.trackFeatureViews({ | |
| hasData: true, | |
| featureType: 'srch', | |
| featureNames: [oData.term] | |
| }, 'srch'); | |
| } | |
| //reset Quick search | |
| kiwi.cookie.sess.prev['isQuick'] = false; | |
| kiwi._sessCookieMod = true; //signal sess cookie updates | |
| })(_satellite.getVar('Search Data')); | |
| /* end Internal Searches */ | |
| /* Get Site Control Modals */ | |
| if (s.pageName.match(/getsitecontrol-/i)) { | |
| s.prop25 = _satellite.getVar('Derived Page Name'); //Page Sending Custom Link | |
| s.list1 = 'D=pageName'; // Promos (CTR) | |
| s.events = s.apl(s.events, 'event98', ',', 2); //Promo Views | |
| } | |
| /* end Get Site Control Modals */ | |
| /* CBOS Optins */ | |
| if (kiwi._thisPage.siteCode === 'opportunity' && | |
| kiwi._thisPage.pageCode === 'my-action-plan' && | |
| kiwi.user.cbId && | |
| kiwi.user.gradYear.match(/[0-9]{4}/i)) { | |
| s.events = s.apl(s.events, 'event34:'+kiwi.user.cbId+'-'+kiwi.user.gradYear, ',', 2); //CBOS Opt Ins | |
| } | |
| /* end CBOS Optins */ | |
| /* Custom Links */ | |
| kiwi._elementToTest = kiwi._elementToTest || false; | |
| if (s.linkType) { | |
| s.prop25 = s.pageName; //Page Sending Custom Link | |
| /* URL Processing */ | |
| var elem = kiwi._elementToTest, | |
| url = ''; | |
| if (elem && elem.href) { | |
| url = elem.href.toLowerCase(); | |
| //remove affiliateId/bannerId params | |
| var urlParts = url.split('?'); | |
| if (urlParts[1]) { | |
| urlParts[1] = urlParts[1].replace(/&affiliateId(=[^&]*)?|^affiliateId(=[^&]*)?&?/i, ''); | |
| urlParts[1] = urlParts[1].replace(/&bannerId(=[^&]*)?|^bannerId(=[^&]*)?&?/i, ''); | |
| if (urlParts[1]) url = urlParts.join('?'); | |
| else url = urlParts[0]; | |
| } | |
| } | |
| /* end URL Processing */ | |
| /* Exit Links */ | |
| if (s.linkType === 'e' && url) { | |
| s.linkName = url; | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'prop24', ',', 2); | |
| s.prop24 = url; //Exit Link | |
| s.prop1 = 'EXTLINK|'+s.prop24; | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop24', ',', 2); | |
| } | |
| /* end Exit Links */ | |
| /* Download/Dynamic/Triggered Download Links */ | |
| if (s.linkType === 'd' && s.linkName === 'Triggered Download Link') { | |
| url = _satellite.getVar('DDL - Download'); | |
| } | |
| if ((s.linkType === 'd' && url) || | |
| (s.linkType === 'o' && s.linkName === 'Dynamic Download Link')) { | |
| if (s.linkType === 'd') { | |
| s.linkName = url; | |
| } else { | |
| url = s.prop32 + '/dynamic-asset/'; | |
| if (elem.attributes['data-cbtrack-download']) { | |
| url += elem.attributes['data-cbtrack-download'].value.replace(/:/gi, '-'); | |
| } else if (elem.attributes['download']) { | |
| url += elem.attributes['download'].value.replace(/:/gi, '-'); | |
| } else if (elem.attributes['dynamic-asset-link-track']) { | |
| url += elem.attributes['dynamic-asset-link-track'].value.replace(/:/gi, '-'); | |
| } | |
| s.linkName += ': ' + url; | |
| } | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'prop10', ',', 2); | |
| s.hier1 = 'D=c10'; | |
| s.eVar4 = 'D=c10'; | |
| kiwi._urlToParse = url; | |
| kiwi._parsingDownloadLink = true; | |
| s.prop10 = _satellite.getVar('Page Name'); //Download PageName | |
| s.prop1 = 'DOWNLOAD|'+s.prop10; | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop1', ',', 2); | |
| //reset urlToParse after parsed | |
| kiwi._urlToParse = ''; | |
| kiwi._parsingDownloadLink = false; | |
| } | |
| /* end Download/Dynamic Download Links */ | |
| if (s.linkType === 'o') { | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'prop1', ',', 2); | |
| s.prop1 = 'CUSTOM|'+s.linkName; | |
| var customLinkActions = { | |
| /* Application Error Link Tracking */ | |
| // see DDL > error.json.js for examples of how this feature is used | |
| 'Application Error': function() { | |
| var oData = _satellite.getVar('AA - Application Error'); | |
| if (oData) { | |
| s.events = s.apl(s.events, 'event193', ',', 2); //Application Errors | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event193', ',', 2); | |
| s.prop4 = oData; //Application Error Code/Message | |
| s.prop11 = 'application-error'; //Error Type | |
| s.prop12 = oData.split(':')[0]; //Error Code | |
| s.prop13 = 'D=25'; //Page with Error | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop4', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop11', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop12', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop13', ',', 2); | |
| //TODO: remove promo tracking events and evars | |
| } | |
| //reset data | |
| kiwi.ddl.appError = {}; | |
| }, | |
| 'Cookie Consent Banner': function() { | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'prop43', ',', 2); | |
| s.prop43 = 'one trust:cookie consent banner'; | |
| }, | |
| 'Promo Click getsitecontrol': function() { | |
| s.events = s.apl(s.events, 'event99', ',', 2); //Promo Clicks | |
| s.list1 = 'D=pageName'; // Promos (CTR) | |
| s.list2 = 'D=pageName'; // Promos (Conv) | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'list1', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'list2', ',', 2); | |
| s.linkTrackEvents = s.apl(s.linkTrackEvents, 'event99', ',', 2); | |
| //modify page name | |
| s.prop25 = _satellite.getVar('Derived Page Name'); //Page Sending Custom Link | |
| }, | |
| /* Widget Display Changes (Old Style Widgets) */ | |
| 'Widget Display Change': function() { | |
| var oData = _satellite.getVar('Data - Widget Display'); | |
| s.list1 = ''; //Promos (CTR) | |
| if (oData && oData.screen) { | |
| _satellite.notify('KIWI: Widget Display Data found!'); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'prop34', ',', 2); | |
| s.prop34 = oData.screen; //Widget Screen | |
| kiwi.lotag = oData.screen; //Lucky Orange Behavior Tag | |
| /* Begin Lucky Orange */ | |
| if (kiwi.lotag && | |
| kiwi.lotag.match(/^(dop-generic|dop-scores-ot|dop-scores-aot)$/i)) { | |
| window._loq = window._loq || []; // ensure queue available | |
| window._loq.push(['tag', kiwi.lotag]); // this will tag, won't star, and will append the tag | |
| } | |
| /* End Lucky Orange */ | |
| if (oData.promos) { | |
| s.events = s.apl(s.events, 'event98', ',', 2); //Promo Views | |
| s.events = s.apl(s.events, 'event12', ',', 2); //Internal Campaign Views (legacy) | |
| s.list1 = oData.promos; //Promos (CTR) | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'list1', ',', 2); | |
| s.linkTrackEvents = s.apl(s.linkTrackEvents, 'event98', ',', 2); | |
| s.linkTrackEvents = s.apl(s.linkTrackEvents, 'event12', ',', 2); | |
| } | |
| if (oData.navs) { | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, oData.navs, ',', 2); | |
| s.events = s.apl(s.events, oData.navs, ',', 2); //[xyz] Nav Views | |
| } | |
| } | |
| }, | |
| 'AP Exam Intent Form Submit': function() { | |
| var oData = _satellite.getVar('Data - AP Exam Intent'); | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: Data - AP Exam Intent found: ' + JSON.stringify(oData)); | |
| /** | |
| * pattern: [Poll ID]:[Submitted Date];[AP Exam]:[count each yes/uns/no];[AP YouTube]:[y/n];[AP Prac]:[y/n] | |
| * eg: ap1:20200413;ex:y00|u01|n02;yt:ys;pr:no | |
| */ | |
| s.eVar92 = oData.pollResponse; //SFMC Poll Responses | |
| s.events = s.apl(s.events, 'event192', ',', 2); //SFMC Poll Submissions | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'eVar92', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event192', ',', 2); | |
| } | |
| }, | |
| 'Parent Opt In Form Submit': function() { | |
| var oData = _satellite.getVar('Data - Parent Opt In'); | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: Data - Parent Opt In found: ' + JSON.stringify(oData)); | |
| s.eVar84 = oData.gradYears; //Parent Opted Grad Years | |
| if (oData.serializeEmail) s.events = s.apl(s.events, 'event114:'+oData.serializeEmail, ',', 2); //Parent Email Opt-Ins | |
| if (oData.serializeText) s.events = s.apl(s.events, 'event115:'+oData.serializeText, ',', 2); //Parent Text Opt-Ins | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events,eVar84', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event114,event115', ',', 2); | |
| } | |
| }, | |
| 'Iframe Report Link': function() { | |
| kiwi.pageCodeOverride = 'reports:' + _satellite.getVar('Data - IFrame Report Name'); | |
| s.eVar74 = kiwi._thisPage.siteCode + ':' + kiwi.pageCodeOverride; //BI Report Name | |
| s.events = s.apl(s.events, 'event89', ',', 2); //BI Report Requested | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events,eVar74', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event89', ',', 2); | |
| }, | |
| 'CBOS Terms Accept': function() { | |
| kiwi.util.fireCustomEvent('CBOS Terms Accept'); | |
| s.abort = true; | |
| }, | |
| 'Confirm ECL Account Create': function() { | |
| kiwi.util.fireCustomEvent('Confirm ECL Account Create'); | |
| s.abort = true; | |
| }, | |
| /* Low Income/Fee Waivers Form Opt Ins/Outs */ | |
| 'LIFW Opt In Form Submit': function() { | |
| var oData = _satellite.getVar('Data - LIFW Form'); | |
| if (oData && oData.hasData) { | |
| var serializeVal = kiwi.user.cbId+'-'+kiwi.user.gradYear; | |
| _satellite.notify('KIWI: Data - LIFW Form found: ' + JSON.stringify(oData)); | |
| if (oData.liQualOption) s.events = s.apl(s.events, 'event35:'+serializeVal, ',', 2); //LIFW Opt Ins | |
| else s.events = s.apl(s.events, 'event36:'+serializeVal, ',', 2); //LIFW Opt Outs | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event35,event36', ',', 2); | |
| } | |
| }, | |
| /* Low Income/Fee Waivers Link Opt Ins */ | |
| 'LIFW Opt In': function() { | |
| var serializeVal = kiwi.user.cbId+'-'+kiwi.user.gradYear; | |
| s.events = s.apl(s.events, 'event35:'+serializeVal, ',', 2); //LIFW Opt Ins | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event35', ',', 2); | |
| }, | |
| /* Low Income/Fee Waivers Link Opt Outs */ | |
| 'LIFW Opt Out': function() { | |
| var serializeVal = kiwi.user.cbId+'-'+kiwi.user.gradYear; | |
| s.events = s.apl(s.events, 'event36:'+serializeVal, ',', 2); //LIFW Opt Outs | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event36', ',', 2); | |
| }, | |
| /* CBOS DCR Link Track Events */ | |
| // see DDL > CBOS > my-action-plan.json.js for details | |
| 'CBOS - FAFSA Confirm': function() { | |
| var serializeVal = kiwi.user.cbId+'-'+kiwi.user.gradYear; | |
| s.events = s.apl(s.events, 'event132:'+serializeVal, ',', 2); //CBOS Students - Complete FAFSA | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event132', ',', 2); | |
| //Reset Event DDL! | |
| kiwi.ddl.event.cbosFafsaConfirm = null; | |
| }, | |
| 'CBOS - Colleges Apply': function() { | |
| var oData = _satellite.getVar('Data - CBOS - Colleges Apply'); | |
| //expecting: oData = {hasData, isNowFulfilled, collegesCount, collegeNames (pipe-sep)} | |
| if (oData && oData.hasData) { | |
| if (oData.isNowFulfilled) { | |
| var serializeVal = kiwi.user.cbId+'-'+kiwi.user.gradYear; | |
| s.events = s.apl(s.events, 'event133:'+serializeVal, ',', 2); //CBOS Students - Apply to Colleges | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event133', ',', 2); | |
| } | |
| s.events = s.apl(s.events, 'event134='+oData.collegesCount, ',', 2); //CBOS College Applications | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event134', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.prop22 = oData.collegeNames; //CBOS College Application Added | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop22', ',', 2); | |
| } | |
| }, | |
| 'CBOS - Low Income Opt In': function() { | |
| var serializeVal = kiwi.user.cbId+'-'+kiwi.user.gradYear; | |
| s.events = s.apl(s.events, 'event35:'+serializeVal, ',', 2); //LIFW Opt Ins | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event35', ',', 2); | |
| //Reset Event DDL! | |
| kiwi.ddl.event.cbosLowIncomeOptIn = null | |
| }, | |
| 'CBOS - Low Income Opt Out': function() { | |
| var serializeVal = kiwi.user.cbId+'-'+kiwi.user.gradYear; | |
| s.events = s.apl(s.events, 'event36:'+serializeVal, ',', 2); //LIFW Opt Outs | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event36', ',', 2); | |
| //Reset Event DDL! | |
| kiwi.ddl.event.cbosLowIncomeOptIn = null | |
| }, | |
| /* Site Search Links */ | |
| 'Site Search Link': function() { | |
| s.events = s.apl(s.events, 'event10', ',', 2); //Search Results Clicks | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event10', ',', 2); | |
| kiwi._urlToParse = url; | |
| s.eVar55 = _satellite.getVar('Page Name'); //Search Results Link | |
| //reset urlToParse after parsed | |
| kiwi._urlToParse = ''; | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'eVar55', ',', 2); | |
| s.linkName += ': ' + url; | |
| if (elem.attributes['data-cb-adcode']) var featureUsed = elem.attributes['data-cb-adcode'].value; | |
| else if (elem.attributes['trackclickvalue']) var featureUsed = elem.attributes['trackclickvalue'].value; | |
| if(featureUsed) { | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'prop43', ',', 2); | |
| s.prop43 = 'sitesearch-banner:' + featureUsed; | |
| } | |
| }, | |
| /* Search Results Clicks */ | |
| 'Search Result Click': function() { | |
| var searchDataPersist = JSON.parse(kiwi.cookie.sess.prev.searchData); | |
| var term = decodeURIComponent(searchDataPersist.term), | |
| type = decodeURIComponent(searchDataPersist.type), | |
| facet = decodeURIComponent(searchDataPersist.facet); | |
| if (term) { | |
| s.events = s.apl(s.events, 'event10', ',', 2); //Search Results Clicks | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event10', ',', 2); | |
| kiwi._urlToParse = url; | |
| s.eVar55 = _satellite.getVar('Page Name'); //Search Results Link | |
| //reset urlToParse after parsed | |
| kiwi._urlToParse = ''; | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'eVar55', ',', 2); | |
| s.eVar1 = term; //Internal Search Term | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'eVar1', ',', 2); | |
| if (document.querySelector('[data-cbtrack-autosuggtermused]')) { | |
| s.eVar9 = term; //Auto-Suggested Search Term | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'eVar9', ',', 2); | |
| } | |
| s.eVar3 = type; //Internal Search Type | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'eVar3', ',', 2); | |
| s.eVar52 = facet; //Search Results Facet | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'eVar52', ',', 2); | |
| //Feature & Promo Clicks | |
| var ssPromoVal = ''; | |
| if (kiwi._elementToTest && kiwi._elementToTest.getAttribute('data-kiwi-sspromo-link')) { | |
| ssPromoVal = kiwi._elementToTest.getAttribute('data-kiwi-sspromo-link'); | |
| } | |
| kiwi.trackFeatureClicks({ | |
| hasData: true, | |
| featureType: 'srch', | |
| featureName: term, | |
| featureOptions: '', | |
| linkTypes: '', | |
| ssPromoName: ssPromoVal | |
| }, 'srch'); | |
| } | |
| }, | |
| /* Auto-Suggested Term Search Links */ | |
| 'Auto-Suggested Term Search Link': function() { | |
| kiwi.cookie.sess.prev['isQuick'] = true; | |
| kiwi._sessCookieMod = true; //signal sess cookie updates | |
| s.abort = true; | |
| }, | |
| /** | |
| * Feature Actions | |
| * Configured by jbeach on 2019-05-03 | |
| * https://jira.collegeboard.org/browse/WAP-2509 | |
| */ | |
| 'Feature Action - Storyline': function() { | |
| s.prop43 = 'storyline:' + _satellite.getVar('AppData Action Code'); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'prop43', ',', 2); | |
| }, | |
| /* Feature Clicks */ | |
| 'Feature': function() { | |
| var elem = kiwi._elementToTest; | |
| s.prop43 = s.prop7 + '|' + kiwi.util.makeLinkName(elem); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'prop43', ',', 2); | |
| }, | |
| /* Video Play Events*/ | |
| /*'': function() { | |
| /** | |
| * Orig provided by Wilder Freed (Adobe consultant) in 2019-01 | |
| * Configured by jbeach on 2019-03-11 | |
| */ | |
| /* example data passed in | |
| kiwi.videoData = { | |
| mediaName: mediaName, | |
| player: 'YouTube', | |
| linkName: 'Video 25%' | |
| }; | |
| var oVidData = kiwi.videoData; | |
| kiwi.videoData = {}; | |
| var oEventMapping = { | |
| 'Video Start': 'event52', | |
| 'Video 25%': 'event60', | |
| 'Video 50%': 'event61', | |
| 'Video 75%': 'event62', | |
| 'Video Complete': 'event53' | |
| }; | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, oEventMapping[oVidData.linkName], ',', 2); | |
| s.events = s.apl(s.events, oEventMapping[oVidData.linkName], ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events, eVar56, eVar58', ',', 2); | |
| s.eVar56 = oVidData.mediaName; | |
| s.eVar58 = oVidData.player; | |
| },*/ | |
| /* Target Link Clicks */ | |
| 'Target Link Click': function() { | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'prop43', ',', 2); | |
| }, | |
| /* Generic Custom Event Tracking */ | |
| 'Custom Event Name': function() { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, _satellite.getVar('Custom Event Code'), ',', 2); | |
| s.events = s.apl(s.events, s.linkTrackEvents, ',', 2); | |
| //reset data | |
| _satellite.setVar('Custom Event Name', ''); | |
| _satellite.setVar('Custom Event Code', ''); | |
| }, | |
| /* Fake Conversions */ | |
| 'Fake Conversion': function() { | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event27,event28,event29', ',', 2); | |
| s.events = s.apl(s.events, 'event27,event28=1,event29=1', ',', 2); //Fake Conversions | |
| }, | |
| /* IAM Account Link Approvals */ | |
| 'Approve Account Link': function() { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| if (s.pageName.match(/khan_academy/i)) { | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event87', ',', 2); | |
| s.events = s.apl(s.events, 'event87', ',', 2); //Khan Account Links | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event87', ',', 2); | |
| kiwi.util.fireCustomEvent('Khan Account Linked'); | |
| } | |
| if (s.pageName.match(/academic_merit/i)) { | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event105', ',', 2); | |
| s.events = s.apl(s.events, 'event105', ',', 2); //Academic Merit Links | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event105', ',', 2); | |
| } | |
| if (s.pageName.match(/rtnation/i)) { | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event106', ',', 2); | |
| s.events = s.apl(s.events, 'event106', ',', 2); //Road Trip Nation Links | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event106', ',', 2); | |
| } | |
| if (s.pageName.match(/collegenet/i)) { | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event131', ',', 2); | |
| s.events = s.apl(s.events, 'event131', ',', 2); //College Net/Coalition Links | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event131', ',', 2); | |
| } | |
| }, | |
| 'Accuplacer Practice - Test Registration': function() { | |
| if (cbTrackData.accupracRegType) { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events,eVar33', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event94', ',', 2); | |
| s.eVar33 = cbTrackData.accupracRegType; | |
| s.events = s.apl(s.events, 'event94:' + (cbTrackData.accupracUserId || ''), ',', 2); //Accuplacer Practice Test Registrations | |
| } | |
| }, | |
| 'SpringBoard Digital - Assignment Made': function() { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events,eVar71', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event84', ',', 2); | |
| s.eVar71 = _satellite.getVar('AppData Assignment Type'); //SpringBoard Digital Assignment Types | |
| s.events = s.apl(s.events, 'event84', ',', 2); //SpringBoard Digital Assignments | |
| }, | |
| 'SpringBoard Digital - Lesson Plan Made': function() { | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event85', ',', 2); | |
| s.events = s.apl(s.events, 'event85', ',', 2); //SpringBoard Digital Lesson Plans | |
| }, | |
| /* Legacy Big Future */ | |
| 'BF: Action Plan Grade Select': function() { | |
| var oData = _satellite.getVar('BF Action Plan Grade Select Data'); | |
| if (oData) { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events,eVar59', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event65', ',', 2); | |
| s.eVar59 = oData.grade; //Action Plan Grad Year | |
| s.events = s.apl(s.events, 'event65', ',', 2); //Action Plans Started | |
| } | |
| //reset data | |
| _satellite.setVar('BF Action Plan Grade Select Data', ''); | |
| }, | |
| 'Scholarship Search Results Click': function() { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event26', ',', 2); | |
| s.events = s.apl(s.events, 'event26', ',', 2); //Scholarship Searches | |
| }, | |
| //locally scoped IIFE function - can't access :( | |
| 'bf-mobi:link': function() { | |
| s.abort = true; | |
| }, | |
| /* end Legacy Big Future */ | |
| 'Widget Screen - BFCL Widget': function() { | |
| var elBfcl = document.querySelector('[data-cbtrack-widget="bfcl"]'), | |
| elMsg = '', strName = ''; | |
| if (elBfcl) {elMsg = elBfcl.querySelector('.college-list-popover-container[data-cbtrack-linkgroup]');} | |
| if (elMsg) {strName = elMsg.getAttribute('data-cbtrack-linkgroup');} | |
| kiwi.trackWidgetScreenView('bfcl',strName, true); | |
| }, | |
| 'BFCL Widget - Popover Dismissed': function() { | |
| kiwi.trackWidgetScreenView('bfcl','popover-dismissed', false); | |
| }, | |
| 'BFCL Widget - Login Modal': function() { | |
| kiwi.trackWidgetScreenView('bfcl','login-modal', false); | |
| }, | |
| 'cbTrack.sssOptin': function() { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event59', ',', 2); | |
| s.events = s.apl(s.events, 'event59:' + kiwi.cookie.sess.user.cbId, ',', 2); //SSS Opt-Ins | |
| _satellite.notify('KIWI: Custom Event Tracked: SSS Opt Ins: event59:' + kiwi.cookie.sess.user.cbId); | |
| }, | |
| 'cbTrack.sssReOptin': function() { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event196', ',', 2); | |
| s.events = s.apl(s.events, 'event196:' + kiwi.cookie.sess.user.cbId, ',', 2); //SSS re-Opt-Ins | |
| _satellite.notify('KIWI: Custom Event Tracked: SSS re-Opt Ins: event196:' + kiwi.cookie.sess.user.cbId); | |
| }, | |
| 'cbTrack.sssOptOut': function() { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event140', ',', 2); | |
| s.events = s.apl(s.events, 'event140:' + kiwi.cookie.sess.user.cbId, ',', 2); //SSS Opt-Outs | |
| _satellite.notify('KIWI: Custom Event Tracked: SSS Opt Outs: event140:' + kiwi.cookie.sess.user.cbId); | |
| }, | |
| 'cbTrack.sssOptout': function() { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event140', ',', 2); | |
| s.events = s.apl(s.events, 'event140:' + kiwi.cookie.sess.user.cbId, ',', 2); //SSS Opt-Outs | |
| _satellite.notify('KIWI: Custom Event Tracked: SSS Opt Outs: event140:' + kiwi.cookie.sess.user.cbId); | |
| }, | |
| 'HEDR - FAS - Download': function() { | |
| if (kiwi._hedr_fas_download.eventCode) { | |
| s.events = s.apl(s.events, kiwi._hedr_fas_download.eventCode+'='+kiwi._hedr_fas_download.total, ',', 2); //HEDR FAS Downloads | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, kiwi._hedr_fas_download.eventCode, ',', 2); | |
| _satellite.notify('KIWI: Custom Event Tracked: HEDR - FAS - Download: ' + kiwi._hedr_fas_download.eventCode+'='+kiwi._hedr_fas_download.total); | |
| } | |
| }, | |
| 'HEDR - Report View': function() { | |
| if (kiwi._hedr_report_view.eventCode) { | |
| s.events = s.apl(s.events, kiwi._hedr_report_view.eventCode, ',', 2); //HEDR Report Views | |
| s.prop39 = kiwi._hedr_report_view.report; //App Data Custom 1: HEDR Report | |
| s.prop40 = kiwi._hedr_report_view.sy; //App Data Custom 2: HEDR Report Year | |
| s.prop41 = kiwi._hedr_report_view.type; //App Data Custom 3: HEDR Report Type | |
| s.prop42 = kiwi._hedr_report_view.source; //App Data Custom 4: HEDR Report View Source | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, kiwi._hedr_report_view.eventCode, ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop39', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop40', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop41', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop42', ',', 2); | |
| _satellite.notify('KIWI: Custom Event Tracked: HEDR - Report View: ' + JSON.stringify(kiwi._hedr_report_view)); | |
| } | |
| }, | |
| 'HEDR - Data File - Download': function() { | |
| if (kiwi._hedr_files_download.eventCodeA) { | |
| s.events = s.apl(s.events, kiwi._hedr_files_download.eventCodeA, ',', 2); //HEDR Data Files Downloads | |
| s.events = s.apl(s.events, kiwi._hedr_files_download.eventCodeB+'='+kiwi._hedr_files_download.count, ',', 2); //HEDR Data Files Downloads | |
| s.prop40 = kiwi._hedr_files_download.type; //App Data Custom 2: HEDR Data Files Type | |
| s.prop41 = kiwi._hedr_files_download.delivMethod; //App Data Custom 3: HEDR Data Files Delivery Method | |
| s.prop42 = kiwi._hedr_files_download.auditCount; //App Data Custom 4: HEDR Data Files Audit Count | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, kiwi._hedr_files_download.eventCodeA, ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, kiwi._hedr_files_download.eventCodeB, ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop40', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop41', ',', 2); | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop42', ',', 2); | |
| _satellite.notify('KIWI: Custom Event Tracked: HEDR - Data File - Download: ' + JSON.stringify(kiwi._hedr_files_download)); | |
| } | |
| }, | |
| 'cbTrack.modalView': function() { | |
| kiwi = window.kiwi || {}; | |
| var modals = document.querySelectorAll('[data-cbtrack-modal]'); | |
| for (var i = 0; i < modals.length; i++) { | |
| var modal = modals[i], | |
| modalName = 'unknown-modal-name', | |
| modalContent = modal.querySelector('.modal-content'); | |
| if (kiwi.util.elementIsVisible(modal) || | |
| (modalContent && kiwi.util.elementIsVisible(modalContent))) { | |
| modalName = modal.getAttribute('data-cbtrack-modal'); | |
| break; | |
| } | |
| } | |
| _satellite.notify('KIWI: cbTrack.modalView: ' + modalName); | |
| if (modalName) { | |
| s.prop34 = 'modal:'+modalName; //Widget/Modal Screen | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'prop34', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'prop1', ',', 2); | |
| s.prop1 = 'MODAL|' +modalName; | |
| modalName = false; | |
| } | |
| } | |
| }; | |
| if (customLinkActions[s.linkName]) customLinkActions[s.linkName](); | |
| /* Search */ | |
| if (s.linkName.match(/^Search - /i)) { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'prop2,eVar1,eVar3,events', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event1,event3,event4,event26,event49,event63,event64', ',', 2); | |
| } | |
| /* end Search */ | |
| } | |
| } | |
| /* end Custom Links */ | |
| /* College Profile Views */ | |
| var oData = _satellite.getVar('College Profile View Data'); | |
| if (oData && oData.event22) { | |
| _satellite.notify('KIWI: College Profile View Data found! Events: ' + oData.event22); | |
| s.events = s.apl(s.events, 'event22', ',', 2); //College Profile Views | |
| //reset data | |
| window.s.events = ''; | |
| } | |
| /* end College Profile Views */ | |
| /* CAFW Printed */ | |
| var oData = _satellite.getVar('Data - CAFW Printed'); | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: Data - CAFW Printed found: ' + JSON.stringify(oData)); | |
| s.events = s.apl(s.events, oData.events, ',', 2); //CAFW Printed | |
| } | |
| /* end CAFW Printed */ | |
| /* BI Report Events */ | |
| if (s.linkType === 'o' && (_satellite.getVar('Report Load Start') || _satellite.getVar('Report Load Partial'))) { | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events,eVar74', ',', 2); | |
| s.eVar74 = 'D=c25'; //Report Name | |
| if (_satellite.getVar('Report Load Start')) { | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event89', ',', 2); | |
| s.events = s.apl(s.events, 'event89', ',', 2); //BI Report Requested | |
| s.pageName = decodeURIComponent(s.prop52); // this ensures previous page pathing works on final page load | |
| _satellite.setVar('Report Loading Page Name', s.pageName); | |
| } | |
| if (_satellite.getVar('Report Load Partial')) { | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event100', ',', 2); | |
| s.events = s.apl(s.events, 'event100', ',', 2); //BI Report Partially Loaded | |
| s.pageName = _satellite.getVar('Report Loading Page Name'); // this ensures previous page pathing works on final page load | |
| _satellite.setVar('Report Loading Page Name', ''); | |
| } | |
| //reset de after track | |
| _satellite.setVar('Report Load Start', false); | |
| _satellite.setVar('Report Load Partial', false); | |
| } | |
| if (_satellite.getVar('Report Load Complete')) { | |
| s.eVar74 = 'D=pageName'; //Report Name | |
| s.events = s.apl(s.events, 'event101', ',', 2); //BI Report Completed | |
| if (s.prop74) s.events = s.apl(s.events, 'event112=' + s.prop74, ',', 2); //BI Report Load Speed | |
| //reset de after track | |
| _satellite.setVar('Report Load Complete', false); | |
| _satellite.setVar('Report Load Speed', ''); | |
| } | |
| /* end BI Report Events */ | |
| /* SpringBoard Digital */ | |
| if (_satellite.textMatch(_satellite.getVar('AppData Site Code'), 'springboarddigital')) { | |
| if (s.pageName == 'springboarddigital:landingpage') { | |
| //var visitor = Visitor.getInstance('5E1B123F5245B29B0A490D45@AdobeOrg'); | |
| //var mcvid = visitor.getMarketingCloudVisitorID(); | |
| var sbDigLoginEvent = 'event83'; //records once per visit in configuration | |
| s.events = s.apl(s.events, sbDigLoginEvent, ',', 2); //SpringBoard Digital Logins | |
| } | |
| } | |
| /* end SpringBoard Digital */ | |
| /* eCommerce Purchases */ | |
| (function(){ | |
| var oData = _satellite.getVar('DDL - ECommerce - Purchase'); | |
| if (oData) { | |
| _satellite.notify('KIWI: eCommerce Purchase Data found! :: Data Found: ' + JSON.stringify(oData)); | |
| s.events = s.apl(s.events, 'purchase', ',', 2); //Orders | |
| s.purchaseID = oData.transaction.id; //Purchase ID | |
| s.eVar16 = oData.transaction.type; //Order Type (e.g. Event Registration) | |
| s.eVar37 = oData.transaction.type; //Product View Source (e.g. Event Registration) | |
| for(var i = 0; i < oData.products.length; i++) { | |
| var oProduct = oData.products[i]; | |
| product = oProduct.category + ';' + oProduct.id + ';' + oProduct.quantity + ';' + oProduct.price; | |
| s.products = s.apl(s.products, product, ',', 2); //Products | |
| } | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'events', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'eVar16', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'eVar37', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'purchaseID', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'products', ',', 2); | |
| _satellite.notify('KIWI: '+oData.transaction.type+'!'); | |
| var deduper = oData.transaction.id, | |
| count = 0; | |
| switch (oData.transaction.type) { | |
| case 'Event Registration': | |
| s.events = s.apl(s.events, 'event23:'+deduper, ',', 2); //Event Registrations | |
| s.eVar62 = oData.products[0].name; //Event Name | |
| s.eVar68 = oData.products[0].category; //Event Type | |
| s.linkTrackEvents = s.apl(s.linkTrackEvents, 'event23', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'eVar62', ',', 2); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'eVar68', ',', 2); | |
| break; | |
| case 'SAT Score Sends': | |
| deduper = 'nsat'+deduper; | |
| s.purchaseID = deduper; //Purchase ID | |
| s.events = s.apl(s.events, 'event205:'+deduper, ',', 2); //SAT Score Sends - All | |
| s.linkTrackEvents = s.apl(s.linkTrackEvents, 'event205', ',', 2); | |
| if (oData.transaction.shipping) { | |
| s.events = s.apl(s.events, 'event209:'+deduper, ',', 2); //SAT Score Sends - Rush | |
| s.linkTrackEvents = s.apl(s.linkTrackEvents, 'event209', ',', 2); | |
| } | |
| var oData2 = _satellite.getVar('DDL - SAT Score Sends'); | |
| if (oData2 && oData2.flow) { | |
| s.prop70 = Object.keys(oData2.schoolsSelected).join(','); | |
| s.linkTrackVars = s.apl(s.linkTrackVars, 'prop70', ',', 2); | |
| count = Object.keys(oData2.schoolsSelected).length; | |
| s.events = s.apl(s.events, 'event210:'+deduper+'='+count, ',', 2); //SAT Score Recipients - Orgs | |
| s.linkTrackEvents = s.apl(s.linkTrackEvents, 'event210', ',', 2); | |
| if (oData2.flow === 'reg') { | |
| s.events = s.apl(s.events, 'event206:'+deduper, ',', 2); //SAT Score Sends - Reg | |
| s.linkTrackEvents = s.apl(s.linkTrackEvents, 'event206', ',', 2); | |
| } | |
| if (oData2.flow === 'asr') { | |
| s.events = s.apl(s.events, 'event207:'+deduper, ',', 2); //SAT Score Sends - ASR | |
| s.linkTrackEvents = s.apl(s.linkTrackEvents, 'event207', ',', 2); | |
| } | |
| if (oData2.fyType && oData2.fyType !== 'none') { | |
| s.events = s.apl(s.events, 'event208:'+deduper, ',', 2); //SAT Score Sends - FW Used | |
| s.linkTrackEvents = s.apl(s.linkTrackEvents, 'event208', ',', 2); | |
| } | |
| } | |
| if (kiwi.ddl.satScoreSends) {kiwi.ddl.satScoreSends = '';} | |
| break; | |
| default: | |
| break; | |
| } | |
| if (kiwi.ddl.eCommerce.purchase) {kiwi.ddl.eCommerce.purchase = '';} | |
| } | |
| })(); | |
| /* end eCommerce Purchases */ | |
| /* CSS/PROFILE Registrations */ | |
| var oCSSPReg = _satellite.getVar('SCode CSS/Profile Registration Event Data'); | |
| if (oCSSPReg && oCSSPReg.event11) { | |
| _satellite.notify('KIWI: CSS/Profile Registration Event Data found!'); | |
| s.events = s.apl(s.events, oCSSPReg.event11, ',', 2); //CSS/PROFILE Registrations | |
| s.eVar66 = oCSSPReg.cssProfileYear; //CSS/PROFILE Year | |
| } | |
| /* end CSS/PROFILE Registrations */ | |
| /* CSS/PROFILE Application Submissions */ | |
| var oCSSPSub = _satellite.getVar('SCode CSS/Profile Application Submission Event Data'); | |
| if (oCSSPSub && oCSSPSub.event81) { | |
| _satellite.notify('KIWI: CSS/Profile Application Submission Event Data found!'); | |
| s.events = s.apl(s.events, oCSSPSub.event81, ',', 2); //CSS/PROFILE Application Submissions | |
| s.eVar66 = oCSSPSub.cssProfileYear; //CSS/PROFILE Year | |
| s.events = s.apl(s.events, 'purchase', ',', 2); //Orders | |
| s.eVar16 = oCSSPSub.orderType; //Order Type | |
| s.purchaseID = oCSSPSub.purchaseId; //Purchase ID | |
| s.products = oCSSPSub.products; //Products | |
| } | |
| /* end CSS/PROFILE Application Submissions */ | |
| /* CLEP Registrations */ | |
| var oCLEPReg = _satellite.getVar('SCode CLEP Registration Event Data'); | |
| if (oCLEPReg && oCLEPReg.event16) { | |
| _satellite.notify('KIWI: CLEP Registration Event Data found!'); | |
| s.events = s.apl(s.events, oCLEPReg.event16, ',', 2); //CLEP Registrations | |
| s.events = s.apl(s.events, 'purchase', ',', 2); //Orders | |
| s.eVar16 = oCLEPReg.orderType; //Order Type | |
| s.purchaseID = oCLEPReg.purchaseId; //Purchase ID | |
| s.products = oCLEPReg.products; //Products | |
| kiwi.util.fireCustomEvent('CLEP Registration'); | |
| } | |
| /* end CLEP Registrations */ | |
| /* SAT Reg Flow Tracking */ | |
| var arrStepEvent = ''; | |
| (function(oData) { | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: SAT Reg Step Data found: ' + JSON.stringify(oData)); | |
| for (var i = 0; i < oData.stepEvents.length; i++) { | |
| s.events = s.apl(s.events, oData.stepEvents[i], ',', 2); // SAT Reg Flow Milestones (unique by Reg), (unique by SY+User) | |
| arrStepEvent = oData.stepEvents[i].split(':'); | |
| var stepEvent; | |
| if (arrStepEvent.length) { | |
| stepEvent = arrStepEvent[0]; | |
| kiwi.util.fireCustomEvent('SAT Reg Step', {stepEvent: stepEvent}); | |
| } | |
| } | |
| } | |
| })(_satellite.getVar('Data - SAT Reg Step')); | |
| /* end SAT Reg Flow Tracking */ | |
| /* SAT Cross-Sell Prod View Tracking */ | |
| (function(oData) { | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: Data - SAT Reg Cross-Sell found: ' + JSON.stringify(oData)); | |
| s.events = s.apl(s.events, 'prodView', ',', 2); // Product Views | |
| s.eVar37=oData.prodViewSource; | |
| s.products=oData.products; | |
| } | |
| })(_satellite.getVar('Data - SAT Reg Cross-Sell')); | |
| /* end SAT Cross-Sell Prod View Tracking */ | |
| /* Test Order Tracking */ | |
| (function(oData) { | |
| if (oData && oData.hasData && | |
| s.pageName.match(/ordering\/testordering\/submitorder/i)) { | |
| _satellite.notify('KIWI: Data - Test Order found: ' + JSON.stringify(oData)); | |
| s.eVar8 = oData.aiCode; //App User Org ID | |
| s.eVar53 = oData.adminCode; //Test Order Admin | |
| s.events = s.apl(s.events, 'event48:'+oData.serializeCode, ',', 2); // Test Orders | |
| } | |
| })(_satellite.getVar('Data - Test Order')); | |
| /* end Test Order Tracking */ | |
| /* SAT Reg Tracking */ | |
| (function(oData) { | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: Data - SAT Reg found: ' + JSON.stringify(oData)); | |
| s.eVar16 = oData.orderType; //Order Type | |
| s.purchaseID = oData.purchaseId; //Purchase ID | |
| s.products = oData.products; //Products | |
| s.eVar26 = oData.testType; //SAT Test Type | |
| s.eVar40 = oData.registrantType; //SAT Registrant Type | |
| s.eVar49 = oData.adminCode; //SAT Reg Admin | |
| s.eVar86 = _satellite.getVar('AA - SAT Fee Waiver Type'); | |
| s.events = s.apl(s.events, oData.events.join(','), ',', 2); // Purchase, SAT Regs by Type | |
| if (arrStepEvent.length) { | |
| var isSubjTest = (oData.testType === 'SAT Subject'), | |
| isRepeat = (oData.registrantType === 'Repeat'), | |
| usedFeeWaiver = (s.events.match(/event50(,|:|$)/i)); | |
| kiwi.util.fireCustomEvent('SAT Reg', {adminType: oData.adminType, isSubjTest: isSubjTest, isRepeat: isRepeat, usedFeeWaiver: usedFeeWaiver, satRegAdminDate: oData.adminCode, purchaseId: oData.purchaseId}); | |
| } | |
| } | |
| })(_satellite.getVar('Data - SAT Reg')); | |
| /* end SAT Reg Tracking */ | |
| /* Other NSAT Purchase Tracking */ | |
| (function(oData) { | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: Data - NSAT Purchase found: ' + JSON.stringify(oData)); | |
| s.eVar16 = oData.orderType; //Order Type | |
| s.purchaseID = oData.purchaseId; //Purchase ID | |
| s.products = oData.products; //Products | |
| s.eVar26 = oData.testType; //SAT Test Type | |
| s.eVar40 = oData.registrantType; //SAT Registrant Type | |
| s.eVar49 = oData.adminCode; //SAT Reg Admin | |
| s.events = s.apl(s.events, oData.events, ',', 2); // Purchase, Score Sends, QAS/SAS | |
| } | |
| })(_satellite.getVar('Data - NSAT Purchase')); | |
| /* end Other NSAT Purchase Tracking */ | |
| /* AP FYM Event Tracking */ | |
| /* DDL SCHEMA | |
| { | |
| hasData: true, | |
| apReg: { | |
| hasData: false, | |
| studentId: apReg.studentId || '', | |
| studentOrgId: apReg.studentOrgId || '', | |
| studentGradeLevel: apReg.studentGradeLevel || '' | |
| }, | |
| apCourse: { | |
| hasData: false, | |
| apCourseIds: apCourse.apCourseIds || '', | |
| educationPeriod: apCourse.educationPeriod || '', | |
| studentIds: apCourse.studentIds || '', | |
| courseOrgId: apCourse.courseOrgId || '' | |
| }, | |
| apExam: { | |
| hasData: false, | |
| apCourseIds: apExam.apCourseIds || '', | |
| educationPeriod: apExam.educationPeriod || '', | |
| studentIds: apExam.studentIds || '', | |
| courseOrgId: apExam.courseOrgId || '' | |
| } | |
| } */ | |
| var oData = _satellite.getVar('Data - AP FYM Event'); | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: Data - AP FYM Event found: ' + JSON.stringify(oData)); | |
| if (oData.apReg.hasData) { | |
| var sApEventDedupeKey = oData.apReg.studentId; | |
| s.eVar77 = oData.apReg.studentGradeLevel; //AP Student Grade Level | |
| s.events = s.apl(s.events, 'event31:'+sApEventDedupeKey, ',', 2); //AP Student Registrants | |
| } | |
| if (oData.apCourse.hasData) { | |
| //loop courses first | |
| for (var i = 0; i <= oData.apCourse.apCourseIds.length-1; i++) { | |
| var sApCourseInst = oData.apCourse.apCourseIds[i] + '-' + oData.apCourse.educationPeriod; | |
| s.eVar79 = sApCourseInst + '-' + oData.apCourse.courseOrgId; //AP Course Offering | |
| //loop students | |
| for (var j = 0; j <= oData.apCourse.studentIds.length-1; j++) { | |
| var sApEventDedupeKey = oData.apCourse.studentIds[j] + '-' + sApCourseInst; | |
| s.events = s.apl(s.events, 'event32:'+sApEventDedupeKey, ',', 2); //AP Course Enrollees | |
| } | |
| } | |
| } | |
| if (oData.apExam.hasData) { | |
| //loop courses first | |
| for (var i = 0; i <= oData.apExam.apCourseIds.length-1; i++) { | |
| var sApCourseInst = oData.apExam.apCourseIds[i] + '-' + oData.apExam.educationPeriod; | |
| s.eVar79 = sApCourseInst + '-' + oData.apExam.courseOrgId; //AP Course Offering | |
| //loop students | |
| for (var j = 0; j <= oData.apExam.studentIds.length-1; j++) { | |
| var sApEventDedupeKey = oData.apExam.studentIds[j] + '-' + sApCourseInst; | |
| s.events = s.apl(s.events, 'event33:'+sApEventDedupeKey, ',', 2); //AP Exam Registrants | |
| } | |
| } | |
| } | |
| s.linkTrackVars=s.apl(s.linkTrackVars, 'events,eVar77,eVar79', ',', 2); | |
| s.linkTrackEvents=s.apl(s.linkTrackEvents, 'event31,event32,event33', ',', 2); | |
| } | |
| /* end AP FYM Event Tracking */ | |
| /* AP Score View Tracking */ | |
| var oData = _satellite.getVar('Data - AP Score View'); | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: Data - AP Score View found: ' + JSON.stringify(oData)); | |
| s.events = s.apl(s.events, oData.event78, ',', 2); //AP Score Views | |
| s.eVar65 = oData.eVar65; //AP Score View Year | |
| } | |
| /* end AP Score View Tracking */ | |
| /* AP Score Send Tracking */ | |
| var oData = _satellite.getVar('Data - AP Score Send'); | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: Data - AP Score Send found: ' + JSON.stringify(oData)); | |
| s.events = s.apl(s.events, oData.event79, ',', 2); //AP Score Sends | |
| s.eVar16 = oData.orderType; //Order Type | |
| s.purchaseID = oData.purchaseId; //Purchase ID | |
| s.products = oData.products; //Products | |
| } | |
| /* end AP Score Send Tracking */ | |
| /* AP Score Match Tracking */ | |
| var oData = _satellite.getVar('Data - AP Score Match'); | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: Data - AP Score Match found: ' + JSON.stringify(oData)); | |
| s.events = s.apl(s.events, oData.event77, ',', 2); //AP Score Matches | |
| } | |
| /* end AP Score Match Tracking */ | |
| /* IAM Score Match Tracking */ | |
| var oData = _satellite.getVar('Data - IAM Score Match'); | |
| if (oData && oData.hasData) { | |
| _satellite.notify('KIWI: Data - IAM Score Match found: ' + JSON.stringify(oData)); | |
| s.events = s.apl(s.events, oData.events, ',', 2); //IAM Score Matches | |
| s.eVar69 = oData.matchAttempts; //IAM Score Match Attempts | |
| s.eVar70 = oData.matchMethod; //IAM Score Match Method | |
| s.eVar73 = oData.matchTestType; //IAM Score Match Test Type | |
| } | |
| /* end IAM Score Match Tracking * | |
| /* Store Tracking */ | |
| //Store Item Views | |
| if (!s.products && s.prop31) { | |
| s.products = ';' + s.prop31; //Products | |
| s.events = s.apl(s.events, 'prodView', ',', 2); //Product Views | |
| } | |
| //Store Purchases | |
| var oSTOPurch = _satellite.getVar('SCode Store Purchase Event Data'); | |
| if (oSTOPurch && oSTOPurch.event47) { | |
| _satellite.notify('KIWI: SCode Store Purchase Event Data found!'); | |
| s.events = s.apl(s.events, oSTOPurch.event47, ',', 2); //Store Orders | |
| s.events = s.apl(s.events, 'purchase', ',', 2); //Orders | |
| s.eVar16 = oSTOPurch.orderType; //Order Type | |
| s.purchaseID = oSTOPurch.purchaseId; //Purchase ID | |
| s.products = oSTOPurch.products; //Products | |
| } | |
| /* end Store Tracking */ | |
| /* Marketing Channels/Campaigns */ | |
| kiwi._thisPage.mktg = { | |
| channel: '', | |
| campaign: '', | |
| mid: '', //Message ID | |
| rid: '', //Recipient ID | |
| sid: '' //Segment ID | |
| }; | |
| //s.channelManager('excmpid,ep_mid,s_kwcid,ef_id', '', 'cmgvo', '', 's_tbm', 60); | |
| //derive this page channel/campaign | |
| s.channelManager('excmpid,sfmc_cid,ep_mid,s_kwcid,ef_id', '', '0', '', 's_tbm', 60); | |
| switch (s._channel) { | |
| case 'Typed/Bookmarked': | |
| s._channel = 'Direct'; | |
| break; | |
| case 'Unknown Paid Channel': | |
| s._channel = 'All Other Campaigns'; | |
| break; | |
| case 'Natural Search': | |
| s._channel = 'Organic Search'; | |
| break; | |
| case 'Other Natural Referrers': | |
| s._channel = 'Other Sites'; | |
| break; | |
| default: | |
| break; | |
| } | |
| /*_satellite.notify('KIWI: Channel settings: _channel: '+ s._channel +'; _campaignID: '+ s._campaignID + | |
| '; _campaign: '+ s._campaign +'; _referrer: '+ s._referrer + | |
| '; _referringDomain: '+ s._referringDomain +'; _partner: '+ s._partner + | |
| '; _keywords: '+ s._keywords);*/ | |
| //set values for this page | |
| if (s._channel) kiwi._thisPage.mktg.channel = s._channel; | |
| if (s._campaignID && s._campaignID != 'n/a') kiwi._thisPage.mktg.campaign = s._campaignID.toLowerCase(); | |
| /* SFMC Campaigns */ | |
| /* SFMC Links pattern (email): ?SFMC_cid=EM%%JobId%%-%%=StringToHex(__AdditionalEmailAttribute1)=%%&rid=%%SubscriberID%% */ | |
| /* SFMC Links pattern (text): ?SFMC_cid=TX%%JobId%%-%%=StringToHex(__AdditionalEmailAttribute1)=%%&rid=%%SubscriberID%% */ | |
| kiwi._thisPage.mktg.mid = _satellite.getVar('QP sfmc_cid'); | |
| kiwi._thisPage.mktg.rid = _satellite.getVar('QP rid'); | |
| if (kiwi._thisPage.mktg.mid.match(/-/)) { | |
| //parse out segment val | |
| var tmp = kiwi._thisPage.mktg.mid.split('-'); | |
| kiwi._thisPage.mktg.mid = tmp[0]; | |
| kiwi._thisPage.mktg.sid = decodeURIComponent(kiwi.util.hex2a(tmp[1])); | |
| } | |
| /* Epsilon DREAM Campaigns */ | |
| if (!kiwi._thisPage.mktg.mid) { | |
| kiwi._thisPage.mktg.mid = _satellite.getVar('QP ep_mid'); | |
| kiwi._thisPage.mktg.rid = _satellite.getVar('QP ep_rid'); | |
| kiwi._thisPage.mktg.sid = _satellite.getVar('QP etId'); | |
| } | |
| //set values for life cookie | |
| if (kiwi._thisPage.mktg.channel) { | |
| kiwi._lifeCookieMod = true; | |
| //check if within 60 days | |
| var todayDate = new Date(), | |
| setDate = new Date(kiwi.cookie.life.mktg.dateSet), | |
| expDate = setDate.setDate(setDate.getDate() + 60); | |
| if (expDate < todayDate) { | |
| //start over | |
| //kiwi.cookie.life.mktg.channels = kiwi._thisPage.mktg.channel; | |
| if (kiwi._thisPage.mktg.campaign) kiwi.cookie.life.mktg.campaigns = kiwi._thisPage.mktg.campaign; | |
| } else { | |
| //add them to the list && pop off first in list if urlencoded new ones are longer than 100 chars | |
| //kiwi.cookie.life.mktg.channels = (kiwi.cookie.life.mktg.channels == '')?kiwi._thisPage.mktg.channel:kiwi.util.appendToList(kiwi.cookie.life.mktg.channels, kiwi._thisPage.mktg.channel, ',', 3); | |
| //kiwi.cookie.life.mktg.channels = kiwi.util.chopToLength( kiwi.cookie.life.mktg.channels, 100, true ); | |
| if (kiwi._thisPage.mktg.campaign) { | |
| kiwi.cookie.life.mktg.campaigns = (kiwi.cookie.life.mktg.campaigns == '')?kiwi._thisPage.mktg.campaign:kiwi.util.appendToList(kiwi.cookie.life.mktg.campaigns, kiwi._thisPage.mktg.campaign, '>', 3); | |
| kiwi.cookie.life.mktg.campaigns = kiwi.util.chopToLength( kiwi.cookie.life.mktg.campaigns, 100, true ); | |
| if (kiwi.cookie.life.mktg.latest) { | |
| kiwi.cookie.life.mktg.latest.channel = kiwi._thisPage.mktg.channel; | |
| kiwi.cookie.life.mktg.latest.campaign = kiwi._thisPage.mktg.campaign; | |
| } | |
| } | |
| } | |
| if (kiwi._thisPage.mktg.mid) { | |
| var tmp = kiwi._thisPage.mktg.mid+kiwi._thisPage.mktg.rid, | |
| regexp = new RegExp('(^|,)'+tmp+'(,|$)', 'i'); | |
| if (!kiwi.cookie.life.mktg.midrids.match(regexp)) s.events = s.apl(s.events, 'event40', ',', 2); //Email Unique Clicked | |
| kiwi.cookie.life.mktg.midrids = kiwi.util.appendToList(kiwi.cookie.life.mktg.midrids, tmp, ',', 3); | |
| } | |
| } | |
| //pass data to analytics | |
| //campaigns | |
| s.prop17 = kiwi.cookie.life.mktg.campaigns; //Marketing Campaign Participation | |
| if (kiwi._thisPage.mktg.campaign) { | |
| s.campaign = s.getValOnce(kiwi._thisPage.mktg.campaign, 's_v0', 30); //Marketing Campaign Last | |
| s.events = s.apl(s.events, 'event30', ',', 2); //Non-Deduped Campaign Clicks | |
| s.prop59 = kiwi._thisPage.mktg.campaign; //Non-Deduped Campaign | |
| } | |
| //other | |
| s.eVar39 = kiwi._thisPage.mktg.sid; //Email Segment ID | |
| s.eVar42 = kiwi._thisPage.mktg.rid; //Email Recipient ID | |
| /* end Marketing Channels/Campaigns */ | |
| /* Referral Promo ID */ | |
| s.eVar12 = _satellite.getVar('QP refid'); | |
| /* Patches/Hacks */ | |
| /*//prevent myap double-page tracking after login, due to way IAM login + SPA application works | |
| if (s.prop32 === 'myap' && s.pageName === s.prop52 && !s.r && !s.linkName) { | |
| s.abort = true; | |
| _satellite.notify('KIWI: Tool > Analytics > Custom JS > DO PLUGINS SECTION > Duplicate APFYM Call aborted.'); | |
| }*/ | |
| //Hacks required after AppMeas upgrade due to APOSR legacy S object tracking and modal popup behavior | |
| if (s.pageName === 'apscore:contactus-thanks' && s.prop52 == 'apscore:contactus-thanks') | |
| s.abort = true; | |
| if (s.pageName === 'apscore:sendscores-disclaimer' && s.prop52 == 'apscore:sendscores-disclaimer') | |
| s.pageName = 'apscore:sendscores-selectcolleges'; | |
| // Purchase, set by NSAT, patch 6/13/2011 | |
| if (s.pageName.toLowerCase().indexOf('step4:orderconfirmation') != -1) | |
| s.events = s.apl(s.events, 'purchase', ',', 2); | |
| /* end Patches/Hacks */ | |
| /* Sync duplicate vars */ | |
| if (s.pageName && !s.eVar4) s.eVar4 = 'D=pageName'; //PageName | |
| if (s.prop18) s.eVar78 = 'D=c18'; //Hour of Day, Day of Week, Weekend/Weekday | |
| /* end Sync duplicate vars */ | |
| //bake in cookied vals | |
| s.prop7 = s.getPreviousValue(s.prop32, 'gpv_c32'); //Previous Site Code | |
| s.prop52 = s.getPreviousValue(s.pageName, 'gpv_pn'); //Previous Page | |
| /* Update Kiwi Cookies */ | |
| if (kiwi._lifeCookieMod) { | |
| var cookieDays = 60, | |
| newExpireOn = new Date().getTime() + (86400000*cookieDays), | |
| expDate = new Date(newExpireOn); | |
| document.cookie = 'kiwi_life=' + JSON.stringify(kiwi.cookie.life) + ';expires=' + expDate.toGMTString() + | |
| ';path=/ ;domain=collegeboard.org'; | |
| } | |
| if (kiwi._sessCookieMod) { | |
| document.cookie = 'kiwi_sess=' + JSON.stringify(kiwi.cookie.sess) + | |
| ';path=/ ;domain=collegeboard.org'; | |
| } | |
| /* end Update Kiwi Cookies */ | |
| //reset stuff | |
| if (cbTrackData.promosViewed) cbTrackData.promosViewed = ''; | |
| if (cbTrackData.promoClicked) cbTrackData.promoClicked = ''; | |
| if (cbTrackData.apRegistration) cbTrackData.apRegistration = ''; | |
| if (cbTrackData.apCourseEnrollment) cbTrackData.apCourseEnrollment = ''; | |
| if (cbTrackData.apExamRegistration) cbTrackData.apExamRegistration = ''; | |
| if (cbTrackData.flowCode) cbTrackData.flowCode = ''; | |
| if (cbTrackData.flowSteps) cbTrackData.flowSteps = ''; | |
| //protect against bad SPA repeat calls | |
| kiwi._thisPage = kiwi._thisPage || {}; | |
| kiwi._thisPage.siteSettings = kiwi._thisPage.siteSettings || {}; | |
| kiwi.appPageTrackCalls = kiwi.appPageTrackCalls || {}; | |
| /*if (typeof kiwi._thisPage.siteSettings.appType !== 'undefined' && kiwi._thisPage.siteSettings.appType === 'spa-noroutes') {// this is handled on pushstate for apps that use meaningful urls | |
| ruleName = 'KIWI: Tool > Analytics > Custom JS > DO PLUGINS SECTION'; | |
| if (typeof kiwi.appPageTrackCalls !== 'undefined' && | |
| typeof kiwi.appPageTrackCalls.totalSinceLastTrack !== 'undefined' && | |
| typeof kiwi.appPageTrackCalls.currentIncrement !== 'undefined' && | |
| kiwi.appPageTrackCalls.totalSinceLastTrack !== kiwi.appPageTrackCalls.currentIncrement) { | |
| s.abort = true; | |
| _satellite.notify(ruleName + ' > appPageTrackCalls.currentIncrement: ' + kiwi.appPageTrackCalls.currentIncrement + ' aborted.'); | |
| } else { | |
| _satellite.notify(ruleName + ' > appPageTrackCalls.currentIncrement: ' + kiwi.appPageTrackCalls.currentIncrement + ' allowed.'); | |
| kiwi.appPageTrackCalls = {totalSinceLastTrack: 0, currentIncrement: 0}; | |
| } | |
| }*/ | |
| //_satellite.notify('KIWI: Tool > Analytics > Custom JS > DO PLUGINS SECTION (end)'); | |
| }; | |
| /** end Do Plugins Section **/ | |
| /************************** PLUGINS SECTION *************************/ | |
| //expire legacy cookies | |
| if (document.cookie.match(/dtm_cbAcctData=/)) document.cookie = 'dtm_cbAcctData=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/ ;domain=collegeboard.org'; | |
| if (document.cookie.match(/kiwi_cookie=/)) document.cookie = 'kiwi_cookie=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/ ;domain=collegeboard.org'; | |
| //if (document.cookie.match(/cbtrack_nav=/)) document.cookie = 'cbtrack_nav=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/ ;domain=collegeboard.org'; | |
| // Kiwi Cookies | |
| kiwi._lifeCookieMod = kiwi._sessCookieMod = false; | |
| kiwi.cookie = { | |
| life: { | |
| mktg: { | |
| dateSet: new Date(), | |
| channels: '', | |
| campaigns: '', | |
| midrids: '' | |
| } | |
| }, | |
| sess: { | |
| user: {}, | |
| prev: { | |
| siteCode: '', | |
| pageName: '', | |
| channel: '', | |
| campaign: '' | |
| }, | |
| mboxEvents: { | |
| track_sat_sv: false, | |
| track_psat_sv: false | |
| }, | |
| features: {} | |
| } | |
| }; | |
| //get cookie data | |
| kiwi._cookielife = _satellite.getVar('Cookie - Kiwi Lifetime'); | |
| if (kiwi._cookielife) { | |
| kiwi.cookie.life = JSON.parse(kiwi._cookielife); | |
| } | |
| kiwi._cookiesess = _satellite.getVar('Cookie - Kiwi Session'); | |
| if (kiwi._cookiesess) { | |
| kiwi.cookie.sess = JSON.parse(kiwi._cookiesess); | |
| } | |
| // general config | |
| kiwi.config = { | |
| subdomainsRegex: { | |
| legacyWAP: /^(account|scores)$/i | |
| } | |
| }; | |
| //Initialize kiwi._thisPage values | |
| kiwi._thisPage = kiwi.util.getThisPageSettings(); | |
| /* | |
| // Utilities | |
| Syntax: s.Util.getQueryParam(key, [url], [delim]) | |
| Parameters: | |
| key (required) The name of the query string parameter that you want to get. This parameter is case sensitive. | |
| url (optional) Default url is s.pageURL or window.location. Specifying a value for this parameter overrides the URL from which the query parameter is retrieved to the one specified. | |
| delim (optional) Parameter delimiter in the URL. Default delimiter is "&". This lets you to specify an alternate query-string delimiter, such as ";". | |
| */ | |
| /* Legacy H27.4 Utility Hacks by jbeach 6/29/2016 */ | |
| s.wd = s.w || window; | |
| s.epa = function (e) { | |
| var t, n, o = this; | |
| return e ? (e = o.rep('' + e, '+', ' '), | |
| 3 == o.em ? (n = new Function('x', 'var y,e;try{y=decodeURIComponent(x)}catch(e){y=unescape(x)}return y'), | |
| n(e)) : unescape(e)) : t; | |
| }; | |
| s.rep = function (e, t, n) { | |
| var o, i = new Array, r = 0; | |
| if (e) | |
| if (e.split) | |
| i = e.split(t); | |
| else if (t) | |
| for (; r >= 0;) | |
| o = e.indexOf(t, r), | |
| i[i.length] = e.substring(r, 0 > o ? e.length : o), | |
| r = o, | |
| r >= 0 && (r += t.length); | |
| else | |
| for (r = 0; r < e.length; r++) | |
| i[i.length] = e.substring(r, r + 1); | |
| if (e = '', | |
| o = i.length, | |
| i && o > 0 && (e = i[0], | |
| o > 1)) | |
| if (i.join) | |
| e = i.join(n); | |
| else | |
| for (r = 1; o > r; r++) | |
| e += n + i[r]; | |
| return e; | |
| }; | |
| s.fl=function(x,l){return x?(''+x).substring(0,l):x;}; | |
| /* end Legacy H27.4 Utility Hacks by jbeach 6/29/2016 */ | |
| /* eslint-disable */ | |
| // Utility Plugins | |
| /* | |
| * Plugin Utility Function: join | |
| */ | |
| s.join = new Function("v","p","" | |
| +"var s = this;var f,b,d,w;if(p){f=p.front?p.front:'';b=p.back?p.back" | |
| +":'';d=p.delim?p.delim:'';w=p.wrap?p.wrap:'';}var str='';for(var x=0" | |
| +";x<v.length;x++){if(typeof(v[x])=='object' )str+=s.join( v[x],p);el" | |
| +"se str+=w+v[x]+w;if(x<v.length-1)str+=d;}return f+str+b;"); | |
| /* | |
| * Plugin Utility Function: split v1.5 - split a string (JS 1.0 compatible) | |
| */ | |
| s.split=new Function("l","d","" | |
| +"var i,x=0,a=new Array;while(l){i=l.indexOf(d);i=i>-1?i:l.length;a[x" | |
| +"++]=l.substring(0,i);l=l.substring(i+d.length);}return a"); | |
| /* | |
| * Plugin Utility: apl v1.1 | |
| */ | |
| s.apl=new Function("l","v","d","u","" | |
| +"var s=this,m=0;if(!l)l='';if(u){var i,n,a=s.split(l,d);for(i=0;i<a." | |
| +"length;i++){n=a[i];m=m||(u==1?(n==v):(n.toLowerCase()==v.toLowerCas" | |
| +"e()));}}if(!m)l=l?l+d+v:v;return l"); | |
| /* | |
| * Utility Function: p_gn | |
| */ | |
| s.p_gn=new Function("t","h","" | |
| +"var i=t?t.indexOf('~'):-1,n,x;if(t&&h){n=i<0?'':t.substring(0,i);x=" | |
| +"t.substring(i+1);if(h.indexOf(x.toLowerCase())>-1)return n?n:'[[';}" | |
| +"return 0;"); | |
| /* | |
| * Utility Function: p_c | |
| */ | |
| s.p_c=new Function("v","c","" | |
| +"var x=v.indexOf('=');return c.toLowerCase()==v.substring(0,x<0?v.le" | |
| +"ngth:x).toLowerCase()?v:0"); | |
| /* | |
| * Utility Function: p_gh | |
| */ | |
| s.p_gh=new Function("" | |
| +"var s=this;if(!s.eo&&!s.lnk)return '';var o=s.eo?s.eo:s.lnk,y=s.ot(" | |
| +"o),n=s.oid(o),x=o.s_oidt;if(s.eo&&o==s.eo){while(o&&!n&&y!='BODY'){" | |
| +"o=o.parentElement?o.parentElement:o.parentNode;if(!o)return '';y=s." | |
| +"ot(o);n=s.oid(o);x=o.s_oidt}}return o.href?o.href:'';"); | |
| /* | |
| * Utility Function: p_fo | |
| */ | |
| s.p_fo=new Function("n","" | |
| +"var s=this;if(!s.__fo){s.__fo=new Object;}if(!s.__fo[n]){s.__fo[n]=" | |
| +"new Object;return 1;}else {return 0;}"); | |
| /* | |
| * pt - utility function | |
| */ | |
| s.pt=function(x,d,f,a){var s=this,t=x,z=0,y,r;while(t){y=t.indexOf(d);y=y<0?t.length:y;t=t.substring(0,y);r=s[f](t,a);if(r)return r;z+=y+d.length;t=x.substring(z,x.length);t=z<x.length?t:""}return""}; | |
| /* | |
| * Plugin Utility: Replace v1.0 | |
| */ | |
| s.repl=new Function("x","o","n","" | |
| +"var i=x.indexOf(o),l=n.length;while(x&&i>=0){x=x.substring(0,i)+n+x." | |
| +"substring(i+o.length);i=x.indexOf(o,i+l)}return x"); | |
| /* | |
| * Plugin: searchValue : 1.0 - searches string and returns value | |
| */ | |
| s.searchValue=new Function("p","d","u","vu","" | |
| +"var s=this,i,t,k,dl,mv,mm,rv,x;while(p){i=p.indexOf(',');i=i<0?p.le" | |
| +"ngth:i;k=p.substring(0,i);dl=k.indexOf(d);mv=k.substring(0,dl);mm=k" | |
| +".substring(dl+1);u=u+'';rv=vu?vu:mv;if(mm=='e'){x=u.indexOf(mv);if(" | |
| +"x>-1) return rv;}else{x=u.substring(mm,mv.length);if(mv==x) return " | |
| +"rv;}p=p.substring(i==p.length?i:i+1)}return ''"); | |
| /* | |
| * Plugin: getVisitStart v2.0 - returns 1 on 1st page of visit, else 0 | |
| */ | |
| s.getVisitStart=new Function("c","" | |
| +"var s=this,v=1,t=new Date;t.setTime(t.getTime()+1800000);if(s.c_r(c" | |
| +")){v=0}if(!s.c_w(c,1,t)){s.c_w(c,1,0)}if(!s.c_r(c)){v=0}return v;"); | |
| /* | |
| * getQueryParam v2.5 - H-code and AppMeasurement Compatible | |
| */ | |
| s.getQueryParam=function(p,d,u,h){var s=this,v="",i,j,t;d=d?d:"";u=u?u:s.pageURL?s.pageURL:s.wd?s.wd.location:window.location;while(p){i=p.indexOf(",");i=i<0?p.length:i;t=s.p_gpv(p.substring(0,i),u+"",h);if(t)t=t.indexOf("#")>-1?t.substring(0,t.indexOf("#")):t;if(t)v+=v?d+t:t;p=p.substring(i==p.length?i:i+1)}return v}; | |
| s.p_gpv=function(k,u,h){var s=this,v="",q;j=h==1?"#":"?";i=u.indexOf(j);if(k&&i>-1){q=u.substring(i+1);v=s.pt(q,"&","p_gvf",k)}return v}; | |
| s.p_gvf=function(t,k){if(t){var s=this,i=t.indexOf("="),p=i<0?t:t.substring(0,i),v=i<0?true:t.substring(i+1);if(p.toLowerCase()==k.toLowerCase())return s.epa?s.epa(v):s.unescape(v)}return""}; | |
| /* | |
| * Plugin: getPreviousValue_v1.0 - return previous value of designated | |
| * variable (requires split utility) | |
| */ | |
| s.getPreviousValue=new Function("v","c","el","" | |
| +"var s=this,t=new Date,i,j,r='';t.setTime(t.getTime()+1800000);if(el" | |
| +"){if(s.events){i=s.split(el,',');j=s.split(s.events,',');for(x in i" | |
| +"){for(y in j){if(i[x]==j[y]){if(s.c_r(c)) r=s.c_r(c);v?s.c_w(c,v,t)" | |
| +":s.c_w(c,'no value',t);return r}}}}}else{if(s.c_r(c)) r=s.c_r(c);v?" | |
| +"s.c_w(c,v,t):s.c_w(c,'no value',t);return r}"); | |
| // Plugins | |
| /* | |
| * Plugin: getTimeParting 3.4 | |
| */ | |
| s.getTimeParting=new Function("h","z","" | |
| +"var s=this,od;od=new Date('1/1/2000');if(od.getDay()!=6||od.getMont" | |
| +"h()!=0){return'Data Not Available';}else{var H,M,D,U,ds,de,tm,da=['" | |
| +"Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturda" | |
| +"y'],d=new Date();z=z?z:0;z=parseFloat(z);if(s._tpDST){var dso=s._tp" | |
| +"DST[d.getFullYear()].split(/,/);ds=new Date(dso[0]+'/'+d.getFullYea" | |
| +"r());de=new Date(dso[1]+'/'+d.getFullYear());if(h=='n'&&d>ds&&d<de)" | |
| +"{z=z+1;}else if(h=='s'&&(d>de||d<ds)){z=z+1;}}d=d.getTime()+(d.getT" | |
| +"imezoneOffset()*60000);d=new Date(d+(3600000*z));H=d.getHours();M=d" | |
| +".getMinutes();M=(M<10)?'0'+M:M;D=d.getDay();U=' AM';if(H>=12){U=' P" | |
| +"M';H=H-12;}if(H==0){H=12;}D=da[D];tm=H+':'+M+U;return(tm+'|'+D);}"); | |
| /* | |
| * Plugin: Days since last Visit 1.1 - capture time from last visit | |
| */ | |
| s.getDaysSinceLastVisit=new Function("c","" | |
| +"var s=this,e=new Date(),es=new Date(),cval,cval_s,cval_ss,ct=e.getT" | |
| +"ime(),day=24*60*60*1000,f1,f2,f3,f4,f5;e.setTime(ct+3*365*day);es.s" | |
| +"etTime(ct+30*60*1000);f0='Cookies Not Supported';f1='First Visit';f" | |
| +"2='More than 30 days';f3='More than 7 days';f4='Less than 7 days';f" | |
| +"5='Less than 1 day';cval=s.c_r(c);if(cval.length==0){s.c_w(c,ct,e);" | |
| +"s.c_w(c+'_s',f1,es);}else{var d=ct-cval;if(d>30*60*1000){if(d>30*da" | |
| +"y){s.c_w(c,ct,e);s.c_w(c+'_s',f2,es);}else if(d<30*day+1 && d>7*day" | |
| +"){s.c_w(c,ct,e);s.c_w(c+'_s',f3,es);}else if(d<7*day+1 && d>day){s." | |
| +"c_w(c,ct,e);s.c_w(c+'_s',f4,es);}else if(d<day+1){s.c_w(c,ct,e);s.c" | |
| +"_w(c+'_s',f5,es);}}else{s.c_w(c,ct,e);cval_ss=s.c_r(c+'_s');s.c_w(c" | |
| +"+'_s',cval_ss,es);}}cval_s=s.c_r(c+'_s');if(cval_s.length==0) retur" | |
| +"n f0;else if(cval_s!=f1&&cval_s!=f2&&cval_s!=f3&&cval_s!=f4&&cval_s" | |
| +"!=f5) return '';else return cval_s;"); | |
| /* | |
| * Plugin: getNewRepeat 1.2 - Returns whether user is new or repeat | |
| */ | |
| s.getNewRepeat=new Function("d","cn","" | |
| +"var s=this,e=new Date(),cval,sval,ct=e.getTime();d=d?d:30;cn=cn?cn:" | |
| +"'s_nr';e.setTime(ct+d*24*60*60*1000);cval=s.c_r(cn);if(cval.length=" | |
| +"=0){s.c_w(cn,ct+'-New',e);return'New';}sval=s.split(cval,'-');if(ct" | |
| +"-sval[0]<30*60*1000&&sval[1]=='New'){s.c_w(cn,ct+'-New',e);return'N" | |
| +"ew';}else{s.c_w(cn,ct+'-Repeat',e);return'Repeat';}"); | |
| /* | |
| * Plugin: getActionDepth v1.0 | |
| */ | |
| s.getActionDepth=new Function("c","" | |
| + "var s=this,v=1,t=new Date;t.setTime(t.getTime()+1800000);" | |
| + "if(!s.c_r(c)){v=1}if(s.c_r(c)){v=s.c_r(c);v++}" | |
| + "if(!s.c_w(c,v,t)){s.c_w(c,v,0)}return v;"); | |
| /* | |
| * Plugin: getValOnce_v1.11 | |
| */ | |
| s.getValOnce=new Function("v","c","e","t","" | |
| +"var s=this,a=new Date,v=v?v:'',c=c?c:'s_gvo',e=e?e:0,i=t=='m'?6000" | |
| +"0:86400000,k=s.c_r(c);if(v){a.setTime(a.getTime()+e*i);s.c_w(c,v,e" | |
| +"==0?0:a);}return v==k?'':v"); | |
| /* | |
| * Plugin: getPercentPageViewed v1.71 | |
| */ | |
| s.getPercentPageViewed=new Function("n","" | |
| +"var s=this,W=window,EL=W.addEventListener,AE=W.attachEvent,E=['load" | |
| +"','unload','scroll','resize','zoom','keyup','mouseup','touchend','o" | |
| +"rientationchange','pan'];W.s_Obj=s;s_PPVid=(n=='-'?s.pageName:n)||s" | |
| +".pageName||location.href;if(!W.s_PPVevent){s.s_PPVg=function(n,r){v" | |
| +"ar k='s_ppv',p=k+'l',c=s.c_r(n||r?k:p),a=c.indexOf(',')>-1?c.split(" | |
| +"',',10):[''],l=a.length,i;a[0]=unescape(a[0]);r=r||(n&&n!=a[0])||0;" | |
| +"a.length=10;if(typeof a[0]!='string')a[0]='';for(i=1;i<10;i++)a[i]=" | |
| +"!r&&i<l?parseInt(a[i])||0:0;if(l<10||typeof a[9]!='string')a[9]='';" | |
| +"if(r){s.c_w(p,c);s.c_w(k,'?')}return a};W.s_PPVevent=function(e){va" | |
| +"r W=window,D=document,B=D.body,E=D.documentElement,S=window.screen|" | |
| +"|0,Ho='offsetHeight',Hs='scrollHeight',Ts='scrollTop',Wc='clientWid" | |
| +"th',Hc='clientHeight',C=100,M=Math,J='object',N='number',s=W.s_Obj|" | |
| +"|W.s||0;e=e&&typeof e==J?e.type||'':'';if(!e.indexOf('on'))e=e.subs" | |
| +"tring(2);s_PPVi=W.s_PPVi||0;if(W.s_PPVt&&!e){clearTimeout(s_PPVt);s" | |
| +"_PPVt=0;if(s_PPVi<2)s_PPVi++}if(typeof s==J){var h=M.max(B[Hs]||E[H" | |
| +"s],B[Ho]||E[Ho],B[Hc]||E[Hc]),X=W.innerWidth||E[Wc]||B[Wc]||0,Y=W.i" | |
| +"nnerHeight||E[Hc]||B[Hc]||0,x=S?S.width:0,y=S?S.height:0,r=M.round(" | |
| +"C*(W.devicePixelRatio||1))/C,b=(D.pageYOffset||E[Ts]||B[Ts]||0)+Y,p" | |
| +"=h>0&&b>0?M.round(C*b/h):0,O=W.orientation,o=!isNaN(O)?M.abs(o)%180" | |
| +":Y>X?0:90,L=e=='load'||s_PPVi<1,a=s.s_PPVg(s_PPVid,L),V=function(i," | |
| +"v,f,n){i=parseInt(typeof a==J&&a.length>i?a[i]:'0')||0;v=typeof v!=" | |
| +"N?i:v;v=f||v>i?v:i;return n?v:v>C?C:v<0?0:v};if(new RegExp('(iPod|i" | |
| +"Pad|iPhone)').exec(navigator.userAgent||'')&&o){o=x;x=y;y=o}o=o?'P'" | |
| +":'L';a[9]=L?'':a[9].substring(0,1);s.c_w('s_ppv',escape(W.s_PPVid)+" | |
| +"','+V(1,p,L)+','+(L||!V(2)?p:V(2))+','+V(3,b,L,1)+','+X+','+Y+','+x" | |
| +"+','+y+','+r+','+a[9]+(a[9]==o?'':o))}if(!W.s_PPVt&&e!='unload')W.s" | |
| +"_PPVt=setTimeout(W.s_PPVevent,333)};for(var f=W.s_PPVevent,i=0;i<E." | |
| +"length;i++)if(EL)EL(E[i],f,false);else if(AE)AE('on'+E[i],f);f()};v" | |
| +"ar a=s.s_PPVg();return!n||n=='-'?a[1]:a"); | |
| /* | |
| * Plugin: Performance Timing Tracking - 0.1 BETA | |
| */ | |
| s.performanceTiming=new Function("v","" | |
| +"var s=this;if(v)s.ptv=v;if(typeof performance!='undefined'){if(perf" | |
| +"ormance.timing.loadEventEnd==0){s.pi=setInterval(function(){s.perfo" | |
| +"rmanceWrite()},250);}if(!s.ptc||s.linkType=='e'){s.performanceRead(" | |
| +");}else{s.rfe();s[s.ptv]='';}}"); | |
| s.performanceWrite=new Function("","" | |
| +"var s=this;if(performance.timing.loadEventEnd>0)clearInterval(s.pi)" | |
| +";try{if(s.c_r('s_ptc')==''&&performance.timing.loadEventEnd>0){try{" | |
| +"var pt=performance.timing;var pta='';pta=s.performanceCheck(pt.fetc" | |
| +"hStart,pt.navigationStart);pta+='^^'+s.performanceCheck(pt.domainLo" | |
| +"okupStart,pt.fetchStart);pta+='^^'+s.performanceCheck(pt.domainLook" | |
| +"upEnd,pt.domainLookupStart);pta+='^^'+s.performanceCheck(pt.connect" | |
| +"End,pt.connectStart);pta+='^^'+s.performanceCheck(pt.responseStart," | |
| +"pt.connectEnd);pta+='^^'+s.performanceCheck(pt.responseEnd,pt.respo" | |
| +"nseStart);pta+='^^'+s.performanceCheck(pt.loadEventStart,pt.domLoad" | |
| +"ing);pta+='^^'+s.performanceCheck(pt.loadEventEnd,pt.loadEventStart" | |
| +");pta+='^^'+s.performanceCheck(pt.loadEventEnd,pt.navigationStart);" | |
| +"s.c_w('s_ptc',pta);if(sessionStorage&&navigator.cookieEnabled&&s.pt" | |
| +"v!='undefined'){var pe=performance.getEntries();var tempPe='';for(v" | |
| +"ar i=0;i<pe.length;i++){tempPe+='!';tempPe+=pe[i].name.indexOf('?')" | |
| +">-1?pe[i].name.split('?')[0]:pe[i].name;tempPe+='|'+(Math.round(pe[" | |
| +"i].startTime)/1000).toFixed(1)+'|'+(Math.round(pe[i].duration)/1000" | |
| +").toFixed(1)+'|'+pe[i].initiatorType;}sessionStorage.setItem('s_pec" | |
| +"',tempPe);}}catch(err){return;}}}catch(err){return;}"); | |
| s.performanceCheck=new Function("a","b","" | |
| +"if(a>=0&&b>=0){if((a-b)<60000&&((a-b)>=0)){return((a-b)/1000).toFix" | |
| +"ed(2);}else{return 600;}}"); | |
| s.performanceRead=new Function("","" | |
| +"var s=this;if(performance.timing.loadEventEnd>0)clearInterval(s.pi)" | |
| +";var cv=s.c_r('s_ptc');if(s.pte){var ela=s.pte.split(',');}if(cv!='" | |
| +"'){var cva=s.split(cv,'^^');if(cva[1]!=''){for(var x=0;x<(ela.lengt" | |
| +"h-1);x++){s.events=s.apl(s.events,ela[x]+'='+cva[x],',',2);}}s.even" | |
| +"ts=s.apl(s.events,ela[ela.length-1],',',2);}s.linkTrackEvents=s.apl" | |
| +"(s.linkTrackEvents,s.pte,',',2);s.c_w('s_ptc','',0);if(sessionStora" | |
| +"ge&&navigator.cookieEnabled&&s.ptv!='undefined'){s[s.ptv]=sessionSt" | |
| +"orage.getItem('s_pec');sessionStorage.setItem('s_pec','',0);}else{s" | |
| +"[s.ptv]='sessionStorage Unavailable';}s.ptc=true;"); | |
| s.rfe=new Function("","" | |
| +"var s=this;var ea=s.split(s.events,',');var pta=s.split(s.pte,',');" | |
| +"try{for(x in pta){var ptr=new RegExp(pta[x]+'[^\,][0-9]*\.[0-9](.*)" | |
| +"');s.events=s.events.match(ptr)[1];s.contextData['events']=s.events" | |
| +";}}catch(e){return;}"); | |
| /* Plugin: channelManager v3.06 */ | |
| /* channelManager seList (Top 40 Search Engines) */ | |
| s.seList="google.,googlesyndication.com,.googleadservices.com|q,as_q|Google>bing.com|q|Bing>yahoo.com,yahoo.co.jp|p,va|Yahoo!>ask.jp,ask.co|q,ask|Ask>search.aol.,suche.aolsvc.de|q,query|AOL>altavista.co,altavista.de|q,r|AltaVista>.mywebsearch.com|searchfor|MyWebSearch>webcrawler.com|q|WebCrawler>wow.com|q|Wow>infospace.com|q|InfoSpace>blekko.com|q|Blekko>dogpile.com|q|DogPile>alhea.com|q|Alhea>duckduckgo.com|q|DuckDuckGo>info.com|qkw|Info.com>contenko.com|q|Contenko>baidu.com|word,wd|Baidu>daum.net,search.daum.net|q|Daum>icqit.com|q|icq>myway.com|searchfor|MyWay.com>naver.com,search.naver.com|query|Naver>netscape.com|query,search|Netscape Search>reference.com|q|Reference.com>seznam|w|Seznam.cz>abcsok.no|q|Startsiden>tiscali.it,www.tiscali.co.uk|key,query|Tiscali>virgilio.it|qs|Virgilio>yandex|text|Yandex.ru>optimum.net|q|Optimum Search>search.earthlink.net|q|Earthlink>search.comcast.net|q|Comcast>libero.it|query|libero.it>excite.co|search|Excite>mail.ru|q|Mail.ru>isearch.avg.com|q|AVG>msn.com|q|MSN>seznam.cz|q|seznam.cz>so.com|q|so.com>ixquick.com|query|ixquick.com>sogou.com|query|sogou.com>360.cn|q|360.cn"; | |
| s._channelDomain="Partner Sites|khanacademy.org,roadtripnation.com,epiconline.org,accuplacer.org"; | |
| s._channelParameter="Email|ep_mid"; | |
| s._channelPattern="Email|em>Triggered|tr>External Email|ex>SMS|tx>Offline Marketing|mtg,cb,dm>Online Media|oc>Social Media|sm,fb>Outbound Callers|ob>Push Notifications|ph>Affiliates|af>Vanity URLs|vt>Partner Sites|pt"; | |
| s.channelManager=function(a,b,c,d,e,f,g){var s=this,h=new Date,i=0,j,k,l,m,n,o,p,q,r,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V;U=s.getQueryParam?1:0;V=s.repl?1:0;if(e){i=1;if(s.c_r(e))i=0;h.setTime(h.getTime()+18E5);s.c_w(e,1,h);if(f&&s.c_r("s_tbm"+e+f.toString()))i=0}j=s.referrer?s.referrer:document.referrer;if(j=="Typed/Bookmarked")j="";j=decodeURIComponent(j.toLowerCase());if(!j)k=1;else{l=j.indexOf("?")>-1?j.indexOf("?"):j.length;m=j.substring(0,l);n=j.split("/");n=n[2].split("?"); | |
| o=n[0].toLowerCase();p=s.linkInternalFilters.toLowerCase();p=p.split(",");for(q=0;q<p.length;q++){r=o.indexOf(p[q])==-1?"":j;if(r)break}}if(!r&&!k){t=j;u=o;w="Other Natural Referrers";v=w+": "+o;x=s.seList+">"+s._extraSearchEngines;if(d==1){m=V?s.repl(m,"oogle","%"):s.replace(m,"oogle","%");m=V?s.repl(m,"ahoo","^"):s.replace(m,"ahoo","^");j=V?s.repl(j,"as_q","*"):s.replace(j,"as_q","*")}y=x.split(">");for(z=0;z<y.length;z++){A=y[z];A=A.split("|");B=A[0].split(",");for(C=0;C<B.length;C++){D=m.indexOf(B[C]); | |
| if(D>-1){if(A[2])E=v=A[2];else E=o;if(d==1){E=V?s.repl(E,"#"," - "):s.replace(E,"#"," - ");j=V?s.repl(j,"*","as_q"):s.replace(j,"*","as_q");E=V?s.repl(E,"^","ahoo"):s.replace(E,"^","ahoo");E=V?s.repl(E,"%","oogle"):s.replace(E,"%","oogle")}F=A[1].split(",");for(G=0;G<F.length;G++){if(j.indexOf(F[G]+"=")>-1||j.indexOf("duckduckgo")>-1||j.indexOf("googlequicksearchbox")>-1||j.indexOf("http://www.google.")==0||j.indexOf("https://www.google.")==0||j.indexOf("https://search.yahoo.com/")==0||j.indexOf("http://r.search.yahoo.com")== | |
| 0||j.indexOf("https://www.bing.com")==0)H=1;I=U?s.getQueryParam(F[G],"",j).toLowerCase():s.Util.getQueryParam(F[G],j).toLowerCase();if(H||I)break}}if(H||I)break}if(H||I)break}}if(!r||g!="1"){J=a.split(",");for(var q in J)if(J.hasOwnProperty(q))if(U?s.getQueryParam(J[q]):s.Util.getQueryParam(J[q]))if(b)T=T?T+b+(U?s.getQueryParam(J[q]):s.Util.getQueryParam(J[q])):U?s.getQueryParam(J[q]):s.Util.getQueryParam(J[q]);else{T=U?s.getQueryParam(J[q]):s.Util.getQueryParam(J[q]);if(T)break}if(T){v=T;if(E)w= | |
| "Paid Search";else w="Unknown Paid Channel"}if(!T&&E&&H){w="Natural Search";v=w+": "+E}}if(i&&k&&!T)t=u=v=w="Typed/Bookmarked";J=s._channelDomain;if(J&&o&&!r){K=J.split(">");for(L=0;L<K.length;L++){M=K[L]?K[L].split("|"):"";N=M[1]?M[1].split(","):"";O=N.length;for(P=0;P<O;P++){Q=N[P].toLowerCase();R=("/"+o).indexOf(Q);if(R>-1){w=M[0];v=T?v:w+": "+o;break}}if(R>-1)break}}J=s._channelParameter;if(J&&g!="1"){K=J.split(">");for(L=0;L<K.length;L++){M=K[L]?K[L].split("|"):"";N=M[1]?M[1].split(","):"";O= | |
| N.length;for(P=0;P<O;P++){R=U?s.getQueryParam(N[P]):s.Util.getQueryParam(N[P]);if(R){w=M[0];v=T?v:w+": "+o;break}}if(R)break}}J=s._channelPattern;if(J&&g!="1"&&T){K=J.split(">");for(L=0;L<K.length;L++){M=K[L]?K[L].split("|"):"";N=M[1]?M[1].split(","):"";O=N.length;for(P=0;P<O;P++){Q=N[P].toLowerCase();R=T?T.toLowerCase():"";S=R.indexOf(Q);if(S==0){w=M[0];break}}if(S==0)break}}S=w?T+u+w+I:"";c=c?c:"c_m";if(c!="0")S=s.getValOnce(S,c,0);if(S){s._campaignID=T?T:"n/a";s._referrer=t?t:"n/a";s._referringDomain= | |
| u?u:"n/a";s._campaign=v?v:"n/a";s._channel=w?w:"n/a";s._partner=E?E:"n/a";s._keywords=H?I?I:"Keyword Unavailable":"n/a";if(f&&w!="Typed/Bookmarked"){h.setTime(h.getTime()+f*864E5);s.c_w("s_tbm"+e+f.toString(),1,h)}}else s._campaignID=s._referrer=s._referringDomain=s._campaign=s._channel=s._partner=s._keywords=""}; | |
| /* | |
| * Plugin: setupLinkTrack v3.02AM | |
| */ | |
| s.setupLinkTrack=new Function("vl","c","e","" | |
| +"var cv=s.c_r(c);if(vl){var vla=vl.split(',');}if(cv!=''){var cva=s." | |
| +"split(cv,'^^');if(cva[1]!=''){for(x in vla){s[vla[x]]=cva[x];if(e){" | |
| +"s.events=s.apl(s.events,e,',',2);}}}}s.c_w(c,'',0);if(typeof s.link" | |
| +"Object!='undefined'&&s.hbx_lt!='manual'){s.lta=[];if(typeof s.pageN" | |
| +"ame!='undefined')s.lta[0]=s.pageName;if(typeof s.linkObject!=null){" | |
| +"slo=s.linkObject;if(s.linkObject!=0){if(s.linkObject.getAttribute('" | |
| +"name')!=null){var b=s.linkObject.getAttribute('name');if(b.indexOf(" | |
| +"'&lpos=')>-1){s.lta[3]=b.match('\&lpos\=([^\&]*)')[1];}if(b.indexOf" | |
| +"('&lid=')>-1){s.lta[1]=b.match('\&lid\=([^\&]*)')[1];}}}if(typeof s" | |
| +".lta[1]=='undefined'){if(s.linkName!=0){s.lta[1]=s.linkName;}else i" | |
| +"f(s.linkObject!=0){if(s.linkObject.innerHTML.indexOf('<img')>-1){s." | |
| +"lta[1]=s.linkObject.innerHTML.match('src=\"([^\"]*)')[1]}else{s.lta[1" | |
| +"]=s.linkObject.innerHTML;}}}s.lta[2]=s.pageName+' | '+s.lta[1];}if(" | |
| +"s.linkType!=0){for(var x=0;x<vla.length;x++){s[vla[x]]=s.cleanStr(s" | |
| +".lta[x]);if(e){s.events=s.apl(s.events,e,',',2);s.linkTrackVars=s.a" | |
| +"pl(s.linkTrackVars,'events',',',2);}}s.linkTrackVars=s.apl(s.linkTr" | |
| +"ackVars,vl,',',2);}else{if(s.lta[1]){var tcv='';for(var x=0;x<s.lta" | |
| +".length;x++){tcv+=s.cleanStr(s.lta[x])+'^^'}s.c_w(c,tcv)}}s.lta=nul" | |
| +"l;}"); | |
| s.cleanStr = function(a){ | |
| if(typeof a != 'undefined'){ | |
| a = a.replace(/<\/?span[^>]*>/g, ''); | |
| return a; | |
| } | |
| }; | |
| /* eslint-enable */ | |
| /************************** DELAY TRACKING SECTION ***************/ | |
| ruleName='KIWI: Tool > Analytics > Custom JS > DELAY TRACKING SECTION'; | |
| //suppress default page load track | |
| kiwi._suppressTrack = true; | |
| // send an event that aa page is ready to track | |
| document.dispatchEvent(new CustomEvent('kiwi.ready.aa', {'bubbles': true})); | |
| if(kiwi._suppressTrack) return false; | |
| } | |
| }, | |
| "e653cea501cb1b08dbc50ef2f1550ad79f81a499": { | |
| "engine": "tnt", | |
| "mboxURL": "7a8a98de0363fbed05b98da851d6b23866ffa7cc/mbox-contents-e653cea501cb1b08dbc50ef2f1550ad79f81a499.js", | |
| "loadSync": true, | |
| "pageParams": { | |
| } | |
| }, | |
| "8c94c038e1dbec941007f34bc69cd4bc3e4b08bc": { | |
| "engine": "visitor_id", | |
| "loadOn": "pagetop", | |
| "name": "VisitorID", | |
| "mcOrgId": "5E1B123F5245B29B0A490D45@AdobeOrg", | |
| "autoRequest": true, | |
| "initVars": { | |
| }, | |
| "customerIDs": { | |
| "crm_id": { | |
| "id": "%Kiwi - CRM ID%", | |
| "authState": "AUTHENTICATED" | |
| } | |
| } | |
| } | |
| }, | |
| "pageLoadRules": [ | |
| {"name":"00 Master - Page Bottom","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-57bf401064746d361f0064e4.js"}]}]}],"event":"pagebottom"}, | |
| {"name":"00 Master - Page Top","trigger":[{"command":"loadBlockingScript","arguments":[{"sequential":true,"scripts":[{"src":"satellite-5a81e11664746d5ff700072d.js"},{"src":"satellite-578e6f6764746d29b90028de.js"},{"src":"satellite-5d8a7a5864746d1e5c001919.js"},{"src":"satellite-5d70120c64746d7144003d1b.js"},{"src":"satellite-5d84ef3264746d48820000fe.js"},{"src":"satellite-5dc5a5ef64746d437e000137.js"}]}]}],"event":"pagetop"}, | |
| {"name":"APRO - DOM Ready","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5d8cf59664746d2d8e000439.js"}]}]}],"scope":{"URI":{"include":[/^\/($|\?)/i]},"subdomains":{"include":[/^apstudents\.collegeboard\.org$/i]}},"event":"domready"}, | |
| {"name":"Big Future - Page Top - Video Tracking","trigger":[{"command":"loadBlockingScript","arguments":[{"sequential":true,"scripts":[{"src":"satellite-58cae8d364746d0bb40060af.js"},{"src":"satellite-58caea1264746d2cd0007976.js"}]}]}],"scope":{"subdomains":{"include":["^bigfuture\\."]}},"event":"pagetop"}, | |
| {"name":"DOM Ready - bfm","trigger":[{"command":"loadScript","arguments":[{"sequential":true,"scripts":[{"src":"satellite-5d45a25764746d56f6000ec3.js"}]}]}],"scope":{"subdomains":{"include":[/^bigfuture\.collegeboard\.org$/i]}},"event":"domready"}, | |
| {"name":"MBOX nsat-orf-button-continue","trigger":[{"engine":"tnt","command":"addMbox","arguments":[{"mboxGoesAround":"#authenticatePage","mboxName":"nsat-orf-button-continue","arguments":[],"timeout":"1500"}]}],"scope":{"URI":{"include":["satweb/registration/viewAuthenticateStudentAction.action"]},"subdomains":{"include":["nsat.collegeboard.org"]}},"event":"pagebottom"}, | |
| {"name":"MBOX nsat-orf-pst-mainContainer","trigger":[{"engine":"tnt","command":"addMbox","arguments":[{"mboxGoesAround":".pst-mainContainer","mboxName":"nsat-orf-pst-mainContainer","arguments":[],"timeout":"1500"}]}],"scope":{"URI":{"include":["satweb/registration/viewAuthenticateStudentAction.action"]},"subdomains":{"include":["nsat.collegeboard.org"]}},"event":"pagetop"}, | |
| {"name":"MBOX nsat-orf-s2-horizontal-step","trigger":[{"engine":"tnt","command":"addMbox","arguments":[{"mboxGoesAround":".row.s2-horizontal-step","mboxName":"nsat-orf-s2-horizontal-step","arguments":[],"timeout":"1500"}]}],"scope":{"URI":{"include":["satweb/registration/viewAuthenticateStudentAction.action"]},"subdomains":{"include":["nsat.collegeboard.org"]}},"event":"pagebottom"}, | |
| {"name":"NSAT - MySAT - COVID-19 Alert","trigger":[{"command":"loadScript","arguments":[{"sequential":true,"scripts":[{"src":"satellite-5e6f910964746d2d2e00046d.js"}]}]}],"scope":{"URI":{"include":["satweb/satHomeAction.action"]},"subdomains":{"include":[/^nsat\.collegeboard\.org$/i]}},"event":"domready"}, | |
| {"name":"NSAT - MySAT - DOM Ready","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5ae75b3164746d59980008bb.js"}]}]}],"scope":{"URI":{"include":["satweb/satHomeAction.action"]},"subdomains":{"include":[/^nsat\.collegeboard\.org$/i]}},"event":"domready"}, | |
| {"name":"NSAT - ST Listening Avail (PLR)","trigger":[{"command":"loadScript","arguments":[{"sequential":true,"scripts":[{"src":"satellite-5ed6966a64746d47ca000d77.js"}]}]}],"scope":{"subdomains":{"include":[/^nsat\.collegeboard\.org$/i]}},"event":"domready"}, | |
| {"name":"NSAT - Test Center Avail","trigger":[{"command":"loadScript","arguments":[{"sequential":true,"scripts":[{"src":"satellite-5ed5798964746d511f0000f3.js"}]}]}],"scope":{"subdomains":{"include":[/^nsat\.collegeboard\.org$/i]}},"event":"domready"}, | |
| {"name":"Page Top - aps","trigger":[{"command":"loadBlockingScript","arguments":[{"sequential":true,"scripts":[{"src":"satellite-5a1dcffe64746d671f008065.js"}]}]}],"scope":{"subdomains":{"include":[/^apstudent.*\./i]}},"event":"pagebottom"}, | |
| {"name":"Page Top - bf","trigger":[{"command":"loadBlockingScript","arguments":[{"sequential":true,"scripts":[{"src":"satellite-58c01a0964746d0bba00152a.js"}]}]}],"scope":{"subdomains":{"include":[/^bigfuture\.collegeboard\.org$/i]}},"event":"pagetop"}, | |
| {"name":"Pages - Download - DOM Ready","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5c795b2c64746d226c002a8d.js"}]}]}],"scope":{"URI":{"include":[/^\/download(\/?|$)/i]},"subdomains":{"include":[/^pages\.collegeboard\.org$/i]},"domains":[/collegeboard\.org$/i]},"event":"domready"}, | |
| {"name":"Pixel - Alorica - Live Agent - APC","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5c75a3ca64746d6c4400069c.js"}]}]}],"scope":{"subdomains":{"include":[/^apcentral(-stg)?\.collegeboard\.org$/i]},"domains":[/collegeboard\.org$/i]},"conditions":[function(event,target){ | |
| /** | |
| * Logic Provided by Dianna Choi in 2019-02 | |
| * https://jira.collegeboard.org/browse/WAP-2266 | |
| * Configured by jbeach on 2019-02-28 | |
| **/ | |
| //include all of apcentral | |
| var bInclude = true, | |
| bMatchFound = false; | |
| //but exclude these paths... | |
| if (document.location.pathname.match(/^\/(about-ap|content|courses|professional-development|score-reports-data\/awards|series|start-grow-ap\/international)/) !== null) { | |
| bInclude = false; | |
| //but include these again... | |
| bInclude = bMatchFound = (document.location.pathname.match(/^\/courses$/) !== null); | |
| if (!bMatchFound) bInclude = bMatchFound = (document.location.pathname.match(/^\/about-ap$/) !== null); | |
| if (!bMatchFound) bInclude = bMatchFound = (document.location.pathname.match(/^\/courses\/exam-dates-and-fees/) !== null); | |
| if (!bMatchFound) bInclude = bMatchFound = (document.location.pathname.match(/^\/courses\/.*\/(course|exam|portfolio|application-timeline)$/) !== null); | |
| if (!bMatchFound) bInclude = bMatchFound = (document.location.pathname.match(/^\/series\/(ap-coordinator-tutorial|studio-art-submission-demo-ap-coordinators|studio-art-submission-demo-ap-teachers)/) !== null); | |
| if (!bMatchFound && document.location.pathname.match(/^\/about-ap\//) !== null) { | |
| bInclude = true; | |
| bMatchFound = ( | |
| (document.location.pathname.match(/^\/about-ap\/how-ap-develops-courses-and-exams/) !== null) || | |
| (document.location.pathname.match(/^\/about-ap\/news-changes\/(ap-2019\/frequently-asked-questions|ap-2019\/support-students-new-online-tools|collaborations-with-ap)/) !== null) || | |
| (document.location.pathname.match(/^\/about-ap\/start-grow-ap\/(access-initiatives|ap-advocates-program|grow-ap\/spotlight-on-success|outreach-support-resources)/) !== null) | |
| ); | |
| if(bMatchFound) bInclude = false; | |
| bMatchFound = true; | |
| } | |
| if (!bMatchFound && document.location.pathname.match(/^\/courses\//) !== null) { | |
| if (document.location.pathname.match(/^\/courses\/(2019-20-course-exam-description-pre-order-form|ap-course-audit|collaborations-with-ap|resources)/) !== null) { | |
| bInclude = false; | |
| bMatchFound = true; | |
| } | |
| if (!bMatchFound && document.location.pathname.match(/^\/courses\/.*/) !== null) { | |
| bInclude = bMatchFound = (document.location.pathname.match(/^\/courses\/[^\/]*$/) !== null); | |
| } | |
| } | |
| } | |
| return bInclude; | |
| /* | |
| For the courses, URLs that end in the following should fire the chat, but any child pages under those directories should not: | |
| รขโฌยข courses/_/course | |
| รขโฌยข courses/_/exam | |
| รขโฌยข courses/_/portfolio | |
| Additionally, any course page URLs that end in the following or the child pages under them should not fire the chat: | |
| รขโฌยข courses/_/course-audit | |
| รขโฌยข courses/_/classroom-resources | |
| รขโฌยข courses/_/professional-development | |
| */ | |
| /* | |
| NOT HERE: | |
| about-ap/news-changes/ap-2019/frequently-asked-questions | |
| about-ap/how-ap-develops-courses-and-exams | |
| about-ap/news-changes/collaborations-with-ap | |
| about-ap/news-changes/ap-2019/support-students-new-online-tools | |
| about-ap/start-grow-ap/access-initiatives | |
| about-ap/start-grow-ap/ap-advocates-program | |
| about-ap/start-grow-ap/grow-ap/spotlight-on-success | |
| about-ap/start-grow-ap/outreach-support-resources | |
| content | |
| courses/2019-20-course-exam-description-pre-order-form | |
| courses/ap-course-audit | |
| courses/collaborations-with-ap | |
| courses/resources | |
| courses/_/[any not listed below], e.g. | |
| courses/_/course-audit | |
| courses/_/classroom-resources | |
| courses/_/professional-development | |
| courses/_/course/_ | |
| courses/_/exam/_ | |
| courses/_/portfolio/_ | |
| professional-development | |
| score-reports-data/awards | |
| series/[not listed below] | |
| start-grow-ap/international | |
| YES HERE: | |
| (_ = any value) [any not listed above] | |
| courses | |
| /courses/exam-dates-and-fees | |
| /courses/exam-dates-and-fees/_ | |
| courses/_ | |
| courses/_/course | |
| courses/_/exam | |
| courses/_/portfolio | |
| courses/_/application-timeline | |
| courses/_/exam-dates-2020 | |
| courses/_/late-testing-dates | |
| courses/_/late-testing-dates-2020 | |
| series/ap-coordinator-tutorial | |
| series/studio-art-submission-demo-ap-coordinators | |
| series/studio-art-submission-demo-ap-teachers | |
| */ | |
| }],"event":"pagebottom"}, | |
| {"name":"Pixel - Alorica - Live Agent - CLEP","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5e7dfd8264746d122b0022a6.js"}]}]}],"scope":{"URI":{"include":[/^\/help-for-students(\/|$)/i]},"subdomains":{"include":[/^clep(-stg)?\.collegeboard\.org$/i]}},"event":"pagebottom"}, | |
| {"name":"Pixel - Aimtell","trigger":[{"command":"loadBlockingScript","arguments":[{"sequential":true,"scripts":[{"src":"satellite-5a5f68c664746d43530021ff.js"}]}]}],"scope":{"subdomains":{"include":[/^(advancesinap|apcentral|apcentral-stg|blog)\.collegeboard\.org/i,/^(collegereadiness|counselors|sat-stage)\.collegeboard\.org/i,/^(pages|pages-stg|parents)\.collegeboard\.org/i,/^(dreamdeferred|forum|nasai|preparate|regionalforums|newenglandforum|middlestatesforum|southernforum|midwesternforum|westernforum|southwesternforum)(-stg)?\.collegeboard\.org/i,/^(apac|apac-stg)\.collegeboard\.org/i,/^(opportunity|opportunity-stg)\.collegeboard\.org/i,/^(apstudents|apstudents-stg)\.collegeboard\.org/i]}},"event":"pagebottom"}, | |
| {"name":"Pixel - Aimtell - Page Views","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5e559fac64746d0821001c05.js"}]}]}],"scope":{"subdomains":{"include":[/^(apstudents|go|signup|pages)\.collegeboard\.org/i]}},"event":"windowload"}, | |
| {"name":"Pixel - DM - AdMedia","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5d6fb1c664746d5140000012.js"}]}]}],"scope":{"subdomains":{"include":[/^collegereadiness\.collegeboard\.org$/i]},"domains":[/collegeboard\.org$/i]},"conditions":[function(event,target){ | |
| var cmet = true; | |
| if (_satellite.getVar('QP userName') || document.referrer.match(/userName=[^\&]+/)) { | |
| cmet = false; | |
| } | |
| return cmet; | |
| }],"event":"windowload"}, | |
| {"name":"Pixel - DM - Bing Ads","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5b4524fd64746d1adb00923e.js"}]}]}],"scope":{"domains":[/collegeboard\.org$/i]},"conditions":[function(event,target){ | |
| var cmet = true; | |
| if (_satellite.getVar('QP userName') || document.referrer.match(/userName=[^\&]+/)) { | |
| cmet = false; | |
| } | |
| return cmet; | |
| }],"event":"pagebottom"}, | |
| {"name":"Pixel - DM - Division D - TTD","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5d1a7e7364746d2e8b0012e8.js"}]}]}],"scope":{"URI":{"include":["cbos-pledge"]},"subdomains":{"include":[/^signup\.collegeboard\.org$/i]},"domains":[/collegeboard\.org$/i]},"conditions":[function(event,target){ | |
| var cmet = true; | |
| if (_satellite.getVar('QP userName') || document.referrer.match(/userName=[^\&]+/)) { | |
| cmet = false; | |
| } | |
| return cmet; | |
| }],"event":"pagebottom"}, | |
| {"name":"Pixel - DM - Division D - Yahoo","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5b9931d464746d6dc000024d.js"}]}]}],"scope":{"subdomains":{"include":[/^(bigfuture|collegereadiness|go|signup|studentscores)\.collegeboard\.org$/i]},"domains":[/collegeboard\.org$/i]},"conditions":[function(event,target){ | |
| var cmet = true; | |
| if (_satellite.getVar('QP userName') || document.referrer.match(/userName=[^\&]+/)) { | |
| cmet = false; | |
| } | |
| if (cmet) { | |
| kiwi = window.kiwi || {}; | |
| kiwi.pixels = kiwi.pixels || {}; | |
| kiwi.pixels.divisiond = kiwi.pixels.divisiond || {}; | |
| kiwi.pixels.divisiond.yahoo = kiwi.pixels.divisiond.yahoo || {}; | |
| var host = document.location.host, | |
| path = document.location.pathname, | |
| hash = document.location.hash; | |
| kiwi.pixels.divisiond.yahoo.projectId = '10000'; | |
| kiwi.pixels.divisiond.yahoo.pixelId = '10063589'; | |
| switch (host) { | |
| case 'bigfuture.collegeboard.org': | |
| //display on specific pages | |
| if (path.match(/^\/(scholarship-search|pay-for-college\/grants-scholarships|college-search)$/i)) { | |
| cmet = true; | |
| } | |
| break; | |
| case 'collegereadiness.collegeboard.org': | |
| //display on specific pages | |
| if (path.match(/^\/sat\/register\/find-test-centers$/i)) { | |
| cmet = true; | |
| } | |
| break; | |
| case 'go.collegeboard.org': | |
| //display on specific pages | |
| if (path.match(/^\/(your-)?best-test$/i)) { //Students + Parents Lead Form + Conversion | |
| cmet = true; | |
| } | |
| break; | |
| case 'signup.collegeboard.org': | |
| //display on specific pages | |
| if (path.match(/^\/next-step-sat\/$/i)) { | |
| cmet = true; | |
| } | |
| break; | |
| case 'studentscores.collegeboard.org': | |
| //display on specific pages | |
| if (path.match(/^\/viewscore$/i)) { | |
| cmet = true; | |
| } | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| return cmet; | |
| }],"event":"pagebottom"}, | |
| {"name":"Pixel - DM - Facebook","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5b3fbc7264746d6050009413.js"}]}]}],"scope":{"subdomains":{"include":[/^(account|bigfuture|cbaccount|clep|clepportal|collegereadiness|go|nsat|opportunity|pages|parents|signup|studentscores)\.collegeboard\.org$/i]}},"conditions":[function(event,target){ | |
| var cmet = true; | |
| if (_satellite.getVar('QP userName') || document.referrer.match(/userName=[^\&]+/)) { | |
| cmet = false; | |
| } | |
| if (cmet) { | |
| kiwi = window.kiwi || {}; | |
| kiwi.pixelTriggers = kiwi.pixelTriggers || {}; | |
| kiwi.pixelTriggers.fb = kiwi.pixelTriggers.fb || {}; | |
| kiwi.pixelTriggers.fb.cbMain = kiwi.pixelTriggers.fb.cbMain || {}; | |
| kiwi.pixelTriggers.fb.cbIndia = kiwi.pixelTriggers.fb.cbIndia || {}; | |
| var ruleName='KIWI: PLR > Pixel - Facebook > Condition'; | |
| _satellite.notify(ruleName); | |
| var cmet = true, | |
| host = document.location.host, | |
| path = document.location.pathname, | |
| hash = document.location.hash, | |
| params = document.location.search; | |
| switch (host) { | |
| case 'bigfuture.collegeboard.org': | |
| case 'clep.collegeboard.org': | |
| case 'clepportal.collegeboard.org': | |
| case 'collegereadiness.collegeboard.org': | |
| case 'opportunity.collegeboard.org': | |
| case 'parents.collegeboard.org': | |
| case 'studentscores.collegeboard.org': | |
| cmet = kiwi.pixelTriggers.fb.cbMain.init = true; | |
| kiwi.pixelTriggers.fb.cbMain.view = true; | |
| break; | |
| case 'go.collegeboard.org': | |
| cmet = kiwi.pixelTriggers.fb.cbMain.init = true; | |
| kiwi.pixelTriggers.fb.cbMain.view = true; | |
| //conversion event | |
| if (path.match(/^\/(your-best-test|best-test)$/i) && | |
| hash.match(/^#thank-you/i)) { | |
| kiwi.pixelTriggers.fb.cbMain.lead = true; | |
| } | |
| break; | |
| case 'pages.collegeboard.org': | |
| if (path.match(/^\/sat\/school-day/i)) { | |
| cmet = kiwi.pixelTriggers.fb.cbMain.init = true; | |
| kiwi.pixelTriggers.fb.cbMain.view = true; | |
| } | |
| break; | |
| case 'nsat.collegeboard.org': | |
| cmet = kiwi.pixelTriggers.fb.cbMain.init = true; | |
| cmet = kiwi.pixelTriggers.fb.cbIndia.init = true; | |
| //conversion events on specific pages - see DE > Kiwi > Custom Events | |
| break; | |
| case 'signup.collegeboard.org': | |
| //view event | |
| if (path.match(/^\/international-sat($|\/)/i)) { | |
| cmet = kiwi.pixelTriggers.fb.cbIndia.init = true; | |
| kiwi.pixelTriggers.fb.cbIndia.view = true; | |
| } | |
| break; | |
| case 'account.collegeboard.org': | |
| //weed out appId=229 (SSD MP3 App) | |
| if (!(params.match(/appId=229/i)) && path.match(/^\/(login\/(login|signUp))$/i)) { | |
| cmet = kiwi.pixelTriggers.fb.cbIndia.init = true; | |
| kiwi.pixelTriggers.fb.cbIndia.view = true; | |
| } | |
| break; | |
| case 'cbaccount.collegeboard.org': | |
| cmet = kiwi.pixelTriggers.fb.cbIndia.init = true; //capture account creation on subdomain confirmation page | |
| if (path.match(/^\/(iamweb\/(smartRegister|registerAccount))$/i)) { | |
| kiwi.pixelTriggers.fb.cbIndia.view = true; | |
| } | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| return cmet; | |
| }],"event":"pagebottom"}, | |
| {"name":"Pixel - DM - JunGroup - Find Test Centers","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5e67d7aa64746d1ac400038d.js"}]}]}],"scope":{"URI":{"include":[/\/sat\/register\/find-test-centers/i]},"subdomains":{"include":[/^collegereadiness\.collegeboard\.org$/i]},"domains":[/collegeboard\.org$/i]},"conditions":[function(event,target){ | |
| var cmet = true; | |
| if (_satellite.getVar('QP userName') || document.referrer.match(/userName=[^\&]+/)) { | |
| cmet = false; | |
| } | |
| return cmet; | |
| }],"event":"windowload"}, | |
| {"name":"Pixel - DM - Pinterest","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5ca38b0464746d2d09009456.js"}]}]}],"scope":{"URI":{"include":["about-ap/news-changes/ap-2019"]},"subdomains":{"include":[/^apcentral\.collegeboard\.org$/i]},"domains":[/collegeboard\.org$/i]},"conditions":[function(event,target){ | |
| var cmet = true; | |
| if (_satellite.getVar('QP userName') || document.referrer.match(/userName=[^\&]+/)) { | |
| cmet = false; | |
| } | |
| return cmet; | |
| }],"event":"pagebottom"}, | |
| {"name":"Pixel - DM - SnapChat","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5c705b1964746d101a0008bf.js"}]}]}],"scope":{"subdomains":{"include":[/^(?:opportunity|eyf)(?:(?:-.*)?\.collegeplanning-(?:non)?prod)?\.collegeboard\.org$/i,/^(account|cbaccount|nsat|signup)\.collegeboard\.org$/i]}},"conditions":[function(event,target){ | |
| var cmet = true; | |
| if (_satellite.getVar('QP userName') || document.referrer.match(/userName=[^\&]+/)) { | |
| cmet = false; | |
| } | |
| return cmet; | |
| }],"event":"pagebottom"}, | |
| {"name":"Pixel - Google Tag - CB India","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5db0501264746d34d4000071.js"}]}]}],"scope":{"subdomains":{"include":[/^(account|cbaccount|nsat|signup)\.collegeboard\.org$/i]},"domains":[/collegeboard\.org$/i]},"conditions":[function(event,target){ | |
| var cmet = true; | |
| if (_satellite.getVar('QP userName') || document.referrer.match(/userName=[^\&]+/)) { | |
| cmet = false; | |
| } | |
| return cmet; | |
| }],"event":"pagebottom"}, | |
| {"name":"Pixel - Google Tag - CB India 2","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5e34689464746d0c4e0009d8.js"}]}]}],"scope":{"subdomains":{"include":[/^(account|cbaccount|nsat|signup)\.collegeboard\.org$/i]},"domains":[/collegeboard\.org$/i]},"conditions":[function(event,target){ | |
| var cmet = true; | |
| if (_satellite.getVar('QP userName') || document.referrer.match(/userName=[^\&]+/)) { | |
| cmet = false; | |
| } | |
| return cmet; | |
| }],"event":"pagebottom"}, | |
| {"name":"Pixel - Google Tag - CB LP","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5d6eaff964746d0c4f0006ab.js"}]}]}],"scope":{"subdomains":{"include":[/^(account|bigfuture|cbaccount|clep|collegereadiness|go|nsat|signup)\.collegeboard\.org$/i]},"domains":[/collegeboard\.org$/i]},"conditions":[function(event,target){ | |
| var cmet = true; | |
| if (_satellite.getVar('QP userName') || document.referrer.match(/userName=[^\&]+/)) { | |
| cmet = false; | |
| } | |
| return cmet; | |
| }],"event":"pagebottom"}, | |
| {"name":"Pixel - Google Tag - CB Main","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5b44fdc364746d17900089e9.js"}]}]}],"scope":{"subdomains":{"include":[/^(account|apstudents|bigfuture|cbaccount|clep|clepportal|collegereadiness|go|nsat|pages|parents|signup|studentscores|www)\.collegeboard\.org$/i]}},"conditions":[function(event,target){ | |
| var cmet = true; | |
| if (_satellite.getVar('QP userName') || document.referrer.match(/userName=[^\&]+/)) { | |
| cmet = false; | |
| } | |
| return cmet; | |
| }],"event":"pagebottom"}, | |
| {"name":"Pixel - OneTrust - v1 PROD","trigger":[{"command":"writeHTML","arguments":[{"html":"\u003c!-- OneTrust Cookies Consent Notice (Production CDN, collegeboard.org, en-GB) start --\u003e\n\u003cscript src=\"https://cdn.cookielaw.org/consent/3700e0a7-263f-4b29-87c0-e1c5fcf7ed80.js\" type=\"text/javascript\" charset=\"UTF-8\"\u003e\u003c/script\u003e\n\u003cscript type=\"text/javascript\"\u003e\n function OptanonWrapper() { }\n\u003c/script\u003e\n\u003c!-- OneTrust Cookies Consent Notice (Production CDN, collegeboard.org, en-GB) end --\u003e\n"}]}],"scope":{"subdomains":{"exclude":[/\.overturecorp\.com$/i,/\.springboardonline\.org$/i,/^profile\.collegeboard\.org$/i,/^idoc\.collegeboard\.org$/i]}},"event":"pagebottom"}, | |
| {"name":"Pixel - UX - Lucky Orange","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-57d84a9d64746d4d4100dc5e.js"}]}]}],"scope":{"domains":[/apscore\.org$/i,/collegeboard\.com$/i,/collegeboard\.org$/i]},"event":"pagebottom"}, | |
| {"name":"Pixel - UX - Mouseflow (Regular) ","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5d6045a964746d4afa000f8a.js"}]}]}],"scope":{"subdomains":{"include":[/^apscore\.collegeboard\.org$/i]}},"event":"pagetop"}, | |
| {"name":"Set Cookie - viewed_college_plan","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5d8a5d8364746d424a000dcc.js"}]}]}],"scope":{"URI":{"include":[/\/fp-your-college-plan-11$/i]},"subdomains":{"include":[/^pages\.collegeboard\.org$/i]},"domains":[/collegeboard\.org$/i]},"event":"pagebottom"}, | |
| {"name":"Survey - GetSiteControl - 1 Recording Intro","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-57e582c264746d0608008af2.js"}]}]}],"scope":{"subdomains":{"include":[/^international\.collegeboard\.org$/i]}},"conditions":[function(event,target){ | |
| /** | |
| * Created by jbeach on 2019-04-10 | |
| * Updated by jbeach on 2019-04-15 | |
| */ | |
| var cmet = false; | |
| if(!_satellite.readCookie('gsc1_fired')) { | |
| document.cookie = 'gsc1_fired=1;path=/;domain=collegeboard.org'; | |
| cmet = true; | |
| } | |
| return cmet; | |
| }],"event":"pagebottom"}, | |
| {"name":"Survey - GetSiteControl - 2 APS Intercept","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-580fa55364746d38fe0099bd.js"}]}]}],"scope":{"subdomains":{"include":[/^(apstudents)\.collegeboard\.org$/i]}},"event":"pagebottom"}, | |
| {"name":"Survey - GetSiteControl - 3 Dynamic Intercept","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5cc06f4964746d5d38000664.js"}]}]}],"scope":{"subdomains":{"include":[/^apcentral\.collegeboard\.org$/i]}},"event":"pagebottom"}, | |
| {"name":"Survey - GetSiteControl - 4 Dynamic Intercept 2","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5d80ec1964746d4b5e0000ed.js"}]}]}],"scope":{"subdomains":{"include":[/^opportunity\.collegeboard\.org$/i]}},"event":"pagebottom"}, | |
| {"name":"Survey - GetSiteControl - 5 Dynamic Intercept","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5db0a6ee64746d728900014b.js"}]}]}],"scope":{"subdomains":{"include":[/^(collegereadiness|nsat|studentscores|k12reports)\.collegeboard\.org$/i]}},"conditions":[function(event,target){ | |
| var cmet = false, | |
| h = document.location.host, | |
| p = document.location.pathname, | |
| isLowerEnv = false, | |
| isProdEnv = true; | |
| if (typeof window.cbEnvLower) { | |
| isLowerEnv = (typeof window.cbEnvLower === 'boolean') | |
| ?window.cbEnvLower | |
| :(window.cbEnvLower === 'true'); | |
| isProdEnv = !isLowerEnv; | |
| } | |
| if (typeof window.cbEnv) { | |
| isProdEnv = (window.cbEnv === 'prod'); | |
| isLowerEnv = !isProdEnv; | |
| } | |
| switch (h) { | |
| case 'nsat.collegeboard.org': | |
| //display only on non-lower/prod environments | |
| cmet = isProdEnv; | |
| break; | |
| default: | |
| //display everywhere | |
| cmet = true; | |
| break; | |
| } | |
| return cmet; | |
| }],"event":"pagebottom"}, | |
| {"name":"Survey - GetSiteControl - Apricot Form Fix","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-57d8406964746d192c00efc1.js"}]}]}],"scope":{"domains":[/apscore\.org$/i,/collegeboard\.com$/i,/collegeboard\.org$/i]},"event":"pagebottom"}, | |
| {"name":"Survey - GetSiteControl - BigFuture","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5b85639364746d7f9d002c8d.js"}]}]}],"scope":{"subdomains":{"include":[/^bigfuture\.collegeboard\.org$/i]},"domains":[/collegeboard\.org$/i]},"event":"pagebottom"}, | |
| {"name":"Survey - GetSiteControl - Usability","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-57d8472b64746d57f400639c.js"}]}]}],"scope":{"URI":{"exclude":[/^\/fp-/i]},"subdomains":{"exclude":[/^(accommodations|go|ssd|signup)\.collegeboard\.org$/i,/^(testday|(dev|qa|uat)-tdtk\.fed-nonprod)\.collegeboard\.org$/i,/^(finaidportalbeta|finaidportal|idoc|idocbeta|cssprofile|profilebeta|profile)\.collegeboard\.org$/i,/^latam\.collegeboard\.org$/i,/^collegeboardsearch\.collegeboard\.org$/i,/^ap2020studentresponses\.collegeboard\.org$/i]},"domains":[/apscore\.org$/i,/collegeboard\.com$/i,/collegeboard\.org$/i]},"conditions":[function(event,target){ | |
| /** | |
| * Created by jbeach on 2020-04-14 | |
| * Updated by jbeach on 2020-04-14 | |
| */ | |
| var cmet = false, | |
| h = document.location.host, | |
| p = document.location.pathname, | |
| cbEnvLower = 'false'; | |
| if (typeof window.cbEnvLower) { | |
| cbEnvLower = window.cbEnvLower; | |
| } | |
| switch (h) { | |
| case 'nsat.collegeboard.org': | |
| case 'satscoresends.collegeboard.org': | |
| //display only on non-lower/prod environments | |
| cmet = !cbEnvLower; | |
| break; | |
| default: | |
| //display everywhere | |
| cmet = true; | |
| break; | |
| } | |
| return cmet; | |
| }],"event":"pagebottom"}, | |
| {"name":"Survey - Helpflns (SG) - AP Sites","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5e67a15c64746d600b0007a8.js"}]}]}],"scope":{"subdomains":{"include":[/^apstudents(-(origin|stg|dev))?\.collegeboard\.org$/i,/^apcentral(-(origin|stg|dev))?\.collegeboard\.org$/i,/^apcoronavirusupdates(-(origin|stg|dev))?\.collegeboard\.org$/i,/^aphighered(-(origin|stg|dev))?\.collegeboard\.org$/i]}},"conditions":[function(event,target){ | |
| /** | |
| * Created by jbeach on 2018-10-29 | |
| * Updated by jbeach on 2020-04-03 | |
| */ | |
| var cmet = false, | |
| h = document.location.host, | |
| p = document.location.pathname; | |
| switch (h) { | |
| case 'apstudents-dev.collegeboard.org': | |
| case 'apstudents-stg.collegeboard.org': | |
| case 'apstudents-origin.collegeboard.org': | |
| case 'apstudents.collegeboard.org': | |
| case 'apcentral-dev.collegeboard.org': | |
| case 'apcentral-stg.collegeboard.org': | |
| case 'apcentral-origin.collegeboard.org': | |
| case 'apcentral.collegeboard.org': | |
| //display everywhere except root/home page | |
| if (!(p.match(/^\/$/i))) { | |
| cmet = true; | |
| } | |
| break; | |
| default: | |
| //display everywhere | |
| cmet = true; | |
| break; | |
| } | |
| return cmet; | |
| }],"event":"pagebottom"}, | |
| {"name":"Survey - Helpflns (SG) - International","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5ef3c09c64746d7f6b001fd9.js"}]}]}],"scope":{"subdomains":{"include":[/^international(-(origin|stg|dev))?\.collegeboard\.org$/i]}},"event":"pagebottom"}, | |
| {"name":"Survey - Helpflns (SG) - Membership","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5ee966e264746d6fc400122d.js"}]}]}],"scope":{"subdomains":{"include":[/^membership(-(origin|stg|dev))?\.collegeboard\.org$/i]}},"event":"pagebottom"}, | |
| {"name":"Survey - Helpflns (SG) - My","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5f18433864746d3fed000e0e.js"}]}]}],"scope":{"subdomains":{"include":[/^my(-(origin|stg|dev))?\.collegeboard\.org$/i,/^mycb-prod\.mycollegeboard-prod\.collegeboard\.org$/i,/^mycb-(dev|qa|staging|oat|perf)\.mycollegeboard-nonprod\.collegeboard\.org$/i]}},"event":"pagebottom"} | |
| ], | |
| "rules": [ | |
| {"name":"BFCL Widget - Login Modal Shown","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"BFCL Widget - Login Modal"}]}],"selector":"html","eventHandlerOnElement":true,"event":"custom","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false,"customEvent":"kiwi.widgetScreenTrack.bfclLoginModal"}, | |
| {"name":"BFCL Widget - Popover Dismissed","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"BFCL Widget - Popover Dismissed"}]}],"selector":"html","eventHandlerOnElement":true,"event":"custom","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false,"customEvent":"kiwi.widgetScreenTrack.bfclHide"}, | |
| {"name":"BFCL Widget - Popover Shown","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"Widget Screen - BFCL Widget"}]}],"selector":"html","eventHandlerOnElement":true,"event":"custom","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false,"customEvent":"kiwi.widgetScreenTrack.bfclShow"}, | |
| {"name":"Click - Accordion Expand","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"Feature Used - Accordion","customSetup":function(event,s){ | |
| /** | |
| * Created by jbeach on 2019-01-23 | |
| * Updated by jbeach on 2019-01-23 | |
| */ | |
| kiwi = window.kiwi || {}; | |
| var ruleName='KIWI: EBR > Click - Accordion Expand > Analytics JS'; | |
| _satellite.notify(ruleName); | |
| kiwi._elementToTest = this; | |
| }}]}],"selector":"[data-cbtrack-accordion] a, [data-cbtrack-accordion] button","eventHandlerOnElement":true,"event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - Auto-Suggested Term Search Link","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"Auto-Suggested Term Search Link"}]}],"selector":"[data-cbtrack-linkgroup=\"search-sugg\"] [data-cbtrack-linktype=\"nav\"], .lv-search-widget .lv-suggestions li a","eventHandlerOnElement":true,"event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - CBOS Opt Out","trigger":[{"command":"loadScript","arguments":[{"sequential":false,"scripts":[{"src":"satellite-5ca63d0c64746d78ba00342f.js"}]}]}],"selector":".cbos-main #optOutModal #opt-out-yes","event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - CBOS Terms Accept","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"CBOS Terms Accept"}]}],"selector":"[data-cbtrack-cbos-optin]:not([disabled])","event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - CTA Card","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"Feature Used - CTA Card","customSetup":function(event,s){ | |
| /** | |
| * Created by jbeach on 2019-05-02 | |
| * Updated by jbeach on 2019-05-02 | |
| */ | |
| kiwi = window.kiwi || {}; | |
| var ruleName='KIWI: EBR > Click - CTA Card > Analytics JS'; | |
| _satellite.notify(ruleName); | |
| kiwi._elementToTest = this; | |
| }}]}],"selector":"[data-cbtrack-ctacard] a, [data-cbtrack-ctacard] button","eventHandlerOnElement":true,"event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - Confirm ECL Account Create","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"Confirm ECL Account Create"}]}],"scope":{"URI":{"include":[/^\/iamweb\/registerAccount/i]},"subdomains":{"include":[/^cbaccount\.collegeboard\.org$/i]},"domains":[/collegeboard\.org$/i]},"conditions":[function(event,target){ | |
| /** | |
| * Created by jbeach on 2019-10-31 | |
| * Updated by jbeach on 2019-10-31 | |
| */ | |
| var cmet = false, | |
| strAriaDisabledVal = this.getAttribute('aria-disabled'); | |
| if (strAriaDisabledVal && strAriaDisabledVal.match(/^false$/i)) { | |
| cmet = true; | |
| } | |
| return cmet; | |
| }],"selector":"button#registerAccount","event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - Crosslink","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"Feature Used - Crosslink","customSetup":function(event,s){ | |
| /** | |
| * Created by jbeach on 2019-04-12 | |
| * Updated by jbeach on 2019-04-12 | |
| */ | |
| kiwi = window.kiwi || {}; | |
| var ruleName='KIWI: EBR > Click - Crosslink > Analytics JS'; | |
| _satellite.notify(ruleName); | |
| kiwi._elementToTest = this; | |
| }}]}],"selector":"[data-cbtrack-crosslink]","eventHandlerOnElement":true,"event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - Download Link","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"d","linkName":"Download Link","customSetup":function(event,s){ | |
| /** | |
| * Created by jbeach on 2016-12-02 | |
| * Updated by jbeach on 2018-01-19 | |
| */ | |
| kiwi = window.kiwi || {}; | |
| var ruleName='KIWI: EBR > Click - Download Link > Analytics JS'; | |
| _satellite.notify(ruleName); | |
| kiwi._elementToTest = this; | |
| }}]},{"command":"delayActivateLink"}],"selector":"a","property":{"href":/\.(?:arf|avi|css|csv|dmg|doc|docx|dotx|eps|exe|ics|js|m4v|mov|mp3|mp4|mpg|pages|pdf|ppt|pptx|rar|rm|rtf|swf|tab|txt|vsd|vxd|wav|wma|wmv|xls|xlsx|xml|zip)($|\&|\?)/i},"event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - Dynamic Download Link","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"Dynamic Download Link","customSetup":function(event,s){ | |
| /** | |
| * Created by jbeach on 2016-12-02 | |
| * Updated by jbeach on 2018-01-19 | |
| */ | |
| kiwi = window.kiwi || {}; | |
| var ruleName='KIWI: EBR > Click > Dynamic Download Link > Analytics JS'; | |
| _satellite.notify(ruleName); | |
| kiwi._elementToTest = this; | |
| }}]}],"selector":"[dynamic-asset-link-track],[data-cbtrack-download],[download]","event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - Event Card","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"Feature Used - Event Card","customSetup":function(event,s){ | |
| /** | |
| * Created by jbeach on 2019-05-17 | |
| * Updated by jbeach on 2019-05-17 | |
| */ | |
| kiwi = window.kiwi || {}; | |
| var ruleName='KIWI: EBR > Click - Event Card > Analytics JS'; | |
| _satellite.notify(ruleName); | |
| kiwi._elementToTest = this; | |
| }}]}],"selector":"[data-cbtrack-ec] a, [data-cbtrack-ec] button","eventHandlerOnElement":true,"event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - Exit Link - New Tab","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"e","linkName":"Exit Link","customSetup":function(event,s){ | |
| /** | |
| * Created by jbeach on 2016-12-02 | |
| * Updated by jbeach on 2018-01-19 | |
| */ | |
| kiwi = window.kiwi || {}; | |
| var ruleName='KIWI: EBR > Click - Exit Link - New Tab > Analytics JS'; | |
| _satellite.notify(ruleName); | |
| kiwi._elementToTest = this; | |
| //if (_satellite.getVar('Async Promo Link Fired')) s.abort; | |
| }}]}],"conditions":[function(event,target){ | |
| /** | |
| * Created by jbeach on 2017-02-16 | |
| * Updated by jbeach on 2017-03-21 | |
| */ | |
| //NEW TAB LOGIC | |
| //check if outbound link | |
| var cmet = false, | |
| outBoundLink = _satellite.isOutboundLink(this), | |
| newTab = false; | |
| if (outBoundLink) { | |
| //check if link opens in a new tab and if not so, set false | |
| var myTarget = this.getAttribute('target'), | |
| myDataTarget = this.getAttribute('data-target'), | |
| myClass = this.getAttribute('class'); | |
| if (myTarget && myTarget.match(/^(_blank|_new)$/i)) { | |
| newTab = true; | |
| } else if (myDataTarget && myDataTarget.match(/^new-window$/i)) { | |
| newTab = true; | |
| } else if (myClass && myClass.match(/(?: |^)nav-item(?: |$)/i)) {//temp logic for SSR + RTN pop tools links until they can use data-target attribute | |
| newTab = true; | |
| } | |
| } | |
| cmet = outBoundLink && newTab; | |
| return cmet; | |
| }],"selector":"a","event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - Exit Link - Same Tab","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"e","linkName":"Exit Link","customSetup":function(event,s){ | |
| /** | |
| * Created by jbeach on 2016-12-02 | |
| * Updated by jbeach on 2018-01-19 | |
| */ | |
| kiwi = window.kiwi || {}; | |
| var ruleName='KIWI: EBR > Click - Exit Link - Same Tab > Analytics JS'; | |
| _satellite.notify(ruleName); | |
| kiwi._elementToTest = this; | |
| }}]},{"command":"delayActivateLink"}],"conditions":[function(event,target){ | |
| /** | |
| * Created by jbeach on 2017-02-16 | |
| * Updated by jbeach on 2017-03-14 | |
| */ | |
| //SAME TAB LOGIC | |
| //check if outbound link | |
| var cmet = _satellite.isOutboundLink(this); | |
| if (cmet) { | |
| //check if link opens in a new tab and if so, set false | |
| var myTarget = this.getAttribute('target'), | |
| myDataTarget = this.getAttribute('data-target'), | |
| myClass = this.getAttribute('class'); | |
| if (myTarget && myTarget.match(/^(_blank|_new)$/i)) { | |
| cmet = false; | |
| } else if (myDataTarget && myDataTarget.match(/^new-window$/i)) { | |
| cmet = false; | |
| } else if (myClass && myClass.match(/(?: |^)nav-item(?: |$)/i)) {//temp logic for SSR + RTN pop tools links until they can use data-target attribute | |
| cmet = false; | |
| } | |
| } | |
| return cmet; | |
| }],"selector":"a","event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - FW Eligibility","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"Feature Used - Custom","customSetup":function(event,s){ | |
| /** | |
| * Created by jbeach on 2019-03-25 | |
| * Updated by jbeach on 2019-03-25 | |
| */ | |
| kiwi = window.kiwi || {}; | |
| var ruleName='KIWI: EBR > Click - FW Eligibility > Analytics JS'; | |
| _satellite.notify(ruleName); | |
| kiwi._elementToTest = this; | |
| }}]}],"scope":{"subdomains":{"include":[/^nsat\.collegeboard\.org$/i]}},"selector":"#s2-fwEligibilitymodal-continueButton","event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - Feature","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"Feature Used - Feature","customSetup":function(event,s){ | |
| kiwi = window.kiwi || {}; | |
| var ruleName='KIWI: EBR > Click - Feature > Analytics JS'; | |
| _satellite.notify(ruleName); | |
| kiwi._elementToTest = this; | |
| }}]}],"selector":"[data-kiwi-featureclick]","event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - Feature (Legacy)","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"Feature","customSetup":function(event,s){ | |
| /** | |
| * Created by jbeach on 2018-04-19 | |
| */ | |
| kiwi = window.kiwi || {}; | |
| var ruleName='KIWI: EBR > Click - Feature > Analytics JS'; | |
| _satellite.notify(ruleName); | |
| kiwi._elementToTest = this; | |
| }}]},{"command":"delayActivateLink"}],"selector":"[data-cbtrack]","event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - Filter Apply","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"Feature Used - Filter","customSetup":function(event,s){ | |
| /** | |
| * Created by jbeach on 2019-01-16 | |
| * Updated by jbeach on 2019-01-16 | |
| */ | |
| kiwi = window.kiwi || {}; | |
| var ruleName='KIWI: EBR > Click - Filter Applied > Analytics JS'; | |
| _satellite.notify(ruleName); | |
| kiwi._elementToTest = this.closest('[data-cbtrack-filter]'); | |
| }}]},{"command":"delayActivateLink"}],"selector":"[data-cbtrack-filter] .cb-filter-apply, [data-cbtrack-filter] form [type=\"submit\"], [data-cbtrack-filter] [name=\"lv-form-college-search-submit\"]","eventHandlerOnElement":true,"event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - Iframe Report Link","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"Iframe Report Link","customSetup":function(event,s){ | |
| /** | |
| * Created by jbeach on 2019-05-06 | |
| * Updated by jbeach on 2019-05-06 | |
| */ | |
| kiwi = window.kiwi || {}; | |
| var ruleName='KIWI: EBR > Click > Iframe Report Link > Analytics JS'; | |
| _satellite.notify(ruleName); | |
| kiwi._elementToTest = this; | |
| }}]}],"selector":"[data-cbtrack-iframereport]","event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - Jump Link Jump","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"Feature Used - Jump Link","customSetup":function(event,s){ | |
| /** | |
| * Created by jbeach on 2019-02-05 | |
| * Updated by jbeach on 2019-02-05 | |
| */ | |
| kiwi = window.kiwi || {}; | |
| var ruleName='KIWI: EBR > Click - Jump Link Jump > Analytics JS'; | |
| _satellite.notify(ruleName); | |
| kiwi._elementToTest = this; | |
| }}]}],"selector":".cb-jumplinks-menu a, .cb-jumplinks-container .cb-jumplinks-back, #help-topics + ul li a, a[href=\"#help-topics\"]","eventHandlerOnElement":true,"event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - Key Benefit","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"Feature Used - Key Benefit","customSetup":function(event,s){ | |
| /** | |
| * Created by jbeach on 2019-11-19 | |
| * Updated by jbeach on 2019-11-19 | |
| */ | |
| kiwi = window.kiwi || {}; | |
| var ruleName='KIWI: EBR > Click - Key Benefit > Analytics JS'; | |
| _satellite.notify(ruleName); | |
| kiwi._elementToTest = this; | |
| }}]}],"selector":"[data-cbtrack-keybenefits] a, [data-cbtrack-keybenefits] button","eventHandlerOnElement":true,"event":"click","bubbleFireIfParent":true,"bubbleFireIfChildFired":true,"bubbleStop":false}, | |
| {"name":"Click - LIFW Opt In Form","trigger":[{"engine":"sc","command":"trackLink","arguments":[{"type":"o","linkName":"LIFW Opt In Form Submit"}]}],"conditions":[function(event,target){ | |
| /** | |