Documentation

Variable Exclusion List

Reference guides for release workflows, command-line usage, cross-file protections, and the desktop app.

Inside the Docs

Practical guides for real release work.

How-to guides Start with release sequencing and command-line usage, then move into feature-specific references.
Advanced protection Browse cross-file controls like Replace Globals and Protect Members when a build spans multiple scripts.

Variable Exclusion List

  • VariableExclusion
  • Free

Variable Exclusion List defines which identifiers must never be renamed during name mangling. It is the escape hatch you reach for when something outside your file refers to a name by its exact text, and a rename would break that contract silently.

How to define exclusions

The setting is a multi-line list of regular expressions. Each line is one matching rule.

^myname$
^myvalue$

Source code:

function () {
    var myname;
    var myvalue;
    var hello;
}

Output with the exclusions above:

function () {
    var myname;
    var myvalue;
    var a;
}

Configuration

In jso.config.json, the publicNames array is the ergonomic form — a list of regular expressions for public names to preserve, mapped to VariableExclusion:

{
  "publicNames": ["^MyWidget$", "^ga$", "^dataLayer$"]
}

The raw engine option takes the same patterns as one newline-separated string:

{
  "options": {
    "VariableExclusion": "^MyWidget$\n^ga$\n^dataLayer$"
  }
}

What actually needs excluding

Most identifiers do not need to be here. Local variables, parameters, and local functions can always be renamed, because nothing outside the file can see them. Exclusions are for names that cross a boundary the obfuscator cannot see:

  • Globals other scripts call. A widget entry point (window.MyWidget), an analytics queue (dataLayer, ga), a callback name a third-party script looks up by string.
  • Names referenced from HTML. An inline onclick="submitForm()" attribute is a string in your markup, not code the obfuscator rewrote — the function it names must keep that name.
  • Names built at runtime. Anything reached through window[someString], eval, or a dynamic import() path. The obfuscator cannot follow a computed reference, so it cannot know the name is load-bearing.
  • Framework and platform contracts. Lifecycle method names a framework invokes by convention, service-worker event names, and anything a native bridge resolves by string.

The failure mode when you miss one is worth internalising: the build succeeds, the file parses, and the feature is broken at runtime in a way that only shows up on the path that uses it. That is why verifying protected output means running your tests, not just checking that the output loads.

Not the same as reservedStrings

Two different escape hatches for two different transform families — mixing them up is a common early mistake:

VariableExclusion / publicNamesreservedStrings
ProtectsIdentifiers (variable and function names)String literals
AgainstReplaceNames, RenameGlobals, DeepObfuscateMoveStrings, EncodeStrings
Use whenSomething calls a name from outside the fileSomething matches a literal byte-for-byte

For a whole region of a file rather than individual names, use inline directives, which mark the region in the source itself. For property and method names specifically, see Protect Members.

Anchor your patterns

These are regular expressions, not exact names, and an unanchored pattern matches far more than people expect. id matches id, but also idx, valid, hidden, and candidate — so a single sloppy line can leave most of your identifiers un-renamed while the build still reports success and the output still looks obfuscated at a glance.

  • Anchor both ends for an exact name: ^dataLayer$, not dataLayer.
  • Anchor the start for a deliberate prefix convention: ^api_ keeps every identifier you have prefixed for export.
  • Matching is case-sensitive. ^myWidget$ does not match MyWidget.
  • Audit the result. Diff the identifier count in protected output before and after adding a pattern. If adding one exclusion left dozens of names readable, the pattern is too broad.
Keep the list short: every excluded name is a name an analyst gets for free, and a long exclusion list is usually a sign the module's public surface is too wide. Where you can, narrow the surface instead — expose one entry point object, exclude that one name, and let everything behind it be renamed.

Try this in the online obfuscator

Paste your own code and see this option applied, or compare plans for larger projects and the desktop app.

Try It Free See Pricing