Overview
Server-Side JavaScript (SSJS) is a scripting language built into Salesforce Marketing Cloud that allows you to interact with the platform's data and services programmatically. Unlike client-side JavaScript, SSJS runs on the SFMC server — it executes before the page or email is delivered to the subscriber.
SSJS is available in three contexts:
- Email content areas — embedded in email HTML alongside AMPscript
- CloudPages — powering dynamic landing pages, microsites, and forms
- Smart Capture forms — processing form submissions and writing to Data Extensions
Both can personalise emails and interact with Data Extensions, but SSJS is better suited for complex logic, loops, and HTTP calls, while AMPscript is lighter and executes faster in high-volume email sends. See the comparison section below.
SSJS vs AMPscript
| Capability | SSJS | AMPscript |
|---|---|---|
| Email personalisation | ✓ | ✓ (preferred) |
| CloudPages / landing pages | ✓ (preferred) | ✓ |
| HTTP / REST API calls | ✓ | Limited |
| Complex loops & logic | ✓ | Limited |
| Write to Data Extensions | ✓ | ✓ |
| Execution speed at scale | Slower | Faster |
| Syntax | JavaScript-like | Proprietary tag language |
A common pattern is to use AMPscript for email content personalisation and SSJS for CloudPage logic, form handling, and API integrations.
Script blocks
SSJS code lives inside <script> tags with the runat attribute. The value controls where the code executes:
<script runat="server">
Platform.Load("Core", "1");
var firstName = Variable.GetValue("@FirstName");
Write("Hello, " + firstName + "!");
</script>
The runat values you'll use most:
runat="server"— standard execution, output replaces the script blockrunat="server" executioncontexttype="post"— runs after the page renders (useful for form processing)
SSJS requires you to explicitly load a library before using its functions. Forgetting Platform.Load() is one of the most common causes of SSJS errors.
Core library
The Core library provides general-purpose utilities — string manipulation, date functions, encoding, and variable access. Load it with:
Platform.Load("Core", "1");
Commonly used Core functions:
Platform.Load("Core", "1");
// Write output to the page
Write("<p>Hello World</p>");
// Get AMPscript variable value
var firstName = Variable.GetValue("@FirstName");
// Set an AMPscript variable from SSJS
Variable.SetValue("@greeting", "Welcome back, " + firstName);
// String utilities
var upper = String.Trim(" hello "); // "hello"
var encoded = Platform.Function.Base64Encode("text");
// Date utilities
var today = Platform.Function.Now();
var formatted = Platform.Function.Format(today, "yyyy-MM-dd");
Platform library
The Platform library gives you access to SFMC-specific objects — Data Extensions, subscriber records, tracking data, and more.
Platform.Load("Core", "1");
// Platform objects are available after loading Core
Key Platform objects:
DataExtension— read, write, and query DE rowsSubscriber— access subscriber attributesContentBlockByKey— retrieve content block HTMLAuthenticatedMemberID— get the current MIDHTTPS— make HTTP requests to external APIs
Working with Data Extensions
SSJS can read, write, update, and upsert rows in any Data Extension your running context has access to.
Platform.Load("Core", "1");
var de = DataExtension.Init("CustomerPreferences");
var row = de.Rows.Lookup(["EmailAddress"], [Variable.GetValue("@EmailAddress")]);
if (row.length > 0) {
var preferredChannel = row[0]["PreferredChannel"];
Write(preferredChannel);
}
Platform.Load("Core", "1");
var de = DataExtension.Init("FormSubmissions");
var result = de.Rows.Add({
EmailAddress: Request.GetFormField("email"),
Name: Request.GetFormField("name"),
SubmittedAt: Platform.Function.Now()
});
if (result === "Created" || result === "Updated") {
// Success
}
Platform.Load("Core", "1");
var de = DataExtension.Init("Products");
var rows = de.Rows.Retrieve({
Property: "CategoryID",
SimpleOperator: "equals",
Value: "42"
});
for (var i = 0; i < rows.length; i++) {
Write("<li>" + rows[i]["ProductName"] + "</li>");
}
HTTP requests
The HTTPS object lets SSJS call external REST APIs — useful for pulling in live data, posting form results to third-party systems, or triggering webhooks.
Platform.Load("Core", "1");
var url = "https://api.example.com/v1/products/42";
var header = ["Authorization", "Bearer YOUR_TOKEN"];
var result = HTTPS.Get(url, [header]);
if (result.StatusCode === 200) {
var data = Platform.Function.ParseJSON(result.Response[0]);
Write(data.productName);
}
Platform.Load("Core", "1");
var url = "https://api.example.com/v1/submissions";
var headers = [["Content-Type", "application/json"], ["Authorization", "Bearer YOUR_TOKEN"]];
var payload = Platform.Function.Stringify({
email: Request.GetFormField("email"),
name: Request.GetFormField("name")
});
var result = HTTPS.Post(url, "application/json", payload, headers);
if (result.StatusCode === 200 || result.StatusCode === 201) {
Redirect("https://yoursite.com/thank-you");
}
Never hardcode API tokens in SSJS code. Instead, store them in a locked Data Extension (accessible only from SSJS/AMPscript) and retrieve them at runtime using DataExtension.Init().
CloudPages & landing pages
SSJS is the primary scripting language for CloudPages. Common use cases:
- Form capture pages — read POST fields with
Request.GetFormField()and write to a DE - Preference centres — show current subscriber preferences and save updates
- Microsites — build multi-page experiences driven by DE data
- API endpoints — create lightweight REST-style endpoints within SFMC
<script runat="server" executioncontexttype="post">
Platform.Load("Core", "1");
var email = Request.GetFormField("email");
var name = Request.GetFormField("name");
if (email && name) {
var de = DataExtension.Init("LeadCapture");
de.Rows.Add({
EmailAddress: email,
FullName: name,
SubmittedAt: Platform.Function.Now(),
Source: "CloudPage-LeadForm"
});
Variable.SetValue("@formStatus", "success");
} else {
Variable.SetValue("@formStatus", "error");
}
</script>
%%[
IF @formStatus == "success" THEN
]%%
<p>Thanks — we'll be in touch!</p>
%%[
ELSE
]%%
<p>Please fill in all fields.</p>
%%[
ENDIF
]%%
Debugging
SSJS errors can be opaque. These techniques help narrow down issues:
Platform.Load("Core", "1");
try {
var de = DataExtension.Init("MyDE");
var rows = de.Rows.Retrieve();
Write("Row count: " + rows.length);
} catch (e) {
Write("Error: " + Stringify(e));
}
- Wrap all DE and HTTP calls in
try/catchblocks to surface error objects - Use
Write(Stringify(obj))to dump object contents during development - Check the SFMC error log via Setup → Monitoring → Error Log
- Test CloudPages with the Preview button before publishing
- Use a test Data Extension to validate writes before touching production data
Best practices
Follow these patterns to keep SSJS reliable and maintainable:
- Always load a library first —
Platform.Load("Core", "1");must be your first line - Use try/catch everywhere — SSJS errors silently fail; wrap all external calls
- Prefer AMPscript for email sends — SSJS adds processing overhead at scale
- Never expose credentials in code — store API keys in locked DEs
- Use
Redirect()not HTML meta refresh — server-side redirect is cleaner and faster - Validate all form inputs — check for empty values and sanitise before writing to DEs
- Test on a sandbox BU — always validate DE writes on a non-production Business Unit first
- Comment your code — SFMC SSJS is often maintained by different teams; clarity matters