Broken tracking code when not used in global scope

I am using the Matomo tracking code in combination with the Cookiebot callback. It looks like this:

window.on('CookiebotOnAccept', function(){
    if (Cookiebot.consent.statistics) {
        // Matomo
        var _paq = window._paq || [];
        /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
        (function() {
            var u="//tracking.***.com/";
            _paq.push(['setTrackerUrl', u+'matomo.php']);
            _paq.push(['setSiteId', '1']);
            var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
            g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
        //- Matomo

The matomo.js is getting loaded but the page view is not tracked.
The problem seems to be that the matomo.js is probably trying to access the global variable “_paq”. But the variable doesn’t exist if you don’t use the snippet in the global context (the window scope).
The code will run if you change

var _paq = window._paq || [];


window._paq = [];
var _paq = window._paq;

Maybe I’m missing something I should have set before.
The current tracking code assumes that window._paq could possibly be set before. Is that really possible?



Not exactly, but your fix also solves the issue behind it:

When you want to use _paq globally, you either have to set it in the global scope when it obviously works.
But when you you add the tracking code in a function, _paq is a local variable.
To make it global, you could simply add a window._paq = paq after the tracking code and everything would work again.

By setting `window._paq beforehand you implicitly make the connection beforehand and _paq is global therefore.

So all in all everything works as it should and the tracking code works without window._paq being set beforehand. But if you want to access it globally, you have to make the variable global.

Now, my intention was not to use _paq globally. At the moment I have no other code than the posted one.
I think the default code provided by matomo should also work if not used in the global scope.
For me it was very confusing. I copied the provided code, the matomo.js was loaded but nothing was tracked without any error message.
Why not making the default code a little bit more stable?