1

I added a Cookies Consent banner. The requirement is that https://cdn.cookielaw.org/consent/c4337328/OtAutoBlock.js loaded before any other script. I now wonder if appendChild is the right choice. Will it load OtAutoBlock at the exact position I wrote it or will it append the script to the end of the tag (which would be too late). It has to be the first script that's loaded.

<!DOCTYPE html>
<html lang="en">
  <head>
    <!-- OneTrust Cookies Consent Notice -->
    <script type="text/javascript">
      if ("%REACT_APP_COOKIE_BAR%" === "true") {
        var otAutoBlock = document.createElement("script");
        otAutoBlock.setAttribute("type", "text/javascript");
        otAutoBlock.setAttribute("src", "https://cdn.cookielaw.org/consent/c4337328/OtAutoBlock.js");
        
        var otSDKStub = document.createElement("script");
        otSDKStub.setAttribute("type", "text/javascript");
        otSDKStub.setAttribute("src", "https://cdn.cookielaw.org/scripttemplates/otSDKStub.js");
        otSDKStub.setAttribute("charset", "UTF-8");
        otSDKStub.setAttribute("data-domain-script", "c4337328");

        document.getElementsByTagName("head")[0].appendChild(otAutoBlock);
        document.getElementsByTagName("head")[0].appendChild(otSDKStub);

        function OptanonWrapper() { }
      }
    </script>

    <script type="text/javascript">
      /* [Should load after OtAutoBlock loads to avoid tracking before consent was given] */
    </script>

  </head>

  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>
Joey Coder
  • 3,199
  • 8
  • 28
  • 60

1 Answers1

0

document.head.appendChild(script) will add it to the end of the <head> tag, so it will load after all other scripts. You can do two things:

  1. You load it with appendChild at the end, and have all your other scripts with a defer attribute, like this: <script defer> /* something */ </script> The defer forces a script to execute after the page is loaded, but if you load the OtAutoBlock without a defer, it will run before the others. The only thing to note is that defer will cause the scripts not to run last, but after the entire page loads, which includes CSS stylesheets, other JavaScripts, icons, images, HTML content, XHR requests in <script> tags, etc.

<script>
const load = true; // your stuff here

if (load)
{
  const script = document.createElement('script');
  
  window.hasRunned = false;
  script.text = 'alert(\'OtAutoBlock running.\'); window.hasRunned = true;';
  
  document.head.appendChild(script);
}
</script>

<script defer>
alert('Another script. Has runned OtAutoBlock: ' + window.hasRunned);
</script>

<script defer>
alert('And yet another. Has runned OtAutoBlock: ' + window.hasRunned);
</script>
  1. You use insertBefore to add it before the other scripts, so it will run before them. No need to use defer with this method. This might be what you want if you need the scripts to run before the page loads.

<script>
const load = true; // your stuff here

if (load)
{
  let script = document.createElement('script');
  
  window.hasRunned = false;
  script.text = 'alert(\'OtAutoBlock running.\'); window.hasRunned = true;';
  
  document.head.insertBefore(script, document.head.children[0]);
}
</script>

<script>
alert('Another script. Has runned OtAutoBlock: ' + window.hasRunned);
</script>

<script>
alert('And yet another. Has runned OtAutoBlock: ' + window.hasRunned);
</script>
LuisAFK
  • 846
  • 4
  • 22