NAV
  • Advanced Implementation Guide
  • Advanced Implementation Guide

    Introduction

    This article is an in-depth technical guide to help you get familiar with the different implementation methods Kameleoon supports. The implementation process in itself is simple, since you only need to add a JavaScript installation tag into the HTML source code of your pages. However, the details are extremely important, so we will focus on them: where exactly should the tags be placed, what are the pros and cons of our different implementations, and when is the Kameleoon application file loaded and parsed by the browser. All these factors are important to take into consideration when optimizing the setup of Kameleoon for performance, while ensuring all the functional depth of the platform remains intact.

    Understanding all this will let you take an informed decision about which type of implementation method best fits your website and requirements. We also have a recommended setup which you should follow if you are not sure or have any doubts about which installation type to use.

    List of Installation Tags & Features

    The table below lists our different types of implementation methods and features. Rows represent the types of implementation (how the Kameleoon JavaScript application file will be loaded), while columns represent their inherent characteristics (mostly related to performance and flickering) and features (ability to track a visitor across domains, possibility to launch our application file via a Tag Manager).

    Definitions of these characteristics and features, as well as code for each implementation are provided in two later sections.

    Implementation MethodFlickerMay block page loadingPrioritized script loadingAffected by ITPUse with Tag Manager
    Asynchronous Loading, with Anti-FlickerNoNoYesNoNo
    Asynchronous LoadingYesNoYes (if not installed via a Tag Manager)NoYes
    Synchronous LoadingNoYesYesNoNo

    In addition, all implementation methods can also support Cross-Domain Tracking if needed.

    Description of Characteristics & Features

    This section defines and explains the characteristics and features presented in the previous table.

    Flicker

    The Flicker column indicates if this type of installation can induce a problem commonly occuring with JavaScript based A/B testing solutions, called the flicker effect. When your webpage is loading, it is possible that the original page displays for a split second instead of the variation. This twinkling is called flicker effect or flickering. Of course, this will confuse the visitor and can greatly distort the results of any experiment. We therefore strongly recommend making sure Kameleoon does not produce ANY flicker effect. Our platform includes built-in advanced techniques to completely eradicate flickering, but for this to happen, our installation recommendations must be followed.

    Flickering has two causes:

    To eliminate flickering due to the first reason, you just need to select an installation tag that has "No" in the corresponding Flicker column (in fact, all except the asynchronous JavaScript file will do the job). These methods guarantee that Kameleoon's code will be executed before any rendering of the page by the browser. In the case of synchronous loading, this is guaranteed automatically as long as the tag is included in the HTML <head> section, since the browser will not display anything until the Kameleoon application file is downloaded and executed. However, loading any resource in a blocking way is not a good practice, and we added a special anti-flickering technique to all the other asynchronous methods. Technically, we use a special CSS rule (* { visibility: hidden !important; background-image: none !important; }) that will "hide" the page being loaded. We remove this rule as soon as Kameleoon's application code has been run, OR if a customer specified time out is reached.

    Even if you use a correct implementation method, flickering effects can still occur, if the underlying engine of your A/B testing solution is not optimized to avoid them. In the case of Kameleoon, we guarantee these optimizations for any modification done by our graphical editor tool. For avanced variations that use custom JavaScript code, we provide APIs to guarantee this as well, but you must of course use them. Any modification on an element, or waiting for an element to appear on the page, should be done via our standard JavaScript API method (namely Kameleoon.API.Core.runWhenElementPresent()), NOT via hand-coded pollers or other custom code.

    May block page loading

    If the servers (usually our Content Delivery Network, but it can also be your own CDN or server) hosting the Kameleoon application file are down or not responding, this characteristic mentions wether the loading of your website will be entirely blocked. Only one type of implementation implies this potential danger, the JavaScript file (Synchronous Loading) tag. All other methods will leave your website entirely functional even if all our hosting servers are down (which is, of course, something that should never happen in the first place).

    Technically, to avoid blocking if the hosting server is not available, we load the Kameleoon application file asynchronously. Still, since we do include a "blocking CSS rule" hiding the entire page's contents, in order to prevent flickering, we have to combine this with a timeout technique. Otherwise we would show a blank page indefinitely, which is not any better than blocking the loading of the page in the browser. After a given period of time (which we call the timeout period), if the Kameleoon application file is still not loaded, the tag will show the usual page's contents (which were hidden to avoid flickering). This way, we guarantee that in no circumstances can Kameleoon ever bring your website down.

    The timeout is controlled by the kameleoonLoadingTimeout JavaScript variable which you can set according to your needs (in the Kameleoon installation tag). By default it is equal to 1000 milliseconds, and we suggest leaving it as is. It represents the maximum amount of time the Kameleoon installation tag can "block" the display of your site while it is waiting for the Kameleoon application file.

    Prioritized script loading

    All static resources that an HTML page references (such as JavaScript files, CSS styles, Iframes, images ...) need to be downloaded by the browser before being used according to their type. For CSS or images they will just get displayed, for JS files and Iframes, some code will be executed, and so on. Browsers usually load resources by putting them in their network queue and then downloading them in a given order of priority. This order of priority is not clearly documented and is browser-dependent, but two important factors are to be considered for our purposes. First, a browser can only download a resource once it has been "discovered". Second, major browsers will assign a higher priority to the scripts that are included in the page statically, compared to the ones that are loaded dynamically via some JavaScript code. Eg, if you want a JS file to be loaded with higher priority, it's better to use this:

    <script type="text/javascript" src="resources/scripts/example.js" async></script>
    

    rather than this:

    <script type="text/javascript">
        var scriptNode = document.createElement("script");
        scriptNode.type = "text/javascript";
        scriptNode.src = "resources/scripts/example.js";
        document.head.appendChild(scriptNode);
    </script>
    

    Prioritized script loading means that the Kameleoon application file will be put at the top of the browser network queue. As a result, it will almost always load faster compared to a non-prioritized setup. This is thus a recommended option for Kameleoon, although the downside is that other resources will be delayed. Since we deem A/B testing an important feature that needs to load as soon as possible (compared to other technologies related to tracking or analytics, which can load later since they don't act on their host pages), we consider this to be a reasonable trade-off. Thus all current Kameleoon implementation methods currently provide Prioritized script loading except if you decide to install Kameleoon via a Tag Manger system.

    Affected by ITP (Intelligent Tracking Prevention)

    Intelligent Tracking Prevention is a technology implemented by Apple in their Safari browsers (both mobile on iPhones and desktop on Macs). Mozilla has implemented a similar technology in their Firefox browser. Basically, the goal of this technology is to prevent unwanted, third-party tracking. Mostly this is intended as a way to prevent advertising trackers to track you accross several sites on the Web, and serve you targeted ads.

    Kameleoon offers a solution to ITP restrictions, but since version 2.3 (with the important March 2020 update) it unfortunately requires an additional configuration step. See our dedicated article on this topic.

    The list of synchronization methods is available here. Pick up the one most appropriate to your situation and implement it to avoid ITP problems.

    Use with Tag Manager

    Use with Tag Manager indicates whether the chosen implementation method allows you to use a tag manager or not. Kameleoon is compatible with all major Tag Management Systems (TMS). However, if possible, we really recommend you install Kameleoon directly in the source code of your pages, and not via a TMS. The reason for this is again related to the flicker effect. Using a TMS delays the load of Kameleoon and automatically creates a very noticeable flickering effect. This is especially problematic if your TMS is loaded at the bottom of your HTML page. However, we know that for some customers the use of a TMS (such as Google Tag Manager, Tag Commander, Tealium, etc) is mandatory.

    Inside a TMS, loading external JavaScript code synchronously is inherently impossible. Also, our anti-flicker prevention technology is not designed to work properly within a TMS. Thus the only implementation method that allows being placed inside a TMS is the asynchronous JavaScript file. For this method, we provide the correct JavaScript code to use within your TMS, to correctly load Kameleoon.

    Cross-Domain Tracking

    Kameleoon offers support for cross-domain tracking which makes it possible to link sessions on several related sites as a single session. For instance, you may wish to consider that a visit started on https://portal.myecommercesite.com and continued on https://transaction-engine.myecommercesite.com (which are two websites that you own) form a single visit.

    This feature is very important for accurate data collection across different domains, if you own several of them. If an installation tag which doesn't support cross-domain tracking has been chosen, then a visit that starts in one domain will be tracked as an entirely new visit once it reaches another related domain. All data gathered on one domain (such as number of page views, time spent on site...) will be reset on another domain, and thus targeting based on these kind of criteria can also produce unexpected results when cross-domain is not used. For instance, let's suppose you have a personalization triggering at the fourth page viewed. A visitor goes to your first website, sees 3 pages, then loads a fourth in a new domain website. With cross-domain tracking, the personalization will indeed trigger; without it, it won't, since the page view on the new domain will be considered the first one of a new visit.

    To be able to use cross-domain tracking, you must host a static resource (an HTML file that never changes - you can just copy it once at setup and leave it untouched) on your main domain.

    Technically, with cross-domain tracking, we will always use your main domain when saving content on the browser's Local Storage. If the current URL corresponds to the main domain, then the Kameleoon engine can directly write data to the Local Storage space associated with this domain. If the URL belongs to another domain, we will load an iFrame file containing a small, static code that only handles the reading and writing of Kameleoon data on the core domain.

    Description of installation tags

    The installation tags presented on the right should ALWAYS be added in the <head> section of your HTML code. Never place the Kameleoon installation tags in the <body>, especially at the end of the page.

    In addition, it is highly recommended that you add these tags as high as possible in the <head> section. Ideally, they should be placed just after the initial opening <head> tag, so that the browser will load the Kameleoon application file before anything else. Any resources (CSS, other scripts...) placed before Kameleoon increase the risk of flickering.

    Asynchronous Loading with Anti-Flicker

    <script type="text/javascript">
        // Duration in milliseconds to wait while the Kameleoon application file is loaded
        var kameleoonLoadingTimeout = 1000;
    
        window.kameleoonQueue = window.kameleoonQueue || [];
        window.kameleoonStartLoadTime = new Date().getTime();
        if (! document.getElementById("kameleoonLoadingStyleSheet") && ! window.kameleoonDisplayPageTimeOut)
        {
            var kameleoonS = document.getElementsByTagName("script")[0];
            var kameleoonCc = "* { visibility: hidden !important; background-image: none !important; }";
            var kameleoonStn = document.createElement("style");
            kameleoonStn.type = "text/css";
            kameleoonStn.id = "kameleoonLoadingStyleSheet";
            if (kameleoonStn.styleSheet)
            {
                kameleoonStn.styleSheet.cssText = kameleoonCc;
            }
            else
            {
                kameleoonStn.appendChild(document.createTextNode(kameleoonCc));
            }
            kameleoonS.parentNode.insertBefore(kameleoonStn, kameleoonS);
            window.kameleoonDisplayPage = function(fromEngine)
            {
                if (!fromEngine)
                {
                    window.kameleoonTimeout = true;
                }
                if (kameleoonStn.parentNode)
                {
                    kameleoonStn.parentNode.removeChild(kameleoonStn);
                }
            };
            window.kameleoonDisplayPageTimeOut = window.setTimeout(window.kameleoonDisplayPage, kameleoonLoadingTimeout);
        }
    
    </script>
    <script type="text/javascript" src="//SITE_CODE.kameleoon.eu/kameleoon.js" async="true"></script>
    

    In this implementation method, the Kameleoon application file is still loaded asynchronously without blocking the page. It's still contained within a JavaScript file. However, until the Kameleoon code is executed, the page will be hidden via the help of a simple CSS rule. See the paragraph about flickering for details.

    Don't forget to replace the SITE_CODE placeholders by your own site code (there are two places where this must be done). Also pay attention to the kameleoonLoadingTimeout variable in the code, which can be changed according to your requirements.

    Asynchronous Loading

    Standard implementation

    <script type="text/javascript">
      window.kameleoonQueue = window.kameleoonQueue || [];
    </script>
    <script
      type="text/javascript"
      src="//SITE_CODE.kameleoon.eu/kameleoon.js"
      async="true"
    ></script>
    

    Tag Manager implementation

    window.kameleoonStartLoadTime = new Date().getTime();
    var scriptNode = document.createElement("script");
    scriptNode.src = "//SITE_CODE.kameleoon.eu/kameleoon.js";
    scriptNode.type = "text/javascript";
    scriptNode.async = true;
    scriptNode.setAttribute("data-tagmanager", true);
    document.head.appendChild(scriptNode);
    

    According to best practice, JavaScript external scripts should be loaded asynchronously. This ensures that page loading is not blocked while scripts are downloaded by the browser.

    To install Kameleoon application file asynchronously, without any attempt to avoid the flicker effect that can happen, use this method. Don't forget to replace the SITE_CODE placeholder by your own.

    Synchronous Loading

    <script type="text/javascript">window.kameleoonQueue = window.kameleoonQueue || [];</script>
    <script type="text/javascript" src="//SITE_CODE.kameleoon.eu/kameleoon.js"></script>
    

    See the example on the right on how to install the Kameleoon application file synchronously. Make sure you replace the SITE_CODE placeholder with your own site code.

    This approach loads the Kameleoon script synchronously, without flickering. However, flickering is avoided because the loading of the page is blocked until the Kameleoon code is downloaded and executed, which is not recommended.

    Additional setup for Cross-Domain Tracking

    <script type="text/javascript">
        // Change the value of this URL to point to your own URL, where the iFrame is hosted
        window.kameleoonIframeURL = "https://www.customerdomain.com/path/to/kameleoon-iframe.html";
    
        window.kameleoonLightIframe = false;
        var kameleoonIframeOriginElement = document.createElement("a");
        kameleoonIframeOriginElement.href = kameleoonIframeURL;
        window.kameleoonIframeOrigin = kameleoonIframeOriginElement.origin || (kameleoonIframeOriginElement.protocol + "//" + kameleoonIframeOriginElement.hostname);
        if (location.href.indexOf(window.kameleoonIframeOrigin) != 0)
        {
            window.kameleoonLightIframe = true;
            var kameleoonProcessMessageEvent = function(event)
            {
                if (window.kameleoonIframeOrigin == event.origin && event.data.slice && event.data.slice(0,9) == "Kameleoon")
                {
                    window.removeEventListener("message", kameleoonProcessMessageEvent);
                    window.kameleoonExternalIFrameLoaded = true;
                    if (window.Kameleoon)
                    {
                        eval(event.data);
                        Kameleoon.Analyst.load();
                    }
                    else
                    {
                        window.kameleoonExternalIFrameLoadedData = event.data;
                    }
                }
            };
            if (window.addEventListener)
            {
                window.addEventListener("message", kameleoonProcessMessageEvent, false);
            }
            var iframeNode = document.createElement("iframe");
            iframeNode.src = kameleoonIframeURL;
            iframeNode.id = "kameleoonExternalIframe";
            iframeNode.style = "float: left !important; opacity: 0.0 !important; width: 0px !important; height: 0px !important;";
            document.head.appendChild(iframeNode);
        }
    
    </script>
    

    To add cross-domain tracking capabilities to Kameleoon (mandatory if your web platform uses several domains or mixes HTTP and HTTPs protocols), you need to host the iFrame file provided below. This iFrame will be loaded whenever, during the visitor's journey, the page URL does not match the main domain of the website. The iFrame HTML file is static and contains only immuable code used to save and restore visitor data in the Local Storage.

    In addition to hosting the iframe, you also need to include an additional installation snippet, provided on the left. You will need to provide the correct value for the kameleoonIframeURL variable in the implementation code. This variable should be set to your own URL where the iFrame is accessible.

    Note that the cross-domain tracking snippet can be used in a Tag Manager installation without any problems.

    Additional configuration for ITP

    Independently of the JavaScript installation tag, you also need to implement a cookie synchronization method to prevent ITP issues on Safari. Choose the most appropriate method for you on this page.

    Recommended implementation Method

    We provide an official recommended implementation method that we feel is best, according to our own extensive expertise related to Kameleoon performance impact on the hosting website. It would be false to claim Kameleoon has a totally null impact on performance. Every script or resource you add to your site inevitably carries some overhead. However, performance has always been a top priority for our engineers at Kameleoon, who have worked hundreds of hours, tweaking our code and technology, to obtain the best results possible. We claim to have the most performance optimized solution on the market - and we hope this article can convince you of this.

    Currently our official recommended method is Asynchronous Loading, with Anti-Flicker. This recommended implementation is not the one that loads Kameleoon in the fastest possible way (for this, you should consider the synchronous loading), but it is the safest. Using an asynchronous script guarantees you that Kameleoon can not block the load your web site. And the added white overlay on the page "simulates" the effect of a synchronously loaded script, preventing flickering.

    Special Case: Using your own CDN or hosting server (self-hosting)

    It is important to note that the Kameleoon application file can safely reside either on the Kameleoon CDN or on your own CDN (or servers). Hosting the Kameleoon application file on your own servers can give a small but noticeable performance boost, by removing the additional DNS query and SSL handshake needed if you use the Kameleoon CDN. Also, you may wish to self-host for security reasons (if the Kameleoon application file is served from your own servers, you can ensure your internal security policies are followed and you are responsible for the security of the hosting servers, instead of entrusting us with this responsibility).

    If you want to self-host the Kameleoon application file, follow these instructions (this is a separate article about the different options for using Kameleoon as an On-Premises platform rather than a SaaS platform).

    Common Mistakes

    <script type="text/javascript" src="resources/scripts/kameloon-loader.js"></script>
    

    while the kameloon-loader.js script contains for instance the following installation code:

    // Duration in milliseconds to wait while the Kameleoon application file is loaded
    var kameleoonLoadingTimeout = 1000;
    
    window.kameleoonQueue = window.kameleoonQueue || [];
    window.kameleoonStartLoadTime = new Date().getTime();
    if (! document.getElementById("kameleoonLoadingStyleSheet") && ! window.kameleoonDisplayPageTimeOut)
    {
    var kameleoonS = document.getElementsByTagName("script")[0];
    var kameleoonCc = "\* { visibility: hidden !important; background-image: none !important; }";
    var kameleoonStn = document.createElement("style");
    kameleoonStn.type = "text/css";
    kameleoonStn.id = "kameleoonLoadingStyleSheet";
    if (kameleoonStn.styleSheet)
    {
    kameleoonStn.styleSheet.cssText = kameleoonCc;
    }
    else
    {
    kameleoonStn.appendChild(document.createTextNode(kameleoonCc));
    }
    kameleoonS.parentNode.insertBefore(kameleoonStn, kameleoonS);
    window.kameleoonDisplayPage = function(fromEngine)
    {
    if (!fromEngine)
    {
    window.kameleoonTimeout = true;
    }
    if (kameleoonStn.parentNode)
    {
    kameleoonStn.parentNode.removeChild(kameleoonStn);
    }
    };
    window.kameleoonDisplayPageTimeOut = window.setTimeout(window.kameleoonDisplayPage, kameleoonLoadingTimeout);
    }
    
    var scriptNode = document.createElement("script");
    scriptNode.src = "//SITE_CODE.kameleoon.eu/kameleoon.js";
    scriptNode.type = "text/javascript";
    scriptNode.async = true;
    document.head.appendChild(scriptNode);
    
    

    While this may technically work, this is an extremely bad practice. It will literally kill the performance of Kameleoon and introduce a huge flicker effect. In fact, you're kind of implementing your own tag manager by doing that: you will suffer all the problems of using a tag manager without any of the associated benefits. Please, really, don't do it.

    FAQ

    Q. My website uses a whitelist of domains for CORS (for instance via the content-security-policy HTTP header). What are the Kameleoon domains that I need to whitelist?

    A. We recommend whitelisting *.kameleoon.eu and *.kameleoon.com. If you don't want to use wildcards, this is the full current list:

    Q. Can I use Subresource Integrity (SRI) with the Kameleoon application file (script or iframe)?

    A. Unfortunately no. While we like SRI's idea, and believe it is a good security feature in modern browsers, our application file changes over time. If it did not, we would not be able to provide most of the features Kameleoon is useful for. Eg, we would lose the ability to start and stop experiments instantly, without requiring a redeployment of the customer's web platform. Since the contents of our file changes, so does the hash of this ressource and thus SRI cannot be used (it would block our ressource as soon as it changes on our servers).

    Q. With Kameleoon, on Firefox only, my website now loads with a huge flash/flicker effect. Why?

    It's an known bug on Firefox. Until it's fixed properly by the Firefox team, there is a workaround: your linked CSS ressource should be followed by a <script> tag (even an almost empty one). Example:

    <link href="https://www.example.com/web/style.css" media="all" rel="stylesheet" type="text/css" />
    <script>/**/</script>
    

    This will remove the flashing effect entirely.

    Q. Can I use minified versions of the installation tags?

    A. You can, but these scripts are already very short and using a minified version won't affect at all the loading time of your web pages (remember that this code should already be compressed using Brotli or Gzip compression). Thus we do not recommend the use of minified versions. If you still want to use them, you can find them here.

    Further Reading

    If you wish to learn even more about the technical details of external JavaScript code loading, here are some useful links.