What this demonstrates

The Ezoic loader is injected 800 milliseconds after the window load event. Every snippet queues into a plain array long before sa.min.js exists, which kills the currentScript fast path and forces the document-order scan: the Nth drained call matches the Nth unconsumed snippet.
Integration used on this page
<!-- Head: consent + queue, loader injected later -->
<script data-cfasync="false" src="https://cmp.gatekeeperconsent.com/min.js"></script>
<script data-cfasync="false" src="https://the.gatekeeperconsent.com/cmp.min.js"></script>
<script>
  window.ezstandalone = window.ezstandalone || {};
  ezstandalone.cmd = ezstandalone.cmd || [];
  window.addEventListener("load", function () {
    setTimeout(function () {
      var s = document.createElement("script");
      s.src = "https://www.ezojs.com/ezoic/sa.min.js";
      document.head.appendChild(s);
    }, 800);
  });
</script>

<!-- Body: queues before the loader exists -->
<script>
  ezstandalone.cmd.push(function () {
    ezstandalone.showAds({sizes: "300x250"});
  });
</script>

View source on GitHub →

Docs: Ad Placements — Simple Setup (No Placement IDs)

Late loader — scan path

The Ezoic loader on this page is injected 800 milliseconds after the window load event. Every snippet queues into a plain array long before sa.min.js exists, which kills the currentScript fast path and forces the document-order scan.

Second paragraph, after the first queued spot. The scan must consume snippets in document order: the first drained call matches this page's first snippet, the second call the second snippet.

Third paragraph giving the article some body before the final queued spot below.

Fourth paragraph closing out the article after the second ad spot.