diff --git a/CHANGELOG.md b/CHANGELOG.md index 753a845d..1c74174f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,20 @@ -### 4.6.0 (February 25, 2018) +### 5.0.0 (Unreleased) + +* Add `onInit` method that accepts a callback that will be invoked after init +* Allow for api endpoints that do not end with a trailing slash +* Sync with upstream ua-parser for user agent parsing +* Upgrade rollup/babel dependencies + +## Breaking Changes +* Drop JSON polyfill. This will break IE 7 and older. You can install your own JSON polyfill before loading amplitude. +* Stop committing generated files to the master branch in the git repository (do not install amplitude from git). +* Drop custom user agent parsing for symbian and blackberry + +### 4.7.0 (March 12, 2019) + +* Cherry-picked from 5.0.0: Add `onInit` method that accepts a callback that will be invoked after init + +### 4.6.0 (February 25, 2019) * Add support for unsetting utm params when a new session is created * Update dependencies to pass yarn audit diff --git a/README.md b/README.md index de019a48..e441d212 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Please see our [installation guide](https://amplitude.zendesk.com/hc/en-us/artic [![npm version](https://badge.fury.io/js/amplitude-js.svg)](https://badge.fury.io/js/amplitude-js) [![Bower version](https://badge.fury.io/bo/amplitude-js.svg)](https://badge.fury.io/bo/amplitude-js) -[4.6.0 - Released on February 25, 2019](https://github.com/amplitude/Amplitude-JavaScript/releases/latest) +[4.7.0 - Released on March 12, 2019](https://github.com/amplitude/Amplitude-JavaScript/releases/latest) # JavaScript SDK Reference # diff --git a/amplitude-snippet.min.js b/amplitude-snippet.min.js index 54e629f4..695e7a95 100644 --- a/amplitude-snippet.min.js +++ b/amplitude-snippet.min.js @@ -1,6 +1,6 @@ (function(e,t){var n=e.amplitude||{_q:[],_iq:{}};var r=t.createElement("script") ;r.type="text/javascript";r.async=true -;r.src="https://cdn.amplitude.com/libs/amplitude-4.6.0-min.gz.js" +;r.src="https://cdn.amplitude.com/libs/amplitude-4.7.0-min.gz.js" ;r.onload=function(){if(e.amplitude.runQueuedFunctions){ e.amplitude.runQueuedFunctions()}else{ console.log("[Amplitude] Error: could not load SDK")}} diff --git a/amplitude.js b/amplitude.js index 3d9cd7d9..a0911aa4 100644 --- a/amplitude.js +++ b/amplitude.js @@ -3801,7 +3801,7 @@ var uuid = function uuid(a) { ); }; -var version = '4.6.0'; +var version = '4.7.0'; var getLanguage = function getLanguage() { return navigator && (navigator.languages && navigator.languages[0] || navigator.language || navigator.userLanguage) || undefined; @@ -3871,6 +3871,7 @@ var AmplitudeClient = function AmplitudeClient(instanceName) { this._q = []; // queue for proxied functions before script load this._sending = false; this._updateScheduled = false; + this._onInit = []; // event meta data this._eventId = 0; @@ -3983,6 +3984,10 @@ AmplitudeClient.prototype.init = function init(apiKey, opt_userId, opt_config, o opt_callback(this); } } + + for (var _i = 0; _i < this._onInit.length; _i++) { + this._onInit[_i](); + } }; /** @@ -4118,6 +4123,14 @@ AmplitudeClient.prototype.isNewSession = function isNewSession() { return this._newSession; }; +/** + * Store callbacks to call after init + * @private + */ +AmplitudeClient.prototype.onInit = function (callback) { + this._onInit.push(callback); +}; + /** * Returns the id of the current session. * @public diff --git a/amplitude.min.js b/amplitude.min.js index aa29dba1..248de96d 100644 --- a/amplitude.min.js +++ b/amplitude.min.js @@ -1 +1 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.amplitude=t()}(this,function(){"use strict";var u="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function e(e,t){return e(t={exports:{}},t.exports),t.exports}e(function(s,a){(function(){var M={function:!0,object:!0},e=M.object&&a&&!a.nodeType&&a,B=M[typeof window]&&window||this,t=e&&M.object&&s&&!s.nodeType&&"object"==typeof u&&u;function L(e,u){e||(e=B.Object()),u||(u=B.Object());var c=e.Number||B.Number,p=e.String||B.String,t=e.Object||B.Object,l=e.Date||B.Date,n=e.SyntaxError||B.SyntaxError,S=e.TypeError||B.TypeError,i=e.Math||B.Math,r=e.JSON||B.JSON;"object"==typeof r&&r&&(u.stringify=r.stringify,u.parse=r.parse);var O,E,N,o=t.prototype,x=o.toString,d=new l(-0xc782b5b800cec);try{d=-109252==d.getUTCFullYear()&&0===d.getUTCMonth()&&1===d.getUTCDate()&&10==d.getUTCHours()&&37==d.getUTCMinutes()&&6==d.getUTCSeconds()&&708==d.getUTCMilliseconds()}catch(e){}function f(e){if(f[e]!==N)return f[e];var t;if("bug-string-char-index"==e)t="a"!="a"[0];else if("json"==e)t=f("json-stringify")&&f("json-parse");else{var n,i='{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}';if("json-stringify"==e){var r=u.stringify,o="function"==typeof r&&d;if(o){(n=function(){return 1}).toJSON=n;try{o="0"===r(0)&&"0"===r(new c)&&'""'==r(new p)&&r(x)===N&&r(N)===N&&r()===N&&"1"===r(n)&&"[1]"==r([n])&&"[null]"==r([N])&&"null"==r(null)&&"[null,null,null]"==r([N,x,null])&&r({a:[n,!0,!1,null,"\0\b\n\f\r\t"]})==i&&"1"===r(null,n)&&"[\n 1,\n 2\n]"==r([1,2],null,1)&&'"-271821-04-20T00:00:00.000Z"'==r(new l(-864e13))&&'"+275760-09-13T00:00:00.000Z"'==r(new l(864e13))&&'"-000001-01-01T00:00:00.000Z"'==r(new l(-621987552e5))&&'"1969-12-31T23:59:59.999Z"'==r(new l(-1))}catch(e){o=!1}}t=o}if("json-parse"==e){var s=u.parse;if("function"==typeof s)try{if(0===s("0")&&!s(!1)){var a=5==(n=s(i)).a.length&&1===n.a[0];if(a){try{a=!s('"\t"')}catch(e){}if(a)try{a=1!==s("01")}catch(e){}if(a)try{a=1!==s("1.")}catch(e){}}}}catch(e){a=!1}t=a}}return f[e]=!!t}if(!f("json")){var h="[object Function]",k="[object Number]",A="[object String]",T="[object Array]",a=f("bug-string-char-index");if(!d)var j=i.floor,s=[0,31,59,90,120,151,181,212,243,273,304,334],C=function(e,t){return s[t]+365*(e-1970)+j((e-1969+(t=+(1>6|192):(t+=String.fromCharCode(i>>12|224),t+=String.fromCharCode(i>>6&63|128)),t+=String.fromCharCode(63&i|128))}return t},T=function(e){for(var t="",n=0,i=0,r=0,o=0;n>2,o=(3&t)<<4|(n=e.charCodeAt(c++))>>4,s=(15&n)<<2|(i=e.charCodeAt(c++))>>6,a=63&i,isNaN(n)?s=a=64:isNaN(i)&&(a=64),u=u+j._keyStr.charAt(r)+j._keyStr.charAt(o)+j._keyStr.charAt(s)+j._keyStr.charAt(a);return u},decode:function(e){try{if(window.btoa&&window.atob)return decodeURIComponent(escape(window.atob(e)))}catch(e){}return j._decode(e)},_decode:function(e){var t,n,i,r,o,s,a="",u=0;for(e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");u>4,n=(15&r)<<4|(o=j._keyStr.indexOf(e.charAt(u++)))>>2,i=(3&o)<<6|(s=j._keyStr.indexOf(e.charAt(u++))),a+=String.fromCharCode(t),64!==o&&(a+=String.fromCharCode(n)),64!==s&&(a+=String.fromCharCode(i));return a=T(a)}},C="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},P=Object.assign||function(e){for(var t=1;t=D.ERROR&&L(e)},warn:function(e){M>=D.WARN&&L(e)},info:function(e){M>=D.INFO&&L(e)}},L=function(e){try{console.log("[Amplitude] "+e)}catch(e){}},F=function(e){return"string"===q(e)&&e.length>t?e.substring(0,t):e},K=function(e){var t=q(e);if("object"!==t)return B.error("Error: invalid properties format. Expecting Javascript object, received "+t+", ignoring"),{};if(Object.keys(e).length>a)return B.error("Error: too many properties (more than 1000), ignoring"),{};var n={};for(var i in e)if(e.hasOwnProperty(i)){var r=i,o=q(r);"string"!==o&&(r=String(r),B.warn("WARNING: Non-string property key, received type "+o+', coercing to string "'+r+'"'));var s=G(r,e[i]);null!==s&&(n[r]=s)}return n},z=["null","nan","undefined","function","arguments","regexp","element"],G=function e(t,n){var i=q(n);if(-1!==z.indexOf(i))B.warn('WARNING: Property key "'+t+'" with invalid value type '+i+", ignoring"),n=null;else if("error"===i)n=String(n),B.warn('WARNING: Property key "'+t+'" with value type error, coercing to '+n);else if("array"===i){for(var r=[],o=0;o>16)+(t>>16)+(n>>16)<<16|65535&n}function a(e,t,n,i,r,o){return l((s=l(l(t,e),l(i,o)))<<(a=r)|s>>>32-a,n);var s,a}function d(e,t,n,i,r,o,s){return a(t&n|~t&i,e,t,r,o,s)}function f(e,t,n,i,r,o,s){return a(t&i|n&~i,e,t,r,o,s)}function h(e,t,n,i,r,o,s){return a(t^n^i,e,t,r,o,s)}function g(e,t,n,i,r,o,s){return a(n^(t|~i),e,t,r,o,s)}function u(e,t){var n,i,r,o,s;e[t>>5]|=128<>>9<<4)]=t;var a=1732584193,u=-271733879,c=-1732584194,p=271733878;for(n=0;n>5]>>>t%32&255);return n}function p(e){var t,n=[];for(n[(e.length>>2)-1]=void 0,t=0;t>5]|=(255&e.charCodeAt(t/8))<>>4&15)+i.charAt(15&t);return r}function n(e){return unescape(encodeURIComponent(e))}function r(e){return c(u(p(t=n(e)),8*t.length));var t}function o(e,t){return function(e,t){var n,i,r=p(e),o=[],s=[];for(o[15]=s[15]=void 0,16>t/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,e)}),ke="4.6.0",Ae={apiEndpoint:"api.amplitude.com",batchEvents:!1,cookieExpiration:3650,cookieName:"amplitude_id",deviceIdFromUrlParam:!1,domain:"",eventUploadPeriodMillis:3e4,eventUploadThreshold:30,forceHttps:!0,includeGclid:!1,includeReferrer:!1,includeUtm:!1,language:{language:navigator&&(navigator.languages&&navigator.languages[0]||navigator.language||navigator.userLanguage)||void 0}.language,logLevel:"WARN",optOut:!1,platform:"Web",savedMaxCount:1e3,saveEvents:!0,saveParamsReferrerOncePerSession:!0,secureCookie:!1,sessionTimeout:18e5,trackingOptions:{city:!0,country:!0,device_model:!0,dma:!0,ip_address:!0,language:!0,os_name:!0,os_version:!0,platform:!0,region:!0,version_name:!0},unsetParamsReferrerOnNewSession:!1,unsentKey:"amplitude_unsent",unsentIdentifyKey:"amplitude_unsent_identify",uploadBatchSize:100},Te=function(e){this._instanceName=$(e)?d:e.toLowerCase(),this._legacyStorageSuffix=this._instanceName===d?"":"_"+this._instanceName,this._unsentEvents=[],this._unsentIdentifys=[],this._ua=new Ne(navigator.userAgent).getResult(),this.options=P({},Ae,{trackingOptions:P({},Ae.trackingOptions)}),this.cookieStorage=(new de).getStorage(),this._q=[],this._sending=!1,this._updateScheduled=!1,this._eventId=0,this._identifyId=0,this._lastEventTime=null,this._newSession=!1,this._sequenceNumber=0,this._sessionId=null,this._userAgent=navigator&&navigator.userAgent||null};Te.prototype.Identify=he,Te.prototype.Revenue=Ee,Te.prototype.init=function(e,t,n,i){if("string"!==q(e)||$(e))V.error("Invalid apiKey. Please re-initialize with a valid apiKey");else try{this.options.apiKey=e,this._storageSuffix="_"+e+this._legacyStorageSuffix,je(this.options,n),"string"===q(this.options.logLevel)&&W(this.options.logLevel);var r=Be(this);if(this._apiPropertiesTrackingOptions=0this.options.sessionTimeout)&&(this.options.unsetParamsReferrerOnNewSession&&this._unsetUTMParams(),this._newSession=!0,this._sessionId=l,this.options.saveParamsReferrerOncePerSession&&this._trackParamsAndReferrer()),this.options.saveParamsReferrerOncePerSession||this._trackParamsAndReferrer(),this._lastEventTime=l,qe(this),this._sendEventsIfReady()}catch(e){V.error(e)}finally{"function"===q(i)&&i(this)}},Te.prototype._trackParamsAndReferrer=function(){this.options.includeUtm&&this._initUtmData(),this.options.includeReferrer&&this._saveReferrer(this._getReferrer()),this.options.includeGclid&&this._saveGclid(this._getUrlParams())};var je=function i(r,o){if("object"===q(o)){var e=function(e){if(r.hasOwnProperty(e)){var t=o[e],n=q(r[e]);Z(t,e+" option",n)&&("boolean"===n?r[e]=!!t:"string"===n&&!$(t)||"number"===n&&0=this.options.eventUploadThreshold?(this.sendEvents(e),!0):(this._updateScheduled||(this._updateScheduled=!0,setTimeout(function(){this._updateScheduled=!1,this.sendEvents()}.bind(this),this.options.eventUploadPeriodMillis)),!1):(this.sendEvents(e),!0))},Te.prototype._getFromStorage=function(e,t){return e.getItem(t+this._storageSuffix)},Te.prototype._getFromStorageLegacy=function(e,t){return e.getItem(t+this._legacyStorageSuffix)},Te.prototype._setInStorage=function(e,t,n){e.setItem(t+this._storageSuffix,n)};var Ce=function(e){var t=e.cookieStorage.get(e.options.cookieName+e._storageSuffix);if("object"!==q(t)&&!("object"===q(t=e.cookieStorage.get(e.options.cookieName+e._legacyStorageSuffix))&&t.deviceId&&t.sessionId&&t.lastEventTime)){var n=function(e){var t=le.getItem(e);return le.removeItem(e),t},i="string"===q(e.options.apiKey)&&"_"+e.options.apiKey.slice(0,6)||"",r=n(w+i),o=n(I+i),s=n(b+i);null!=s&&(s="true"===String(s));var a=parseInt(n(_)),u=parseInt(n(v)),c=parseInt(n(g)),p=parseInt(n(y)),l=parseInt(n(m)),d=function(e){return"object"===q(t)&&t[e]};e.options.deviceId=d("deviceId")||r,e.options.userId=d("userId")||o,e._sessionId=d("sessionId")||a||e._sessionId,e._lastEventTime=d("lastEventTime")||u||e._lastEventTime,e._eventId=d("eventId")||c||e._eventId,e._identifyId=d("identifyId")||p||e._identifyId,e._sequenceNumber=d("sequenceNumber")||l||e._sequenceNumber,e.options.optOut=s||!1,t&&void 0!==t.optOut&&null!==t.optOut&&(e.options.optOut="true"===String(t.optOut)),qe(e)}},Pe=function(e){var t=e.cookieStorage.get(e.options.cookieName+e._storageSuffix);if("object"===q(t))Re(e,t);else{var n=e.cookieStorage.get(e.options.cookieName+e._legacyStorageSuffix);"object"===q(n)&&(e.cookieStorage.remove(e.options.cookieName+e._legacyStorageSuffix),Re(e,n))}},Re=function(e,t){t.deviceId&&(e.options.deviceId=t.deviceId),t.userId&&(e.options.userId=t.userId),null!==t.optOut&&void 0!==t.optOut&&(e.options.optOut=t.optOut),t.sessionId&&(e._sessionId=parseInt(t.sessionId)),t.lastEventTime&&(e._lastEventTime=parseInt(t.lastEventTime)),t.eventId&&(e._eventId=parseInt(t.eventId)),t.identifyId&&(e._identifyId=parseInt(t.identifyId)),t.sequenceNumber&&(e._sequenceNumber=parseInt(t.sequenceNumber))},qe=function(e){e.cookieStorage.set(e.options.cookieName+e._storageSuffix,{deviceId:e.options.deviceId,userId:e.options.userId,optOut:e.options.optOut,sessionId:e._sessionId,lastEventTime:e._lastEventTime,eventId:e._eventId,identifyId:e._identifyId,sequenceNumber:e._sequenceNumber})};Te.prototype._initUtmData=function(e,t){e=e||this._getUrlParams(),t=t||this.cookieStorage.get("__utmz");var n,i,r,o,s,a,u,c,p,l,d,f=(i=e,r=(n=t)?"?"+n.split(".").slice(-1)[0].replace(/\|/g,"&"):"",s=(o=function(e,t,n,i){return X(e,t)||X(n,i)})(O,i,"utmcsr",r),a=o(E,i,"utmcmd",r),u=o(N,i,"utmccn",r),c=o(x,i,"utmctr",r),p=o(k,i,"utmcct",r),l={},(d=function(e,t){$(t)||(l[e]=t)})(O,s),d(E,a),d(N,u),d(x,c),d(k,p),l);Ue(this,f)},Te.prototype._unsetUTMParams=function(){var e=new he;e.unset(S),e.unset(O),e.unset(E),e.unset(N),e.unset(x),e.unset(k),this.identify(e)};var Ue=function(e,t){if("object"===q(t)&&0!==Object.keys(t).length){var n=new he;for(var i in t)t.hasOwnProperty(i)&&(n.setOnce("initial_"+i,t[i]),n.set(i,t[i]));e.identify(n)}};Te.prototype._getReferrer=function(){return document.referrer},Te.prototype._getUrlParams=function(){return location.search},Te.prototype._saveGclid=function(e){var t=X("gclid",e);$(t)||Ue(this,{gclid:t})},Te.prototype._getDeviceIdFromUrlParam=function(e){return X(l,e)},Te.prototype._getReferringDomain=function(e){if($(e))return null;var t=e.split("/");return 3<=t.length?t[2]:null},Te.prototype._saveReferrer=function(e){if(!$(e)){var t={referrer:e,referring_domain:this._getReferringDomain(e)};Ue(this,t)}},Te.prototype.saveEvents=function(){try{this._setInStorage(le,this.options.unsentKey,JSON.stringify(this._unsentEvents))}catch(e){}try{this._setInStorage(le,this.options.unsentIdentifyKey,JSON.stringify(this._unsentIdentifys))}catch(e){}},Te.prototype.setDomain=function(e){if(Z(e,"domain","string"))try{this.cookieStorage.options({domain:e}),this.options.domain=this.cookieStorage.options().domain,Pe(this),qe(this)}catch(e){V.error(e)}},Te.prototype.setUserId=function(e){try{this.options.userId=null!=e&&""+e||null,qe(this)}catch(e){V.error(e)}},Te.prototype.setGroup=function(e,t){if(this._apiKeySet("setGroup()")&&Z(e,"groupType","string")&&!$(e)){var n={};n[e]=t;var i=(new he).set(e,t);this._logEvent(f,null,null,i.userPropertiesOperations,n,null,null,null)}},Te.prototype.setOptOut=function(e){if(Z(e,"enable","boolean"))try{this.options.optOut=e,qe(this)}catch(e){V.error(e)}},Te.prototype.setSessionId=function(e){if(Z(e,"sessionId","number"))try{this._sessionId=e,qe(this)}catch(e){V.error(e)}},Te.prototype.resetSessionId=function(){this.setSessionId((new Date).getTime())},Te.prototype.regenerateDeviceId=function(){this.setDeviceId(xe()+"R")},Te.prototype.setDeviceId=function(e){if(Z(e,"deviceId","string"))try{$(e)||(this.options.deviceId=""+e,qe(this))}catch(e){V.error(e)}},Te.prototype.setUserProperties=function(e){if(this._apiKeySet("setUserProperties()")&&Z(e,"userProperties","object")){var t=H(Y(e));if(0!==Object.keys(t).length){var n=new he;for(var i in t)t.hasOwnProperty(i)&&n.set(i,t[i]);this.identify(n)}}},Te.prototype.clearUserProperties=function(){if(this._apiKeySet("clearUserProperties()")){var e=new he;e.clearAll(),this.identify(e)}};var De=function(e,t){for(var n=0;nthis.options.sessionTimeout)&&(this._sessionId=p),this._lastEventTime=p,qe(this),i=i||{};var l=P({},this._apiPropertiesTrackingOptions);n=P({},n||{},l),t=t||{},r=r||{},o=o||{};var d={device_id:this.options.deviceId,user_id:this.options.userId,timestamp:p,event_id:u,session_id:this._sessionId||-1,event_type:e,version_name:Me(this,"version_name")&&this.options.versionName||null,platform:Me(this,"platform")?this.options.platform:null,os_name:Me(this,"os_name")&&this._ua.browser.name||null,os_version:Me(this,"os_version")&&this._ua.browser.major||null,device_model:Me(this,"device_model")&&this._ua.os.name||null,language:Me(this,"language")?this.options.language:null,api_properties:n,event_properties:H(Y(t)),user_properties:H(Y(i)),uuid:xe(),library:{name:"amplitude-js",version:ke},sequence_number:c,groups:H(Q(r)),group_properties:H(Y(o)),user_agent:this._userAgent};return e===f||e===h?(this._unsentIdentifys.push(d),this._limitEventsQueued(this._unsentIdentifys)):(this._unsentEvents.push(d),this._limitEventsQueued(this._unsentEvents)),this.options.saveEvents&&this.saveEvents(),this._sendEventsIfReady(a)||"function"!==q(a)||a(0,"No request sent",{reason:"No events to send or upload queued"}),u}catch(e){V.error(e)}else"function"===q(a)&&a(0,"No request sent",{reason:"Missing eventType"})};var Me=function(e,t){return!!e.options.trackingOptions[t]},Be=function(e){for(var t=["city","country","dma","ip_address","region"],n={},i=0;ithis.options.savedMaxCount&&e.splice(0,e.length-this.options.savedMaxCount)},Te.prototype.logEvent=function(e,t,n){return this.logEventWithTimestamp(e,t,null,n)},Te.prototype.logEventWithTimestamp=function(e,t,n,i){return this._apiKeySet("logEvent()")?Z(e,"eventType","string")?$(e)?("function"===q(i)&&i(0,"No request sent",{reason:"Missing eventType"}),-1):this._logEvent(e,t,null,null,null,null,n,i):("function"===q(i)&&i(0,"No request sent",{reason:"Invalid type for eventType"}),-1):("function"===q(i)&&i(0,"No request sent",{reason:"API key not set"}),-1)},Te.prototype.logEventWithGroups=function(e,t,n,i){return this._apiKeySet("logEventWithGroups()")?Z(e,"eventType","string")?this._logEvent(e,t,null,null,n,null,null,i):("function"===q(i)&&i(0,"No request sent",{reason:"Invalid type for eventType"}),-1):("function"===q(i)&&i(0,"No request sent",{reason:"API key not set"}),-1)};var Le=function(e){return!isNaN(parseFloat(e))&&isFinite(e)};Te.prototype.logRevenueV2=function(e){if(this._apiKeySet("logRevenueV2()"))if("object"===q(e)&&e.hasOwnProperty("_q")&&(e=De(new Ee,e)),e instanceof Ee){if(e&&e._isValidRevenue())return this.logEvent(i,e._toJSONObject())}else V.error("Invalid revenue input type. Expected Revenue object but saw "+q(e))},Te.prototype.logRevenue=function(e,t,n){return this._apiKeySet("logRevenue()")&&Le(e)&&(void 0===t||Le(t))?this._logEvent(i,{},{productId:n,special:"revenue_amount",quantity:t||1,price:e},null,null,null,null,null):-1},Te.prototype.removeEvents=function(e,t){Fe(this,"_unsentEvents",e),Fe(this,"_unsentIdentifys",t)};var Fe=function(e,t,n){if(!(n<0)){for(var i=[],r=0;rn&&i.push(e[t][r]);e[t]=i}};Te.prototype.sendEvents=function(n){if(this._apiKeySet("sendEvents()"))if(this.options.optOut)"function"===q(n)&&n(0,"No request sent",{reason:"optOut is set to true"});else if(0!==this._unsentCount())if(this._sending)"function"===q(n)&&n(0,"No request sent",{reason:"Request already in progress"});else{this._sending=!0;var e=(this.options.forceHttps?"https":"https:"===window.location.protocol?"https":"http")+"://"+this.options.apiEndpoint+"/",i=Math.min(this._unsentCount(),this.options.uploadBatchSize),t=this._mergeEventsAndIdentifys(i),r=t.maxEventId,o=t.maxIdentifyId,s=JSON.stringify(t.eventsToSend),a=(new Date).getTime(),u={client:this.options.apiKey,e:s,v:p,upload_time:a,checksum:ge(p+this.options.apiKey+s+a)},c=this;new Oe(e,u).send(function(e,t){c._sending=!1;try{200===e&&"success"===t?(c.removeEvents(r,o),c.options.saveEvents&&c.saveEvents(),c._sendEventsIfReady(n)||"function"!==q(n)||n(e,t)):413===e?(1===c.options.uploadBatchSize&&c.removeEvents(r,o),c.options.uploadBatchSize=Math.ceil(i/2),c.sendEvents(n)):"function"===q(n)&&n(e,t)}catch(e){}})}else"function"===q(n)&&n(0,"No request sent",{reason:"No events to send"});else"function"===q(n)&&n(0,"No request sent",{reason:"API key not set"})},Te.prototype._mergeEventsAndIdentifys=function(e){for(var t=[],n=0,i=-1,r=0,o=-1;t.length=this._unsentIdentifys.length,u=n>=this._unsentEvents.length;if(u&&a){V.error("Merging Events and Identifys, less events and identifys than expected");break}a?i=(s=this._unsentEvents[n++]).event_id:u?o=(s=this._unsentIdentifys[r++]).event_id:!("sequence_number"in this._unsentEvents[n])||this._unsentEvents[n].sequence_number>6|192):(t+=String.fromCharCode(i>>12|224),t+=String.fromCharCode(i>>6&63|128)),t+=String.fromCharCode(63&i|128))}return t},T=function(e){for(var t="",n=0,i=0,r=0,o=0;n>2,o=(3&t)<<4|(n=e.charCodeAt(c++))>>4,s=(15&n)<<2|(i=e.charCodeAt(c++))>>6,a=63&i,isNaN(n)?s=a=64:isNaN(i)&&(a=64),u=u+j._keyStr.charAt(r)+j._keyStr.charAt(o)+j._keyStr.charAt(s)+j._keyStr.charAt(a);return u},decode:function(e){try{if(window.btoa&&window.atob)return decodeURIComponent(escape(window.atob(e)))}catch(e){}return j._decode(e)},_decode:function(e){var t,n,i,r,o,s,a="",u=0;for(e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");u>4,n=(15&r)<<4|(o=j._keyStr.indexOf(e.charAt(u++)))>>2,i=(3&o)<<6|(s=j._keyStr.indexOf(e.charAt(u++))),a+=String.fromCharCode(t),64!==o&&(a+=String.fromCharCode(n)),64!==s&&(a+=String.fromCharCode(i));return a=T(a)}},C="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},P=Object.assign||function(e){for(var t=1;t=D.ERROR&&L(e)},warn:function(e){M>=D.WARN&&L(e)},info:function(e){M>=D.INFO&&L(e)}},L=function(e){try{console.log("[Amplitude] "+e)}catch(e){}},F=function(e){return"string"===q(e)&&e.length>t?e.substring(0,t):e},K=function(e){var t=q(e);if("object"!==t)return B.error("Error: invalid properties format. Expecting Javascript object, received "+t+", ignoring"),{};if(Object.keys(e).length>a)return B.error("Error: too many properties (more than 1000), ignoring"),{};var n={};for(var i in e)if(e.hasOwnProperty(i)){var r=i,o=q(r);"string"!==o&&(r=String(r),B.warn("WARNING: Non-string property key, received type "+o+', coercing to string "'+r+'"'));var s=G(r,e[i]);null!==s&&(n[r]=s)}return n},z=["null","nan","undefined","function","arguments","regexp","element"],G=function e(t,n){var i=q(n);if(-1!==z.indexOf(i))B.warn('WARNING: Property key "'+t+'" with invalid value type '+i+", ignoring"),n=null;else if("error"===i)n=String(n),B.warn('WARNING: Property key "'+t+'" with value type error, coercing to '+n);else if("array"===i){for(var r=[],o=0;o>16)+(t>>16)+(n>>16)<<16|65535&n}function a(e,t,n,i,r,o){return l((s=l(l(t,e),l(i,o)))<<(a=r)|s>>>32-a,n);var s,a}function d(e,t,n,i,r,o,s){return a(t&n|~t&i,e,t,r,o,s)}function f(e,t,n,i,r,o,s){return a(t&i|n&~i,e,t,r,o,s)}function h(e,t,n,i,r,o,s){return a(t^n^i,e,t,r,o,s)}function g(e,t,n,i,r,o,s){return a(n^(t|~i),e,t,r,o,s)}function u(e,t){var n,i,r,o,s;e[t>>5]|=128<>>9<<4)]=t;var a=1732584193,u=-271733879,c=-1732584194,p=271733878;for(n=0;n>5]>>>t%32&255);return n}function p(e){var t,n=[];for(n[(e.length>>2)-1]=void 0,t=0;t>5]|=(255&e.charCodeAt(t/8))<>>4&15)+i.charAt(15&t);return r}function n(e){return unescape(encodeURIComponent(e))}function r(e){return c(u(p(t=n(e)),8*t.length));var t}function o(e,t){return function(e,t){var n,i,r=p(e),o=[],s=[];for(o[15]=s[15]=void 0,16>t/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,e)}),ke="4.7.0",Ae={apiEndpoint:"api.amplitude.com",batchEvents:!1,cookieExpiration:3650,cookieName:"amplitude_id",deviceIdFromUrlParam:!1,domain:"",eventUploadPeriodMillis:3e4,eventUploadThreshold:30,forceHttps:!0,includeGclid:!1,includeReferrer:!1,includeUtm:!1,language:{language:navigator&&(navigator.languages&&navigator.languages[0]||navigator.language||navigator.userLanguage)||void 0}.language,logLevel:"WARN",optOut:!1,platform:"Web",savedMaxCount:1e3,saveEvents:!0,saveParamsReferrerOncePerSession:!0,secureCookie:!1,sessionTimeout:18e5,trackingOptions:{city:!0,country:!0,device_model:!0,dma:!0,ip_address:!0,language:!0,os_name:!0,os_version:!0,platform:!0,region:!0,version_name:!0},unsetParamsReferrerOnNewSession:!1,unsentKey:"amplitude_unsent",unsentIdentifyKey:"amplitude_unsent_identify",uploadBatchSize:100},Te=function(e){this._instanceName=$(e)?f:e.toLowerCase(),this._legacyStorageSuffix=this._instanceName===f?"":"_"+this._instanceName,this._unsentEvents=[],this._unsentIdentifys=[],this._ua=new Ne(navigator.userAgent).getResult(),this.options=P({},Ae,{trackingOptions:P({},Ae.trackingOptions)}),this.cookieStorage=(new de).getStorage(),this._q=[],this._sending=!1,this._updateScheduled=!1,this._onInit=[],this._eventId=0,this._identifyId=0,this._lastEventTime=null,this._newSession=!1,this._sequenceNumber=0,this._sessionId=null,this._userAgent=navigator&&navigator.userAgent||null};Te.prototype.Identify=he,Te.prototype.Revenue=Ee,Te.prototype.init=function(e,t,n,i){if("string"!==q(e)||$(e))V.error("Invalid apiKey. Please re-initialize with a valid apiKey");else{try{this.options.apiKey=e,this._storageSuffix="_"+e+this._legacyStorageSuffix,je(this.options,n),"string"===q(this.options.logLevel)&&W(this.options.logLevel);var r=Be(this);if(this._apiPropertiesTrackingOptions=0this.options.sessionTimeout)&&(this.options.unsetParamsReferrerOnNewSession&&this._unsetUTMParams(),this._newSession=!0,this._sessionId=l,this.options.saveParamsReferrerOncePerSession&&this._trackParamsAndReferrer()),this.options.saveParamsReferrerOncePerSession||this._trackParamsAndReferrer(),this._lastEventTime=l,qe(this),this._sendEventsIfReady()}catch(e){V.error(e)}finally{"function"===q(i)&&i(this)}for(var d=0;d=this.options.eventUploadThreshold?(this.sendEvents(e),!0):(this._updateScheduled||(this._updateScheduled=!0,setTimeout(function(){this._updateScheduled=!1,this.sendEvents()}.bind(this),this.options.eventUploadPeriodMillis)),!1):(this.sendEvents(e),!0))},Te.prototype._getFromStorage=function(e,t){return e.getItem(t+this._storageSuffix)},Te.prototype._getFromStorageLegacy=function(e,t){return e.getItem(t+this._legacyStorageSuffix)},Te.prototype._setInStorage=function(e,t,n){e.setItem(t+this._storageSuffix,n)};var Ce=function(e){var t=e.cookieStorage.get(e.options.cookieName+e._storageSuffix);if("object"!==q(t)&&!("object"===q(t=e.cookieStorage.get(e.options.cookieName+e._legacyStorageSuffix))&&t.deviceId&&t.sessionId&&t.lastEventTime)){var n=function(e){var t=le.getItem(e);return le.removeItem(e),t},i="string"===q(e.options.apiKey)&&"_"+e.options.apiKey.slice(0,6)||"",r=n(b+i),o=n(S+i),s=n(I+i);null!=s&&(s="true"===String(s));var a=parseInt(n(w)),u=parseInt(n(y)),c=parseInt(n(v)),p=parseInt(n(m)),l=parseInt(n(_)),d=function(e){return"object"===q(t)&&t[e]};e.options.deviceId=d("deviceId")||r,e.options.userId=d("userId")||o,e._sessionId=d("sessionId")||a||e._sessionId,e._lastEventTime=d("lastEventTime")||u||e._lastEventTime,e._eventId=d("eventId")||c||e._eventId,e._identifyId=d("identifyId")||p||e._identifyId,e._sequenceNumber=d("sequenceNumber")||l||e._sequenceNumber,e.options.optOut=s||!1,t&&void 0!==t.optOut&&null!==t.optOut&&(e.options.optOut="true"===String(t.optOut)),qe(e)}},Pe=function(e){var t=e.cookieStorage.get(e.options.cookieName+e._storageSuffix);if("object"===q(t))Re(e,t);else{var n=e.cookieStorage.get(e.options.cookieName+e._legacyStorageSuffix);"object"===q(n)&&(e.cookieStorage.remove(e.options.cookieName+e._legacyStorageSuffix),Re(e,n))}},Re=function(e,t){t.deviceId&&(e.options.deviceId=t.deviceId),t.userId&&(e.options.userId=t.userId),null!==t.optOut&&void 0!==t.optOut&&(e.options.optOut=t.optOut),t.sessionId&&(e._sessionId=parseInt(t.sessionId)),t.lastEventTime&&(e._lastEventTime=parseInt(t.lastEventTime)),t.eventId&&(e._eventId=parseInt(t.eventId)),t.identifyId&&(e._identifyId=parseInt(t.identifyId)),t.sequenceNumber&&(e._sequenceNumber=parseInt(t.sequenceNumber))},qe=function(e){e.cookieStorage.set(e.options.cookieName+e._storageSuffix,{deviceId:e.options.deviceId,userId:e.options.userId,optOut:e.options.optOut,sessionId:e._sessionId,lastEventTime:e._lastEventTime,eventId:e._eventId,identifyId:e._identifyId,sequenceNumber:e._sequenceNumber})};Te.prototype._initUtmData=function(e,t){e=e||this._getUrlParams(),t=t||this.cookieStorage.get("__utmz");var n,i,r,o,s,a,u,c,p,l,d,f=(i=e,r=(n=t)?"?"+n.split(".").slice(-1)[0].replace(/\|/g,"&"):"",s=(o=function(e,t,n,i){return X(e,t)||X(n,i)})(O,i,"utmcsr",r),a=o(E,i,"utmcmd",r),u=o(N,i,"utmccn",r),c=o(x,i,"utmctr",r),p=o(k,i,"utmcct",r),l={},(d=function(e,t){$(t)||(l[e]=t)})(O,s),d(E,a),d(N,u),d(x,c),d(k,p),l);Ue(this,f)},Te.prototype._unsetUTMParams=function(){var e=new he;e.unset(d),e.unset(O),e.unset(E),e.unset(N),e.unset(x),e.unset(k),this.identify(e)};var Ue=function(e,t){if("object"===q(t)&&0!==Object.keys(t).length){var n=new he;for(var i in t)t.hasOwnProperty(i)&&(n.setOnce("initial_"+i,t[i]),n.set(i,t[i]));e.identify(n)}};Te.prototype._getReferrer=function(){return document.referrer},Te.prototype._getUrlParams=function(){return location.search},Te.prototype._saveGclid=function(e){var t=X("gclid",e);$(t)||Ue(this,{gclid:t})},Te.prototype._getDeviceIdFromUrlParam=function(e){return X(l,e)},Te.prototype._getReferringDomain=function(e){if($(e))return null;var t=e.split("/");return 3<=t.length?t[2]:null},Te.prototype._saveReferrer=function(e){if(!$(e)){var t={referrer:e,referring_domain:this._getReferringDomain(e)};Ue(this,t)}},Te.prototype.saveEvents=function(){try{this._setInStorage(le,this.options.unsentKey,JSON.stringify(this._unsentEvents))}catch(e){}try{this._setInStorage(le,this.options.unsentIdentifyKey,JSON.stringify(this._unsentIdentifys))}catch(e){}},Te.prototype.setDomain=function(e){if(Z(e,"domain","string"))try{this.cookieStorage.options({domain:e}),this.options.domain=this.cookieStorage.options().domain,Pe(this),qe(this)}catch(e){V.error(e)}},Te.prototype.setUserId=function(e){try{this.options.userId=null!=e&&""+e||null,qe(this)}catch(e){V.error(e)}},Te.prototype.setGroup=function(e,t){if(this._apiKeySet("setGroup()")&&Z(e,"groupType","string")&&!$(e)){var n={};n[e]=t;var i=(new he).set(e,t);this._logEvent(h,null,null,i.userPropertiesOperations,n,null,null,null)}},Te.prototype.setOptOut=function(e){if(Z(e,"enable","boolean"))try{this.options.optOut=e,qe(this)}catch(e){V.error(e)}},Te.prototype.setSessionId=function(e){if(Z(e,"sessionId","number"))try{this._sessionId=e,qe(this)}catch(e){V.error(e)}},Te.prototype.resetSessionId=function(){this.setSessionId((new Date).getTime())},Te.prototype.regenerateDeviceId=function(){this.setDeviceId(xe()+"R")},Te.prototype.setDeviceId=function(e){if(Z(e,"deviceId","string"))try{$(e)||(this.options.deviceId=""+e,qe(this))}catch(e){V.error(e)}},Te.prototype.setUserProperties=function(e){if(this._apiKeySet("setUserProperties()")&&Z(e,"userProperties","object")){var t=H(Y(e));if(0!==Object.keys(t).length){var n=new he;for(var i in t)t.hasOwnProperty(i)&&n.set(i,t[i]);this.identify(n)}}},Te.prototype.clearUserProperties=function(){if(this._apiKeySet("clearUserProperties()")){var e=new he;e.clearAll(),this.identify(e)}};var De=function(e,t){for(var n=0;nthis.options.sessionTimeout)&&(this._sessionId=p),this._lastEventTime=p,qe(this),i=i||{};var l=P({},this._apiPropertiesTrackingOptions);n=P({},n||{},l),t=t||{},r=r||{},o=o||{};var d={device_id:this.options.deviceId,user_id:this.options.userId,timestamp:p,event_id:u,session_id:this._sessionId||-1,event_type:e,version_name:Me(this,"version_name")&&this.options.versionName||null,platform:Me(this,"platform")?this.options.platform:null,os_name:Me(this,"os_name")&&this._ua.browser.name||null,os_version:Me(this,"os_version")&&this._ua.browser.major||null,device_model:Me(this,"device_model")&&this._ua.os.name||null,language:Me(this,"language")?this.options.language:null,api_properties:n,event_properties:H(Y(t)),user_properties:H(Y(i)),uuid:xe(),library:{name:"amplitude-js",version:ke},sequence_number:c,groups:H(Q(r)),group_properties:H(Y(o)),user_agent:this._userAgent};return e===h||e===g?(this._unsentIdentifys.push(d),this._limitEventsQueued(this._unsentIdentifys)):(this._unsentEvents.push(d),this._limitEventsQueued(this._unsentEvents)),this.options.saveEvents&&this.saveEvents(),this._sendEventsIfReady(a)||"function"!==q(a)||a(0,"No request sent",{reason:"No events to send or upload queued"}),u}catch(e){V.error(e)}else"function"===q(a)&&a(0,"No request sent",{reason:"Missing eventType"})};var Me=function(e,t){return!!e.options.trackingOptions[t]},Be=function(e){for(var t=["city","country","dma","ip_address","region"],n={},i=0;ithis.options.savedMaxCount&&e.splice(0,e.length-this.options.savedMaxCount)},Te.prototype.logEvent=function(e,t,n){return this.logEventWithTimestamp(e,t,null,n)},Te.prototype.logEventWithTimestamp=function(e,t,n,i){return this._apiKeySet("logEvent()")?Z(e,"eventType","string")?$(e)?("function"===q(i)&&i(0,"No request sent",{reason:"Missing eventType"}),-1):this._logEvent(e,t,null,null,null,null,n,i):("function"===q(i)&&i(0,"No request sent",{reason:"Invalid type for eventType"}),-1):("function"===q(i)&&i(0,"No request sent",{reason:"API key not set"}),-1)},Te.prototype.logEventWithGroups=function(e,t,n,i){return this._apiKeySet("logEventWithGroups()")?Z(e,"eventType","string")?this._logEvent(e,t,null,null,n,null,null,i):("function"===q(i)&&i(0,"No request sent",{reason:"Invalid type for eventType"}),-1):("function"===q(i)&&i(0,"No request sent",{reason:"API key not set"}),-1)};var Le=function(e){return!isNaN(parseFloat(e))&&isFinite(e)};Te.prototype.logRevenueV2=function(e){if(this._apiKeySet("logRevenueV2()"))if("object"===q(e)&&e.hasOwnProperty("_q")&&(e=De(new Ee,e)),e instanceof Ee){if(e&&e._isValidRevenue())return this.logEvent(i,e._toJSONObject())}else V.error("Invalid revenue input type. Expected Revenue object but saw "+q(e))},Te.prototype.logRevenue=function(e,t,n){return this._apiKeySet("logRevenue()")&&Le(e)&&(void 0===t||Le(t))?this._logEvent(i,{},{productId:n,special:"revenue_amount",quantity:t||1,price:e},null,null,null,null,null):-1},Te.prototype.removeEvents=function(e,t){Fe(this,"_unsentEvents",e),Fe(this,"_unsentIdentifys",t)};var Fe=function(e,t,n){if(!(n<0)){for(var i=[],r=0;rn&&i.push(e[t][r]);e[t]=i}};Te.prototype.sendEvents=function(n){if(this._apiKeySet("sendEvents()"))if(this.options.optOut)"function"===q(n)&&n(0,"No request sent",{reason:"optOut is set to true"});else if(0!==this._unsentCount())if(this._sending)"function"===q(n)&&n(0,"No request sent",{reason:"Request already in progress"});else{this._sending=!0;var e=(this.options.forceHttps?"https":"https:"===window.location.protocol?"https":"http")+"://"+this.options.apiEndpoint+"/",i=Math.min(this._unsentCount(),this.options.uploadBatchSize),t=this._mergeEventsAndIdentifys(i),r=t.maxEventId,o=t.maxIdentifyId,s=JSON.stringify(t.eventsToSend),a=(new Date).getTime(),u={client:this.options.apiKey,e:s,v:p,upload_time:a,checksum:ge(p+this.options.apiKey+s+a)},c=this;new Oe(e,u).send(function(e,t){c._sending=!1;try{200===e&&"success"===t?(c.removeEvents(r,o),c.options.saveEvents&&c.saveEvents(),c._sendEventsIfReady(n)||"function"!==q(n)||n(e,t)):413===e?(1===c.options.uploadBatchSize&&c.removeEvents(r,o),c.options.uploadBatchSize=Math.ceil(i/2),c.sendEvents(n)):"function"===q(n)&&n(e,t)}catch(e){}})}else"function"===q(n)&&n(0,"No request sent",{reason:"No events to send"});else"function"===q(n)&&n(0,"No request sent",{reason:"API key not set"})},Te.prototype._mergeEventsAndIdentifys=function(e){for(var t=[],n=0,i=-1,r=0,o=-1;t.length=this._unsentIdentifys.length,u=n>=this._unsentEvents.length;if(u&&a){V.error("Merging Events and Identifys, less events and identifys than expected");break}a?i=(s=this._unsentEvents[n++]).event_id:u?o=(s=this._unsentIdentifys[r++]).event_id:!("sequence_number"in this._unsentEvents[n])||this._unsentEvents[n].sequence_number", - "version": "4.6.0", + "version": "4.7.0", "license": "MIT", "description": "Javascript library for Amplitude Analytics", "keywords": [ diff --git a/src/amplitude-client.js b/src/amplitude-client.js index c3cb518e..c48e022a 100644 --- a/src/amplitude-client.js +++ b/src/amplitude-client.js @@ -31,6 +31,7 @@ var AmplitudeClient = function AmplitudeClient(instanceName) { this._q = []; // queue for proxied functions before script load this._sending = false; this._updateScheduled = false; + this._onInit = []; // event meta data this._eventId = 0; @@ -149,6 +150,10 @@ AmplitudeClient.prototype.init = function init(apiKey, opt_userId, opt_config, o opt_callback(this); } } + + for (let i = 0; i < this._onInit.length; i++) { + this._onInit[i](); + } }; /** @@ -285,6 +290,14 @@ AmplitudeClient.prototype.isNewSession = function isNewSession() { return this._newSession; }; +/** + * Store callbacks to call after init + * @private + */ +AmplitudeClient.prototype.onInit = function (callback) { + this._onInit.push(callback); +}; + /** * Returns the id of the current session. * @public diff --git a/src/amplitude-snippet.js b/src/amplitude-snippet.js index 1702d408..2a092f88 100644 --- a/src/amplitude-snippet.js +++ b/src/amplitude-snippet.js @@ -3,7 +3,7 @@ var as = document.createElement('script'); as.type = 'text/javascript'; as.async = true; - as.src = 'https://cdn.amplitude.com/libs/amplitude-4.6.0-min.gz.js'; + as.src = 'https://cdn.amplitude.com/libs/amplitude-4.7.0-min.gz.js'; as.onload = function() {if(window.amplitude.runQueuedFunctions) {window.amplitude.runQueuedFunctions();} else {console.log('[Amplitude] Error: could not load SDK');}}; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(as, s); diff --git a/src/version.js b/src/version.js index 21421399..b0add3fb 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -export default '4.6.0'; +export default '4.7.0'; diff --git a/test/amplitude-client.js b/test/amplitude-client.js index 5720f05b..fa306a81 100644 --- a/test/amplitude-client.js +++ b/test/amplitude-client.js @@ -54,6 +54,17 @@ describe('AmplitudeClient', function() { assert.equal(new AmplitudeClient('$DEFAULT_INSTANCE')._instanceName, '$default_instance'); }); + it('should invoke onInit callbacks', function() { + let onInitCalled = false; + let onInit2Called = false; + amplitude.onInit(() => { onInitCalled = true; }); + amplitude.onInit(() => { onInit2Called = true; }); + + amplitude.init(apiKey); + assert.ok(onInitCalled); + assert.ok(onInit2Called); + }); + it('fails on invalid apiKeys', function() { amplitude.init(null); assert.equal(amplitude.options.apiKey, undefined);