JS SDK [Deprecated]

❗️

JS SDK Update

We’ve released a new and updated version of our JS SDK with significant improvements to functionality, as well as unifying method signatures with our Mobile SDKs to ensure consistency across all platforms.

For more information on the new changes, please view our JS SDK upgrade guide here.

Please reach out to [email protected] if you have any questions about the migration process.

Getting Started

To fully utilize the power of Taplytics.js, get started by initializing Taplytics using one of either the Synchronous or Asynchronous initialization methods.


1A Synchronous script loading

To best utilize Taplytics JS SDK you will want to install it as a synchronous loading script. This will ensure your users never see your content switching from baseline to their bucketed variations.

Please note that the syncLoader will not work on 2g connections.

We recommend installing the Taplytics JS SDK script as high as possible in your <head> tag, ideally before any other analytics tools or other scripts are loaded.

To install the Taplytics JS SDK synchronously, use one of the following methods to load the Taplytics SDK. Then call TaplyticsInit with your JS_SDK_Key found on the Taplytics web dashboard:

i) Option 1: Using the CDN

Including referrerpolicy is highly recommended for Visual Web Editor users in this case but can be omitted if necessary.

<script type="text/javascript" src="https://cdn.taplytics.com/syncLoader.min.js" referrerpolicy="no-referrer-when-downgrade"></script>
<script>
	TaplyticsInit({
	    token: "JS_SDK_Key"
	});	
</script>

ii ) Option 2: Inline

<script type="text/javascript">
	var TaplyticsInit=function(t){var e={};function r(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)r.d(n,o,function(e){return t[e]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,r){"use strict";function n(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),r.push.apply(r,n)}return r}function o(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function i(t,e){if(null==t)return{};var r,n,o=function(t,e){if(null==t)return{};var r,n,o={},i=Object.keys(t);for(n=0;n<i.length;n++)r=i[n],e.indexOf(r)>=0||(o[r]=t[r]);return o}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n<i.length;n++)r=i[n],e.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}function c(t){for(var e=decodeURIComponent(document.cookie).split(";"),r=t+"=",n=0;n<e.length;n++){for(var o=e[n];" "===o.charAt(0);)o=o.substring(1);if(0===o.indexOf(r))return o.substring(r.length,o.length)}return""}function u(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.token,r=t.env,u=t.test_experiments,a=t.user_attributes,s=t.alias_host,f=t.version,l=i(t,["token","env","test_experiments","user_attributes","alias_host","version"]);if(!e)throw new Error("Project token must be provided in order to initialize Taplytics!");var p=(s||{}).api_host,b="https://".concat(r?"".concat(r):"js",".taplytics.com"),d="".concat(p||b,"/jssdk/").concat(f?f.concat("/"):"").concat(e,".min.js"),y=function(t){for(var e=1;e<arguments.length;e++){var r=null!=arguments[e]?arguments[e]:{};e%2?n(r,!0).forEach((function(e){o(t,e,r[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):n(r).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(r,e))}))}return t}({test_experiments:u&&JSON.stringify(u),user_attributes:a&&JSON.stringify(a),alias_host:s&&JSON.stringify(s),env:r},l,{uid:c("_tl_uid"),ad:c("_tl_duuid"),sync:!0}),O=Object.keys(y).filter((function(t){return void 0!==y[t]&&null!==y[t]&&""!==y[t]})).map((function(t){return"".concat(t,"=").concat(encodeURIComponent(y[t]))})).join("&");document.write("<script type='text/javascript' src='".concat(d).concat(O?"?".concat(O):"","'><\/script>"))}r.r(e),r.d(e,"default",(function(){return u}))}]).default;
	TaplyticsInit({
	    token: "JS_SDK_Key"
	});	
</script>

Example implementation:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <!-- Add other meta information -->
        <!-- Add stylesheets -->
	<script type="text/javascript">
		var TaplyticsInit=function(t){var e={};function r(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)r.d(n,o,function(e){return t[e]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,r){"use strict";function n(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),r.push.apply(r,n)}return r}function o(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function i(t,e){if(null==t)return{};var r,n,o=function(t,e){if(null==t)return{};var r,n,o={},i=Object.keys(t);for(n=0;n<i.length;n++)r=i[n],e.indexOf(r)>=0||(o[r]=t[r]);return o}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n<i.length;n++)r=i[n],e.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}function c(t){for(var e=decodeURIComponent(document.cookie).split(";"),r=t+"=",n=0;n<e.length;n++){for(var o=e[n];" "===o.charAt(0);)o=o.substring(1);if(0===o.indexOf(r))return o.substring(r.length,o.length)}return""}function u(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.token,r=t.env,u=t.test_experiments,a=t.user_attributes,s=t.alias_host,f=t.version,l=i(t,["token","env","test_experiments","user_attributes","alias_host","version"]);if(!e)throw new Error("Project token must be provided in order to initialize Taplytics!");var p=(s||{}).api_host,b="https://".concat(r?"".concat(r):"js",".taplytics.com"),d="".concat(p||b,"/jssdk/").concat(f?f.concat("/"):"").concat(e,".min.js"),y=function(t){for(var e=1;e<arguments.length;e++){var r=null!=arguments[e]?arguments[e]:{};e%2?n(r,!0).forEach((function(e){o(t,e,r[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):n(r).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(r,e))}))}return t}({test_experiments:u&&JSON.stringify(u),user_attributes:a&&JSON.stringify(a),alias_host:s&&JSON.stringify(s),env:r},l,{uid:c("_tl_uid"),ad:c("_tl_duuid"),sync:!0}),O=Object.keys(y).filter((function(t){return void 0!==y[t]&&null!==y[t]&&""!==y[t]})).map((function(t){return"".concat(t,"=").concat(encodeURIComponent(y[t]))})).join("&");document.write("<script type='text/javascript' src='".concat(d).concat(O?"?".concat(O):"","'><\/script>"))}r.r(e),r.d(e,"default",(function(){return u}))}]).default;

		TaplyticsInit({
		    token: "JS_SDK_Key"
		});
	</script>
        <!-- Add other scripts and content -->
    </head>
    <body>
    ...
    </body>
</html>    

Pin SDK version

To pin the SDK to a specific version add the version option to the TaplyticsInit call along with the Version Number that you are targeting.

<script type="text/javascript">
    var TaplyticsInit=function(t){var e={};function r(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)r.d(n,o,function(e){return t[e]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,r){"use strict";function n(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),r.push.apply(r,n)}return r}function o(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function i(t,e){if(null==t)return{};var r,n,o=function(t,e){if(null==t)return{};var r,n,o={},i=Object.keys(t);for(n=0;n<i.length;n++)r=i[n],e.indexOf(r)>=0||(o[r]=t[r]);return o}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n<i.length;n++)r=i[n],e.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}function c(t){for(var e=decodeURIComponent(document.cookie).split(";"),r=t+"=",n=0;n<e.length;n++){for(var o=e[n];" "===o.charAt(0);)o=o.substring(1);if(0===o.indexOf(r))return o.substring(r.length,o.length)}return""}function u(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.token,r=t.env,u=t.test_experiments,a=t.user_attributes,s=t.alias_host,f=t.version,l=i(t,["token","env","test_experiments","user_attributes","alias_host","version"]);if(!e)throw new Error("Project token must be provided in order to initialize Taplytics!");var p=(s||{}).api_host,b="https://".concat(r?"".concat(r):"js",".taplytics.com"),d="".concat(p||b,"/jssdk/").concat(f?f.concat("/"):"").concat(e,".min.js"),y=function(t){for(var e=1;e<arguments.length;e++){var r=null!=arguments[e]?arguments[e]:{};e%2?n(r,!0).forEach((function(e){o(t,e,r[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):n(r).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(r,e))}))}return t}({test_experiments:u&&JSON.stringify(u),user_attributes:a&&JSON.stringify(a),alias_host:s&&JSON.stringify(s),env:r},l,{uid:c("_tl_uid"),ad:c("_tl_duuid"),sync:!0}),O=Object.keys(y).filter((function(t){return void 0!==y[t]&&null!==y[t]&&""!==y[t]})).map((function(t){return"".concat(t,"=").concat(encodeURIComponent(y[t]))})).join("&");document.write("<script type='text/javascript' src='".concat(d).concat(O?"?".concat(O):"","'><\/script>"))}r.r(e),r.d(e,"default",(function(){return u}))}]).default;

	TaplyticsInit({
		token: "JS_SDK_Key",
	  	version: 'x.y.z',
	  	...startOptions
	})

</script>

Start Options

Start Options allow you to control how certain SDK features function, such as the default request timeout. Simply add them to the TaplyticsInit call.

Start OptionTypeDescription
alias_hostObjectThis is used to replace the hosts of the urls to bypass adblockers
auto_page_viewBooleanEnable or disable to automatically track page views when starting up the sdk
cookie_domainStringSet the domain that Taplytics will use to create cookies with. By default Taplytics will use a wildcard version of your top level domain that will work across sub-domains. For example a cookie from web.taplytics.com will be set as .taplytics.com, that will also work on another subdomain such as: new.taplytics.com.
manual_trigger_editsBooleanTurn this ON to prevent applying visual edits automatically by the sdk
test_experimentsObjectSet an Object containing pairs of experiment/variation combinations as key/value pairs to test with. Docs
timeoutNumberSet the request timeout in seconds. If requests timeout variables will use the default value, but no events will be saved. The default timeout is 4 seconds.
user_attributesObjectSet initial user attributes to be used during initial segmentation. This allows you to set custom data and user attributes that will be used by Taplytics to segment your user into experiments. Format of user attributes defined here.
adobe_obj_nameStringThe adobe_obj_name is optional. The default variable that comes with Adobe Analytics integration is s. The s variable contains all of the tracking tags to be sent to Adobe Analytics for a given visitor. You only need to provide this if you are using a custom variable name.
track_adobe_analyticsBooleanEnable Adobe Analytics events to be collected into Taplytics.
user_bucketingBooleanEnables User-Based bucketing in the SDK and requires a user_id to provide consistent bucketing rather than bucketing by a device ID. Default is false. For more information please view this doc first.

Example:

TaplyticsInit({
	token: "JS_SDK_Key",
	version: '2.1.0',
	timeout: 10,
	test_experiments: {
	    "JS experiment": "Variation 1",
	    "JS experiment 2": "baseline"
	},
	user_attributes:{
	    email: "[email protected]",
	    qa_user: true,
	    purchases: 15
	}
})

1B Asynchronous script loading

Note: you only need to load the script once, do not load the synchronous script and the asynchronous script!

To install Taplytics JS SDK asynchronously, you have to include the following snippet into the header or body of your site:

<script type="text/javascript">
    !function(){var t=window.Taplytics=window.Taplytics||[];if(window._tlq=window._tlq||[],!t.identify&&!t.loaded){t.loaded=!0,t.funcs=["init","identify","track","page","reset","propertiesLoaded","runningExperiments","variable","codeBlock"],t.mock=function(n){return function(){var e=Array.prototype.slice.call(arguments);return e.unshift(n),window._tlq.push(e),t}};for(var n=0;n<t.funcs.length;n++){var e=t.funcs[n];t[e]=t.mock(e)}t.load=function(){var t=document.createElement("script");t.type="text/javascript",t.async=!0,t.src="//cdn.taplytics.com/taplytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(t,n)},t.load()}}();
</script>

This will load Taplytics.js asynchronously, so it will not affect your page load speed. We advise you use the synchronous script loading for any experiments applying content changes.

Other than that, all you have to do is initialize our SDK by using the init function:

Taplytics.init("JS_SDK_TOKEN");

Replace JS_SDK_TOKEN with your JS SDK token. You can find your token in the settings page of your project in the Taplytics dashboard.

❗️

When Taplytics.init() should be called

Taplytics.init() should be called if initializing asynchronously only. Calling Taplytics.init() alongside the synchronous script will cause multiple calls to Taplytics, which can result in undesired behaviour.

Note that this will send a page view event to us. If you want to disable the automatic page view event when Taplytics.js is initialized, check the documentation on the init function here and about calling the page function manually here.

Pin SDK version

If you would like to pin the JS SDK to a specific SDK version change the //cdn.taplytics.com/taplytics.min.js url in the snip-it above using the following url where sdk_version is the version you would like to pin to: //cdn.taplytics.com/jssdk/sdk_version/taplytics.min.js

Start Options

Start options allow you to control how certain SDK features, such as the default request timeout.

Start OptionTypeDescription
alias_hostObjectThis is used to replace the hosts of the urls to bypass adblockers
auto_page_viewBooleanEnable or disable to automatically track page views when starting up the sdk
cookie_domainStringSet the domain that Taplytics will use to create cookies with. By default Taplytics will use a wildcard version of your top level domain that will work across sub-domains. For example a cookie from web.taplytics.com will be set as .taplytics.com, that will also work on another subdomain such as: new.taplytics.com.
test_experimentsObjectSet an Object containing pairs of experiment/variation combinations as key/value pairs to test with. Learn more.
timeoutNumberSet the request timeout in seconds. If requests timeout variables will use the default value, but no events will be saved. The default timeout is 4 seconds.
user_attributesObjectSet initial user attributes to be used during initial segmentation. This allows you to set custom data and user attributes that will be used by Taplytics to segment your user into experiments, user attributes set after calling Taplytics.init() won't be used for segmentation until the next session. For the format of user attributes, visit our reference documentation.
adobe_obj_nameStringThe adobe_obj_name is optional. The default variable that comes with Adobe Analytics integration is s. The s variable contains all of the tracking tags to be sent to Adobe Analytics for a given visitor. You only need to provide this if you are using a custom variable name.
track_adobe_analyticsBooleanEnable Adobe Analytics events to be collected into Taplytics.
user_bucketingBooleanEnables User-Based bucketing in the SDK and requires a user_id to provide consistent bucketing rather than bucketing by a device ID. Default is false. For more information please view this doc first.

Example:

Taplytics.init("JS_SDK_TOKEN", {
    timeout: 10,
    test_experiments: {
        "JS experiment": "Variation 1",
        "JS experiment 2": "baseline"
    },
    user_attributes:{
        email: "[email protected]",
        qa_user: true,
        purchases: 15
    }
});

2. Identify Users

Using the identify function, you can let us know who the current user is on the page. It can also be used to let us know about any user attribute that can be used for segmentation in our system.

We accept a few known attributes and all unknown attributes are saved as custom attributes that can also be used. Read more about the identify function here.

Here's a quick example:

Taplytics.identify({
    email: "[email protected]",
    user_id: "abbc-123-axx-123-okl-123",
    first_name: "Nima",
    last_name: "Gardideh",
    age: 23,
    gender: "male",
    friends_count: 10,
    purchases_count: 10,
    store_credit: 102.14
});

User Attributes set before the TaplyticsInit() function is called will be used for experiment segmentation on the first session of your app. Any attributes that are set after the TaplyticsInit() function is called will not be used for experiment segmentation until the next session of your app.

To manually start a new session, check out our docs here.


3. Track Events

You can use the track function to send us events and let us know what actions the user is performing on the page. You can use these events within Taplytics to create more personalized and rich a/b tests and push notifications.

Here's how to do it:

Taplytics.track("Purchase", 10, {
    product_id: 100,
    product_name: "Cyan-Pink Shirt",
    product_price: 80.00
});

Note that you can send us revenue information by passing a value to the function and any other data that you can use when creating segments within Taplytics. Read more about the track function here.


4. Track Page Views

As we mentioned earlier, we automatically track page views for you when you initialize our SDK. You will have to call the page function if you would like to perform the following; rename your page views, attach more information to your page views, or if you're using a one-page web framework (Angular, React, Backbone, Ember, etc.).

You can specify a category, a name, and extra attributes when calling the page function:

Taplytics.page("Product Listings", "Shirts", {
    products_count: 100
});

Note that you can call the function by itself without any arguments as well. Read more about the page function here.


5. Experiments and Feature Flags

To setup code experiments with the Taplytics JS SDK check out the Experiments section here.

To setup feature flags with the Taplytics JS SDK check out the Feature Flags section here.


6. Opt-In/Out

Using the User Opt-In / Opt-Out APIs allows you to simplify the process to get user consent for analytics tracking and experimentation. Calling optOutTracking will disable all Taplytics analytics tracking and experiments and delete all Taplytics cookies, and calling optInTracking will re-enable all Taplytics analytics tracking and experiments. You can retrieve the current status using: hasUserOptedOutTracking.

function optIn() {
    console.log("opt in")
    Taplytics.optInTracking();
}

function optOut() {
    console.log("opt out")
    Taplytics.optOutTracking();
}

function hasOptedOut() {
    let hasUserOptedOut = Taplytics.hasUserOptedOutTracking();
    console.log(`Has user opted out tracking: ${hasUserOptedOut}`)
}

7. Integrations

Visit our 3rd Party Integrations page to learn more about our integrations with your favourite analytics platforms!

Adobe

Adobe Analytics by default uses s.t() and s.tl() for tracking page views and link clicks. By setting track_adobe_analytics variable to true in Taplytics.init function, We inject our tracking code into the definitions of these functions. Learn more about the Adobe integration for Web here.

Amplitude

Taplytics will automatically track incoming Amplitude events and you have the option to send experiment/variation data back to Amplitude. Learn more about the Amplitude integration for Web here.

Google Analytics

Taplytics will automatically track incoming Google Analytics events and you have the option to send experiment/variation data back to Google Analytics. Learn more about the Google Analytics integration for Web here.

Mixpanel

Taplytics can send experiment/variation data back to Mixpanel. Learn more about the Mixpanel integration for Web here.

MParticle / Segment

Integrate Taplytics with mParticle or Segment to connect your users and events to Taplytics without needing to create them separately. To get started, visit their respective pages here:

Extra Start Options

MParticle and Segment both allow you to enable/disable Taplytics specific Start Options from their platforms but you may also add start options using the following code to append and/or override existing start options. This is helpful when the options don't exist on mParticle/Segment.

<script>
   window.tl_options = {
      'cookie_domain': '...',
      'manual_trigger_edits': true,
      'user_attributes':{ ... },
      ...
   }
</script>

</script> 
   // Initialize Segment/mParticle 
</script>

8. Adblockers: How to Navigate

Custom Domain Proxy

Implement a Custom Domain Proxy to bypass 3rd party cookie blockers that block requests to Taplytics SDKs and APIs. The Custom Domain Proxy allows all Taplytics requests to be sent through your recognized domain. A CNAME hostname and certificate will be created need to be created in order to leverage this feature and both options can be customized if needed.

  1. Identifying a Hostname and Certificate Owner
    The first step involves identifying a hostname to use as the CNAME to Taplytics’ service as well as deciding whether you'd like Taplytics to manage a new certificate or manage the certificate yourselves.
  • If there is more than one service in use, each one will need a unique CNAME
  • If you'd like to create a custom hostname, you'll need to provide us with the hostname. Otherwise, Taplytics will create one for you
  • If you need to manage the certificate instead of having Taplytics manage the renewal, you'll need to provide both the Certificate and Private Key for the certificate(s) that you've created
  1. Setup Hostname and Certificate
    Taplytics to start the setup with the certificate and hostname. We can start this process immediately if you do not need to customize your hostname or certificate.

  2. DNS Validation
    Once the setup is complete, two DNS record will be provided by Taplytics and you will need to add those records to your DNS provider (TXT validation records).

  3. Additional Setup Step
    Once validation is complete, there may be an extra step involved here with Taplytics depending on your SDK configuration. Taplytics will let you know if this is needed.

  4. Creating a CNAME
    Once all steps are complete, Taplytics will send the details for the DNS CNAME. Once added, the service will be immediately available at the given hostname. You can use this hostname for all requests to Taplytics instead.

  5. Self-Managed Certificates
    If you are managing your own certificate, please provide Taplytics with any new certificates if they expire in the future. Failure to do so will result in an invalid certificate error.

If you have any questions regarding this process, please reach out to your CSM or to our support team.

CNAME Aliasing

Implementing CNAME aliasing can prevent adblockers from blocking requests to our api servers and our SDK. In order to workaround adblockers, please follow the implementation details below to add the alias_host start option and update the url to the SDK. In addition, Taplytics also requires a certificate for the domain that you will create a CNAME record for. If you would prefer not to create a certificate and send it to Taplytics, see the “Using a Reverse Proxy” section below.

1. Setup a CNAME on a DNS which points to our API Domains:

https://api-alias.your-domain.com -> https://api.taplytics.com
https://ping-alias.your-domain.com -> https://ping.taplytics.com

Once you have generated a CNAME, proceed in modifying your existing JS SDK loading scripts and include the alias_host start option.

Two options exist in loading the JS SDK. Please follow one of the two options below to successfully load the JS SDK dependent on your configuration.

a) Asynchronous Script Loading

Replace cdn.taplytics.com/taplytics.min.js with api-alias.your-domain.com/jssdk/

<script type="text/javascript"> !function(){var t=window.Taplytics=window.Taplytics||[];if(window._tlq=window._tlq||[],!t.identify&&!t.loaded){t.loaded=!0,t.funcs=["init","identify","track","page","reset","propertiesLoaded","runningExperiments","variable","codeBlock"],t.mock=function(n){return function(){var e=Array.prototype.slice.call(arguments);return e.unshift(n),window._tlq.push(e),t}};for(var n=0;n<t.funcs.length;n++){var e=t.funcs[n];t[e]=t.mock(e)}t.load=function(){var t=document.createElement("script");t.type="text/javascript",t.async=!0,t.src="//api-alias.your-domain.com/jssdk";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(t,n)},t.load()}}(); </script>

Add the alias_host start option and your CNAME domains

Taplytics.init("JS_SDK_Key", {
    alias_host: {
        api_host: 'https://api-alias.your-domain.com',
        ping_host: 'https://ping-alias.your-domain.com'
    }
});

b) Synchronous Script Loading

Add the alias_host start option as a URL parameter to the sync loading script

<script type="text/javascript">
  var head = document.getElementsByTagName('head')[0];
  var script = document.createElement('script');
  script.type = 'text/javascript';
  const alias = {
    api_host: 'https://api-alias.your-domain.com',
    ping_host: 'https://ping-alias.your-domain.com'
  }
  const encodedAlias = encodeURIComponent(JSON.stringify(alias));
  script.src = `https://api-alias.your-domain.com/jssdk/{JS_SDK_Key}.min.js?alias_host=${encodedAlias}`;
  head.appendChild(script);
</script>

2. Generate a new Certificate

You will then need to create a new Certificate for the domain you wish to whitelist. The certificate will contain 4 files, three of which are required:

  • cert.pem*
  • privkey.pem*
  • chain.pem*
  • fullchain.pem

Required: cert.pem, privkey.pem, and chain.pem.

To submit your certificate in addition to completing the setup, please contact your CSM or email us directly at [email protected].


Using a Reverse Proxy

Another way to navigate adblockers is to implement a reverse proxy from your server to ours. In this case, rather than using a CNAME to direct traffic from specific subdomains to our API and PING domains, you will need to implement routes on your server that would proxy traffic from your server to ours. Please note: unlike the CNAME option above, this option does not require a certificate to be created.

Below is a sample NginX configuration exemplifying reverse proxies:

...
location /tap-api/ {
 proxy_pass https://api.taplytics.com/;
}
location /tap-ping/ {
 proxy_pass https://ping.taplytics.com/;
}
...

Once you have implemented routes on your servers, proceed in modifying your existing JS SDK loading scripts and include the alias_host start option.

Two options exist in loading the JS SDK. Please follow one of the two options below to successfully load the JS SDK dependent on your configuration.

a) Asynchronous Script Loading

Replace cdn.taplytics.com/taplytics.min.js with your-domain.com/tap-api/jssdk

<script type="text/javascript"> !function(){var t=window.Taplytics=window.Taplytics||[];if(window._tlq=window._tlq||[],!t.identify&&!t.loaded){t.loaded=!0,t.funcs=["init","identify","track","page","reset","propertiesLoaded","runningExperiments","variable","codeBlock"],t.mock=function(n){return function(){var e=Array.prototype.slice.call(arguments);return e.unshift(n),window._tlq.push(e),t}};for(var n=0;n<t.funcs.length;n++){var e=t.funcs[n];t[e]=t.mock(e)}t.load=function(){var t=document.createElement("script");t.type="text/javascript",t.async=!0,t.src="//your-domain.com/tap-api/jssdk";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(t,n)},t.load()}}(); </script>

Add the alias_host start option and your CNAME domains

Taplytics.init("JS_SDK_Key", {
    alias_host: {
        api_host: 'https://your-domain.com/tap-api',
        ping_host: 'https://your-domain.com/tap-ping'
    }
});

b) Synchronous Script Loading

Add the alias_host start option as a URL parameter to the sync loading script

<script type="text/javascript">
  var head = document.getElementsByTagName('head')[0];
  var script = document.createElement('script');
  script.type = 'text/javascript';
  const alias = {
    api_host: 'https://your-domain.com/tap-api',
    ping_host: 'https://your-domain.com/tap-ping'
  }
  const encodedAlias = encodeURIComponent(JSON.stringify(alias));
  script.src = `https:/https://your-domain.com/tap-api/jssdk/{JS_SDK_Key}.min.js?alias_host=${encodedAlias}`;
  head.appendChild(script);
</script>

After completing the steps above, users should be able to freely maneuver around adblockers and prevent them from blocking requests to our api servers and our SDK.


Sessions

A session is defined as user activity from the start of a new session until 30 minutes from last activity logged into Taplytics. If a user has not done anything to trigger updating their user information in Taplytics, we consider their next activity afterwards to be a new session.

Start New Session

You can also manually start a new session using the startNewSession method if you need to load new properties from Taplytics. ie. After setting custom user attributes for segmentation.

Taplytics.startNewSession();

Experiments

Creating experiments is easy, using the Taplytics Javascript SDK you can create code-based experiments with Dynamic Variables or Code Blocks. Continue reading to find out how to set up those up in code below and find instructions on setting up Experiments on the Taplytics dashboard here.


Dynamic Variables

Taplytics variables are values in your website that are controlled by Experiments. Changing the values can update the content or functionality of your website. Variables are reusable between Experiments but may cause issues if they are used in multiple Active Experiments.

There are two types of code variables that you can leverage, synchronous and asynchronous variables. More info on those below.


Synchronous Variables

Due to the synchronous nature of the variable, if it is used before the experiments have been loaded from Taplytics servers, it's value will be the default value rather than the value set for that experiment. This could taint the results of the experiment. In order to prevent this you can ensure that the experiments are loaded before using the variable. This can be done using the propertiesLoaded method. See example below.

Synchronous variables take two parameters in its constructor:

  1. Variable Name (String)
  2. Default Value (String, Number, or Boolean)

The type of the variable is defined by the type of the default value, and can be a String, Number or a Boolean.

For example, using a variable of type String with propertiesLoaded:

Taplytics.propertiesLoaded(() => {
    var syncVar = Taplytics.variable("JS String", "default");
    console.log("JS String Sync value: " + syncVar.value);
});

Asynchronous Variables

Asynchronous variables take care of insuring that the experiments have been loaded before returning a value. This removes any danger of tainting the results of your experiment with bad data. What comes with the insurance of using the correct value is the possibility that the value will not be set immediately. If the variable is constructed before the experiments are loaded, you won't have the correct value until the experiments have finished loading. If the experiments fail to load, then you will be given the default value, as specified in the variables constructor.

Asynchronous variables take three parameters in its constructor:

  1. Variable Name (String)
  2. Default Value (String, Number, or Boolean)
  3. Updated Function (Function)

The type of the variable is defined by the type of the default value, and can be a String, Number or a Boolean.

For example, using a variable of type Number:

When the SDK has loaded the experiment config from our servers, the updated block will be called with that updated value.

Taplytics.variable("JS Number", 1, (value) => {
    // function called when experiment config has loaded and value has been set
    console.log("JS Number value: " + value);
});

Note: To see and modify the code variables you've added in code on the dashboard, the SDK must be launched and this code containing the variable or block must be navigated to a least once. This will auto-populate the Experiments dashboard with your newly created variables. You may manually create code variables on the dashboard as well.


Code Blocks

Similar to Dynamic Variables, Taplytics has an option for 'Code Blocks'. Code blocks are linked to Experiments through the Taplytics website very much the same way that Dynamic Variables are, and will be executed based on the configuration of the experiment through the Taplytics dashboard

A Code Block is a function that can be enabled or disabled depending on the variation. If enabled, the function will be executed asynchronously once the experiment config has loaded from our servers. If disabled, the function will not be executed.

Example:

Taplytics.codeBlock("enableFeature", function() {
    // enable your feature here
});

A Code Block can be used alongside as many other Code Blocks as you would like to determine a combination that yields the best results. Perhaps there are three different Code Blocks on one view. This means there could be 8 different combinations of Code Blocks being enabled / disabled on that view if you'd like.

Note: To see and modify your code blocks on the dashboard, the SDK must be launched and this code containing the variable or block must be navigated to a least once. This will auto-populate the Experiments dashboard with your newly created variables. You may manually create code blocks on the dashboard as well.


Get Running Experiments

If you would like to see a list of all experiments and variations that are running, use the runningExperiments function. This will return the current experiments and their variations that the browser is receiving once the SDK has loaded the config from our servers.

The block can return asynchronously once Taplytics config has loaded and will return an Object with experiment names as the key values, and variation names as the values. Example:

Taplytics.runningExperiments(function(expAndVars) {
    // Example of expAndVars: 
    // expAndVars = {
    //  "Experiment 1": "baseline",
    //  "Experiment 2": "Variation 1"
    //};
});

Feature Flags

Taplytics feature flags operate in synchronous mode. Synchronous feature flags are guaranteed to have the same value for the entire session and will have that value immediately after construction.

if (Taplytics.featureFlagEnabled("featureFlagKey")) {
    //Put feature code here, or launch feature from here
}

Due to the synchronous nature of feature flags, if it is used before the feature flags have been loaded from Taplytics servers, it will default to as if the feature flag is not present. In order to prevent this you can ensure that the feature flags are loaded before using the feature flag. This can be done using the propertiesLoaded method, as an example:

Taplytics.propertiesLoaded((loaded) => {
    if (Taplytics.featureFlagEnabled("featureFlagKey")) {
        // Put feature code here, or launch feature from here
    }
})

Get Running Feature Flags

If you would like to see a list of feature flags that are running on the browser, there exists a getRunningFeatureFlags function which provides a callback with an object that contains the current active feature flags.

The block can return asynchronously once Taplytics properties have loaded. The feature flags will be provided in an object where the properties are the feature flag key names and their corresponding values are the names of the associated feature flags.

Taplytics.runningFeatureFlags((runningFF) => {
    // For example runningFF will contain:
    //    {
    //        "featureFlagKey": "My First Feature Flag",
    //        "key with spaces": "My Second Feature Flag"
    //    }
});

Test Experiments and Feature Flags

To test/QA specific Experiment and Variation combinations as well as Feature flags, use the test_experiments option with an Object containing keys of the Experiment or Feature flag names, and values of Variation names (or baseline).

Taplytics.init("JS_SDK_TOKEN", {
    test_experiments: {
        "JS experiment": "Variation 1",
        "JS experiment 2": "baseline",
        "JS Feature Flag": "baseline"
    }
});

Reference

Below you will find the APIs that Taplytics.js exposes.

If you haven't already, check out our guide on how to get started with our Javascript SDK here.


init

Usage: Taplytics.init(token, [options])

Instantiates Taplytics.js.

This should be the first function to be called on the page before all other functions. You can find your JS SDK Key in the Settings section of your project.

It also automatically calls the page function (with no arguments) right away. You can disable this in the options.

Arguments

  1. token (string): Taplytics JS SDK
  2. [options] (Object): The options object.
Options ParamsTypeDescription
timeoutNumberSet the request timeout in seconds. If requests timeout variables will use the default value, but no events will be saved. The default timeout is 4 seconds.
test_experimentsObjectSet an Object containing pairs of experiment/variation combinations as key/value pairs to test with. Learn more.
cookie_domainStringSet the domain that Taplytics will use to create cookies with. By default Taplytics will use a wildcard version of your top level domain that will work across sub-domains. For example a cookie from web.taplytics.com will be set as .taplytics.com, that will also work on another subdomain such as: new.taplytics.com.
user_attributesObjectSet inital user attributes to be used during inital segmenation. This allows you to set custom data and user attributes that will be used by Taplytics to segment your user into experiments, user attributes set after calling Taplytics.init() won't be used for segmentation until the next session.

Returns

(Object): Returns the Taplytics object on success, useful for chaining. When no token is provided, it returns undefined.

Example

// Without options
Taplytics.init("JS_SDK_TOKEN");

// With some options
Taplytics.init("JS_SDK_TOKEN", {
    auto_page_view: false,
    log_level: 1
});

identify

Usage: Taplytics.identify(user_attributes)

Identifies the user that's currently on the page. This helps link their activity on the web with their activity on other platforms (iOS, Android).

You should call this function as soon as a user signs up or has logged in.

Setting a user_id will manually cause a new session to be triggered and new properties to be loaded so there is no need to manually start a new session.

Arguments

  1. [user_attributes={}] (Object): User Attributes object.
  2. [user_attributes.user_id] (string/integer): User's ID (optional).
  3. [user_attributes.email] (string): User's Email (optional).
  4. [user_attributes.gender] (string): User's Gender, one of male or female (optional).
  5. [user_attributes.age] (integer): User's age as a number (optional).
  6. [user_attributes.firstName] (string): User's first name (optional).
  7. [user_attributes.lastName] (string): User's last name (optional).
  8. [user_attributes.name] (string): User's full name (optional).
  9. [user_attributes.avatarUrl] (string): User's avatar/profile image URL (optional).
  10. [user_attributes.custom_attr_name] (string/integer/object): Any extra custom attributes (optional).

Returns

(Object): Returns the Taplytics object, useful for chaining.

Example

// With just a few named user attributes
Taplytics.identify({
    email: "[email protected]",
    age: 23,
    gender: "male",
    firstName: "Nima",
    lastName: "Gardideh"
});

// With non-named custom attributes
Taplytics.identify({
    user_id: 1015,
    loyalty_group: "very_loyal",
    purchases_count: 15,
    friends_Count: 800
});

track

Usage: Taplytics.track(event_name, [value], [event_attributes])

Tracks the occurrence of an event for the current visitor (anonymous or identified).

Note that value is identified as revenue. If you want to send information about the event itself, send it through event_attributes.

Aliases

This function can also be called as follows:
Taplytics.track(event_name, [event_attributes])

Arguments

  1. event_name (string): Event name.
  2. value (integer/double): Value of the event (optional).
  3. event_attributes (Object): Event attributes to be sent with the event (optional).

Returns

(Object): Returns the Taplytics object, useful for chaining.

Example

// Simple event
Taplytics.track("Clicked Button");

// Event with value (revenue)
Taplytics.track("Purchased", 180.50);

// Event with value (revenue) and extra attributes
Taplytics.track("Purchased", 180.50, {
    product_id: 100,
    product_name: "Shirt"
});

// Event just with attributes
Taplytics.track("Finished Tutorial", {
    time_on_tutorial: 100
});

page

Usage: Taplytics.page([category], [name], [page_attributes])

Tracks a page view. This is called once automatically from the init function.

You can call it manually yourself to structure the page view events, as well as when you have a single page Javascript application that does its own routing.

Currently, we do not listen on window.History state change events to do this automatically.

Aliases

This function can also be called as follows:
Taplytics.page([name], [page_attributes]);

Arguments

  1. [category] (string): Page Category (optional).
  2. [name] (string): Page Name (optional).
  3. [page_attributes] (Object): Page attributes object.

Returns

(Object): Returns the Taplytics object, useful for chaining.

Example

// Track a page view with no attributes
Taplytics.page();

// Track it by setting a name
Taplytics.page("Page Name");

// Track a page view with a category and a name
Taplytics.page("Product Listings", "Shirts");

// Track a page view with a name and attributes
Taplytics.page("Shirts Page", {
    products_count: 150
});

// Track a page view with a name, a category, and attributes
Taplytics.page("Product Listings", "Shirts", {
    products_count: 150
});

reset

Usage: Taplytics.reset()

Resets the user object and assumes the visitor is now anonymous. This can be used to deatach the visitor from the user that you had used identify on earlier in the session.

Returns

(Object): Returns the Taplytics object, useful for chaining.

Example

// Reset user
Taplytics.reset();

propertiesLoaded

Usage: Taplytics.propertiesLoaded([callback])

Calls the function provided when the SDK's properties have loaded from Taplytics's servers.

Arguments

  1. [callback] (function): function to callback when properties have loaded.

Example

Taplytics.propertiesLoaded(function() { 
    // properties have loaded
});

runningExperiments

Usage: Taplytics.runningExperiments(callback)

Calls the function provided with an Object containing the running experiments and variation names when the SDK's config has loaded from Taplytics's servers.

Arguments

  1. callback (function): function to callback with running experiments and variations. With the Object's keys as experiment names, and values as the variation name.

Example

Taplytics.runningExperiments(function(expAndVars) {
    // For example: 
    // expAndVars = {
    //  "Experiment 1": "baseline",
    //  "Experiment 2": "Variation 1"
    //};
});

variable

Usage: Taplytics.variable(name, defaultValue, [updatedBlock])

Creates a Taplytics Variable with values that are controlled by your running experiments.

Arguments

  1. name (string): Variable Name.
  2. defaultValue (string/number/boolean): Variable's default value.
  3. [updatedBlock] (function): Update block to be called when the Variable's value is set (optional).

Returns

(TLVariable): Returns a Taplytics Variable, use value to get the variable's value

Example

// Using a asynchronous variable with the updated block
Taplytics.variable("JS String", "default", function(value) {
    console.log("JS String value: " + value);
});

// Using a synchronous variable
Taplytics.propertiesLoaded(function() {
    var syncVar = Taplytics.variable("JS String", "default");
    console.log("JS String Sync value: " + syncVar.value);
});

codeBlock

Usage: Taplytics.codeBlock(name, codeBlock)

Creates a Taplytics Code Block that will be run if enabled for the running experiment/variation through Taplytics website.

Arguments

  1. name (string): Variable Name.
  2. codeBlock (function): Code Block to be called if enabled for the experiment's variation.

Example

Taplytics.codeBlock("JS CodeBlock", function() {
    console.log("JS Code Block");
    // run your code here
});

applyVisualEdits

Usage: Taplytics.applyVisualEdits()

Applies Visual Editor Changes to the page whenever this is called. By default, this is automatically run during initialization of Taplytics. Use this if your contents load after Taplytics has already initialized.

Example

// Apply Visual Edits to page
Taplytics.applyVisualEdits()

trackClickGoals

Usage: Taplytics.trackClickGoals()

Attaches Instant Click Goals created via the Visual Web Editor to the elements on the page whenever this is called. By default this is automatically run during initialization of Taplytics. Use this if your contents load after Taplytics has already initialized.

Example

// Attach Instant Goals to elements
Taplytics.trackClickGoals()

Cookies

Below you'll find the Cookies that Taplytics is setting for session tracking, bucketing and identification purposes.

NameDescription
_tl_auidTaplytics App User identifier
_tl_csidTaplytics Cookie Session identifier
_tl_duuidTaplytics Device identifier
_tl_sidTaplytics Session identifier
_tl_uidTaplytics user_id
_tl_configTaplytics Cached Config
tl_sopts_{ }_p_p_l_hPage Conversion Goals - previous page href
tl_sopts_{ }_p_p_lPage Conversion Goals - previous page location
tl_sopts_{ }_p_p_l_tPage Conversion Goals - previous page title
tl_sopts_{ }_p_p_v_dPage Conversion Goals - previous page view date

Enable the Visual Editor

Making visual edits on the web with Taplytics is super easy! Similar to mobile, once the visual web editor tool has been enabled it's as simple as hovering over the element you'd like to edit and making the change.

All you need to do to enable the visual web editing tool is provide a google email address and then download the Taplytics Chrome Web Extension. From there you'll be able to make edits directly from on your website.


Making Visual Edits

All edits are done on your actual website and are only launched to production once you've started the experiment.

Using the visual editor you are able to make most types of changes to any static element on your website, including copy, size, colour, font, and image changes.

Changes are applied to the CSS selectors on each page and will be applied to specific pages based on the URL path.

If you'd like changes to stick to additional pages there is an option to "Match on all URL's". Checking this box will ensure changes made on one page will carry over to the matching element on another page. Taplytics does this by matching both on the base URL and then looking for additional CSS selectors to carry the change over to additional pages.

Check out our Web Visual Experiments User Guide