
Global JS panel. One editor, byte counter, publish-gated.
What it is
A single JavaScript block that runs once per page per visitor, before any variant’s code. Useful for:- Shared helpers. A
waitForpolyfill, a debounce utility, a branded logger. Instead of copying the same function into every variant, put it here. - One-time analytics wiring. A GA4
configurecall, a Segment identify, something your variants can then use without repeating. - Feature flags read from your own system. Cache your feature flag values into a global so your variant JS can read them synchronously.
When it runs
- Consent gate has passed (see Consent).
- Visitor is not opted out (see Opt-out).
- Global JS runs. Once per page. Wrapped in a
try / catch. - The rest of the runtime decides variants and applies them.
Once per page per site
window.__abtestlyGlobalJsRan[siteId] is set on first run. A second
call, for example on a SPA route change, is a no-op. The block runs
once and stays.
That is deliberate: shared helpers are almost always things you want
to define once. Anything that needs to fire on route change belongs in
SPA panel, not here.
Size cap
50 KiB UTF-8. The editor counts bytes and refuses to save over the cap. Almost every real Global JS is well under this, even a large utility library gzip-inlined into base64 has room.Errors
Errors thrown inside Global JS are caught, logged to the browser console with a prefixed message, and reported to ABTestly via the/err beacon (first-occurrence-per-session, deduped).
An error in Global JS does not stop variant JS from running. It
does mean whatever your Global JS was supposed to provide is not
available to variants; if variants blindly assume it worked, they will
throw too.
Wrap risky code in try/catch inside Global JS and fall back gracefully.
Example
What Global JS is not for
- Variant code. If it belongs to a specific experiment, put it in the variant. Global JS is site-wide, always-on. A “test” living in Global JS is not a test.
- Anything with heavy DOM manipulation. DOM changes belong in variants where they can be scoped and cleaned up on SPA route change.
- Third-party script loading. Load third parties from your own
<script>tags in<head>or from a tag manager. Adding them through Global JS makes it hard to reason about their load order relative to the rest of the page.