Window._paq not ready, only tracks events if using a delayed interval

I have the following code. The core of the tracking is just the 4 lines with the _paq. However, I have found that I have had to wrap it with the Matomo.initialized setInterval check for it to track.

This seems counter to the docs that suggest you can push things into _paq and it will just send them when the Tag Manager has loaded the tracking code.

Any ideas how to debug this, or what is going on here?

So for clarity, this on its own does not work:

<script type="text/javascript" id="datalayer">
    var _paq = window._paq = window._paq || [];
    _paq.push(["addEcommerceItem","PID3","Name",["Group"],"99.99",1]);
    _paq.push(["trackEcommerceOrder","1435370443","99.99","99.99","0",0,true]);
    _paq.push(["trackEvent","User","CustomerType","existing"]);
</script>

Wrapping it with the check for Matomo being ready and it sends the requests as you would expect:

<script type="text/javascript" id="datalayer">
  var mt = setInterval(function () {
      if (Matomo.initialized) {
          clearInterval(mt);

          window.console.log('running tracking additions', Matomo.initialized);

          var _paq = window._paq = window._paq || [];
          _paq.push(["addEcommerceItem","PID3","Name",["Group"],"99.99",1]);
          _paq.push(["trackEcommerceOrder","1435370443","99.99","99.99","0",0,true]);
          _paq.push(["trackEvent","User","CustomerType","existing"]);
      }
  }, 250);
</script>

I think it’s better to paq-push after document ready event is fired

That does seem counter to the docs that suggest you can just keep appending to _paq and Matomo will take care of it all? And document.ready doesn’t necessarily mean Matomo will be ready?

If you are loading the tracker asyncronously, you can only push after that.
Tracker loader should sit inside the html. near the ending body tag or inside the head tag of HTML page.

https://developer.matomo.org/guides/tracking-javascript-guide

For asynchronous tracking, configuration and tracking calls are pushed onto the global _paq array for execution, independent of the asynchronous loading of matomo.js .

The docs say it doesn’t matter though? Are the docs wrong?

Looks like your tracker call is wrong. Different from the example inside the docs.

What exactly is wrong? Note that the Matomo analytics tracker itself is loaded by the Matomo Tag Manager elsewhere. So it is just the _paq pushing code that is needed. I don’t see how that differs to the examples given.

In the example you posted setTrackerUrl and setSiteId are missing

They’re not missing, they’re set by the Tag Manager, just aren’t visible here.

The events all track through to Matomo with the code as posted - the set interval.