
Company News
AWS Security Hub Adds Socket for Supply Chain Security
Socket is now in the AWS Security Hub Extended plan. Adopt it through AWS, apply committed spend, and block malicious open source packages.
eslint-plugin-sfmc
Advanced tools
ESLint plugin for Salesforce Marketing Cloud Engagement+Next - AMPscript, Server-Side JavaScript (SSJS) and Handlebars
Unified ESLint plugin for Salesforce Marketing Cloud — linting rules for both AMPscript and Server-Side JavaScript (SSJS).
npm install eslint-plugin-sfmc --save-dev
Requires ESLint 9+ (flat config).
// eslint.config.js
import sfmc from 'eslint-plugin-sfmc';
export default [
// Lint standalone .ampscript/.amp and .ssjs files
...sfmc.configs.recommended,
// Lint AMPscript + SSJS embedded in .html files
...sfmc.configs.embedded,
];
To see eslint(sfmc/...) diagnostics in VS Code for .amp, .ssjs, and .html files you need the VS Code ESLint extension to validate the custom SFMC language IDs.
Option A — Install vscode-sfmc-language (recommended)
The SFMC Language Service extension contributes the SFMC language IDs and automatically configures eslint.validate for you. No manual settings required.
Option B — Manual configuration
Add the following to your .vscode/settings.json:
{
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"html",
"vue",
"markdown",
"ampscript",
"ssjs",
"sfmc",
"handlebars"
]
}
Why
eslint.validateand noteslint.probe?eslint.probesilently skips files for language IDs that the ESLint extension does not natively recognise.eslint.validateforces the extension to process those files regardless of language ID.
| Config | Files | What it does |
|---|---|---|
sfmc.configs.ampscript | **/*.ampscript, **/*.amp | AMPscript rules only (recommended severity) |
sfmc.configs.ssjs | **/*.ssjs | SSJS rules only (recommended severity) |
sfmc.configs.recommended | Both of the above | All rules at recommended severity for standalone files |
sfmc.configs.embedded | **/*.html | Combined processor extracts both languages from HTML |
sfmc.configs.strict | All of the above + HTML | All rules at error severity for standalone and embedded |
recommended, embedded, and strict are arrays — spread them with ....
Use the -next config variants when targeting Marketing Cloud Next (MCN). MCN supports only a subset of AMPscript functions and does not support SSJS at all. Handlebars is MCN's templating language, so the -next configs also lint the {{...}} helpers and {!$...} bindings extracted from HTML and standalone .hbs files (see Handlebars Rules).
| Config | Files | What it does |
|---|---|---|
sfmc.configs['ampscript-next'] | **/*.ampscript, **/*.amp | AMPscript rules + flags functions unsupported in MCN (single config object) |
sfmc.configs['ssjs-next'] | **/*.ssjs | Flags all SSJS API calls as MCN-unsupported; all other SSJS quality rules disabled |
sfmc.configs['recommended-next'] | Both of the above + **/*.hbs | AMPscript MCN-aware + SSJS flagged + Handlebars rules for standalone .hbs files |
sfmc.configs['embedded-next'] | **/*.html, **/*.hbs | AMPscript MCN-aware + SSJS flagged + Handlebars rules for HTML-embedded code and .hbs |
sfmc.configs['strict-next'] | All of the above + HTML + **/*.hbs | All AMPscript rules at error severity + MCN flag; SSJS fully flagged; Handlebars rules on |
Standalone .hbs files (VS Code's built-in Handlebars language) are treated as MCN by default — Handlebars only runs on Marketing Cloud Next, so a .hbs file is always linted with the full Handlebars rule set. This is deliberately wired only into the -next configs; the classic recommended / strict (Engagement) configs never lint .hbs.
recommended-next, embedded-next, and strict-next are arrays — spread them with ....
// eslint.config.js — targeting Marketing Cloud Next
import sfmc from 'eslint-plugin-sfmc';
export default [...sfmc.configs['recommended-next'], ...sfmc.configs['embedded-next']];
amp-*)| Rule | Default | Description |
|---|---|---|
sfmc/amp-no-unknown-function | error | Disallow calls to unknown AMPscript functions |
sfmc/amp-no-mcn-unsupported | off (error in -next) | Flag AMPscript functions unavailable in the targeted MCN API version (apiVersion) |
sfmc/amp-function-arity | error | Enforce correct argument counts |
sfmc/amp-arg-types | error | Check that literal arguments match expected parameter types and allowed values |
sfmc/amp-set-requires-target | error | Require set to have a target variable |
sfmc/amp-no-smart-quotes | error | Disallow smart/curly quotes in strings |
sfmc/amp-no-var-redeclaration | warn | Disallow re-declaring a variable with var |
sfmc/amp-no-empty-block | warn | Disallow empty %%[ ]%% blocks |
sfmc/amp-no-loop-counter-assign | warn | Disallow assigning to the for loop counter |
sfmc/amp-no-inline-statement | warn | Disallow statements inside inline expressions |
sfmc/amp-no-deprecated-function | warn | Flag deprecated functions and suggest replacements |
sfmc/amp-naming-convention | warn | Enforce variable naming convention |
sfmc/amp-no-empty-then | warn | Disallow IF with empty THEN branch |
sfmc/amp-require-rowcount-check | warn | Require RowCount check before FOR on LookupRows |
sfmc/amp-no-html-comment | warn | Disallow HTML comments inside AMPscript blocks |
sfmc/amp-no-js-line-comment | warn | Disallow JS-style // line comments in AMPscript |
sfmc/amp-no-nested-script-tag | error | Disallow <script> tags nested inside AMPscript script tags |
sfmc/amp-no-nested-ampscript-delimiter | error | Disallow AMPscript delimiters nested inside AMPscript blocks |
sfmc/amp-prefer-attribute-value | off | Prefer AttributeValue() over bare personalization |
sfmc/amp-require-variable-declaration | off | Require var before set |
sfmc/amp-no-email-excluded-function | off | Flag functions unavailable in email context |
ssjs-*)| Rule | Default | Description |
|---|---|---|
sfmc/ssjs-require-platform-load | error | Require Platform.Load("core") before Core or requiresCoreLoad globals |
sfmc/ssjs-no-unsupported-syntax | error | Flag ES6+ syntax not supported by SFMC |
sfmc/ssjs-no-unknown-function | error | Disallow unknown methods on Platform.*, HTTP, Core Library, and WSProxy |
sfmc/ssjs-no-mcn-unsupported | off (error in -next) | Flag all SSJS API usage as unsupported in Marketing Cloud Next |
sfmc/ssjs-no-deprecated-function | error | Flag use of deprecated SFMC SSJS APIs (Classic Content classes, ErrorUtil) |
sfmc/ssjs-no-nonexistent-global | error | Flag documented SSJS globals that throw ReferenceError at runtime |
sfmc/ssjs-no-property-call | error | Disallow calling Platform.Request/Response properties as functions |
sfmc/ssjs-no-clr-header-access | error | Disallow CLR-unsafe reads of HttpResponse.headers; read via for..in |
sfmc/ssjs-require-string-clr-content | error | Require wrapping HttpResponse.content with String() before use |
sfmc/ssjs-platform-function-arity | error | Enforce correct arity for Platform.Function.* |
sfmc/ssjs-require-platform-load-order | error | Require Platform.Load() before Core usage in order |
sfmc/ssjs-no-hardcoded-credentials | error | Flag hardcoded keys in encryption calls |
sfmc/ssjs-cache-loop-length | warn | Require caching .length in for-loops |
sfmc/ssjs-require-hasownproperty | warn | Require hasOwnProperty guard in for-in loops |
sfmc/ssjs-prefer-platform-load-version | warn | Enforce a minimum Platform.Load version string |
sfmc/ssjs-no-unavailable-method | warn | Flag Array/String methods unavailable or broken in SFMC's ES3 engine |
sfmc/ssjs-no-nonfunctional-method | warn | Flag Core Library methods that never take effect at runtime |
sfmc/ssjs-prefer-parsejson-safe-arg | warn | Require string coercion on ParseJSON argument |
sfmc/ssjs-no-switch-default | warn | Disallow default clause in switch statements |
sfmc/ssjs-no-treatascontent-injection | warn | Flag dynamic string concatenation in TreatAsContent calls |
sfmc/ssjs-core-method-arity | warn | Enforce correct argument counts for Core Library object methods |
sfmc/ssjs-arg-types | warn | Check that literal arguments match expected parameter types |
hbs-*)Handlebars is the templating language for Marketing Cloud Next (MCN) only. These rules are enabled at error severity in the -next configs — applied both to {{...}} extracted from HTML and to standalone .hbs files — and are off in the classic (Engagement) configs — in classic SFMC, {{...}} is plain content and must not be flagged.
| Rule | Default (-next) | Description |
|---|---|---|
sfmc/hbs-no-unknown-helper | error | Disallow helper invocations that are not part of the MCN catalog |
sfmc/hbs-no-unknown-binding | error | Disallow unknown {!$...} built-in data bindings |
sfmc/hbs-helper-arity | error | Enforce correct positional-argument counts for known helpers |
sfmc/hbs-no-unsupported-construct | error | Disallow constructs unsupported by the MCN engine (partials, decorators, log) |
sfmc/hbs-no-mcn-unsupported | error | Flag helpers and bindings unavailable in the targeted MCN API version (apiVersion) |
Email HTML for SFMC frequently contains Outlook conditional comments (<!--[if mso]>…<![endif]-->), MSO-only CSS, and VML fallbacks. These checks are provided by eslint-plugin-mso-email, which ships as a bundled dependency of eslint-plugin-sfmc — you do not load it separately.
The MSO rules are auto-included in the HTML-embedded configs: embedded, strict, embedded-next, and strict-next. When you lint an .html file with any of these, the combined sfmc/sfmc processor also extracts MSO conditional comments and the document body and runs the MSO rules on them — no extra processor or config to wire up, and no processor conflict.
Rule (mso/*) | Default (embedded/strict) | Description |
|---|---|---|
mso/valid-mso-condition | error | Validate the [if …] expression syntax of MSO comments |
mso/matching-mso-endif | error | Require every MSO opener to have a matching <![endif]> |
mso/matching-mso-endif-type | warn | Require the endif comment style to match its opener |
mso/no-unknown-mso-property | warn | Flag unknown mso-* CSS properties |
mso/vml-requires-namespace | warn | Require the v: VML namespace declaration when VML is used |
mso/no-unknown-vml-tag | warn | Flag unknown v:* VML tags |
mso/no-unknown-vml-attribute | warn | Flag unknown attributes on VML tags |
mso/table-presentation-role | warn | Require role="presentation" on layout tables |
Severities above are the same in embedded, strict, embedded-next, and strict-next (MSO markup is engine-agnostic — it behaves identically for Engagement and Next). For MSO rule details and options, see the eslint-plugin-mso-email docs.
eslint-plugin-unicorn with SFMCeslint-plugin-unicorn is a high-quality, widely used plugin that we strongly recommend — but it is built for modern JavaScript, not SFMC's SSJS runtime. SFMC SSJS runs on a JINT-based ES3/ES5-era engine that lacks many built-ins (Array#includes, String#startsWith, Set, Map, Object.fromEntries, Math.trunc, spread ..., ES modules, async/await, …).
If you enable unicorn's recommended set on SSJS, about 46 of its 308 recommended rules would either autofix your code to a missing built-in (breaking it at runtime) or forbid a required SFMC workaround. eslint-plugin-sfmc offers an optional override config that turns off exactly those 46 rules for SSJS.
Important — this is optional and only needed if you use unicorn. eslint-plugin-sfmc does not depend on or load unicorn. The override configs are plain rules objects with no plugins key, so they only resolve when your own unicorn config (which registers the unicorn plugin) is loaded earlier in the flat-config array. Spread the sfmc override after it:
import sfmc from 'eslint-plugin-sfmc';
import eslintPluginUnicorn from 'eslint-plugin-unicorn';
export default [
eslintPluginUnicorn.configs.recommended, // you opt in — registers the `unicorn` plugin
...sfmc.configs.recommended,
...sfmc.configs.embedded, // AMPscript + SSJS embedded in HTML (<script runat="server">)
...sfmc.configs['unicorn-ssjs'], // OPTIONAL: off the 46 SFMC-incompatible unicorn rules for SSJS
...sfmc.configs['unicorn-ssjs-embedded'], // OPTIONAL: same override for SSJS embedded in HTML (<script runat="server">)
];
| Config | Files | What it does |
|---|---|---|
sfmc.configs['unicorn-ssjs'] | **/*.ssjs | Turns off the 46 SFMC-incompatible unicorn rules for SSJS |
sfmc.configs['unicorn-ssjs-embedded'] | **/*.html/*.js | Same 46-rule override for SSJS embedded in HTML |
Only 46 of unicorn's 308 recommended rules are overridden — the other 262 stay active. If you don't use unicorn, omit these configs entirely. For the full rule-by-rule breakdown (with rationale and SFMC evidence links, pinned to unicorn v73.0.0), see docs/unicorn-compatibility.md.
| Processor | Purpose |
|---|---|
sfmc/ampscript | Extract %%[ ]%%, %%= =%%, <script language="ampscript"> |
sfmc/ssjs | Extract <script runat="server"> (non-ampscript) |
sfmc/sfmc | Combined: extracts AMPscript, SSJS, Handlebars, and MSO from HTML |
MIT
FAQs
ESLint plugin for Salesforce Marketing Cloud Engagement+Next - AMPscript, Server-Side JavaScript (SSJS) and Handlebars
The npm package eslint-plugin-sfmc receives a total of 397 weekly downloads. As such, eslint-plugin-sfmc popularity was classified as not popular.
We found that eslint-plugin-sfmc demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Socket is now in the AWS Security Hub Extended plan. Adopt it through AWS, apply committed spend, and block malicious open source packages.

Research
/Security News
Popular npm packages keyv and cacheable compromised.

Security News
A misconfiguration gave three Anthropic models internet access, and one, believing it was in a simulation, shipped a credential-stealing package to PyPI.