Environments

Environments

Environments

💡
Besides production, you can run Trackingplan on other environments – like staging or development – to detect problems before any release.

Trackingplan allows you to specify your “environment” dynamically at run-time. This way, you can:

  • Differentiate between what data and specifications you have in one environment and another.
  • Compare environments to detect mistakes before they reach production. For example, compare staging data to your master specification baseline to capture bugs or regressions before they reach production.
  • Create as many environments as you need. The most common setup is having ~3 environments (production, staging, and development) to check changes before a release. However, some Trackingplan users even have one environment per branch or automated test, allowing them to detect errors with more granularity.

Setting up Trackingplan for different environments

Trackingplan supports complex deployment setups with custom preproduction environments.

You just have to modify this init according to your specifications and your own TP_ID and add it at the top of the <head> section of your site (instructions here), or include it as a new Google Tag Manager Script (instructions here).

<script type="text/javascript">
(function(){function a(a){var b={method:"POST",endpoint:"TRACKINGPLAN",payload:JSON.stringify(a)};m(b)}function b(a){if($.includes("img"))try{f(a)}catch(a){E(a)}if($.includes("xhr"))try{h(a)}catch(a){E(a)}if($.includes("beacon"))try{i(a)}catch(a){E(a)}if($.includes("form"))try{l(a)}catch(a){E(a)}if($.includes("ws"))try{k(a)}catch(a){E(a)}if($.includes("fetch"))try{j(a)}catch(a){E(a)}}function c(){var a=d();if(null!==a&&!Y)return!1;var b={landing:document.location.href,referrer:document.referrer};return H.setItem("_trackingplan_initial",JSON.stringify(b)),!0}function d(){return JSON.parse(H.getItem("_trackingplan_initial"))}function e(){try{if(H.setItem("_tp_t","a"),"a"!==H.getItem("_tp_t"))return!1;if(H.removeItem("_tp_t"),"function"!=typeof navigator.sendBeacon)return!1}catch(a){return!1}return!0}function f(a){var b=a.Object.getOwnPropertyDescriptor(a.HTMLImageElement.prototype,"src").set;a.Object.defineProperty(a.HTMLImageElement.prototype,"src",{set:function(a){return 2048<a.length?b.apply(this,arguments):(m({method:"GET",endpoint:a,protocol:"img"}),b.apply(this,arguments))}});var c=a.HTMLImageElement.prototype.setAttribute;a.HTMLImageElement.prototype.setAttribute=function(a,b){if("src"==a.toLowerCase()){if(b.length>2048)return c.apply(this,arguments);m({method:"GET",endpoint:b,protocol:"img"})}return c.apply(this,arguments)}}function g(a){var b=a;try{b instanceof FormData&&(b=JSON.stringify(Object.fromEntries(b)))}catch(a){}return b}function h(a){var b=a.XMLHttpRequest.prototype.open,c=a.XMLHttpRequest.prototype.send;a.XMLHttpRequest.prototype.open=function(a,c){return this._tpUrl=c,this._tpMethod=a,b.apply(this,arguments)},a.XMLHttpRequest.prototype.send=function(a){var b=g(a);return m({method:this._tpMethod,endpoint:this._tpUrl,payload:b,protocol:"xhr"}),c.apply(this,arguments)}}function i(a){var b=a.navigator.sendBeacon;a.navigator.sendBeacon=function(a,c){if(2048<a.length)return b.apply(this,arguments);var d=g(c);return m({method:"POST",endpoint:a,payload:d,protocol:"beacon"}),b.apply(this,arguments)}}function j(a){var b=a.fetch;a.fetch=function(a,c){if(2048<a.length)return b.apply(this,arguments);var d="GET",e=null;return void 0!==c&&(void 0!==c.method&&(d=c.method.toUpperCase()),void 0!==c.body&&(e=g(c.body))),m({method:d,endpoint:a,payload:e,protocol:"fetch"}),b.apply(this,arguments)}}function k(a){var c=a.WebSocket;a.WebSocket=function(d,a){return a?new c(d,a):new c(d)};var b=c.prototype.send;c.prototype.send=function(a){({method:"WS",endpoint:this.url,payload:a,protocol:"ws"});return m({method:"WS",endpoint:this.url,payload:a,protocol:"ws"}),b.apply(this,arguments)},a.WebSocket.prototype=c.prototype}function l(a){a.addEventListener("submit",function(a){try{var b=a?a.target:this,c={method:b.method,endpoint:b.action,payload:JSON.stringify({location:I.location.href,form_id:b.id,method:b.method,form_data:Object.fromEntries(new FormData(b))}),protocol:"form"};m(c)}catch(a){}},!0)}function m(a,b){setTimeout(function(){try{var c=C(a);if("TRACKINGPLAN"==a.endpoint&&(c="trackingplan"),!c)return;var d=A();return!1===d?(ea.push(a),E({m:"Pre queued, queue length = "+ea.length}),setTimeout(y,T),!1):(null===ha&&(ha=u(),ia=JSON.stringify(ha).length),!r(V,d))?(E({m:"Request ignored (sampling)",mode:V,dict:d}),!0):(n(s(a,c)),"function"==typeof b&&b(),!0)}catch(b){F({m:"Trackingplan process error",error:b,request:a})}},0)}function n(a){aa(a);var b=JSON.stringify(a);if(2e5<b.length&&E({m:"Track Too big, ignored: "+b.length}),b.length+2+ia>W)return q("["+b+"]",P),void E({m:"Track > Batch Size: "+b.length});var c=fa.length+b.length+ia;c>W&&(E({m:"Batch reaching limit: "+c}),o(P)),c=fa.length+b.length+ia,E({m:"Queue len: "+c,rawTrack:a}),0!==fa.length&&(fa+=","),fa+=b}function o(a){if(0!=fa.length){var b=fa;fa="";var c={requests:JSON.parse("["+b+"]"),common:ha};q(c,a)}}function p(){var a=R+M;return ca&&(a+="?debug=true"),a}function q(a,b){return("function"==typeof ba&&(a=ba(a)),E({m:"Sent",payload:a}),Z)?void E("Not sending, is dry run"):void("xhr"===b?function(a){var b=new XMLHttpRequest;b.open("POST",p(),!0),b.onreadystatechange=function(){if(4===b.readyState)try{E({m:"Parsed",response:JSON.parse(b.response)}),_(a,b.response)}catch(a){}},b.send(a)}(JSON.stringify(a)):"beacon"===b?function(a){navigator.sendBeacon(p(),a)}(JSON.stringify(a)):void 0)}function r(a,b){switch(a){case"user":return 1===b.isSampledUser;case"track":return Math.random()<1/b.sampleRate;case"all":return!0;case"none":default:return!1;}}function s(a,b){return{provider:b,request:{endpoint:a.endpoint,method:a.method,post_payload:a.payload||null,protocol:a.protocol,href:I.location.href}}}function t(){return D({hostname:I.location.hostname,user_agent:navigator.userAgent,load_url:ga},d())}function u(){return{context:t(),tp_id:M,source_alias:O,environment:N,sdk:ja.sdk,sdk_version:ja.sdkVersion,sampling_rate:A().sampleRate,debug:Q}}function v(){try{for(var a=window.performance.getEntriesByType("resource"),b={},c=[],d=0;d<a.length;d++){c.push(a[d].name);var e="",f=a[d].name.replace(/(^\w+:|^)\/\//,""),g=f.split("?"),h=g[0];g=h.split("/"),e=1<g.length?g[0]+"/"+g[1]:g[0];var j=e;b.hasOwnProperty(j)||(b[j]=0),b[j]++}return b}catch(a){return null}}function w(){for(;ea.length;){var a=ea.shift();m(a)}}function x(a,b){var c=Object.prototype.hasOwnProperty;return c.call(a,"environment_rates")&&c.call(a.environment_rates,b)?a.environment_rates[b]:a.sample_rate}function y(){if(!da){var b=new XMLHttpRequest,c=S+"config-"+M+".json";b.onreadystatechange=function(){if(4==this.readyState)try{z(x(JSON.parse(this.responseText),N)),a({event_name:"new_dau"}),w()}catch(a){}da=!1},b.open("GET",c,!0),da=!0,b.send()}}function z(a){if(!1===a)return H.removeItem("_trackingplan_sample_rate"),H.removeItem("_trackingplan_sample_rate_ts"),void H.removeItem("_trackingplan_is_sampled_user");var b=Math.random()<1/a?1:0;E({m:"Trackingplan sample rate = "+a+". isSampledUser "+b}),H.setItem("_trackingplan_sample_rate_ts",new Date().getTime()),H.setItem("_trackingplan_sample_rate",a),H.setItem("_trackingplan_is_sampled_user",b)}function A(){var a=H.getItem("_trackingplan_sample_rate_ts");return null!==a&&(parseInt(a)+1e3*U<new Date().getTime()?(E({m:"Trackingplan sample rate expired"}),z(!1),!1):{sampleRate:parseInt(H.getItem("_trackingplan_sample_rate")),isSampledUser:parseInt(H.getItem("_trackingplan_is_sampled_user"))})}function B(a,b){if(null===a||null===b)return!0;if("/"===a[0]){var c=new RegExp(a.slice(1,-1));return c.test(b)}return-1!==b.indexOf(a)}function C(a){var b=a.endpoint,c=a.payload;if("string"==typeof b||b instanceof String){for(var d in L){var e=d.split("%"),f=e[0],g=2===e.length?e[1]:null;if(B(f,b)&&B(g,c))return L[d]}return!1}}function D(b,c){for(var d in c)b[d]=c[d];return b}function E(a){Q&&J.log("TP "+M,a)}function F(a){I.console&&J.warn&&J.warn(a)}function G(){function a(){for(var a=document.getElementsByTagName("IFRAME"),b=0;b<a.length;b++)d(a[b])}function c(a){try{return!!a.contentDocument}catch(a){return!1}}function d(a){try{c(a)&&(b(a.contentWindow),E("Intercepted frame "+a.id))}catch(a){}}function e(){var a=new MutationObserver(function(a){a.forEach(function(a){a.addedNodes.forEach(function(a){"IFRAME"==a.tagName&&d(a)})})});a.observe(document,{subtree:!0,childList:!0,attributes:!1,characterData:!1}),setTimeout(a.disconnect(),4e3)}"complete"===document.readyState?(a(),e()):document.onreadystatechange=function(){"complete"===document.readyState&&(a(),e())}}var H=localStorage,I=window,J=console;if(I.Trackingplan)return void F("Trackingplan snippet included twice.");var K={"google-analytics.com":"googleanalytics","analytics.google.com":"googleanalytics","api.segment.io":"segment",segmentapi:"segment","seg-api":"segment","segment-api":"segment","/.*api-iam.intercom.io/messenger/web/(ping|events|metrics|open).*/":"intercom","api.amplitude.com":"amplitude","ping.chartbeat.net":"chartbeat","/.*api(-eu)?(-js)?.mixpanel.com.*/":"mixpanel","trk.kissmetrics.io":"kissmetrics","ct.pinterest.com":"pinterest","facebook.com/tr/":"facebook","track.hubspot.com/__":"hubspot","/.*.heapanalytics.com/(h|api).*/":"heap","/.*snowplow.*/":"snowplow","/.*ws.*.hotjar.com/api/v2/client/ws/%identify_user":"hotjar","/.*ws.*.hotjar.com/api/v2/client/ws/%tag_recording":"hotjar","klaviyo.com/api/track":"klaviyo","app.pendo.io/data":"pendo","matomo.php":"matomo","rs.fullstory.com/rec%8137":"fullstory","rs.fullstory.com/rec%8193":"fullstory","logx.optimizely.com/v1/events":"optimizely","track.customer.io/events/":"customerio","alb.reddit.com/rp.gif":"reddit","px.ads.linkedin.com":"linkedin","/i/adsct":"twitter","bat.bing.com":"bing","pdst.fm":"podsights"},L={},M=null,N="PRODUCTION",O=null,P="xhr",Q=!1,R="https://tracks.trackingplan.com/v1/",S="https://config.trackingplan.com/",T=0,U=86400,V="user",W=6e4,X=20,Y=!1,Z=!1,$=["img","xhr","beacon","ws","fetch"],_=function(){},aa=function(){},ba=function(a){return a},ca=!1,da=!1,ea=[],fa="",ga="",ha=null,ia=0,ja=I.Trackingplan={sdk:"js",sdkVersion:"1.11.0",setOptions:function(a,b){b=b||{},M=a,N=b.environment||N,O=b.sourceAlias||O,P=b.sendMethod||P,L=D(K,b.customDomains||{}),Q=b.debug||Q,R=b.tracksEndPoint||R,S=b.configEndPoint||S,T=b.delayConfigDownload||T,U=b.sampleRateTTL||U,V=b.samplingMode||V,W=b.batchSize||W,X=b.batchInterval||X,Y=b.alwaysSendNewUser||Y,Z=b.dryRun||Z,$=b.intercept||$,_=b.onSubmit||_,ca=b.parse||ca,aa=b.onQueue||aa,ba=b.onBeforeSubmit||ba,E({m:"TP options updated",options:b})},init:function(d,f){f=f||{};try{if(!e())throw new Error("TP Not compatible browser");if(null!==M)throw new Error("TP Init already happened");ja.setOptions(d,f),ga=I.location.href,b(window),$.includes("frame")&&G(),document.addEventListener("visibilitychange",function(){"hidden"===document.visibilityState&&o("beacon")}),I.addEventListener("pagehide",function(){o("beacon")}),c()&&a({event_name:"new_user"}),a({event_name:"page_load"}),setTimeout(function(){a({event_name:"pixels",properties:{pixels:v()}})},1e4),setInterval(function(){o(P)},1e3*X),E({m:"TP init finished",options:f})}catch(a){F({m:"TP init error",error:a})}}}})();
	Trackingplan.init("your TP_ID", {
		'environment': 'how you want to name the environment (e.g. testing, staging)',
	});
</script>

As you can see, the installation process is the same as the one you carried out when installing Trackingplan. The only thing that changes here is the environment variable within the init provided above.

  • Note: The same applies for iOS and Android, where you will only need to set the environment variable in the init.

After this easy installation, you’ll be able to see Trackingplan’s results in real-time or through automated digests (e.g. reporting results on daily or weekly development cycles).

  • Note: To integrate different environments using Segment, just add the query parameter &environment=<environment_name> to your webhook endpoint to have the desired behavior. For the production environment, you should use PRODUCTION.

Integrating your staging and testing environments and comparing them to your baseline allows you to see the differences between one release and the next, detecting broken events or schemas before releasing them. Any existing automated QA you have implemented, such as functional or non-functional regression testing (e.g. with Cypress), will stress your analytics under the watch of our system.

As a result, you can also cover the analytics service integrations in your existing release testing by simply integrating Trackingplan without changing your feature or testing code in any way.

If you want to know more about how tracking can become a first-class citizen in your QA, check out our latest blog post here.

After that, choosing an environment like development, staging, or production is simple. All you need to do is select which environment you want to view with the dropdown menu shown at the top left of your dashboard.

image