{"version":3,"sources":["../node_modules/countly-sdk-web/lib/countly.js"],"names":["root","window","this","Countly","lastBeat","platform","startTime","SDK_VERSION","SDK_NAME","inited","sessionStarted","apiPath","readPath","beatInterval","queueSize","requestQueue","eventQueue","remoteConfigs","crashLogs","timedEvents","ignoreReferrers","crashSegments","autoExtend","storedDuration","lastView","lastViewTime","lastViewStoredDuration","failTimeout","failTimeoutAmount","inactivityTime","inactivityCounter","sessionUpdate","maxEventBatch","maxCrashLogs","useSessionCookie","sessionCookieTimeout","lastMsTs","readyToProcess","hasPulse","offlineMode","syncConsents","lastParams","urlParseRE","searchBotRE","trackTime","features","consentTimer","consents","i","length","init","ob","namespace","getConfig","getTimestamp","store","ignore_prefetch","debug","app_key","test_mode","device_id","getId","url","stripTrailingSlash","app_version","country_code","city","ip_address","ignore_bots","force_post","remote_config","q","onload","ignore_visitor","require_consent","ignore_referrers","Array","isArray","log","checkIgnore","name","indexOf","passed_data","JSON","parse","replace","ex","location","hash","token","purpose","setToken","showLoader","loadJS","hideLoader","constructor","utm","search","parts","substring","split","utms","hasUTM","nv","tag","userData","set","unset","save","heartBeat","notifyLoaders","fetch_remote_config","group_features","check_consent","feature","optin","check_any_consent","add_consent","updateConsent","setTimeout","begin_session","apply","track_pageview","change_id","remove_consent","clearTimeout","hasAnyProperties","toRequestQueue","consent","stringify","add_cly_events","event","key","count","e","getProperties","timestamp","getMsTimestamp","date","Date","hour","getHours","dow","getDay","push","enable_offline_mode","disable_offline_mode","needResync","noHeartBeat","force","expire","parseInt","req","metrics","getMetrics","arguments","session_duration","sec","extendSession","end_session","reportViewDuration","newId","merge","events","oldId","old_device_id","add_event","start_event","end_event","dur","user_details","user","props","report_conversion","campaign_id","campaign_user_id","campaign_user","customData","change_custom_property","value","mod","document","visibilityState","test","navigator","userAgent","getMultiSelectValues","input","values","options","j","selected","join","processWidget","currentWidget","hasSticker","wrapper","createElement","className","id","_id","closeIcon","innerHTML","iframe","src","body","appendChild","getElementById","style","display","sticker","color","trigger_font_color","backgroundColor","trigger_bg_color","trigger_position","trigger_button_text","smileySvg","fill","segments","getLastView","prepareRequest","request","sdk_name","sdk_version","shift","slice","userdata","last","splice","params","sendXmlHttpRequest","err","unshift","generateUUID","d","getTime","c","r","Math","random","floor","toString","isUUID","_app_version","_ua","screen","width","height","devicePixelRatio","round","abs","orientation","temp","_resolution","_density","locale","language","browserLanguage","systemLanguage","userLanguage","_locale","referrer","matches","exec","hostname","ignoring","k","RegExp","_store","console","prototype","call","ts","override","recordError","nonfatal","error","stack","message","fileName","lineNumber","columnNumber","_error","_run","battery","webkitBattery","mozBattery","msBattery","_bat","level","onLine","_online","_background","hasFocus","_logs","_nonfatal","_view","pathname","_custom","gl","getContext","_opengl","getParameter","VERSION","crash","callback","xhr","XMLHttpRequest","ActiveXObject","data","prepareParams","method","open","setRequestHeader","onreadystatechange","readyState","status","responseText","send","str","encodeURIComponent","substr","orig","prop","set_once","increment","increment_by","multiply","max","min","push_unique","pull","custom","track_errors","onerror","msg","line","col","errorCharacter","f","callee","caller","addEventListener","Error","reason","log_error","add_log","record","keys","omit_keys","configs","get_remote_config","stop_time","start_time","track_sessions","hidden","onchange","resetInactivity","setInterval","page","ignoreList","getViewName","getViewUrl","start","track_view","track_clicks","parent","shouldProcess","processClick","get_page_coord","pageX","pageY","getDocHeight","getDocWidth","track_scrolls","scrollY","processScroll","scrollTop","documentElement","processScrollView","viewportHeight","getViewportHeight","track_links","elem","get_event_target","closest","href","innerText","track_forms","trackHidden","getInputName","type","nodeName","processForm","form","segmentation","action","elements","toLowerCase","multiple","selectedIndex","checked","collect_from_forms","useCustom","hasUserInfo","labelData","labels","getElementsByTagName","htmlFor","textContent","classes","email","username","phone","organization","collect_from_facebook","FB","api","resp","gender","birthday","byear","pop","work","employer","get","opt_out","opt_in","show_feedback_popup","widget_id","JSONParseError","enable_feedback","loadCSS","enableWidgets","popups","widgets","insertAdjacentHTML","is_active","target_devices","detect_device","device","hide_sticker","target_page","pages","target_pages","Element","el","toUpperCase","parentElement","element","listener","attachEvent","target","srcElement","b","a","detect","isMobile","clientX","scrollLeft","clientY","D","scrollHeight","offsetHeight","clientHeight","scrollWidth","offsetWidth","clientWidth","innerHeight","getToken","Object","hasOwnProperty","storageOnly","lsSupport","localStorage","setItem","serialize","createCookie","getItem","readCookie","deserialize","exp","setTime","expires","toGMTString","cookie","nameEQ","ca","charAt","removeItem","loadFile","attr","loaded","fileref","setAttribute","js","css","loader","head","styleSheet","cssText","createTextNode","getEventQueue","getRequestQueue","newValue","_internals","clearQueue","factory"],"mappings":"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","file":"static/js/19.867549e7.chunk.js","sourcesContent":["/************\n* Countly Web SDK\n* https://github.com/Countly/countly-sdk-web\n************/\n\n/**\n * Countly object to manage the internal queue and send requests to Countly server. More information on {@link http://resources.count.ly/docs/countly-sdk-for-web}\n * @name Countly\n * @global\n * @namespace Countly\n * @example <caption>SDK integration</caption>\n * <script type=\"text/javascript\">\n *   \n * //some default pre init\n * var Countly = Countly || {};\n * Countly.q = Countly.q || [];\n * \n * //provide your app key that you retrieved from Countly dashboard\n * Countly.app_key = \"YOUR_APP_KEY\";\n * \n * //provide your server IP or name. Use try.count.ly for EE trial server.\n * //if you use your own server, make sure you have https enabled if you use\n * //https below.\n * Countly.url = \"https://yourdomain.com\"; \n * \n * //start pushing function calls to queue\n * //track sessions automatically\n * Countly.q.push([\"track_sessions\"]);\n *   \n * //track sessions automatically\n * Countly.q.push([\"track_pageview\"]);\n *   \n * //load countly script asynchronously\n * (function() {\n *  var cly = document.createElement(\"script\"); cly.type = \"text/javascript\"; \n *  cly.async = true;\n *  //enter url of script here\n *  cly.src = \"https://cdn.jsdelivr.net/countly-sdk-web/latest/countly.min.js\";\n *  cly.onload = function(){Countly.init()};\n *  var s = document.getElementsByTagName(\"script\")[0]; s.parentNode.insertBefore(cly, s);\n * })();\n * </script>\n */\n(function (root, factory) {\n    if(typeof define === \"function\" && define.amd) {\n        define([], function(){ return factory(root.Countly);});\n    } else if(typeof module === \"object\" && module.exports) {\n        module.exports = factory(root.Countly);\n    } else {\n        root.Countly = factory(root.Countly);\n    }\n}(typeof window !== \"undefined\" ? window : this, function (Countly) {\n    \"use strict\";\n    /** @lends Countly */\n    Countly = Countly || {};\n    var SDK_VERSION = \"19.08\";\n    var SDK_NAME = \"javascript_native_web\";\n\n    var inited = false,\n        sessionStarted = false,\n        apiPath = \"/i\",\n        readPath = \"/o/sdk\",\n        beatInterval = 500,\n        queueSize = 1000,\n        requestQueue = [],\n        eventQueue = [],\n        remoteConfigs = {},\n        crashLogs = [],\n        timedEvents = {},\n        ignoreReferrers = [],\n        crashSegments = null,\n        autoExtend = true,\n        lastBeat,\n        storedDuration = 0,\n        lastView = null,\n        lastViewTime = 0,\n        lastViewStoredDuration = 0,\n        failTimeout = 0,\n        failTimeoutAmount = 60,\n        inactivityTime = 20,\n        inactivityCounter = 0,\n        sessionUpdate = 60,\n        maxEventBatch = 10,\n        maxCrashLogs = 100,\n        useSessionCookie = true,\n        sessionCookieTimeout = 30,\n        lastMsTs = 0,\n        readyToProcess = true,\n        platform,\n        hasPulse = false,\n        offlineMode = false,\n        syncConsents = {},\n        lastParams = {},\n        urlParseRE = /^(((([^:\\/#\\?]+:)?(?:(\\/\\/)((?:(([^:@\\/#\\?]+)(?:\\:([^:@\\/#\\?]+))?)@)?(([^:\\/#\\?\\]\\[]+|\\[[^\\/\\]@#?]+\\])(?:\\:([0-9]+))?))?)?)?((\\/?(?:[^\\/\\?#]+\\/+)*)([^\\?#]*)))?(\\?[^#]+)?)(#.*)?/,\n        searchBotRE = /(CountlySiteBot|nuhk|Googlebot|GoogleSecurityScanner|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\\/Teoma|ia_archiver|bingbot|Google Web Preview|Mediapartners-Google|AdsBot-Google|Baiduspider|Ezooms|YahooSeeker|AltaVista|AVSearch|Mercator|Scooter|InfoSeek|Ultraseek|Lycos|Wget|YandexBot|Yandex|YaDirectFetcher|SiteBot|Exabot|AhrefsBot|MJ12bot|TurnitinBot|magpie-crawler|Nutch Crawler|CMS Crawler|rogerbot|Domnutch|ssearch_bot|XoviBot|netseer|digincore|fr-crawler|wesee|AliasIO|contxbot|PingdomBot|BingPreview|HeadlessChrome)/,\n        trackTime = true,\n        startTime;\n\n    \n\n    /**\n     * Array with list of available features that you can require consent for\n     */\n    Countly.features = [\"sessions\", \"events\", \"views\", \"scrolls\", \"clicks\", \"forms\", \"crashes\", \"attribution\", \"users\", \"star-rating\", \"location\"];\n\n    //create object to store consents\n    var consents = {};\n    for (var i = 0; i < Countly.features.length; i++) {\n        consents[Countly.features[i]] = {};\n    }\n\n    /**\n     * Initialize Countly object\n     * @param {Object} conf - Countly initialization {@link Init} object with configuration options\n     * @param {string} conf.app_key - app key for your app created in Countly\n     * @param {string} conf.device_id - to identify a visitor, will be auto generated if not provided\n     * @param {string} conf.url - your Countly server url, you can use your server URL or IP here\n     * @param {string} [conf.app_version=0.0] - the version of your app or website\n     * @param {string=} conf.country_code - country code for your visitor\n     * @param {string=} conf.city - name of the city of your visitor\n     * @param {string=} conf.ip_address - ip address of your visitor\n     * @param {boolean} [conf.debug=false] - output debug info into console\n     * @param {boolean} [conf.ignore_bots=true] - option to ignore traffic from bots\n     * @param {number} [conf.interval=500] - set an interval how often to check if there is any data to report and report it in miliseconds\n     * @param {number} [conf.queue_size=1000] - maximum amount of queued requests to store\n     * @param {number} [conf.fail_timeout=60] - set time in seconds to wait after failed connection to server in seconds\n     * @param {number} [conf.inactivity_time=20] - after how many minutes user should be counted as inactive, if he did not perform any actions, as mouse move, scroll or keypress\n     * @param {number} [conf.session_update=60] - how often in seconds should session be extended\n     * @param {number} [conf.max_events=10] - maximum amount of events to send in one batch\n     * @param {number} [conf.max_logs=100] - maximum amount of breadcrumbs to store for crash logs\n     * @param {array=} conf.ignore_referrers - array with referrers to ignore\n     * @param {boolean} [conf.ignore_prefetch=true] - ignore prefetching and pre rendering from counting as real website visits\n     * @param {boolean} [conf.force_post=false] - force using post method for all requests\n     * @param {boolean} [conf.ignore_visitor=false] - ignore this current visitor\n     * @param {boolean} [conf.require_consent=false] - Pass true if you are implementing GDPR compatible consent management. It would prevent running any functionality without proper consent\n     * @param {boolean} [conf.utm={\"source\":true, \"medium\":true, \"campaign\":true, \"term\":true, \"content\":true}] - Object instructing which UTM parameters to track\n     * @param {boolean} [conf.use_session_cookie=true] - Use cookie to track session\n     * @param {number} [conf.session_cookie_timeout=30] - How long till cookie session should expire in minutes\n     * @param {boolean|function} [conf.remote_config=false] - Enable automatic remote config fetching, provide callback function to be notified when fetching done\n     * @param {string=} [conf.namespace=\"\"] - Have separate namespace of of persistant data\n     * @example\n     * Countly.init({\n     *   //provide your app key that you retrieved from Countly dashboard\n     *   app_key: \"YOUR_APP_KEY\",\n     *   //provide your server IP or name. Use try.count.ly for EE trial server.\n     *   url: \"http://yourdomain.com\" \n     * });\n     */\n    Countly.init = function (ob) {\n        if (!inited) {\n            ob = ob || {};\n            Countly.namespace = getConfig(\"namespace\", ob, \"\");\n            startTime = getTimestamp();\n            inited = true;\n            requestQueue = store(\"cly_queue\") || [];\n            timedEvents = {};\n            eventQueue = store(\"cly_event\") || [];\n            remoteConfigs = store(\"cly_remote_configs\") || {};\n            beatInterval = getConfig(\"interval\", ob, beatInterval);\n            queueSize = getConfig(\"queue_size\", ob, queueSize);\n            offlineMode = getConfig(\"offline_mode\", ob, offlineMode);\n            failTimeoutAmount = getConfig(\"fail_timeout\", ob, failTimeoutAmount);\n            inactivityTime = getConfig(\"inactivity_time\", ob, inactivityTime);\n            sessionUpdate = getConfig(\"session_update\", ob, sessionUpdate);\n            maxEventBatch = getConfig(\"max_events\", ob, maxEventBatch);\n            maxCrashLogs = getConfig(\"max_logs\", ob, maxCrashLogs);\n            useSessionCookie = getConfig(\"use_session_cookie\", ob, useSessionCookie);\n            sessionCookieTimeout = getConfig(\"session_cookie_timeout\", ob, sessionCookieTimeout);\n            Countly.ignore_prefetch = getConfig(\"ignore_prefetch\", ob, true);\n            Countly.debug = getConfig(\"debug\", ob, false);\n            Countly.app_key = getConfig(\"app_key\", ob, null);\n            Countly.test_mode = getConfig(\"test_mode\", ob, false);\n            if (!offlineMode) {\n                Countly.device_id = getConfig(\"device_id\", ob, getId());\n            }\n            else if (!Countly.device_id) {\n                Countly.device_id = \"[CLY]_temp_id\";\n            }\n            Countly.url = stripTrailingSlash(getConfig(\"url\", ob, \"\"));\n            Countly.app_version = getConfig(\"app_version\", ob, \"0.0\");\n            Countly.country_code = getConfig(\"country_code\", ob, null);\n            Countly.city = getConfig(\"city\", ob, null);\n            Countly.ip_address = getConfig(\"ip_address\", ob, null);\n            Countly.ignore_bots = getConfig(\"ignore_bots\", ob, true);\n            Countly.force_post = getConfig(\"force_post\", ob, false);\n            Countly.remote_config = getConfig(\"remote_config\", ob, false);\n            Countly.q = Countly.q || [];\n            Countly.onload = Countly.onload || [];\n            Countly.ignore_visitor = getConfig(\"ignore_visitor\", ob, false);\n            Countly.require_consent = getConfig(\"require_consent\", ob, false);\n            if (ob.ignore_referrers && Array.isArray( ob.ignore_referrers ) ) {\n                ignoreReferrers = ob.ignore_referrers;\n            }\n            else if (Countly.ignore_referrers && Array.isArray( Countly.ignore_referrers ) ) {\n                ignoreReferrers = Countly.ignore_referrers;\n            }\n\n            if (Countly.url === \"\") {\n                log(\"Please provide server URL\");\n                Countly.ignore_visitor = true;\n            }\n            if (store(\"cly_ignore\")) {\n                //opted out user\n                Countly.ignore_visitor = true;\n            }\n            \n            checkIgnore();\n            \n            if (window.name && window.name.indexOf(\"cly:\") === 0) {\n                try{\n                    Countly.passed_data = JSON.parse(window.name.replace(\"cly:\", \"\"));\n                } catch(ex){log(\"Could not parse name\", window.name);}\n            }\n            else if (location.hash && location.hash.indexOf(\"#cly:\") === 0) {\n                try{\n                    Countly.passed_data = JSON.parse(location.hash.replace(\"#cly:\", \"\"));\n                } catch(ex){log(\"Could not parse hash\", location.hash);}\n            }\n\n            if (Countly.passed_data) {\n                if (Countly.passed_data.token && Countly.passed_data.purpose) {\n                    if (Countly.passed_data.token !== store(\"cly_old_token\")) {\n                        setToken(Countly.passed_data.token);\n                        store(\"cly_old_token\", Countly.passed_data.token);\n                    }\n                    if (Countly.passed_data.purpose === \"heatmap\") {\n                        Countly.ignore_visitor = true;\n                        showLoader();\n                        loadJS(Countly.url + \"/views/heatmap.js\", hideLoader);\n                    }\n                }\n            }\n\n            if (!Countly.ignore_visitor) {\n                log(\"Countly initialized\");\n                //let code waiting for us to load, know that we have loaded\n                if (Countly.onload.constructor !== Array) {\n                    Countly.onload = [];\n                }\n\n                if (Countly.q.constructor !== Array) {\n                    Countly.q = [];\n                }\n                \n                var i = 0;\n                Countly.utm = Countly.utm || {\"source\":true, \"medium\":true, \"campaign\":true, \"term\":true, \"content\":true};\n                \n                if (location.search) {\n                    var parts = location.search.substring(1).split(\"&\");\n                    var utms = {};\n                    var hasUTM = false;\n                    for (i = 0; i < parts.length; i++) {\n                        var nv = parts[i].split(\"=\");\n                        if (nv[0] === \"cly_id\") {\n                            store(\"cly_cmp_id\", nv[1]);\n                        }\n                        else if (nv[0] === \"cly_uid\") {\n                            store(\"cly_cmp_uid\", nv[1]);\n                        }\n                        else if (nv[0] === \"cly_device_id\") {\n                            Countly.device_id = nv[1];\n                        }\n                        else if((nv[0]+\"\").indexOf(\"utm_\") === 0 && Countly.utm[nv[0].replace(\"utm_\", \"\")]){\n                            utms[nv[0].replace(\"utm_\", \"\")] = nv[1];\n                            hasUTM = true;\n                        }\n                    }\n                    if(hasUTM){\n                        for(var tag in Countly.utm){\n                            if(utms[tag]){\n                                Countly.userData.set(\"utm_\"+tag, utms[tag]);\n                            }\n                            else{\n                                Countly.userData.unset(\"utm_\"+tag);\n                            }\n                        }\n                        Countly.userData.save();\n                    }\n                }\n                \n                if (!offlineMode) {\n                    if (Countly.device_id !== store(\"cly_id\")) {\n                        store(\"cly_id\", Countly.device_id);\n                    }\n                }\n                heartBeat();\n\n                notifyLoaders();\n                \n                if (Countly.remote_config) {\n                    Countly.fetch_remote_config(Countly.remote_config);\n                }\n            }\n        }\n    };\n\n    /**\n    * Modify feature groups for consent management. Allows you to group multiple features under one feature group\n    * @param {object} features - object to define feature name as key and core features as value\n    * @example <caption>Adding all features under one group</caption>\n    * Countly.group_features({all:[\"sessions\",\"events\",\"views\",\"scrolls\",\"clicks\",\"forms\",\"crashes\",\"attribution\",\"users\"]});\n    * //After this call Countly.add_consent(\"all\") to allow all features\n    @example <caption>Grouping features</caption>\n    * Countly.group_features({\n    *    activity:[\"sessions\",\"events\",\"views\"],\n    *    interaction:[\"scrolls\",\"clicks\",\"forms\"]\n    * });\n    * //After this call Countly.add_consent(\"activity\") to allow \"sessions\",\"events\",\"views\"\n    * //or call Countly.add_consent(\"interaction\") to allow \"scrolls\",\"clicks\",\"forms\"\n    * //or call Countly.add_consent(\"crashes\") to allow some separate feature\n    */\n    Countly.group_features = function (features) {\n        if (features) {\n            for (var i in features) {\n                if (!consents[i]) {\n                    if (typeof features[i] === \"string\") {\n                        consents[i] = { features: [features[i]] };\n                    }\n                    else if (features[i] && Array.isArray( features[i] ) && features[i].length) {\n                        consents[i] = { features: features[i] };\n                    }\n                    else {\n                        log(\"Incorrect feature list for \" + i + \" value: \" + features[i]);\n                    }\n                }\n                else {\n                    log(\"Feature name \" + i + \" is already reserved\");\n                }\n            }\n        }\n        else {\n            log(\"Incorrect features: \" + features);\n        }\n    };\n\n    /**\n    * Check if consent is given for specific feature (either core feature of from custom feature group)\n    * @param {string} feature - name of the feature, possible values, \"sessions\",\"events\",\"views\",\"scrolls\",\"clicks\",\"forms\",\"crashes\",\"attribution\",\"users\" or customly provided through {@link Countly.group_features}\n    */\n    Countly.check_consent = function (feature) {\n        if (!Countly.require_consent) {\n            //we don't need to have specific consents\n            return true;\n        }\n        if (consents[feature]) {\n            return (consents[feature] && consents[feature].optin) ? true : false;\n        }\n        else {\n            log(\"No feature available for \" + feature);\n        }\n        return false;\n    };\n\n    /**\n    * Check if any consent is given, for some cases, when crucial parts are like device_id are needed for any request\n    */\n    Countly.check_any_consent = function () {\n        if (!Countly.require_consent) {\n            //we don't need to have consents\n            return true;\n        }\n        for (var i in consents) {\n            if (consents[i] && consents[i].optin) {\n                return true;\n            }\n        }\n        return false;\n    };\n\n    /**\n    * Add consent for specific feature, meaning, user allowed to track that data (either core feature of from custom feature group)\n    * @param {string|array} feature - name of the feature, possible values, \"sessions\",\"events\",\"views\",\"scrolls\",\"clicks\",\"forms\",\"crashes\",\"attribution\",\"users\", etc or customly provided through {@link Countly.group_features}\n    */\n    Countly.add_consent = function (feature) {\n        log(\"Adding consent for \" + feature);\n        if ( Array.isArray( feature ) ) {\n            for (var i = 0; i < feature.length; i++) {\n                Countly.add_consent(feature[i]);\n            }\n        }\n        else if (consents[feature]) {\n            if (consents[feature].features) {\n                consents[feature].optin = true;\n                //this is added group, let's iterate through sub features\n                Countly.add_consent(consents[feature].features);\n            }\n            else {\n                //this is core feature\n                if (consents[feature].optin !== true) {\n                    syncConsents[feature] = true;\n                    consents[feature].optin = true;\n                    updateConsent();\n                    setTimeout(function () {\n                        if (feature === \"sessions\" && lastParams.begin_session) {\n                            Countly.begin_session.apply(Countly, lastParams.begin_session);\n                            lastParams.begin_session = null;\n                        }\n                        else if (feature === \"views\" && lastParams.track_pageview) {\n                            lastView = null;\n                            Countly.track_pageview.apply(Countly, lastParams.track_pageview);\n                            lastParams.track_pageview = null;\n                        }\n                        if (lastParams.change_id) {\n                            Countly.change_id.apply(Countly, lastParams.change_id);\n                            lastParams.change_id = null;\n                        }\n                    }, 1);\n\n                }\n            }\n        }\n        else {\n            log(\"No feature available for \" + feature);\n        }\n    };\n\n\n    /**\n    * Remove consent for specific feature, meaning, user opted out to track that data (either core feature of from custom feature group)\n    * @param {string|array} feature - name of the feature, possible values, \"sessions\",\"events\",\"views\",\"scrolls\",\"clicks\",\"forms\",\"crashes\",\"attribution\",\"users\", etc or customly provided through {@link Countly.group_features}\n    */\n    Countly.remove_consent = function (feature) {\n        log(\"Removing consent for \" + feature);\n        if ( Array.isArray( feature ) ) {\n            for (var i = 0; i < feature.length; i++) {\n                Countly.remove_consent(feature[i]);\n            }\n        }\n        else if (consents[feature]) {\n            if (consents[feature].features) {\n                //this is added group, let's iterate through sub features\n                Countly.remove_consent(consents[feature].features);\n            }\n            else {\n                //this is core feature\n                if (consents[feature].optin !== false) {\n                    syncConsents[feature] = false;\n                    updateConsent();\n                }\n            }\n            consents[feature].optin = false;\n        }\n        else {\n            log(\"No feature available for \" + feature);\n        }\n    };\n\n    var consentTimer;\n    var updateConsent = function () {\n        if (consentTimer) {\n            //delay syncing consents\n            clearTimeout(consentTimer);\n            consentTimer = null;\n        }\n        consentTimer = setTimeout(function () {\n            if (hasAnyProperties(syncConsents)) {\n                //we have consents to sync, create request\n                toRequestQueue({ consent: JSON.stringify(syncConsents) });\n                //clear consents that needs syncing\n                syncConsents = {};\n            }\n        }, 1000);\n    };\n    \n    Countly.enable_offline_mode = function(){\n        offlineMode = true;\n        Countly.device_id = \"[CLY]_temp_id\";\n    };\n    \n    Countly.disable_offline_mode = function(device_id){\n        offlineMode = false;\n        if (device_id && Countly.device_id !== device_id) {\n            Countly.device_id = device_id;\n            store(\"cly_id\", Countly.device_id);\n            log(\"Changing id\");\n        }\n        else {\n            Countly.device_id = getId();\n            if (Countly.device_id !== store(\"cly_id\")) {\n                store(\"cly_id\", Countly.device_id);\n            }\n        }\n        var needResync = false;\n        if (requestQueue.length > 0) {\n            for (var i = 0; i < requestQueue.length; i++) {\n                if (requestQueue[i].device_id === \"[CLY]_temp_id\") {\n                    requestQueue[i].device_id = Countly.device_id;\n                    needResync = true;\n                }\n            }\n        }\n        if (needResync) {\n            store(\"cly_queue\", requestQueue, true);\n        }\n    };\n\n    /**\n    * Start session\n    * @param {boolean} noHeartBeat - true if you don't want to use internal heartbeat to manage session\n    * @param {bool} force - force begin session request even if session cookie is enabled\n    */\n\n    Countly.begin_session = function (noHeartBeat, force) {\n        if (Countly.check_consent(\"sessions\")) {\n            if (!sessionStarted) {\n                lastBeat = getTimestamp();\n                sessionStarted = true;\n                autoExtend = (noHeartBeat) ? false : true;\n                var expire = store(\"cly_session\");\n                if (force || !useSessionCookie || !expire || parseInt(expire) <= getTimestamp()) {\n                    log(\"Session started\");\n                    var req = {};\n                    req.begin_session = 1;\n                    req.metrics = JSON.stringify(getMetrics());\n                    toRequestQueue(req);\n                }\n                store(\"cly_session\", getTimestamp() + (sessionCookieTimeout * 60));\n            }\n        }\n        else {\n            lastParams.begin_session = arguments;\n        }\n    };\n\n    /**\n    * Report session duration\n    * @param {int} sec - amount of seconds to report for current session\n    */\n    Countly.session_duration = function (sec) {\n        if (Countly.check_consent(\"sessions\")) {\n            if (sessionStarted) {\n                log(\"Session extended\", sec);\n                toRequestQueue({ session_duration: sec });\n                extendSession();\n            }\n        }\n    };\n\n    /**\n    * End current session\n    * @param {int} sec - amount of seconds to report for current session, before ending it\n    * @param {bool} force - force end session request even if session cookie is enabled\n    */\n    Countly.end_session = function (sec, force) {\n        if (Countly.check_consent(\"sessions\")) {\n            if (sessionStarted) {\n                sec = sec || getTimestamp() - lastBeat;\n                reportViewDuration();\n                if (!useSessionCookie || force) {\n                    log(\"Ending session\");\n                    toRequestQueue({ end_session: 1, session_duration: sec });\n                }\n                else{\n                    Countly.session_duration(sec);\n                }\n                sessionStarted = false;\n            }\n        }\n    };\n\n    /**\n    * Change current user/device id\n    * @param {string} newId - new user/device ID to use\n    * @param {boolean} merge - move data from old ID to new ID on server\n    **/\n    Countly.change_id = function (newId, merge) {\n        if (Countly.device_id !== newId) {\n            if (!merge) {\n                //empty event queue\n                if (eventQueue.length > 0) {\n                    toRequestQueue({ events: JSON.stringify(eventQueue) });\n                    eventQueue = [];    \n                    store(\"cly_event\", eventQueue);\n                }\n                //end current session\n                Countly.end_session(null, true);\n                //clear timed events\n                timedEvents = {};\n            }\n            var oldId = Countly.device_id;\n            Countly.device_id = newId;\n            store(\"cly_id\", Countly.device_id);\n            log(\"Changing id\");\n            if (merge) {\n                if (Countly.check_any_consent()) {\n                    toRequestQueue({ old_device_id: oldId });\n                }\n                else {\n                    lastParams.change_id = arguments;\n                }\n            }\n            else {\n                //start new session for new id\n                Countly.begin_session(!autoExtend, true);\n            }\n            if (Countly.remote_config) {\n                remoteConfigs = {};\n                store(\"cly_remote_configs\", remoteConfigs);\n                Countly.fetch_remote_config(Countly.remote_config);\n            }\n        }\n    };\n\n    /**\n    * Report custom event\n    * @param {Object} event - Countly {@link Event} object\n    * @param {string} event.key - name or id of the event\n    * @param {number} [event.count=1] - how many times did event occur\n    * @param {number=} event.sum - sum to report with event (if any)\n    * @param {number=} event.dur - duration to report with event (if any)\n    * @param {Object=} event.segmentation - object with segments key /values\n    **/\n    Countly.add_event = function (event) {\n        if (Countly.check_consent(\"events\")) {\n            add_cly_events(event);\n        }\n    };\n\n    //internal method for events, in case there is no consent for custom events, but internal events has consents\n    function add_cly_events(event) {\n        //ignore bots\n        if (Countly.ignore_visitor) {\n            return;\n        }\n\n        if (!event.key) {\n            log(\"Event must have key property\");\n            return;\n        }\n\n        if (!event.count) {\n            event.count = 1;\n        }\n\n        var props = [\"key\", \"count\", \"sum\", \"dur\", \"segmentation\"];\n        var e = getProperties(event, props);\n        e.timestamp = getMsTimestamp();\n        var date = new Date();\n        e.hour = date.getHours();\n        e.dow = date.getDay();\n        eventQueue.push(e);\n        store(\"cly_event\", eventQueue);\n        log(\"Adding event: \", event);\n    }\n\n    /**\n    * Start timed event, which will fill in duration property upon ending automatically\n    * @param {string} key - event name that will be used as key property\n    **/\n    Countly.start_event = function (key) {\n        if (timedEvents[key]) {\n            log(\"Timed event with key \" + key + \" already started\");\n            return;\n        }\n        timedEvents[key] = getTimestamp();\n    };\n\n    /**\n    * End timed event\n    * @param {string|object} event - event key if string or Countly event same as passed to {@link Countly.add_event}\n    **/\n    Countly.end_event = function (event) {\n        if (typeof event == \"string\") {\n            event = { key: event };\n        }\n        if (!event.key) {\n            log(\"Event must have key property\");\n            return;\n        }\n        if (!timedEvents[event.key]) {\n            log(\"Timed event with key \" + event.key + \" was not started\");\n            return;\n        }\n        event.dur = getTimestamp() - timedEvents[event.key];\n        Countly.add_event(event);\n        delete timedEvents[event.key];\n    };\n\n    /**\n    * Provide information about user\n    * @param {Object} user - Countly {@link UserDetails} object\n    * @param {string=} user.name - user's full name\n    * @param {string=} user.username - user's username or nickname\n    * @param {string=} user.email - user's email address\n    * @param {string=} user.organization - user's organization or company\n    * @param {string=} user.phone - user's phone number\n    * @param {string=} user.picture - url to user's picture\n    * @param {string=} user.gender - M value for male and F value for femail\n    * @param {number=} user.byear - user's birth year used to calculate current age\n    * @param {Object=} user.custom - object with custom key value properties you want to save with user\n    **/\n    Countly.user_details = function (user) {\n        if (Countly.check_consent(\"users\")) {\n            log(\"Adding userdetails: \", user);\n            var props = [\"name\", \"username\", \"email\", \"organization\", \"phone\", \"picture\", \"gender\", \"byear\", \"custom\"];\n            toRequestQueue({ user_details: JSON.stringify(getProperties(user, props)) });\n        }\n    };\n\n    /**\n    * Report user conversion to the server (when user signup or made a purchase, or whatever your conversion is), if there is no campaign data, user will be reported as organic\n    * @param {string=} campaign_id - id of campaign, or will use the one that is stored after campaign link click\n    * @param {string=} campaign_user_id - id of user's click on campaign, or will use the one that is stored after campaign link click\n    **/\n    Countly.report_conversion = function (campaign_id, campaign_user_id) {\n        if (Countly.check_consent(\"attribution\")) {\n            campaign_id = campaign_id || store(\"cly_cmp_id\") || \"cly_organic\";\n            campaign_user_id = campaign_user_id || store(\"cly_cmp_uid\");\n\n            if (campaign_id && campaign_user_id) {\n                toRequestQueue({ campaign_id: campaign_id, campaign_user: campaign_user_id });\n            }\n            else if (campaign_id) {\n                toRequestQueue({ campaign_id: campaign_id });\n            }\n        }\n    };\n\n    /**************************\n    * Modifying custom property values of user details\n    * Possible modification commands\n    *  - inc, to increment existing value by provided value\n    *  - mul, to multiply existing value by provided value\n    *  - max, to select maximum value between existing and provided value\n    *  - min, to select minimum value between existing and provided value\n    *  - setOnce, to set value only if it was not set before\n    *  - push, creates an array property, if property does not exist, and adds value to array\n    *  - pull, to remove value from array property\n    *  - addToSet, creates an array property, if property does not exist, and adds unique value to array, only if it does not yet exist in array\n    **************************/\n    var customData = {};\n    var change_custom_property = function (key, value, mod) {\n        if (Countly.check_consent(\"users\")) {\n            if (!customData[key]) {\n                customData[key] = {};\n            }\n            if (mod === \"$push\" || mod === \"$pull\" || mod === \"$addToSet\") {\n                if (!customData[key][mod]) {\n                    customData[key][mod] = [];\n                }\n                customData[key][mod].push(value);\n            }\n            else {\n                customData[key][mod] = value;\n            }\n        }\n    };\n\n    /**\n    * Control user related custom properties. Don't forget to call save after finishing manipulation of custom data\n    * @namespace Countly.userData\n    * @name Countly.userData\n    * @example\n    * //set custom key value property\n    * Countly.userData.set(\"twitter\", \"ar2rsawseen\");\n    * //create or increase specific number property\n    * Countly.userData.increment(\"login_count\");\n    * //add new value to array property if it is not already there\n    * Countly.userData.push_unique(\"selected_category\", \"IT\");\n    * //send all custom property modified data to server\n    * Countly.userData.save();\n    */\n    Countly.userData = {\n        /**\n        * Sets user's custom property value\n        * @param {string} key - name of the property to attach to user\n        * @param {string|number} value - value to store under provided property\n        **/\n        set: function (key, value) {\n            customData[key] = value;\n        },\n        /**\n        * Unset's/delete's user's custom property\n        * @param {string} key - name of the property to delete\n        **/\n        unset: function (key) {\n            customData[key] = \"\";\n        },\n        /**\n        * Sets user's custom property value only if it was not set before\n        * @param {string} key - name of the property to attach to user\n        * @param {string|number} value - value to store under provided property\n        **/\n        set_once: function (key, value) {\n            change_custom_property(key, value, \"$setOnce\");\n        },\n        /**\n        * Increment value under the key of this user's custom properties by one\n        * @param {string} key - name of the property to attach to user\n        **/\n        increment: function (key) {\n            change_custom_property(key, 1, \"$inc\");\n        },\n        /**\n        * Increment value under the key of this user's custom properties by provided value\n        * @param {string} key - name of the property to attach to user\n        * @param {number} value - value by which to increment server value\n        **/\n        increment_by: function (key, value) {\n            change_custom_property(key, value, \"$inc\");\n        },\n        /**\n        * Multiply value under the key of this user's custom properties by provided value\n        * @param {string} key - name of the property to attach to user\n        * @param {number} value - value by which to multiply server value\n        **/\n        multiply: function (key, value) {\n            change_custom_property(key, value, \"$mul\");\n        },\n        /**\n        * Save maximal value under the key of this user's custom properties\n        * @param {string} key - name of the property to attach to user\n        * @param {number} value - value which to compare to server's value and store maximal value of both provided\n        **/\n        max: function (key, value) {\n            change_custom_property(key, value, \"$max\");\n        },\n        /**\n        * Save minimal value under the key of this user's custom properties\n        * @param {string} key - name of the property to attach to user\n        * @param {number} value - value which to compare to server's value and store minimal value of both provided\n        **/\n        min: function (key, value) {\n            change_custom_property(key, value, \"$min\");\n        },\n        /**\n        * Add value to array under the key of this user's custom properties. If property is not an array, it will be converted to array\n        * @param {string} key - name of the property to attach to user\n        * @param {string|number} value - value which to add to array\n        **/\n        push: function (key, value) {\n            change_custom_property(key, value, \"$push\");\n        },\n        /**\n        * Add value to array under the key of this user's custom properties, storing only unique values. If property is not an array, it will be converted to array\n        * @param {string} key - name of the property to attach to user\n        * @param {string|number} value - value which to add to array\n        **/\n        push_unique: function (key, value) {\n            change_custom_property(key, value, \"$addToSet\");\n        },\n        /**\n        * Remove value from array under the key of this user's custom properties\n        * @param {string} key - name of the property\n        * @param {string|number} value - value which to remove from array\n        **/\n        pull: function (key, value) {\n            change_custom_property(key, value, \"$pull\");\n        },\n        /**\n        * Save changes made to user's custom properties object and send them to server\n        **/\n        save: function () {\n            if (Countly.check_consent(\"users\")) {\n                toRequestQueue({ user_details: JSON.stringify({ custom: customData }) });\n            }\n            customData = {};\n        }\n    };\n\n    /**\n    * Automatically track javascript errors that happen on the website and report them to the server\n    * @param {string=} segments - additional key value pairs you want to provide with error report, like versions of libraries used, etc.\n    **/\n    Countly.track_errors = function (segments) {\n        crashSegments = segments;\n        //override global uncaught error handler\n        window.onerror = function (msg, url, line, col, err) {\n            if (typeof err !== \"undefined\") {\n                recordError(err, false);\n            }\n            else {\n                col = col || (window.event && window.event.errorCharacter);\n                var error = \"\";\n                if (typeof msg !== \"undefined\") {\n                    error += msg + \"\\n\";\n                }\n                if (typeof url !== \"undefined\") {\n                    error += \"at \" + url;\n                }\n                if (typeof line !== \"undefined\") {\n                    error += \":\" + line;\n                }\n                if (typeof col !== \"undefined\") {\n                    error += \":\" + col;\n                }\n                error += \"\\n\";\n\n                try {\n                    var stack = [];\n                    var f = arguments.callee.caller; // jshint ignore:line\n                    while (f) {\n                        stack.push(f.name);\n                        f = f.caller;\n                    }\n                    error += stack.join(\"\\n\");\n                } catch (ex) { \n                    //silent error\n                }\n                recordError(error, false);\n            }\n        };\n        \n        window.addEventListener('unhandledrejection', function(event) {\n            recordError(new Error('Unhandled rejection (reason: ' + (event.reason && event.reason.stack ? event.reason.stack : event.reason ) + ').'), true);\n        });\n    };\n\n    /**\n    * Log an exception that you catched through try and catch block and handled yourself and just want to report it to server\n    * @param {Object} err - error exception object provided in catch block\n    * @param {string=} segments - additional key value pairs you want to provide with error report, like versions of libraries used, etc.\n    **/\n    Countly.log_error = function (err, segments) {\n        recordError(err, true, segments);\n    };\n\n    /**\n    * Add new line in the log of breadcrumbs of what user did, will be included together with error report\n    * @param {string} record - any text describing what user did\n    **/\n    Countly.add_log = function (record) {\n        if (Countly.check_consent(\"crashes\")) {\n            if(crashLogs.length > maxCrashLogs) {\n                crashLogs.shift();\n            }\n            crashLogs.push(record);\n        }\n    };\n\n    /**\n    * Fetch remote config\n    * @param {array=} keys - Array of keys to fetch, if not provided will fetch all keys\n    * @param {array=} omit_keys - Array of keys to omit, if provided will fetch all keys except provided ones\n    * @param {function=} callback - Callback to notify with first param error and second param remote config object\n    **/\n    Countly.fetch_remote_config = function (keys, omit_keys, callback) {\n        if (Countly.check_any_consent()) {\n            var request = {\n                method: \"fetch_remote_config\"\n            };\n            if (Countly.check_consent(\"sessions\")) {\n                request.metrics = JSON.stringify(getMetrics());\n            }\n            if (keys) {\n                if (!callback && typeof keys === \"function\") {\n                    callback = keys;\n                    keys = null;\n                }\n                else if (Array.isArray(keys) && keys.length) {\n                    request.keys = JSON.stringify(keys);\n                }\n            }\n            if (omit_keys) {\n                if (!callback && typeof omit_keys === \"function\") {\n                    callback = omit_keys;\n                    omit_keys = null;\n                }\n                else if (Array.isArray(omit_keys) && omit_keys.length) {\n                    request.omit_keys = JSON.stringify(omit_keys);\n                }\n            }\n            prepareRequest(request);\n            sendXmlHttpRequest(Countly.url + readPath, request, function(err, params, responseText){\n                try {\n                    var configs = JSON.parse(responseText);\n                    if (request.keys || request.omit_keys) {\n                        //we merge config\n                        for (var i in configs) {\n                            remoteConfigs[i] = configs[i];\n                        }\n                    }\n                    else {\n                        //we replace config\n                        remoteConfigs = configs;\n                    }\n                    store(\"cly_remote_configs\", remoteConfigs);\n                }\n                catch(ex) {\n                    //silent catch\n                }\n                if (typeof callback === \"function\") {\n                    callback(err, remoteConfigs);\n                }\n            });\n        }\n    };\n    \n    /**\n    * Get Remote config object or specific value for provided key\n    * @param {string=} key - if provided, will return value for key, or return whole object\n    **/\n    Countly.get_remote_config = function (key) {\n        if (typeof key !== \"undefined\") {\n            return remoteConfigs[key];\n        }\n        return remoteConfigs;\n    };\n    \n    /**\n    * Stop tracking duration time for this user\n    **/\n    Countly.stop_time = function () {\n        if (trackTime) {\n            trackTime = false;\n            storedDuration = getTimestamp() - lastBeat;\n            lastViewStoredDuration = getTimestamp() - lastViewTime;\n        }\n    };\n\n    /**\n    * Start tracking duration time for this user, by default it is automatically tracked if you are using internal session handling\n    **/\n    Countly.start_time = function () {\n        if (!trackTime) {\n            trackTime = true;\n            lastBeat = getTimestamp() - storedDuration;\n            lastViewTime = getTimestamp() - lastViewStoredDuration;\n            lastViewStoredDuration = 0;\n            extendSession();\n        }\n    };\n\n    /**\n    * Track user sessions automatically, including  time user spent on your website\n    **/\n    Countly.track_sessions = function () {\n        //start session\n        Countly.begin_session();\n        Countly.start_time();\n\n        //end session on unload\n        add_event(window, \"beforeunload\", function () {\n            Countly.end_session();\n        });\n        add_event(window, \"unload\", function () {\n            Countly.end_session();\n        });\n\n        //manage sessions on window visibility events\n        var hidden = \"hidden\";\n\n        function onchange() {\n            if (document[hidden]) {\n                Countly.stop_time();\n            } else {\n                Countly.start_time();\n            }\n        }\n\n        //Page Visibility API\n        if (hidden in document) {\n            document.addEventListener(\"visibilitychange\", onchange);\n        }\n        else if ((hidden = \"mozHidden\") in document) {\n            document.addEventListener(\"mozvisibilitychange\", onchange);\n        }\n        else if ((hidden = \"webkitHidden\") in document) {\n            document.addEventListener(\"webkitvisibilitychange\", onchange);\n        }\n        else if ((hidden = \"msHidden\") in document) {\n            document.addEventListener(\"msvisibilitychange\", onchange);\n        }\n        // IE 9 and lower:\n        else if (\"onfocusin\" in document) {\n            add_event(window, \"focusin\", function () {\n                Countly.start_time();\n            });\n            add_event(window, \"focusout\", function () {\n                Countly.stop_time();\n            });\n        }\n        // All others:\n        else {\n            //old way\n            add_event(window, \"focus\", function () {\n                Countly.start_time();\n            });\n            add_event(window, \"blur\", function () {\n                Countly.stop_time();\n            });\n\n            //newer mobile compatible way\n            add_event(window, \"pageshow\", function () {\n                Countly.start_time();\n            });\n            add_event(window, \"pagehide\", function () {\n                Countly.stop_time();\n            });\n        }\n\n        function resetInactivity() {\n            if (inactivityCounter >= inactivityTime) {\n                Countly.start_time();\n            }\n            inactivityCounter = 0;\n        }\n\n        add_event(window, \"mousemove\", resetInactivity);\n        add_event(window, \"click\", resetInactivity);\n        add_event(window, \"keydown\", resetInactivity);\n        add_event(window, \"scroll\", resetInactivity);\n\n        //track user inactivity\n        setInterval(function () {\n            inactivityCounter++;\n            if (inactivityCounter >= inactivityTime) {\n                Countly.stop_time();\n            }\n        }, 60000);\n    };\n\n    /**\n    * Track page views user visits\n    * @param {string=} page - optional name of the page, by default uses current url path\n    * @param {array=} ignoreList - optional array of strings or regexes to test for the url/view name to ignore and not report\n    **/\n    Countly.track_pageview = function (page, ignoreList) {\n        reportViewDuration();\n        //we got ignoreList first\n        if (page && Array.isArray( page ) ) {\n            ignoreList = page;\n            page = null;\n        }\n        if (!page) {\n            page = Countly.getViewName();\n        }\n        if (ignoreList && ignoreList.length) {\n            for (var i = 0; i < ignoreList.length; i++) {\n                try {\n                    var reg = new RegExp(ignoreList[i]);\n                    if (reg.test(page)) {\n                        log(\"Ignored:\", page);\n                        return;\n                    }\n                }\n                catch (ex) {log(\"Problem with regex\", ignoreList[i]); }\n            }\n        }\n        lastView = page;\n        lastViewTime = getTimestamp();\n        var segments = {\n            \"name\": page,\n            \"visit\": 1,\n            \"domain\": window.location.hostname,\n            \"view\": Countly.getViewUrl()\n        };\n\n        if (typeof document.referrer !== \"undefined\" && document.referrer.length) {\n            var matches = urlParseRE.exec(document.referrer);\n            //do not report referrers of current website\n            if (matches && matches[11] && matches[11] !== window.location.hostname) {\n                segments.start = 1;\n            }\n        }\n\n        //track pageview\n        if (Countly.check_consent(\"views\")) {\n            add_cly_events({\n                \"key\": \"[CLY]_view\",\n                \"segmentation\": segments\n            });\n        }\n        else {\n            lastParams.track_pageview = arguments;\n        }\n    };\n\n    /**\n    * Track page views user visits. Alias of {@link track_pageview} method for compatability with NodeJS SDK\n    * @param {string=} page - optional name of the page, by default uses current url path\n    * @param {array=} ignoreList - optional array of strings or regexes to test for the url/view name to ignore and not report\n    **/\n    Countly.track_view = function (page, ignoreList) {\n        Countly.track_pageview(page, ignoreList);\n    };\n\n    /**\n    * Track all clicks on this page\n    * @param {Object=} parent - DOM object which children to track, by default it is document body\n    **/\n    Countly.track_clicks = function (parent) {\n        parent = parent || document;\n        var shouldProcess = true;\n        function processClick(event) {\n            if (shouldProcess) {\n                shouldProcess = false;\n\n                //cross browser click coordinates\n                get_page_coord(event);\n                if (typeof event.pageX !== \"undefined\" && typeof event.pageY !== \"undefined\") {\n                    var height = getDocHeight();\n                    var width = getDocWidth();\n\n                    //record click event\n                    if (Countly.check_consent(\"clicks\")) {\n                        add_cly_events({\n                            \"key\": \"[CLY]_action\",\n                            \"segmentation\": {\n                                \"type\": \"click\",\n                                \"x\": event.pageX,\n                                \"y\": event.pageY,\n                                \"width\": width,\n                                \"height\": height,\n                                \"domain\": window.location.hostname,\n                                \"view\": Countly.getViewUrl()\n                            }\n                        });\n                    }\n                }\n                setTimeout(function () { shouldProcess = true; }, 1000);\n            }\n        }\n        //add any events you want\n        add_event(parent, \"click\", processClick);\n    };\n\n    /**\n    * Track all scrolls on this page\n    * @param {Object=} parent - DOM object which children to track, by default it is document body\n    **/\n    Countly.track_scrolls = function (parent) {\n        parent = parent || window;\n        var shouldProcess = true;\n        var scrollY = 0;\n\n        function processScroll() {\n            scrollY = Math.max(scrollY, window.scrollY, document.body.scrollTop, document.documentElement.scrollTop);\n        }\n\n        function processScrollView() {\n            if (shouldProcess) {\n                shouldProcess = false;\n                var height = getDocHeight();\n                var width = getDocWidth();\n\n                var viewportHeight = getViewportHeight();\n\n                if (Countly.check_consent(\"scrolls\")) {\n                    add_cly_events({\n                        \"key\": \"[CLY]_action\",\n                        \"segmentation\": {\n                            \"type\": \"scroll\",\n                            \"y\": scrollY + viewportHeight,\n                            \"width\": width,\n                            \"height\": height,\n                            \"domain\": window.location.hostname,\n                            \"view\": Countly.getViewUrl()\n                        }\n                    });\n                }\n            }\n        }\n\n        add_event(parent, \"scroll\", processScroll);\n        add_event(parent, \"beforeunload\", processScrollView);\n        add_event(parent, \"unload\", processScrollView);\n    };\n\n    /**\n    * Generate custom event for all links that were clicked on this page\n    * @param {Object=} parent - DOM object which children to track, by default it is document body\n    **/\n    Countly.track_links = function (parent) {\n        parent = parent || document;\n        function processClick(event) {\n\n            //get element which was clicked\n            var elem = get_event_target(event).closest(\"a\");\n\n            if (elem) {\n                //cross browser click coordinates\n                get_page_coord(event);\n\n                //record click event\n                if (Countly.check_consent(\"clicks\")) {\n                    add_cly_events({\n                        \"key\": \"linkClick\",\n                        \"segmentation\": {\n                            \"href\": elem.href,\n                            \"text\": elem.innerText,\n                            \"id\": elem.id,\n                            \"view\": Countly.getViewUrl()\n                        }\n                    });\n                }\n            }\n        }\n\n        //add any events you want\n        add_event(parent, \"click\", processClick);\n    };\n\n    /**\n    * Generate custom event for all forms that were submitted on this page\n    * @param {Object=} parent - DOM object which children to track, by default it is document body\n    * @param {boolean=} trackHidden - provide true to also track hidden inputs, default false\n    **/\n    Countly.track_forms = function (parent, trackHidden) {\n        parent = parent || document;\n        function getInputName(input) {\n            return input.name || input.id || input.type || input.nodeName;\n        }\n        function processForm(event) {\n            var form = get_event_target(event);\n            var segmentation = {\n                \"id\": form.id,\n                \"name\": form.name,\n                \"action\": form.action,\n                \"method\": form.method,\n                \"view\": Countly.getViewUrl()\n            };\n\n            //get input values\n            var input;\n            if (typeof form.elements !== \"undefined\") {\n                for (var i = 0; i < form.elements.length; i++) {\n                    input = form.elements[i];\n                    if (input && input.type !== \"password\" && input.className.indexOf(\"cly_user_ignore\") === -1) {\n                        if (typeof segmentation[\"input:\" + getInputName(input)] === \"undefined\") {\n                            segmentation[\"input:\" + getInputName(input)] = [];\n                        }\n                        if (input.nodeName.toLowerCase() === \"select\") {\n                            if (typeof input.multiple !== \"undefined\") {\n                                segmentation[\"input:\" + getInputName(input)].push(getMultiSelectValues(input));\n                            }\n                            else {\n                                segmentation[\"input:\" + getInputName(input)].push(input.options[input.selectedIndex].value);\n                            }\n                        }\n                        else if (input.nodeName.toLowerCase() === \"input\") {\n                            if (typeof input.type !== \"undefined\") {\n                                if (input.type.toLowerCase() === \"checkbox\" || input.type.toLowerCase() === \"radio\") {\n                                    if (input.checked) {\n                                        segmentation[\"input:\" + getInputName(input)].push(input.value);\n                                    }\n                                }\n                                else if(input.type.toLowerCase() !== \"hidden\" || trackHidden) {\n                                    segmentation[\"input:\" + getInputName(input)].push(input.value);\n                                }\n                            }\n                            else {\n                                segmentation[\"input:\" + getInputName(input)].push(input.value);\n                            }\n                        }\n                        else if (input.nodeName.toLowerCase() === \"textarea\") {\n                            segmentation[\"input:\" + getInputName(input)].push(input.value);\n                        }\n                        else if (typeof input.value !== \"undefined\") {\n                            segmentation[\"input:\" + getInputName(input)].push(input.value);\n                        }\n                    }\n                }\n                for (var key in segmentation) {\n                    if (typeof segmentation[key].join != \"undefined\") {\n                        segmentation[key] = segmentation[key].join(\", \");\n                    }\n                }\n            }\n\n            //record submit event\n            if (Countly.check_consent(\"forms\")) {\n                add_cly_events({\n                    \"key\": \"formSubmit\",\n                    \"segmentation\": segmentation\n                });\n            }\n        }\n\n        //add any events you want\n        add_event(parent, \"submit\", processForm);\n    };\n\n    /**\n    * Collect possible user data from submitted forms. Add cly_user_ignore class to ignore inputs in forms or cly_user_{key} to collect data from this input as specified key, as cly_user_username to save collected value from this input as username property. If not class is provided, Countly SDK will try to determine type of information automatically.\n    * @param {Object=} parent - DOM object which children to track, by default it is document body\n    * @param {boolean} [useCustom=false] - submit collected data as custom user properties, by default collects as main user properties\n    **/\n    Countly.collect_from_forms = function (parent, useCustom) {\n        parent = parent || document;\n        function processForm(event) {\n            var form = get_event_target(event);\n            var userdata = {};\n            var hasUserInfo = false;\n\n            //get input values\n            var input;\n            if (typeof form.elements !== \"undefined\") {\n                //load labels for inputs\n                var labelData = {};\n                var labels = parent.getElementsByTagName(\"LABEL\");\n                var i, j;\n                for (i = 0; i < labels.length; i++) {\n                    if (labels[i].htmlFor && labels[i].htmlFor !== \"\") {\n                        labelData[labels[i].htmlFor] = labels[i].innerText || labels[i].textContent || labels[i].innerHTML;\n                    }\n                }\n                for (i = 0; i < form.elements.length; i++) {\n                    input = form.elements[i];\n                    if (input && input.type !== \"password\") {\n                        //check if element should be ignored\n                        if (input.className.indexOf(\"cly_user_ignore\") === -1) {\n                            var value = \"\";\n                            //get value from input\n                            if (input.nodeName.toLowerCase() === \"select\") {\n                                if (typeof input.multiple !== \"undefined\") {\n                                    value = getMultiSelectValues(input);\n                                }\n                                else {\n                                    value = input.options[input.selectedIndex].value;\n                                }\n                            }\n                            else if (input.nodeName.toLowerCase() === \"input\") {\n                                if (typeof input.type !== \"undefined\") {\n                                    if (input.type.toLowerCase() === \"checkbox\" || input.type.toLowerCase() === \"radio\") {\n                                        if (input.checked) {\n                                            value = input.value;\n                                        }\n                                    }\n                                    else {\n                                        value = input.value;\n                                    }\n                                }\n                                else {\n                                    value = input.value;\n                                }\n                            }\n                            else if (input.nodeName.toLowerCase() === \"textarea\") {\n                                value = input.value;\n                            }\n                            else if (typeof input.value !== \"undefined\") {\n                                value = input.value;\n                            }\n                            //check if input was marked to be collected\n                            if (input.className && input.className.indexOf(\"cly_user_\") !== -1) {\n                                var classes = input.className.split(\" \");\n                                for (j = 0; j < classes.length; j++) {\n                                    if (classes[j].indexOf(\"cly_user_\") === 0) {\n                                        userdata[classes[j].replace(\"cly_user_\", \"\")] = value;\n                                        hasUserInfo = true;\n                                        break;\n                                    }\n                                }\n                            }\n                            //check for email\n                            else if ((input.type && input.type.toLowerCase() === \"email\") ||\n                                (input.name && input.name.toLowerCase().indexOf(\"email\") !== -1) ||\n                                (input.id && input.id.toLowerCase().indexOf(\"email\") !== -1) ||\n                                (input.id && labelData[input.id] && labelData[input.id].toLowerCase().indexOf(\"email\") !== -1) ||\n                                (/[^@\\s]+@[^@\\s]+\\.[^@\\s]+/).test(value)) {\n                                if (!userdata.email) {\n                                    userdata.email = value;\n                                }\n                                hasUserInfo = true;\n                            }\n                            else if ((input.name && input.name.toLowerCase().indexOf(\"username\") !== -1) ||\n                                (input.id && input.id.toLowerCase().indexOf(\"username\") !== -1) ||\n                                (input.id && labelData[input.id] && labelData[input.id].toLowerCase().indexOf(\"username\") !== -1)) {\n                                if (!userdata.username) {\n                                    userdata.username = value;\n                                }\n                                hasUserInfo = true;\n                            }\n                            else if ((input.name && (input.name.toLowerCase().indexOf(\"tel\") !== -1 || input.name.toLowerCase().indexOf(\"phone\") !== -1 || input.name.toLowerCase().indexOf(\"number\") !== -1)) ||\n                                (input.id && (input.id.toLowerCase().indexOf(\"tel\") !== -1 || input.id.toLowerCase().indexOf(\"phone\") !== -1 || input.id.toLowerCase().indexOf(\"number\") !== -1)) ||\n                                (input.id && labelData[input.id] && (labelData[input.id].toLowerCase().indexOf(\"tel\") !== -1 || labelData[input.id].toLowerCase().indexOf(\"phone\") !== -1 || labelData[input.id].toLowerCase().indexOf(\"number\") !== -1))) {\n                                if (!userdata.phone) {\n                                    userdata.phone = value;\n                                }\n                                hasUserInfo = true;\n                            }\n                            else if ((input.name && (input.name.toLowerCase().indexOf(\"org\") !== -1 || input.name.toLowerCase().indexOf(\"company\") !== -1)) ||\n                                (input.id && (input.id.toLowerCase().indexOf(\"org\") !== -1 || input.id.toLowerCase().indexOf(\"company\") !== -1)) ||\n                                (input.id && labelData[input.id] && (labelData[input.id].toLowerCase().indexOf(\"org\") !== -1 || labelData[input.id].toLowerCase().indexOf(\"company\") !== -1))) {\n                                if (!userdata.organization) {\n                                    userdata.organization = value;\n                                }\n                                hasUserInfo = true;\n                            }\n                            else if ((input.name && input.name.toLowerCase().indexOf(\"name\") !== -1) ||\n                                (input.id && input.id.toLowerCase().indexOf(\"name\") !== -1) ||\n                                (input.id && labelData[input.id] && labelData[input.id].toLowerCase().indexOf(\"name\") !== -1)) {\n                                if (!userdata.name) {\n                                    userdata.name = \"\";\n                                }\n                                userdata.name += value + \" \";\n                                hasUserInfo = true;\n                            }\n                        }\n                    }\n                }\n            }\n\n            //record user info, if any\n            if (hasUserInfo) {\n                log(\"Gathered user data\", userdata);\n                if (useCustom) {\n                    Countly.user_details({ custom: userdata });\n                }\n                else {\n                    Countly.user_details(userdata);\n                }\n            }\n        }\n\n        //add any events you want\n        add_event(parent, \"submit\", processForm);\n    };\n\n    /**\n    * Collect information about user from Facebook, if your website integrates Facebook SDK. Call this method after Facebook SDK is loaded and user is authenticated.\n    * @param {Object=} custom - Custom keys to collected from Facebook, key will be used to store as key in custom user properties and value as key in Facebook graph object. For example, {\"tz\":\"timezone\"} will collect Facebook's timezone property, if it is available and store it in custom user's property under \"tz\" key. If you want to get value from some sub object properties, then use dot as delimiter, for example, {\"location\":\"location.name\"} will collect data from Facebook's {\"location\":{\"name\":\"MyLocation\"}} object and store it in user's custom property \"location\" key\n    **/\n    Countly.collect_from_facebook = function (custom) {\n        /* globals FB */\n        if (FB && FB.api) {\n            FB.api(\"/me\", function (resp) {\n                var data = {};\n                if (resp.name) {\n                    data.name = resp.name;\n                }\n                if (resp.email) {\n                    data.email = resp.email;\n                }\n                if (resp.gender === \"male\") {\n                    data.gender = \"M\";\n                }\n                else if (resp.gender === \"female\") {\n                    data.gender = \"F\";\n                }\n                if (resp.birthday) {\n                    var byear = resp.birthday.split(\"/\").pop();\n                    if (byear && byear.length === 4) {\n                        data.byear = byear;\n                    }\n                }\n                if (resp.work && resp.work[0] && resp.work[0].employer && resp.work[0].employer.name) {\n                    data.organization = resp.work[0].employer.name;\n                }\n                //check if any custom keys to collect\n                if (custom) {\n                    data.custom = {};\n                    for (var i in custom) {\n                        var parts = custom[i].split(\".\");\n                        var get = resp;\n                        for (var j = 0; j < parts.length; j++) {\n                            get = get[parts[j]];\n                            if (typeof get === \"undefined\") {\n                                break;\n                            }\n                        }\n                        if (typeof get !== \"undefined\") {\n                            data.custom[i] = get;\n                        }\n                    }\n                }\n                Countly.user_details(data);\n            });\n        }\n    };\n    /**\n    * Opts out user of any metric tracking\n    **/\n    Countly.opt_out = function () {\n        Countly.ignore_visitor = true;\n        store(\"cly_ignore\", true);\n    };\n\n    /**\n    * Opts in user for tracking, if complies with other user ignore rules like bot useragent and prefetch settings\n    **/\n    Countly.opt_in = function () {\n        store(\"cly_ignore\", false);\n        Countly.ignore_visitor = false;\n        checkIgnore();\n        if (!Countly.ignore_visitor && !hasPulse) {\n            heartBeat();\n        }\n    };\n\n    /**\n    * Show specific widget popup by the widget id\n    * @param {string} id - id value of related feedback widget, you can get this value by click \"Copy ID\" button in row menu at \"Feedback widgets\" screen\n    */\n    Countly.show_feedback_popup = function(id) {\n        if (offlineMode) {\n            log(\"Cannot show feedback popup in offline mode\");\n        }\n        else {\n            sendXmlHttpRequest(Countly.url+ '/o/feedback/widget', {widget_id:id}, function(err, params, responseText){\n                if(err){\n                    log(\"Error occurred\", err);\n                }\n                try {\n                    // widget object\n                    var currentWidget = JSON.parse(responseText);     \n                    processWidget(currentWidget, false);   \n                } catch (JSONParseError) {\n                    log(\"JSON parse failed: \" + JSONParseError);\n                }\n            });\n        }\n    };\n    \n    /**\n    * Show feedback popup by passed widget ids array\n    * @param {object=} configuration - required - includes \"popups\" property as string array of widgets (\"widgets\" for old versions)\n    * example configuration: {\"popups\":[\"5b21581b967c4850a7818617\"]}\n    **/\n    Countly.enable_feedback = function(params){\n        if (offlineMode) {\n            log(\"Cannot enable feedback in offline mode\");\n        }\n        else {\n            // inject feedback styles\n            loadCSS(Countly.url + '/star-rating/stylesheets/countly-feedback-web.css');\n            // get enable widgets by app_key\n            // define xhr object\n            var enableWidgets = params.popups || params.widgets;\n    \n            if (enableWidgets.length > 0) {\n                document.body.insertAdjacentHTML('beforeend', '<div id=\"cfbg\"></div>');\n    \n                sendXmlHttpRequest(Countly.url + '/o/feedback/multiple-widgets-by-id', {widgets:JSON.stringify(enableWidgets)}, function(err, params, responseText){\n                    if(err){\n                        log(\"Errors occurred:\", err);\n                    }\n                    try {\n                        // widgets array\n                        var widgets = JSON.parse(responseText);    \n                        for (var i = 0; i < widgets.length; i++) {\n                            if (widgets[i].is_active === \"true\") {\n                                var target_devices = widgets[i].target_devices;\n                                var currentDevice = detect_device.device;\n                                // device match check\n                                if (target_devices[currentDevice]) {\n                                    // is hide sticker option selected?\n                                    widgets[i].hide_sticker = widgets[i].hide_sticker === \"true\" ? true : false;\n                                    // is target_page option provided as \"All\"?\n                                    if (widgets[i].target_page === \"all\" && !widgets[i].hide_sticker) {\n                                        processWidget(widgets[i], true);\n                                    }\n                                    // is target_page option provided as \"selected\"?\n                                    else {\n                                        var pages = widgets[i].target_pages;\n                                        for (var k = 0; k < pages.length; k++) {\n                                            if (pages[k] === window.location.pathname && !widgets[i].hide_sticker) {\n                                                processWidget(widgets[i], true);\n                                            }\n                                        }    \n                                    }\n                                }\n                            }\n                        }   \n                        \n                    } catch (JSONParseError) {\n                        log(\"JSON parse error: \" + JSONParseError);\n                    }\n                });\n            } else {\n                log(\"You should provide at least one widget id as param. Read documentation for more detail. https://resources.count.ly/plugins/feedback\");\n            }\n        }\n    };\n    \n    /**\n    *  PRIVATE METHODS\n    **/\n    function checkIgnore(){\n        if (Countly.ignore_prefetch && typeof document.visibilityState !== \"undefined\" && document.visibilityState === \"prerender\") {\n            Countly.ignore_visitor = true;\n        }\n        if (Countly.ignore_bots && searchBotRE.test(navigator.userAgent)) {\n            Countly.ignore_visitor = true;\n        }\n    }\n    \n    function getMultiSelectValues(input){\n        var values = [];\n        if (typeof input.options !== \"undefined\") {\n            for (var j = 0; j < input.options.length; j++) {\n                if (input.options[j].selected) {\n                    values.push(input.options[j].value);\n                }\n            }\n        }\n        return values.join(\", \");\n    }\n    \n    function notifyLoaders(){\n        //notify load waiters\n        var i;\n        if (typeof Countly.onload !== \"undefined\" && Countly.onload.length > 0) {\n            for (i = 0; i < Countly.onload.length; i++) {\n                if (typeof Countly.onload[i] === \"function\") {\n                    Countly.onload[i]();\n                }\n            }\n            Countly.onload = [];\n        }\n    }\n    \n    function processWidget(currentWidget, hasSticker){\n        try {\n            // create wrapper div\n            var wrapper = document.createElement(\"div\");\n            wrapper.className = 'countly-iframe-wrapper';\n            wrapper.id = 'countly-iframe-wrapper-'+currentWidget._id;\n            // create close icon for iframe popup\n            var closeIcon = document.createElement(\"span\");\n            closeIcon.className = \"countly-feedback-close-icon\";\n            closeIcon.id = \"countly-feedback-close-icon-\"+currentWidget._id;\n            closeIcon.innerHTML = \"x\";\n            // create iframe \n            var iframe = document.createElement(\"iframe\");\n            iframe.name = \"countly-feedback-iframe\";\n            iframe.id = \"countly-feedback-iframe\";\n            iframe.src = Countly.url + \"/feedback?widget_id=\" + currentWidget._id + \"&app_key=\" + Countly.app_key + '&device_id=' + Countly.device_id + '&sdk_version=' + SDK_VERSION;\n            // inject them to dom\n            document.body.appendChild(wrapper);\n            wrapper.appendChild(closeIcon);\n            wrapper.appendChild(iframe);\n            add_event(document.getElementById('countly-feedback-close-icon-'+currentWidget._id), 'click', function(){\n                document.getElementById('countly-iframe-wrapper-'+currentWidget._id).style.display = \"none\";\n                document.getElementById('cfbg').style.display = \"none\";\n            });\n            if(hasSticker) {\n                var sticker = document.createElement(\"div\");\n                sticker.style.color = ((currentWidget.trigger_font_color < 7) ? '#'+currentWidget.trigger_font_color : currentWidget.trigger_font_color);\n                sticker.style.backgroundColor = ((currentWidget.trigger_bg_color.length < 7) ? '#'+currentWidget.trigger_bg_color : currentWidget.trigger_bg_color);\n                sticker.className = 'countly-feedback-sticker '+ currentWidget.trigger_position;\n                sticker.id = 'countly-feedback-sticker-'+currentWidget._id;\n                sticker.innerHTML = '<svg id=\"feedback-sticker-svg\" aria-hidden=\"true\" data-prefix=\"far\" data-icon=\"grin\" class=\"svg-inline--fa fa-grin fa-w-16\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 496 512\"><path id=\"smileyPathInStickerSvg\" fill=\"white\" d=\"M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm105.6-151.4c-25.9 8.3-64.4 13.1-105.6 13.1s-79.6-4.8-105.6-13.1c-9.9-3.1-19.4 5.4-17.7 15.3 7.9 47.1 71.3 80 123.3 80s115.3-32.9 123.3-80c1.6-9.8-7.7-18.4-17.7-15.3zM168 240c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32z\"></path></svg> ' + currentWidget.trigger_button_text;\n                document.body.appendChild(sticker);\n                var smileySvg = document.getElementById(\"smileyPathInStickerSvg\");\n                if(smileySvg) {\n                    smileySvg.style.fill = ((currentWidget.trigger_font_color < 7) ? '#'+currentWidget.trigger_font_color : currentWidget.trigger_font_color);\n                }\n                add_event(document.getElementById('countly-feedback-sticker-'+currentWidget._id), 'click', function(){\n                    document.getElementById('countly-iframe-wrapper-'+currentWidget._id).style.display = \"block\";\n                    document.getElementById('cfbg').style.display = \"block\";\n                });\n            }\n            else {\n                document.getElementById('countly-iframe-wrapper-'+currentWidget._id).style.display = \"block\";\n                document.getElementById('cfbg').style.display = \"block\";\n            }\n        } catch (e) {\n            log(\"Somethings went wrong while element injecting process: \" + e);\n        }\n    }\n    \n    function reportViewDuration() {\n        if (lastView) {\n            var segments = {\n                \"name\": lastView,\n                \"segment\": platform\n            };\n\n            //track pageview\n            if (Countly.check_consent(\"views\")) {\n                add_cly_events({\n                    \"key\": \"[CLY]_view\",\n                    \"dur\": (trackTime) ? getTimestamp() - lastViewTime : lastViewStoredDuration,\n                    \"segmentation\": segments\n                });\n            }\n            lastView = null;\n        }\n    }\n\n    function getLastView() {\n        return lastView;\n    }\n    \n    //extend session\n    function extendSession(){\n        if(useSessionCookie){\n            //if session expired, we should start a new one\n            var expire = store(\"cly_session\");\n            if (!expire || parseInt(expire) <= getTimestamp()) {\n                sessionStarted = false;\n                Countly.begin_session(!autoExtend);\n            }\n            store(\"cly_session\", getTimestamp() + (sessionCookieTimeout * 60));\n        }\n    }\n\n    //prepare request by adding basic info to it\n    function prepareRequest(request) {\n        request.app_key = Countly.app_key;\n        request.device_id = Countly.device_id;\n        request.sdk_name = SDK_NAME;\n        request.sdk_version = SDK_VERSION;\n        \n        if (Countly.check_consent(\"location\")) {\n            if (Countly.country_code) {\n                request.country_code = Countly.country_code;\n            }\n\n            if (Countly.city) {\n                request.city = Countly.city;\n            }\n\n            if (Countly.ip_address !== null) {\n                request.ip_address = Countly.ip_address;\n            }\n        }\n        else {\n            request.location = \"\";\n        }\n\n        request.timestamp = getMsTimestamp();\n\n        var date = new Date();\n        request.hour = date.getHours();\n        request.dow = date.getDay();\n    }\n    \n    //insert request to queue\n    function toRequestQueue(request) {\n        \n        if (Countly.ignore_visitor) {\n            return;\n        }\n\n        if (!Countly.app_key || !Countly.device_id) {\n            log(\"app_key or device_id is missing\");\n            return;\n        }\n        \n        prepareRequest(request);\n\n        if (requestQueue.length > queueSize) {\n            requestQueue.shift();\n        }\n\n        requestQueue.push(request);\n        store(\"cly_queue\", requestQueue, true);\n    }\n\n    //heart beat\n    function heartBeat() {\n        notifyLoaders();\n        \n        //ignore bots\n        if (Countly.test_mode || Countly.ignore_visitor) {\n            hasPulse = false;\n            return;\n        }\n\n        hasPulse = true;\n        var i = 0;\n        //process queue\n        if (typeof Countly.q !== \"undefined\" && Countly.q.length > 0) {\n            var req;\n            var q = Countly.q;\n            Countly.q = [];\n            for (i = 0; i < q.length; i++) {\n                req = q[i];\n                log(\"Processing queued call\", req);\n                if (typeof req === \"function\") {\n                    req();\n                }\n                else if ( Array.isArray( req ) && req.length > 0) {\n                    if (typeof Countly[req[0]] !== \"undefined\") {\n                        Countly[req[0]].apply(null, req.slice(1));\n                    }\n                    else {\n                        var userdata = req[0].replace(\"userData.\", \"\");\n                        if (typeof Countly.userData[userdata] !== \"undefined\") {\n                            Countly.userData[userdata].apply(null, req.slice(1));\n                        }\n                    }\n                }\n            }\n        }\n\n        //extend session if needed\n        if (sessionStarted && autoExtend && trackTime) {\n            var last = getTimestamp();\n            if (last - lastBeat > sessionUpdate) {\n                Countly.session_duration(last - lastBeat);\n                lastBeat = last;\n            }\n        }\n\n        //process event queue\n        if (eventQueue.length > 0) {\n            if (eventQueue.length <= maxEventBatch) {\n                toRequestQueue({ events: JSON.stringify(eventQueue) });\n                eventQueue = [];\n            }\n            else {\n                var events = eventQueue.splice(0, maxEventBatch);\n                toRequestQueue({ events: JSON.stringify(events) });\n            }\n            store(\"cly_event\", eventQueue);\n        }\n\n        //process request queue with event queue\n        if (!offlineMode && requestQueue.length > 0 && readyToProcess && getTimestamp() > failTimeout) {\n            readyToProcess = false;\n            var params = requestQueue.shift();\n            //check if any consent to sync\n            if (hasAnyProperties(syncConsents)) {\n                if (consentTimer) {\n                    clearTimeout(consentTimer);\n                    consentTimer = null;\n                }\n                params.consent = JSON.stringify(syncConsents);\n                syncConsents = {};\n            }\n            log(\"Processing request\", params);\n            store(\"cly_queue\", requestQueue, true);\n            sendXmlHttpRequest(Countly.url + apiPath, params, function(err, params){\n                log(\"Request Finished\", params, err);\n                if (err) {\n                    requestQueue.unshift(params);\n                    failTimeout = getTimestamp() + failTimeoutAmount;\n                }\n                store(\"cly_queue\", requestQueue, true);\n                readyToProcess = true;\n            });\n        }\n\n        setTimeout(heartBeat, beatInterval);\n    }\n\n    //get ID\n    function getId() {\n        return store(\"cly_id\") || generateUUID();\n    }\n\n    //generate UUID\n    function generateUUID() {\n        var d = new Date().getTime();\n        var uuid = \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function (c) {\n            var r = (d + Math.random() * 16) % 16 | 0;\n            d = Math.floor(d / 16);\n            return (c === \"x\" ? r : (r & 0x3 | 0x8)).toString(16);\n        });\n        return uuid;\n    }\n    \n    function isUUID() {\n        return /[0-9a-fA-F]{8}\\-[0-9a-fA-F]{4}\\-4[0-9a-fA-F]{3}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{12}/.test(Countly.device_id);\n    }\n\n    //get metrics of the browser\n    function getMetrics() {\n        var metrics = {};\n\n        //getting app version\n        metrics._app_version = Countly.app_version;\n        metrics._ua = navigator.userAgent;\n\n        //getting resolution\n        if (screen.width) {\n            var width = (screen.width) ? parseInt(screen.width) : 0;\n            var height = (screen.height) ? parseInt(screen.height) : 0;\n            if (width !== 0 && height !== 0) {\n                var iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);\n                if (iOS && window.devicePixelRatio) {\n                    //ios provides dips, need to multiply\n                    width = Math.round(width * window.devicePixelRatio);\n                    height = Math.round(height * window.devicePixelRatio);\n                }\n                else {\n                    if (Math.abs(window.orientation) === 90) {\n                        //we have landscape orientation\n                        //switch values for all except ios\n                        var temp = width;\n                        width = height;\n                        height = temp;\n                    }\n                }\n                metrics._resolution = \"\" + width + \"x\" + height;\n            }\n        }\n\n        //getting density ratio\n        if (window.devicePixelRatio) {\n            metrics._density = window.devicePixelRatio;\n        }\n\n        //getting locale\n        var locale = navigator.language || navigator.browserLanguage || navigator.systemLanguage || navigator.userLanguage;\n        if (typeof locale !== \"undefined\") {\n            metrics._locale = locale;\n        }\n\n        if (typeof document.referrer !== \"undefined\" && document.referrer.length) {\n            var matches = urlParseRE.exec(document.referrer);\n            //do not report referrers of current website\n            if (matches && matches[11] && matches[11] !== window.location.hostname) {\n                var ignoring = false;\n                if (ignoreReferrers && ignoreReferrers.length) {\n                    for (var k = 0; k < ignoreReferrers.length; k++) {\n                        try {\n                            var reg = new RegExp(ignoreReferrers[k]);\n                            if (reg.test(document.referrer)) {\n                                log(\"Ignored:\", document.referrer);\n                                ignoring = true;\n                                break;\n                            }\n                        }\n                        catch (ex) { log(\"Problem with regex\", ignoreReferrers[k]); }\n                    }\n                }\n                if (!ignoring) {\n                    metrics._store = document.referrer;\n                }\n            }\n        }\n\n        log(\"Got metrics\", metrics);\n        return metrics;\n    }\n\n    //log stuff\n    function log() {\n        if (Countly.debug && typeof console !== \"undefined\") {\n            if (arguments[1] && typeof arguments[1] == \"object\") {\n                arguments[1] = JSON.stringify(arguments[1]);\n            }\n            // eslint-disable-next-line no-console\n            console.log(Array.prototype.slice.call(arguments).join(\"\\n\"));\n        }\n    }\n\n    //get current timestamp\n    function getTimestamp() {\n        return Math.floor(new Date().getTime() / 1000);\n    }\n\n    //get unique timestamp in miliseconds\n    function getMsTimestamp() {\n        var ts = new Date().getTime();\n        if (lastMsTs >= ts) {\n            lastMsTs++;\n        }\n        else {\n            lastMsTs = ts;\n        }\n        return lastMsTs;\n    }\n    \n    function getConfig(key, ob, override) {\n        if(typeof ob[key] !== \"undefined\")\n        {return ob[key];}\n        if(typeof Countly[key] !== \"undefined\")\n        {return Countly[key];}\n        return override;\n    }\n\n    function recordError(err, nonfatal, segments) {\n        if (Countly.check_consent(\"crashes\") && err) {\n            segments = segments || crashSegments;\n            var error = \"\";\n            if (typeof err === \"object\") {\n                if (typeof err.stack !== \"undefined\") {\n                    error = err.stack;\n                }\n                else {\n                    if (typeof err.name !== \"undefined\") {\n                        error += err.name + \":\";\n                    }\n                    if (typeof err.message !== \"undefined\") {\n                        error += err.message + \"\\n\";\n                    }\n                    if (typeof err.fileName !== \"undefined\") {\n                        error += \"in \" + err.fileName + \"\\n\";\n                    }\n                    if (typeof err.lineNumber !== \"undefined\") {\n                        error += \"on \" + err.lineNumber;\n                    }\n                    if (typeof err.columnNumber !== \"undefined\") {\n                        error += \":\" + err.columnNumber;\n                    }\n                }\n            }\n            else {\n                error = err + \"\";\n            }\n            nonfatal = (nonfatal) ? true : false;\n            var metrics = getMetrics();\n            var ob = { _resolution: metrics._resolution, _error: error, _app_version: metrics._app_version, _run: getTimestamp() - startTime };\n\n            ob._not_os_specific = true;\n\n            var battery = navigator.battery || navigator.webkitBattery || navigator.mozBattery || navigator.msBattery;\n            if (battery) {\n                ob._bat = Math.floor(battery.level * 100);\n            }\n\n            if (typeof navigator.onLine !== \"undefined\") {\n                ob._online = (navigator.onLine) ? true : false;\n            }\n\n            ob._background = (document.hasFocus()) ? false : true;\n\n            if (crashLogs.length > 0) {\n                ob._logs = crashLogs.join(\"\\n\");\n            }\n            crashLogs = [];\n            \n            ob._nonfatal = nonfatal;\n\n            ob._view = (window.location.pathname || \"\") + (window.location.search || \"\") + (window.location.hash || \"\");\n\n            if (typeof segments !== \"undefined\") {\n                ob._custom = segments;\n            }\n\n            try {\n                var canvas = document.createElement(\"canvas\");\n                var gl = canvas.getContext(\"experimental-webgl\");\n                ob._opengl = gl.getParameter(gl.VERSION);\n            }\n            catch (ex) {\n                //silent error\n            }\n\n            toRequestQueue({ crash: JSON.stringify(ob) });\n        }\n    }\n\n    //sending xml HTTP request\n    function sendXmlHttpRequest(url, params, callback) {\n        try {\n            log(\"Sending XML HTTP request\");\n            var xhr = window.XMLHttpRequest ? new window.XMLHttpRequest() : window.ActiveXObject ? new window.ActiveXObject(\"Microsoft.XMLHTTP\") : null;\n            params = params || {};\n            var data = prepareParams(params);\n            var method = \"GET\";\n            if (Countly.force_post || data.length >= 2000) {\n                method = \"POST\";\n            }\n            if(method === \"GET\") {\n                xhr.open('GET', url + \"?\" + data, true);\n            } else {\n                xhr.open('POST', url, true);\n                xhr.setRequestHeader(\"Content-type\", \"application/x-www-form-urlencoded\");\n            }\n            // fallback on error\n            xhr.onreadystatechange = function () {\n                if (this.readyState === 4 && this.status >= 200 && this.status < 300) {\n                    if (typeof callback === 'function') { callback(false, params, this.responseText); }\n                } else if (this.readyState === 4) {\n                    log(\"Failed Server XML HTTP request\", this.status);\n                    if (typeof callback === \"function\") { callback(true, params); }\n                }\n            };\n            if (method === \"GET\") {\n                xhr.send();\n            }\n            else {\n                xhr.send(data);\n            }\n        } catch (e) {\n            // fallback\n            log(\"Failed XML HTTP request\", e);\n            if (typeof callback === \"function\") { callback(true, params); }\n        }\n    }\n\n    //convert JSON object to query params\n    function prepareParams(params) {\n        var str = [];\n        for (var i in params) {\n            str.push(i + \"=\" + encodeURIComponent(params[i]));\n        }\n        return str.join(\"&\");\n    }\n\n    //removing trailing slashes\n    function stripTrailingSlash(str) {\n        if (str.substr(str.length - 1) === \"/\") {\n            return str.substr(0, str.length - 1);\n        }\n        return str;\n    }\n\n    //retrieve only specific properties from object\n    function getProperties(orig, props) {\n        var ob = {};\n        var prop;\n        for (var i = 0; i < props.length; i++) {\n            prop = props[i];\n            if (typeof orig[prop] !== \"undefined\") {\n                ob[prop] = orig[prop];\n            }\n        }\n        return ob;\n    }\n\n    //get closest parent matching nodeName\n    if (!Element.prototype.closest) {\n        Element.prototype.closest = function (nodeName) {\n            var el = this;\n            nodeName = nodeName.toUpperCase();\n            while (el) {\n                if (el.nodeName.toUpperCase() === nodeName) {\n                    return el;\n                }\n                el = el.parentElement;\n            }\n        };\n    }\n\n    //add event\n    var add_event = function (element, type, listener) {\n        if (typeof element.addEventListener !== \"undefined\") {\n            element.addEventListener(type, listener, false);\n        }\n        else {\n            element.attachEvent(\"on\" + type, listener);\n        }\n    };\n\n    //get element that fired event\n    var get_event_target = function (event) {\n        if (!event) {\n            return window.event.srcElement;\n        }\n        else if (typeof event.target !== \"undefined\") {\n            return event.target;\n        }\n        else {\n            return event.srcElement;\n        }\n    };\n\n    // detect current device\n    var detect_device = (function() {\n        var b = navigator.userAgent.toLowerCase(),\n            a = function(a) {\n                if(a){\n                    b = (a+\"\").toLowerCase();\n                }\n                return /(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/.test(b) ? \"tablet\" : /(mobi|ipod|phone|blackberry|opera mini|fennec|minimo|symbian|psp|nintendo ds|archos|skyfire|puffin|blazer|bolt|gobrowser|iris|maemo|semc|teashark|uzard)/.test(b) ? \"phone\" : \"desktop\";\n            };\n        return {\n            device: a(),\n            detect: a,\n            isMobile: \"desktop\" !== a() ? !0 : !1,\n            userAgent: b\n        };\n    }());\n    \n    //get page coordinates\n    function get_page_coord(e) {\n        //checking if pageY and pageX is already available\n        if (typeof e.pageY == \"undefined\" &&\n            typeof e.clientX == \"number\" &&\n            document.documentElement) {\n            //if not, then add scrolling positions\n            e.pageX = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;\n            e.pageY = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;\n        }\n        //return e which now contains pageX and pageY attributes\n        return e;\n    }\n\n    function getDocHeight() {\n        var D = document;\n        return Math.max(\n            Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),\n            Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),\n            Math.max(D.body.clientHeight, D.documentElement.clientHeight)\n        );\n    }\n    \n    function getDocWidth() {\n        var D = document;\n        return Math.max(\n            Math.max(D.body.scrollWidth, D.documentElement.scrollWidth),\n            Math.max(D.body.offsetWidth, D.documentElement.offsetWidth),\n            Math.max(D.body.clientWidth, D.documentElement.clientWidth)\n        );\n    }\n\n    function getViewportHeight() {\n        var D = document;\n        return Math.min(\n            Math.min(D.body.clientHeight, D.documentElement.clientHeight),\n            Math.min(D.body.offsetHeight, D.documentElement.offsetHeight),\n            window.innerHeight\n        );\n    }\n\n    function setToken(token) {\n        store(\"cly_token\", token);\n    }\n\n    function getToken() {\n        var token = store(\"cly_token\");\n        store(\"cly_token\", null);\n        return token;\n    }\n\n    function hasAnyProperties(ob) {\n        if (ob) {\n            for (var prop in ob) {\n                if(Object.prototype.hasOwnProperty.call(ob, prop))\n                {return true;}\n            }\n        }\n        return false;\n    }\n\n    /**\n    * Simple localStorage with Cookie Fallback\n    * v.1.0.0\n    *\n    * USAGE:\n    * ----------------------------------------\n    * Set New / Modify:\n    *   store(\"my_key\", \"some_value\");\n    *\n    * Retrieve:\n    *   store(\"my_key\");\n    *\n    * Delete / Remove:\n    *   store(\"my_key\", null);\n    */\n\n    var store = function store(key, value, storageOnly) {\n        //apply namespace\n        key = Countly.namespace + key;\n        storageOnly = storageOnly || false;\n        var lsSupport = false,\n            data;\n\n        // Check for native support\n        lsSupport = true;\n        try {\n            if (typeof localStorage !== \"undefined\") {\n                localStorage.setItem(\"testLocal\", true);\n            }\n        }\n        catch (e) {\n            lsSupport = false;\n        }\n\n        // If value is detected, set new or modify store\n        if (typeof value !== \"undefined\" && value !== null) {\n            value = Countly.serialize(value);\n            // Set the store\n            if (lsSupport) { // Native support\n                localStorage.setItem(key, value);\n            } else if (!storageOnly) { // Use Cookie\n                createCookie(key, value, 30);\n            }\n        }\n\n        // No value supplied, return value\n        if (typeof value === \"undefined\") {\n            // Get value\n            if (lsSupport) { // Native support\n                data = localStorage.getItem(key);\n            } else if (!storageOnly) { // Use cookie \n                data = readCookie(key);\n            }\n\n            return Countly.deserialize(data);\n\n        }\n\n        // Null specified, remove store\n        if (value === null) {\n            if (lsSupport) { // Native support\n                localStorage.removeItem(key);\n            } else if (!storageOnly) { // Use cookie\n                createCookie(key, \"\", -1);\n            }\n        }\n\n        /**\n        * Creates new cookie or removes cookie with negative expiration\n        * @param  key       The key or identifier for the store\n        * @param  value     Contents of the store\n        * @param  exp       Expiration - creation defaults to 30 days\n        */\n\n        function createCookie(key, value, exp) {\n            var date = new Date();\n            date.setTime(date.getTime() + (exp * 24 * 60 * 60 * 1000));\n            var expires = \"; expires=\" + date.toGMTString();\n            document.cookie = key + \"=\" + value + expires + \"; path=/\";\n        }\n\n        /**\n        * Returns contents of cookie\n        * @param  key       The key or identifier for the store\n        */\n\n        function readCookie(key) {\n            var nameEQ = key + \"=\";\n            var ca = document.cookie.split(\";\");\n            for (var i = 0, max = ca.length; i < max; i++) {\n                var c = ca[i];\n                while (c.charAt(0) === \" \") {\n                    c = c.substring(1, c.length);\n                }\n                if (c.indexOf(nameEQ) === 0) {\n                    return c.substring(nameEQ.length, c.length);\n                }\n            }\n            return null;\n        }\n    };\n    \n    window.addEventListener('storage', function(e) {\n        var key = (e.key + \"\").replace(Countly.namespace, \"\");\n        \n        switch(key) {\n        //queue of requests\n        case \"cly_queue\":\n            requestQueue = Countly.deserialize(e.newValue);\n            break;\n            //queue of events\n        case \"cly_event\":\n            eventQueue = Countly.deserialize(e.newValue);\n            break;\n        case \"cly_remote_configs\":\n            remoteConfigs = Countly.deserialize(e.newValue);\n            break;\n        case \"cly_ignore\":\n            Countly.ignore_visitor = Countly.deserialize(e.newValue);\n            break;\n        case \"cly_id\":\n            Countly.device_id = Countly.deserialize(e.newValue);\n            break;\n        default:\n                // do nothing\n        }\n    });\n\n    //load external js files\n    function loadFile(tag, attr, type, src, data, callback) {\n        var fileref = document.createElement(tag),\n            loaded;\n        fileref.setAttribute(attr, type);\n        fileref.setAttribute(src, data);\n        if (callback) {\n            fileref.onreadystatechange = fileref.onload = function () {\n                if (!loaded) {\n                    callback();\n                }\n                loaded = true;\n            };\n        }\n        document.getElementsByTagName(\"head\")[0].appendChild(fileref);\n    }\n    \n    //load external js files\n    function loadJS(js, callback) {\n        loadFile(\"script\", \"type\", \"text/javascript\", \"src\", js, callback);\n    }\n\n    //load external css files\n    function loadCSS(css, callback) {\n        loadFile(\"link\", \"rel\", \"stylesheet\", \"href\", css, callback);\n    }\n\n    function showLoader() {\n        var loader = document.getElementById(\"cly-loader\");\n        if (!loader) {\n            log(\"setting up loader\");\n            var css = \"#cly-loader {height: 4px; width: 100%; position: absolute; z-index: 99999; overflow: hidden; background-color: #fff; top:0px; left:0px;}\" +\n                \"#cly-loader:before{display: block; position: absolute; content: ''; left: -200px; width: 200px; height: 4px; background-color: #2EB52B; animation: cly-loading 2s linear infinite;}\" +\n                \"@keyframes cly-loading { from {left: -200px; width: 30%;} 50% {width: 30%;} 70% {width: 70%;} 80% { left: 50%;} 95% {left: 120%;} to {left: 100%;}}\",\n                head = document.head || document.getElementsByTagName(\"head\")[0],\n                style = document.createElement(\"style\");\n            style.type = \"text/css\";\n            if (style.styleSheet) {\n                style.styleSheet.cssText = css;\n            } else {\n                style.appendChild(document.createTextNode(css));\n            }\n            head.appendChild(style);\n            loader = document.createElement(\"div\");\n            loader.setAttribute(\"id\", \"cly-loader\");\n            document.body.appendChild(loader);\n        }\n        loader.style.display = \"block\";\n    }\n\n    function hideLoader() {\n        var loader = document.getElementById(\"cly-loader\");\n        if (loader) {\n            loader.style.display = \"none\";\n        }\n    }\n\n    function getEventQueue() {\n        return eventQueue;\n    }\n\n    function getRequestQueue() {\n        return requestQueue;\n    }\n    \n    /**\n    * Overwrite serialization function for extending SDK with encryption, etc\n    * @param {any} value - value to serialize\n    * @return {string} serialized value\n    **/\n    Countly.serialize = function(value) {\n        // Convert object values to JSON\n        if (typeof value === \"object\") {\n            value = JSON.stringify(value);\n        }\n        return value;\n    };\n    \n    /**\n    * Overwrite deserialization function for extending SDK with encryption, etc\n    * @param {string} data - value to deserialize\n    * @return {varies} deserialized value\n    **/\n    Countly.deserialize = function(data) {\n        // Try to parse JSON...\n        try {\n            data = JSON.parse(data);\n        }\n        catch (e) {\n            //it means data is not json, \n            //dont do anything\n        }\n\n        return data;\n    };\n    \n    /**\n    * Overwrite a way to retrieve view name\n    * @return {string} view name\n    **/\n    Countly.getViewName = function() {\n        return window.location.pathname;\n    };\n    \n    /**\n    * Overwrite a way to retrieve view url\n    * @return {string} view url\n    **/\n    Countly.getViewUrl = function() {\n        return window.location.pathname;\n    };\n\n    //expose internal methods for pluggable code to reuse them\n    Countly._internals = {\n        store: store,\n        getDocWidth: getDocWidth,\n        getDocHeight: getDocHeight,\n        getViewportHeight: getViewportHeight,\n        get_page_coord: get_page_coord,\n        get_event_target: get_event_target,\n        add_event: add_event,\n        getProperties: getProperties,\n        stripTrailingSlash: stripTrailingSlash,\n        prepareParams: prepareParams,\n        sendXmlHttpRequest: sendXmlHttpRequest,\n        recordError: recordError,\n        getMsTimestamp: getMsTimestamp,\n        getTimestamp: getTimestamp,\n        log: log,\n        getMetrics: getMetrics,\n        generateUUID: generateUUID,\n        isUUID: isUUID,\n        getId: getId,\n        heartBeat: heartBeat,\n        toRequestQueue: toRequestQueue,\n        reportViewDuration: reportViewDuration,\n        loadJS: loadJS,\n        loadCSS: loadCSS,\n        getLastView: getLastView,\n        setToken: setToken,\n        getToken: getToken,\n        showLoader: showLoader,\n        hideLoader: hideLoader,\n        add_cly_events:add_cly_events,\n        detect_device: detect_device,\n        getRequestQueue: getRequestQueue,\n        getEventQueue: getEventQueue,\n        clearQueue: function (){\n            requestQueue = [];\n            store(\"cly_queue\", []);\n            eventQueue = [];\n            store(\"cly_event\", []);\n        }\n    };\n\n    return Countly;\n}));"],"sourceRoot":""}