The asynchronous snippet may be a better option if blocking scripts are a concern on your site, or you're loading FunnelEnvy through an asynchronous tag management solution (e.g. Google Tag Manager).
We recommend placing the asynchronous code in the page <head>
, which will create a DOM element, fetch the snippet and initialize it when ready, while the page continues to load.
The code for the asynchronous snippet looks like this:
!function(a,b){var c=document.createElement("script");c.type="text/javascript",c.async=!0,c.readyState?c.onreadystatechange=function(){("loaded"==c.readyState||"complete"==c.readyState)&&(c.onreadystatechange=null,b&&"function"==typeof b&&b())}:c.onload=function(){b&&"function"==typeof b&&b()},c.src=a,(document.getElementsByTagName("head")[0]||document.getElementsByTagName("body")[0]).appendChild(c)}("SCRIPT_URL",function(){var a=window.funnelEnvyConfig||{};a.customerId="CUSTOMER_ID",a.apiUrl="API_URL",window.funnelEnvy=new window.FunnelEnvy(a)});
Note that the following placeholders variables above must be replaced for your organization, which can be found in your organization settings:
SCRIPT_URL - The URL for your FunnelEnvy script
CUSTOMER_ID - Your customer (organization) id
API_URL - The FunnelEnvy API URL
Because some or all of the page can render with this asynchronous snippet we recommend implementing the 'anti-flicker' code below to minimize content flash.
The Anti-Flicker Code
The anti-flicker code uses a simple CSS technique to "mask" the page content without blocking it, until the FunnelEnvy script has been able to load. It includes an emergency timeout (default 4s) which will remove the mask if for some reason FunnelEnvy is unable to load. Note however that this does not mean that every page will be delayed for four seconds, the emergency timeout should occur very rarely and the anti-flicker code should only mask the page for a few hundred milliseconds.
This code should be inserted on every page that FunnelEnvy will be installed on and includes a <style>
and <script>
tag:
<style>.async-hide {opacity: 0 !important}</style>
<script>!function(a,b,c,d,e,f,g){b.className+=" "+c,f.start=1*new Date,f.end=g=function(){b.className=b.className.replace(RegExp(" ?"+c),"")},(a[d]=a[d]||{}).hide=f,setTimeout(function(){g(),f.end=null},e),f.timeout=e}(window,document.documentElement,"async-hide","funnelEnvyConfig",4e3,{});</script>
Note: We recommend deploying the asynchronous snippet before, or concurrently with the anti-flicker snippet. If the anti-flicker snippet is deployed without the asynchronous snippet the page will be blank for a few seconds (duration of the emergency timeout).
Understanding the Anti-Flicker Code
How do the anti-flicker code, asynchronous snippet and FunnelEnvy client side library work together? Here's an order of operations
Anti-Flicker Code - Adds a class
async-hide
to the<html>
tag of the page withopacity: 0 !important
. This prevents the page from being visible to humans.Anti-Flicker Code - Instantiates a
funnelEnvyConfig
object with ahide.end
function that removes theasync-hide
style.Anti-Flicker Code - Sets a an emergency timeout (default 4 seconds) in the rare case that FunnelEnvy has trouble loading from the CDN
Asynchronous Snippet - Creates a DOM
<script>
element and loads the script from the URL provided.Asynchronous Snippet - Once loading is complete, instantiates the
window.funnelEnvy
object and passes in the configuration, which includes thehide.end
functionFunnelEnvy Client Library - Checks for the
hide.end
function and removes theasync-hide
style from the<html>
element.
Here's an expanded version of the pre-hide snippet with comments.
/**
* Adds a class to the <html> element that hides the page until the FunnelEnvy
* object is loaded and. Once FunnelEnvy is ready
* (or 4 seconds has passed), the class is removed from the <html> element.
*
* @param {Window} a The global object.
* @param {HTMLHtmlElement} s The <html> element.
* @param {string} y The name of the class used to hide the <html> element.
* @param {string} n The name of property that references the funnelEnvyConfig object.
* @param {number} c The max time (in milliseconds) the page will be hidden.
* @param {Object} h An initial config object.
* @param {undefined} i (unused parameter).
* @param {undefined} d (unused parameter).
* @param {undefined} e (unused parameter).
*/
(function(a, s, y, n, c, h, i, d, e) {
// Adds a class (defaulting to 'async-hide') to the <html> element.
s.className += ' ' + y;
// Keeps track of the exact time that the snippet executes.
h.start = 1*new Date;
// Creates a function and assigns it to a local variable `i` as well as
// the `end` property of the funnelEnvyConfig object. Once FunnelEnvy is
// loaded it will call this function, which will remove the 'async-hide'
// class from the <html> element, causing the page to become visible again.
h.end = i = function() {
s.className = s.className.replace(RegExp(' ?' + y), '');
};
// Initializes the FunnelEnvy configuration as an empty object if it's not already initialized
// and assigns the new object to the funnelEnvyConfig `hide`
// property. This makes the function defined above accessible globally at the
// path `window.funnelEnvyConfig.hide.end`.
(a[n] = a[n] || {}).hide = h;
// Creates a timeout that will call the page-showing function after the
// timeout amount (defaulting to 4 seconds), in the event that FunnelEnvy has
// not already loaded. This ensures your page will not stay hidden in the
// event that FunnelEnvy takes too long to load.
setTimeout(function() {
i();
h.end = null
}, c);
h.timeout = c;
})(
window, // The initial value for local variable `a`.
document.documentElement, // The initial value for local variable `s`.
'async-hide', // The initial value for local variable `y`.
'funnelEnvyConfig', // The initial value for local variable `n`.
4000, // The initial value for local variable `c`.
{} // The initial value for local variable `h`.
);
Changing the Anti-Flicker CSS Class
It may be necessary to change the class name used for anti-flicker hiding, for example if you plan to also have another anti-flicker snippet (e.g. Google Optimize) running at the same time.
If you plan to do this please note you'll have to change the style name in the tag and in the parameter passed to the Javascript function. An example of how to do this is presented below, with the changed sections in bold:
<style>.funnelenvy-hide {opacity: 0 !important}</style>
<script>!function(a,b,c,d,e,f,g){b.className+=" "+c,f.start=1*new Date,f.end=g=function(){b.className=b.className.replace(RegExp(" ?"+c),"")},(a[d]=a[d]||{}).hide=f,setTimeout(function(){g(),f.end=null},e),f.timeout=e}(window,document.documentElement,"funnelenvy-hide","funnelEnvyConfig",4e3,{});</script>
It's also possible to control the name the global configuration object and the emergency timeout duration. Please contact your FunnelEnvy support manager for more details on how to do this.