Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delay JS #4

Open
samikeijonen opened this issue Apr 10, 2022 · 0 comments
Open

Delay JS #4

samikeijonen opened this issue Apr 10, 2022 · 0 comments

Comments

@samikeijonen
Copy link
Member

samikeijonen commented Apr 10, 2022

There is interesting approach to delay 3. party JS.

I'm not suggesting to delay our JS by default but document how it can be done.

Change src attributes to delay attributes.

We already have filters for this:

/**
 * Delay JS by changing `src=` to `delay=` in GTM and Cookiebot.
 *
 * @link https://blog.speedvitals.com/delay-javascript/
 *
 * @return void
 */
function delay_js( $code, $id ) {
    return str_replace( 'src=', 'delay=', $code );
}
add_filter( 'mtps_gtm_head_code', 'delay_js', 10, 2 );
add_filter( 'mtps_cookiebot_code', 'delay_js', 10, 2 );

Add custom JS

I'm testing a little bit modified version of the JS:

/**
 * Change `delay` attributes back to `src` attributes.
 *
 * @return void
 */
function print_delay_js() {
    ?>
    <script>
        var delayLoaded = false;
        var autoLoadDuration = 5;
        var eventList = ["keydown", "mousemove", "wheel", "touchmove", "touchstart", "touchend"];

        var autoLoadTimeout = setTimeout(runScripts, autoLoadDuration * 1000);

        eventList.forEach(function(event) {
            window.addEventListener(event, triggerScripts, { passive: true })
        });

        function triggerScripts() {
            runScripts();
            clearTimeout(autoLoadTimeout);
            eventList.forEach(function(event) {
                window.removeEventListener(event, triggerScripts, { passive: true });
            });
        }

        function runScripts() {
            if (!delayLoaded) {
                document.querySelectorAll("script[data-cookieconsent]").forEach(function(scriptTag) {
                    <?php // Create new script tag and replace "delay=" with "src=". ?>
                    var newNode = document.createElement('script');
                    newNode.setAttribute("data-cookieconsent", "ignore");
                    var newContent = scriptTag.textContent.replace("delay=", "src=");
                    newNode.textContent = newContent;
                    scriptTag.parentNode.replaceChild(newNode, scriptTag);
                });

                document.querySelectorAll("script[delay]").forEach(function(scriptTag) {
                    <?php // Replace "delay=" with "src=" attribute. ?>
                    scriptTag.setAttribute("src", scriptTag.getAttribute("delay"));
                });
            }

            delayLoaded = true;
        }
    </script>
    <?php
}
add_action( 'wp_head', 'print_delay_js' );

Suggestion for new data attribute

In the above code I'm using document.querySelectorAll("script[data-cookieconsent]") to detect GTM code. It doesn't feel like bullet proof because we might not even have Cookiebot on the page.

We should have our own data attribute, for example data-meom-delay and hook into that:

document.querySelectorAll("script[data-meom-delay]").

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant