Recaptcha V3 assets cause Pagespeed issues - how to defer
Asked Answered
O

3

8

We're currently using Google Recaptcha V3 across the public-facing portions of our site - while doing Pagespeed Insights performance testing (Mobile), Google themselves is reporting unused/undeferred CSS as a problem on their own Recaptcha css file:

enter image description here

Full resource address is: https://www.gstatic.com/recaptcha/releases/[...]/styles__ltr.css (so it is clearly coming from a subsequent Google Recaptcha script request)

We are including the original Google recaptcha script with the 'defer' attribute set - not sure what else we can do to cause this css to be deferred such that Pagespeed does not complain about it. Can't find any documentation on the Google Recaptcha site itself to help with this issue.

Does anyone know how to defer this CSS to improve page load time? Not sure if this is somehow a Mobile specific issue, as Pagespeed doesn't report it at all on Desktop.

Ozenfant answered 21/11, 2019 at 19:5 Comment(0)
C
6

Firstly, bear in mind that 'remove unused CSS' is more of a guidance point (provided it isn't render blocking), it is indicating that it is wasted bytes (which it actually isn't if recaptcha triggers, as it then needs that CSS to render the image 'are you human check' etc.)

Although I can't give you an ideal answer as it is code you have no control over, I can give you two ways to test it's impact / whether it is actually a problem and a 'hack' to get around the load order.

Test using applied throttling

Simulated throttling can cause unexpect behaviour sometimes, which is what the Page Speed Insights website uses.

If you use the browser audit (which uses the same engine - Lighthouse) to run the tests you have an option to change the throttling from simulated to applied.

Although your score will change (applied throttling is less forgiving than simulated throttling), you get a much more realistic order of events as the latency and slowdown is 'real' vs making best guesses based on loading the page at full speed and applying formula's to guess load times.

Open Dev Tools in Chrome (F12) -> Audits -> Throttling -> set to Applied Slow 4G, 4x CPU Slowdown. -> Run Audits.

See if the problem persists when using this way of assessing page speed.

If it does, a workaround / test for real world performance is as follows:-

Force the script to load after an amount of time (the hacky way!)

This is not an ideal solution but it is good for testing and as a last resort if it does actually slow down your website key load times.

Insert the script dynamically after 5 seconds.

(please note the below code is untested and is likely to not work, it is for illustration only to point you in the right direction. It is highly probable that you don't need the script.onload section and can include that normally)

setTimeout(function(){
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.onload = function() {
        grecaptcha.ready(function() {
            grecaptcha.execute('_reCAPTCHA_site_key_', {action: 'homepage'}).then(function(token) {
               ...
            });
        });
    }
    script.src = "https://www.google.com/recaptcha/api.js?render=_reCAPTCHA_site_key";
    head.appendChild(script);
 }, 5000);
Cerys answered 29/11, 2019 at 0:44 Comment(2)
Your solution works well but less hacky if wrapped in a function and called on focus for instance. $('#newsletter_register .form-control').focus(function(){ if ( captchaLoaded ==false) { loadCaptcha(); } });Ashur
yes, the only reason I would choose this option over loading on focus is if someone is on 3G there may be an issue with the script taking a while to load which can upset it when it is trying to work out if you are a human. Either way it is a hacky way to solve the issue but your way should be fine in 99% of cases.Cerys
N
4

We can use IntersectionObserver to defer Recaptcha script.

var io = new IntersectionObserver(
    entries => {
        console.log(entries[0]);
        if (entries[0].isIntersecting) {
            var recaptchaScript = document.createElement('script');
            recaptchaScript.src = 'https://www.google.com/recaptcha/api.js?hl=en';
            recaptchaScript.defer = true;
            document.body.appendChild(recaptchaScript);
        }
    },
    {
        root: document.querySelector('.page-wrapper'),
        rootMargin: "0px",
        threshold: 1.0,
    }
);
io.observe(initForm);
Neume answered 4/10, 2020 at 1:52 Comment(0)
L
3

We can load the reCaptcha v3 script once after an initial scroll on load:

    var fired = false;
window.addEventListener('scroll', function () {
  let scroll = window.scrollY;
  if (scroll > 0 && fired === false) {
    var recaptchaScript = document.createElement('script');
    recaptchaScript.src = 'https://www.google.com/recaptcha/api.js?render=Your_SITE_KEY';
    recaptchaScript.defer = true;
    document.body.appendChild(recaptchaScript);
    fired = true;
   
    // console.log('On scroll fired');
  }
}, true);

Code Example: https://codepen.io/iamrobert/pen/NWazNpd

Page Speed Insight Score Page Speed

Libnah answered 5/1, 2022 at 7:38 Comment(2)
This one can be futher improved by using {once: true} in addEventListener options instead of fired variable. Also, if anyone need to wait for script to load (which might be true in most cases) script should define recaptchaScript.onload = function () { /* … */}.Ockham
The {once: true} is indeed a nice addition. If targeting mobile users, you may also wish to add a listener on the touchstart event.Locarno

© 2022 - 2024 — McMap. All rights reserved.