"Types" property not available in browser SDK before main library loads
salomoneb opened this issue · 0 comments
Expected Behavior
amplitude.Types
should be immediately defined after the browser SDK snippet is inserted. Example:
<script type="text/javascript">
!function(){"use strict";!function(e,t){var r=e.amplitude||{_q:[],_iq:{}};if(r.invoked)e.console&&console.error&&console.error("Amplitude snippet has been loaded.");else{var n=function(e,t){e.prototype[t]=function(){return this._q.push({name:t,args:Array.prototype.slice.call(arguments,0)}),this}},s=function(e,t,r){return function(n){e._q.push({name:t,args:Array.prototype.slice.call(r,0),resolve:n})}},o=function(e,t,r){e._q.push({name:t,args:Array.prototype.slice.call(r,0)})},i=function(e,t,r){e[t]=function(){if(r)return{promise:new Promise(s(e,t,Array.prototype.slice.call(arguments)))};o(e,t,Array.prototype.slice.call(arguments))}},a=function(e){for(var t=0;t<g.length;t++)i(e,g[t],!1);for(var r=0;r<m.length;r++)i(e,m[r],!0)};r.invoked=!0;var c=t.createElement("script");c.type="text/javascript",c.integrity="sha384-Dv01ylQWH3OMRpOnXgNXTEJypJSg/Si512H2KxfFik12c676LxjHoC1W2pF8xyR5",c.crossOrigin="anonymous",c.async=!0,c.src="https://cdn.amplitude.com/libs/analytics-browser-2.6.0-min.js.gz",c.onload=function(){e.amplitude.runQueuedFunctions||console.log("[Amplitude] Error: could not load SDK")};var u=t.getElementsByTagName("script")[0];u.parentNode.insertBefore(c,u);for(var p=function(){return this._q=[],this},l=["add","append","clearAll","prepend","set","setOnce","unset","preInsert","postInsert","remove","getUserProperties"],d=0;d<l.length;d++)n(p,l[d]);r.Identify=p;for(var f=function(){return this._q=[],this},v=["getEventProperties","setProductId","setQuantity","setPrice","setRevenue","setRevenueType","setEventProperties"],y=0;y<v.length;y++)n(f,v[y]);r.Revenue=f;var g=["getDeviceId","setDeviceId","getSessionId","setSessionId","getUserId","setUserId","setOptOut","setTransport","reset","extendSession"],m=["init","add","remove","track","logEvent","identify","groupIdentify","setGroup","revenue","flush"];a(r),r.createInstance=function(e){return r._iq[e]={_q:[]},a(r._iq[e]),r._iq[e]},e.amplitude=r}}(window,document)}(); // eslint-disable-line
console.log(amplitude) // typeof amplitude.Types should not equal undefined
amplitude.init("<YOUR_API_KEY>");
</script>
Current Behavior
amplitude.Types
is undefined
right below the browser SDK snippet and remains undefined
until the Amplitude library injected by the snippet is loaded. My team discovered this when we tried to do something like:
const configOptions = {
logLevel: window.amplitude.Types.LogLevel[<string passed in through env variable, e.g. "Debug">],
defaultTracking: false,
};
amplitude.init(<key>, null, configOptions);
Our code fails the first (and only the first) time this runs. This seems to be because the amplitude
object properties are stubbed prior to the Amplitude library loading. However, the Types
property does not appear to stubbed with the other expected properties.
On subsequent page loads, our code runs fine because the browser has cached the Amplitude library script (which loaded on the previous page load) and the amplitude
object is fully hydrated immediately.
Possible Solution
Stub Types
in amplitude-snippet.js
so that the property is available before the library loads.
Steps to Reproduce
- In a clean Chrome browser profile (it's important that you're in a window where the Amplitude library file hasn't been cached), add the following code:
<script type="text/javascript">
!function(){"use strict";!function(e,t){var r=e.amplitude||{_q:[],_iq:{}};if(r.invoked)e.console&&console.error&&console.error("Amplitude snippet has been loaded.");else{var n=function(e,t){e.prototype[t]=function(){return this._q.push({name:t,args:Array.prototype.slice.call(arguments,0)}),this}},s=function(e,t,r){return function(n){e._q.push({name:t,args:Array.prototype.slice.call(r,0),resolve:n})}},o=function(e,t,r){e._q.push({name:t,args:Array.prototype.slice.call(r,0)})},i=function(e,t,r){e[t]=function(){if(r)return{promise:new Promise(s(e,t,Array.prototype.slice.call(arguments)))};o(e,t,Array.prototype.slice.call(arguments))}},a=function(e){for(var t=0;t<g.length;t++)i(e,g[t],!1);for(var r=0;r<m.length;r++)i(e,m[r],!0)};r.invoked=!0;var c=t.createElement("script");c.type="text/javascript",c.integrity="sha384-Dv01ylQWH3OMRpOnXgNXTEJypJSg/Si512H2KxfFik12c676LxjHoC1W2pF8xyR5",c.crossOrigin="anonymous",c.async=!0,c.src="https://cdn.amplitude.com/libs/analytics-browser-2.6.0-min.js.gz",c.onload=function(){e.amplitude.runQueuedFunctions||console.log("[Amplitude] Error: could not load SDK")};var u=t.getElementsByTagName("script")[0];u.parentNode.insertBefore(c,u);for(var p=function(){return this._q=[],this},l=["add","append","clearAll","prepend","set","setOnce","unset","preInsert","postInsert","remove","getUserProperties"],d=0;d<l.length;d++)n(p,l[d]);r.Identify=p;for(var f=function(){return this._q=[],this},v=["getEventProperties","setProductId","setQuantity","setPrice","setRevenue","setRevenueType","setEventProperties"],y=0;y<v.length;y++)n(f,v[y]);r.Revenue=f;var g=["getDeviceId","setDeviceId","getSessionId","setSessionId","getUserId","setUserId","setOptOut","setTransport","reset","extendSession"],m=["init","add","remove","track","logEvent","identify","groupIdentify","setGroup","revenue","flush"];a(r),r.createInstance=function(e){return r._iq[e]={_q:[]},a(r._iq[e]),r._iq[e]},e.amplitude=r}}(window,document)}(); // eslint-disable-line
console.log(amplitude);
debugger;
amplitude.init("<YOUR_API_KEY>");
</script>
- When
debugger
pauses script execution, take a look at theamplitude
object in the console. You should see something like:
Notice that Types
is not defined.
- Wait a few seconds and/or refresh your page, and type
amplitude
into the devtools console.Types
should now be defined on theamplitude
object.
Environment
- JS SDK Version: 2.6.0
- Installation Method: script loader
- Browser and Version: Chrome 123.0.6312.87