How to tell when Zaraz has loaded in JS?

We’re working to implement Zaraz and we have the following issue: We have several zaraz.set(…) commands in the HTML of our page, but they get executed before Zaraz has loaded. As a result, these commands throw errors.

Essentially, we want to set some custom dimensions before the Pageview system event is triggered for Google Analytics. If we include zaraz.set(…) in the HTML code of the page, it executed before Zaraz is loaded. If we put it into a custom HTML block inside Zaraz, it doesn’t appear to have access to all the data on the page.

How can we delay the execution of zaraz.set(…) until Zaraz has loaded?

1 Like

Hey @whencyclopedia, thanks for bringing this to our attention. We have fixed it and the things you track using zaraz.set() commands should now be available to use with the Pageview trigger as well. You can use zaraz.set() anytime, and it should be fine. Please let me know if you are still facing issues with this!

1 Like

Thanks! I can confirm that it’s now working.

We needed to custom-code though, because some of the data we want to send to Zaraz is not available immediately after page load yet. So this is the solution we came up with:

We set up a custom pageview trigger and disabled the default pageview trigger. We then use zaraz.track() to send the custom trigger once our code has all the data. We do double-check that zaraz is already loaded, though, just in case:

    <!-- Zaraz -->
    <script>
        function zarazPageView() {
            try {
                zaraz.set('ci_author',window.AHE.ci_author);
                zaraz.set('ci_type', window.AHE.ci_type_id + '-' + window.AHE.ci_type);
                zaraz.set('ci_translator', window.AHE.ci_translator);
                zaraz.set('ci_lang', window.AHE.contentLang);
                zaraz.set('userKnown', window.AHE.knownUser);
                zaraz.set('userInterest', window.AHE.interestGroup);
                zaraz.set('ab', window.AHE.ab);
                zaraz.track('customPageview');
            } catch (e) {
                window.zarazAttempts = (window.zarazAttempts + 100) || 100;
                console.log(window.zarazAttempts);
                console.warn('Zaraz is not yet loaded; trying again in ' + window.zarazAttempts + 'ms...');
                setTimeout(function() {
                    zarazPageView();
                }, zarazAttempts);
            }
        }
        zarazPageView();
    </script>
1 Like

PS: To make this more elegant it would be super cool if Zaraz could emit a JavaScript event when it’s loaded and ready. Then we could wait for that event before running any Zaraz-related code.

2 Likes

Another update on this… Our code solution above actually does not work.

There is a short period of time between zaraz.track() being a valid function and when zaraz.track() actually executes something. In the code above, sometimes zaraz.track() gets executed, other times it does not. We’ve checked it using Zaraz debug, where we sometimes see the default PageView event being triggered (too early for our purposes) but the zaraz.track(“customPageview”) does not get executed.

However, if we put in a JavaScript delay of a few hundred milliseconds, zaraz.track(“customPageview”) does get executed properly in our tests.

So… a proper way of knowing in JavaScript when Zaraz is ready to process input would be essential.

1 Like

Thanks for your message, let us look into this and update.

Hey @whencyclopedia , can you show us an example page where you’re having the issue? We intentionally not adding a “Zaraz loaded” event because we these things to Just Work. so if they don’t, we rather fix it and not just provide workarounds.

Hi @yoav_zaraz, thanks for looking into this!

So we’ve set up a test page here:

Compare this to our normal live website:

The test page already sets the debug cookie, so you can see debug output straight away. On the live page, you’ll have to set it manually: document.cookie = 'debug=c7icqqh303fbvgsofasg';

The Zaraz code is found on lines 332-371 in the HTML and on lines 354-392 on the normal page. As you can see, we’re triggering zaraz.track('customPageview',zarazData) once both the page DOM and our core JS libraries are loaded (that’s our pageReady() event). Both pages are essentially the same, the difference is that the live page has a 500ms delay before triggering the Zaraz code.

Now if you refresh the test page a few times, you’ll see that the events triggered are not always the same, and in particular our customPageview event rarely gets triggered. On the live page, with the 500ms delay, all the events always get triggered.

We did try this in our live environment, as we’re running two GA properties in parallel to make sure everything is the same before switching to Zaraz. We did notice that without the 500ms delay, we were seeing about 40% of the pageviews missing.

I hope that helps. Feel free to ask for more information if needed.

Thanks for this info @whencyclopedia ! It seems like the script tags that are calling zaraz.track are part of the <head> and not of the <body>. Zaraz is inject at the end of the <head> tag, which means sometimes your script will run earlier. Can you try moving your script to the <body> of the HTML?

Sure thing! We’ve moved the script to the beginning of the <body> tag; same problem. You can see it in action here:

I’m sorry, your HTML is completely broken. There’s no </head> tag at all - you’re not closing the <head> element.

Also, I recommend not naming your object zarazData - it’s reserved to internal Zaraz usage.

Sorry about that! That must have been a manual error when we converted our live page to a static HTML. It’s now fixed (the is a bit hidden at the very end of the line where Zaraz inserts itself):
Screen Shot 2022-02-08 at 9.24.41 AM

We also renamed zarazData to zData.

Still the same result: It sometimes triggers the zaraz.track() event and sometimes it does not. Reload it several times and you’ll see:

Why do you think it doesn’t trigger the zaraz.track() call?

Can you completely remove the whole jsQueue, try/catch, zarazAttempts etc?

The way Zaraz is implemented now, you should be able to just include your code:

         let zData = {};
                zData.ab                = window.AHE.ab;
                zData.userKnown         = window.AHE.knownUser;
                zData.ci_lang           = window.AHE.contentLang;
                if (window.AHE.ci_author) {
                    zData.ci_author     = window.AHE.ci_author;
                }
                if (window.AHE.ci_type_id) {
                    zData.ci_type       = window.AHE.ci_type_id + '-' + window.AHE.ci_type;
                }
                if (window.AHE.ci_translator) {
                    zData.ci_translator = window.AHE.ci_translator;
                }
                if (window.AHE.interestGroup) {
                    zData.userInterest  = window.AHE.interestGroup;
                } else {
                    zData.userInterest  = 'Unknown';
                }
                zaraz.track('customPageview',zData);
                console.log('Zaraz sent.');

without anything else.

Thanks!

I think it doesn’t trigger the zaraz.track() call because there’s no debug output. It only says it triggered the pageview (which we’re not tracking in Zaraz) but there’s no output for customPageview.

I’ve removed it to the minimum now. We need at least to wait for our pageReady event, otherwise we don’t have all of the data that we need yet.

Here’s the stripped down version: World History Encyclopedia

Aha! Apparently your waiting script waited until just a moment when the initial Zaraz code gets unloaded but the full Zaraz code isn’t yet loaded, so it fell between the cracks. We fixed it now!

Amazing! Thanks a lot.