Avada Cookie Consent
Auto-block Cookies
Add the early blocker snippet

How to add the early blocker snippet

The Avada - Script Blocker app embed loads at Shopify's compliance_head position - early, but not the very first thing that runs. A tracker placed above it in your theme, or one your theme's own JavaScript injects before that point, can still get away. This snippet closes that gap: it installs the same interception at the very top of <head>, so anything added afterwards is caught.

Plan: Available on every plan.

Do you need this?

Add the snippet only if both of these are true:

  • A tracker still fires before consent after you have applied the blocked markup from How to block each kind of tracker.
  • That tracker is written into theme.liquid or your theme's own JavaScript, high in the <head>.

If neither applies, the app embed already covers you.

It does not replace the blocked markup. A tag still carrying a working src is fetched before any JavaScript runs, this snippet included. Make your tags inert and add the snippet - the two work together.

Prerequisites

Step 1: Create the snippet file

Go to Online StoreThemesEdit codeSnippetsAdd a new snippet.

Name it avada-early-script-blocker. Shopify creates snippets/avada-early-script-blocker.liquid for you.

Snippets, not Assets. The file has to be a .liquid file, because it reads your Cookie Bar settings through Liquid and Shopify only processes Liquid in .liquid files. In assets/theme.js, or any plain .js file, it does nothing at all.

Step 2: Paste the code

Copy the whole block below, from the opening {% if %} line to the closing {% endif %}, into the file you just created. Then click Save.

{% if shop.metafields.cookies_bar_avada.data %}
  <script>
    (function () {
      if (window.__avadaScriptNeutralizerActive) return;
 
      let meta = {{ shop.metafields.cookies_bar_avada.data | default: false }} || {};
      let config = meta.autoBlocker;
      if (!config || config.enabled === false) return;
 
      let SCRIPT_HOSTS = config.blockedScriptHosts || [];
      let CUSTOM_HOSTS_OBJ = config.customHosts || {};
      let CUSTOM_SCRIPT_HOSTS = CUSTOM_HOSTS_OBJ.script || [];
      let CUSTOM_IFRAME_HOSTS = CUSTOM_HOSTS_OBJ.iframe || [];
      let CUSTOM_PIXEL_HOSTS = CUSTOM_HOSTS_OBJ.pixel || [];
 
      window.__avadaBlockerConfig = config;
 
      function rawConsentCookie() {
        let nameEQ = 'avada_cookie_consent=';
        let ca = document.cookie ? document.cookie.split(';') : [];
        for (let i = 0; i < ca.length; i++) {
          let c = ca[i];
          while (c.charAt(0) === ' ') c = c.substring(1);
          if (c.indexOf(nameEQ) === 0) {
            try {
              return JSON.parse(decodeURIComponent(c.substring(nameEQ.length)));
            } catch (e) {
              return null;
            }
          }
        }
        return null;
      }
 
      function getMarketingConsent() {
        let consent = rawConsentCookie();
        if (!consent || typeof consent !== 'object') return null;
        let hasChoice =
          typeof consent.marketing === 'boolean' ||
          typeof consent.analytics === 'boolean' ||
          typeof consent.preferences === 'boolean';
        if (!hasChoice) return null;
        return consent.marketing === true;
      }
 
      function cmpAllowsTracking() {
        let c = window.Shopify && window.Shopify.customerPrivacy;
        if (!c || typeof c.userCanBeTracked !== 'function') return null;
        try { return c.userCanBeTracked() === true; } catch (e) { return null; }
      }
 
      // Whether Shopify says this visitor has to be asked at all. userCanBeTracked()
      // conflates "refused" with "never asked", so on a shop that shows the banner in
      // one region only it stays false forever outside that region.
      function cmpNeedsBanner() {
        let c = window.Shopify && window.Shopify.customerPrivacy;
        if (!c || typeof c.shouldShowBanner !== 'function') return null;
        try { return c.shouldShowBanner() === true; } catch (e) { return null; }
      }
 
      // Region verdict published by the cookie bar: 'out' = the banner never shows to
      // this visitor, so no consent can ever arrive and blocking would be permanent.
      // Parsed once - shouldBlock() runs on every node insertion.
      let SCOPE_CACHE = {read: false, value: null};
 
      function readScopeCache() {
        try {
          let raw = window.localStorage.getItem('avadaBlockerScope');
          if (!raw) return null;
          let parsed = JSON.parse(raw);
          if (!parsed || !parsed.expiry || parsed.expiry < Date.now()) return null;
          return parsed.value === 'in' || parsed.value === 'out' ? parsed.value : null;
        } catch (e) {
          return null;
        }
      }
 
      function regionScope() {
        let live = window.__avadaBlockerScope;
        if (live === 'in' || live === 'out') return live;
        if (!SCOPE_CACHE.read) {
          SCOPE_CACHE.read = true;
          SCOPE_CACHE.value = readScopeCache();
        }
        return SCOPE_CACHE.value;
      }
 
      function shouldBlock() {
        let m = getMarketingConsent();
        if (m === true) return false;
        if (m === false) return true;
        if (cmpAllowsTracking() === true) return false;
        let needsBanner = cmpNeedsBanner();
        // Shopify saying a regulation applies outranks our own banner scope - see
        // consentState() in auto-blocker.liquid.
        if (needsBanner === true) return true;
        if (needsBanner === false) return false;
        if (regionScope() === 'out') return false;
        // Customer Privacy can hydrate after the early bootstrap. Fail closed until
        // Shopify can provide an authoritative answer - the app embed re-enables
        // anything neutralized here as soon as the decision resolves.
        return true;
      }
 
      function matchesHostList(host, list) {
        for (let i = 0; i < list.length; i++) {
          let frag = list[i];
          if (host === frag || host.endsWith('.' + frag)) return true;
        }
        return false;
      }
 
      function hostFromSrc(src) {
        try { return new URL(src, location.href).hostname.toLowerCase(); }
        catch (e) { return ''; }
      }
 
      function isBlockedScriptSrc(src) {
        if (!src) return false;
        let host = hostFromSrc(src);
        return matchesHostList(host, SCRIPT_HOSTS) || matchesHostList(host, CUSTOM_SCRIPT_HOSTS);
      }
 
      function isBlockedIframeSrc(src) {
        if (!src || !CUSTOM_IFRAME_HOSTS.length) return false;
        return matchesHostList(hostFromSrc(src), CUSTOM_IFRAME_HOSTS);
      }
 
      function isBlockedPixelSrc(src) {
        if (!src || !CUSTOM_PIXEL_HOSTS.length) return false;
        return matchesHostList(hostFromSrc(src), CUSTOM_PIXEL_HOSTS);
      }
 
      function neutralizeScriptNode(node) {
        try {
          if (!node || node.tagName !== 'SCRIPT') return;
          if (node.type === 'javascript/blocked') return;
          let src =
            (node.getAttribute && node.getAttribute('src')) ||
            (node.src && String(node.src)) ||
            '';
          if (!src || src === location.href) return;
          if (isBlockedScriptSrc(src)) {
            node.type = 'javascript/blocked';
            node.setAttribute('data-avada-blocked-src', src);
            node.removeAttribute('src');
          }
        } catch (e) {}
      }
 
      function neutralizeIframeNode(node) {
        try {
          if (!node || node.tagName !== 'IFRAME') return;
          if (node.getAttribute('data-avada-blocked-iframe')) return;
          let src = node.getAttribute('src');
          if (isBlockedIframeSrc(src)) {
            node.setAttribute('data-avada-blocked-iframe', src);
            node.removeAttribute('src');
          }
        } catch (e) {}
      }
 
      function neutralizePixelNode(node) {
        try {
          if (!node || node.tagName !== 'IMG') return;
          if (node.getAttribute('data-avada-blocked-pixel')) return;
          let src = node.getAttribute('src');
          if (isBlockedPixelSrc(src)) {
            node.setAttribute('data-avada-blocked-pixel', src);
            node.removeAttribute('src');
            node.style.display = 'none';
          }
        } catch (e) {}
      }
 
      function scanAddedNode(node) {
        if (!node || node.nodeType !== 1) return;
        let tag = node.tagName;
        if (tag === 'SCRIPT') neutralizeScriptNode(node);
        else if (tag === 'IFRAME') neutralizeIframeNode(node);
        else if (tag === 'IMG') neutralizePixelNode(node);
        if (!node.querySelectorAll) return;
        let scripts = node.querySelectorAll('script[src]');
        for (let i = 0; i < scripts.length; i++) neutralizeScriptNode(scripts[i]);
        let iframes = node.querySelectorAll('iframe[src]');
        for (let i = 0; i < iframes.length; i++) neutralizeIframeNode(iframes[i]);
        let imgs = node.querySelectorAll('img[src]');
        for (let i = 0; i < imgs.length; i++) neutralizePixelNode(imgs[i]);
      }
 
      window.__avadaScriptNeutralizerActive = true;
 
      try {
        ['appendChild', 'insertBefore'].forEach(function (method) {
          let orig = Node.prototype[method];
          if (!orig || orig.__avadaPatched) return;
          let patched = function (node) {
            if (node && shouldBlock()) scanAddedNode(node);
            return orig.apply(this, arguments);
          };
          patched.__avadaPatched = true;
          Node.prototype[method] = patched;
        });
      } catch (e) {}
 
      try {
        let srcDesc = Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype, 'src');
        if (srcDesc && srcDesc.configurable && srcDesc.set && !srcDesc.set.__avadaPatched) {
          let nativeSrcSet = srcDesc.set;
          let nativeSrcGet = srcDesc.get;
          let patchedSet = function (value) {
            if (shouldBlock() && isBlockedScriptSrc(value)) {
              this.type = 'javascript/blocked';
              this.setAttribute('data-avada-blocked-src', value);
              this.removeAttribute('src');
              return;
            }
            return nativeSrcSet.call(this, value);
          };
          patchedSet.__avadaPatched = true;
          Object.defineProperty(HTMLScriptElement.prototype, 'src', {
            configurable: true,
            enumerable: true,
            get: nativeSrcGet
              ? function () {
                  return nativeSrcGet.call(this);
                }
              : function () {
                  return this.getAttribute('src');
                },
            set: patchedSet
          });
        }
      } catch (e) {}
 
      try {
        let observer = new MutationObserver(function (mutations) {
          if (!shouldBlock()) return;
          for (let i = 0; i < mutations.length; i++) {
            let nodes = mutations[i].addedNodes;
            for (let j = 0; j < nodes.length; j++) scanAddedNode(nodes[j]);
          }
        });
        let target = document.documentElement || document;
        if (target) observer.observe(target, {childList: true, subtree: true});
      } catch (e) {}
 
      if (shouldBlock()) {
        let scripts = document.querySelectorAll('script[src]');
        for (let i = 0; i < scripts.length; i++) neutralizeScriptNode(scripts[i]);
      }
    })();
  </script>
{% endif %}

Step 3: Render it from your layout

Open layout/theme.liquid and add this line immediately after the opening <head> tag, above every tracker tag on the page:

{% render 'avada-early-script-blocker' %}

Click Save.

Step 4: Confirm the app embed is still on

Go to Online StoreThemesCustomizeApp embeds and check that Avada - Script Blocker is on.

The app embed is not optional here. The snippet only holds scripts back - releasing them after Accept is done entirely by the app embed. Turn the embed off and blocked trackers stay blocked for the whole visit, even after the visitor accepts.

Verify it works

  1. Open your storefront in a private or incognito window and decline on the banner.

  2. Open the browser console and run:

    document.querySelectorAll('script[data-avada-blocked-src]').length

    A number greater than zero means tags are being held back.

  3. Accept on the banner. The count should drop to zero and your trackers should start loading.

What the snippet holds back

The snippet reads the same block list as the app embed: domains of the integrations you turned on with an ID filled in, plus your own custom rules, split by target - script, iframe and pixel.

With no integration in blocking mode and no custom rules it has nothing to match and holds nothing back. That is expected, not a fault. See How to block each kind of tracker to set the block list up first.

Updating or removing it

To update the snippet, replace the contents of snippets/avada-early-script-blocker.liquid - you never have to touch theme.liquid again. If your store already has an older copy, replace it rather than adding a second one. A duplicate is harmless, because the second copy detects the first and stops, but an out-of-date copy is not worth keeping.

Before you remove Cookie Bar, delete the {% render 'avada-early-script-blocker' %} line from theme.liquid and delete the snippet file. Left in place with no app embed to release them, it holds your trackers back permanently.

Related articles

And there you have it! Trackers that used to slip through at the very top of your page now wait for consent like every other tag. If you have any questions or run into any issues, don't hesitate to reach out. We're here to help!

Previous: How to block each kind of tracker | Next: Auto-block cookies FAQ

Products
Avada SEO SuiteAvada AEO OptimizerAvada AI Blog BuilderAvada Product CopyAvada Images & Page Speed UpAvada Shipping LabelsAvada Backups & Restore
Resources
DocumentationSEO Suite DocsBlog DocsSpeed DocsShipping Labels DocsBackups & Restore Docs
Company
Avada GroupPrivacy Policy
© 2026 Avada Group. All rights reserved.