0

I have created a small library in JS that do some analytics for our customers.

So far, we are including it like the following near the </body> tag :

<script type="text/javascript" src="https://cdn.myapp.net/main.min.js"></script>
<script type="text/javascript">
     MyLib.init("idofthecustomer");
</script>

But apparently, it's not running on some browsers. I have looked other analytics libraries and they are including their scripts in multiple differents ways.

Heap :

<script type="text/javascript">
    window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=t.forceSSL||"https:"===document.location.protocol,a=document.createElement("script");a.type="text/javascript",a.async=!0,a.src=(r?"https:":"http:")+"//cdn.heapanalytics.com/js/heap-"+e+".js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(a,n);for(var o=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","removeEventProperty","setEventProperties","track","unsetEventProperty"],c=0;c<p.length;c++)heap[p[c]]=o(p[c])};
    heap.load("YOUR_APP_ID");
</script>

GoogleAnalytics :

<!-- Google Analytics -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
<!-- End Google Analytics -->

Why are they doing such thing? Can you explain me what the goal of this?

In another way, how can we be sure that our script will be loaded and run?

Thanks for your answers !

Xavierh95
  • 283
  • 4
  • 13
  • Its not clear what your problem is here. Are your script files not loading? Or is your MyLib.init("idofthecustomer"); function not running at all or simply throwing errors? Have you checked the debugger console in the browsers where its not working for errors? – MplsAmigo Oct 12 '17 at 14:45
  • It's not clear because it's not clear for me too. The "init" method is calling a remote API and track some specific details. It seems that it's not running fine on some browsers (stats are not matching between differents tools). But we don't have any idea on which browser the problem occurs etc. The real question is then : What is the best way to load a JS library (most compatible way) and use it on any page of a website? (like GoogleAnalytics, Heap, etc.) – Xavierh95 Oct 12 '17 at 14:53
  • The problem isn't how you are loading the script. And its not a cors issue because you are loading the external libraries directly using a – MplsAmigo Oct 12 '17 at 15:30
  • This is the problem. As the library does not work, the data is not arriving on our side. So we don't know which browsers are impacted. – Xavierh95 Oct 12 '17 at 15:33
  • I don't know heap, but Google Analytics uses this to build a command queue (commands are stored in the ga object until the analytics file is loaded. That way your site can send tracking commands even before the code that processes them is available). Also they initialize a date object that is not relevant to tracking, but used for some internal purpose. – Eike Pierstorff Oct 12 '17 at 15:48

2 Answers2

1

Many statistics are loaded using javascript and not with a "classical <script> balise" for diffrents reasons :

  • Don't load 2 times the same library if the script is already declared in page
  • Allow to develop an async library loading
  • It's more user-friendly for noobs, to copy an only one unreadable script

If your library isn't loaded all times on all browsers, it may not be an integration error.

  • Minimum 21% of internet users use statistics Adsblockers
  • Javascript is not always allowed (often bots, many bots)
  • Somes browsers doesn't allow cross domain (charging js library or if your main.min.js send cross domain requests)
  • IE have a hard cross site script filter (XSS Protection)

If someone see anothers reasons, you can edit my answer ;)

GGO
  • 2,700
  • 3
  • 16
  • 35
0

Are you def sure script is being loaded on the page? Check the value of Access-Control-Allow-Origin in header since you are not including the JS file in your own website. Browsers block external JS files if

Access-Control-Allow-Origin

is not set to

*

or defined domains.

---UPDATE---

My guess is sometime file gets loaded quick enough and then your function gets called and it works but sometime function executes before the file is being loaded.

Minified version of this code

window._ls = function(e,t){var a=document.createElement("script");a.type="text/javascript",a.readyState?a.onreadystatechange=function(){("loaded"===a.readyState||"complete"===a.readyState)&&(a.onreadystatechange=null,t())}:a.onload=function(){t()},a.src=e,document.getElementsByTagName("head")[0].appendChild(a)}

and then you can use the code like this,

_ls("https://cdn.myapp.net/main.min.js",function(){MyLib.init("idofthecustomer")})
Himan
  • 371
  • 1
  • 7
  • Oooh, bad idea. There is a reason browsers don't allow this by default. This will open you up to cross site scripting attacks making you vulnerable to hackers. Please review the OWASP top 10 web security vulnerabilities. https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project#tab=OWASP_Top_10_for_2013 – MplsAmigo Oct 12 '17 at 14:43
  • Yes, it's not a CORS issue. – Xavierh95 Oct 12 '17 at 14:44
  • 1
    @BrianPickens I disagree, you set this header on the CDN server, all the public CDNs have this header setup that's how people are able to use public CDN libraries on their own site. – Himan Oct 12 '17 at 14:44
  • @Xavierh95 just a thought, is your function MyLib is in global scope? – Himan Oct 12 '17 at 14:47
  • @Himan: I init MyLib with the following line in the JS file : var MyLib = MyLib || {}; Is this enough to make it "global" ? – Xavierh95 Oct 12 '17 at 14:50
  • @Xavierh95 my bad, since you said it works in few browser it might not be scoping issue. My guess is sometime file gets loaded quick enough and then your function gets called and it works but sometime function executes before the file is being loaded. Call the MyLib.init("idofthecustomer"); when DOMContentLoaded event is triggered – Himan Oct 12 '17 at 14:57
  • This might help you. https://stackoverflow.com/questions/14644558/call-javascript-function-after-script-is-loaded – Himan Oct 12 '17 at 14:59
  • Isn't it possible to do a cleaner way like heap do in the example I have put in the initial post? – Xavierh95 Oct 12 '17 at 15:13
  • What they are using is just a minified version of js. See updated answer. – Himan Oct 12 '17 at 15:24
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/156574/discussion-between-himan-and-xavierh95). – Himan Oct 12 '17 at 15:30