SSJS executes in several different contexts within Salesforce Marketing Cloud, each with different capabilities and constraints.

CloudPages (Landing Pages)

CloudPages is the most flexible SSJS environment. A landing page is a publicly accessible URL hosted by SFMC.

Capabilities:

  • Full request/response access (Platform.Request.*, Platform.Response.*)
  • Read query strings, POST bodies, cookies, headers
  • Set response headers, cookies, redirect
  • Make external HTTP calls
  • Full Data Extension CRUD

Limitations:

  • Requests time out (no documented limit, but ~30s is a practical ceiling for external calls)
Platform.Load("core", "1.1.5");
// String() converts the CLR value so === against a literal works
var method = String(Platform.Request.Method); // "GET" or "POST"
Write("<p>Request method: " + method + "</p>");
Show test script
<script runat="server">
/*
 * Chapter: CloudPages
 * Proves:
 *   1. On this CloudPage GET, Request.Method is GET.
 * EXPECTED OUTPUT: every line starts with PASS.
 */
function assert(id, actual, expected) {
    Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function typeOfThunk(fn) {
    try { return "" + fn(); } catch (ex) { return "THREW:" + ("" + ex.message); }
}
assert("Method GET", "" + Platform.Request.Method, "GET");
</script>

JSON Code Resources

A special CloudPages type that sets Content-Type: application/json. Perfect for building simple API endpoints:

Platform.Load("core", "1.1.5");

var result = { status: "ok", timestamp: Platform.Function.Now() };
Write(Platform.Function.Stringify(result));

You cannot write HTML and JSON in the same resource — the first Write() determines the content type behavior. Set the header explicitly at the top.

Show test script
<script runat="server">
/*
 * Chapter: JSON Code Resources
 * Proves:
 *   1. ContentType assignment works (opaque read is CLR).
 * EXPECTED OUTPUT: every line starts with PASS.
 */
function assert(id, actual, expected) {
    Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function typeOfThunk(fn) {
    try { return "" + fn(); } catch (ex) { return "THREW:" + ("" + ex.message); }
}
Platform.Response.ContentType = "application/json";
assert("ContentType read typeof clr", typeof Platform.Response.ContentType, "clr");
</script>

Email (Precompile)

SSJS in emails runs during precompile — when SFMC personalizes the email for each subscriber before sending. This is the most constrained environment.

Limitations:

  • No request/response access (Platform.Request.* returns empty values)
  • No Platform.Response.*
  • Significant performance penalty compared to AMPscript — prefer AMPscript for data lookups
  • Short execution window — keep logic minimal
  • WSProxy works but is slower per-send than AMPscript equivalents

Valid use cases in email:

  • Complex conditional logic that AMPscript can’t express cleanly
  • JSON manipulation
  • Custom function definitions for reuse
<script runat="server">
// String() first — a Lookup result throws on a truthiness test when the field is empty
var firstName = String(Platform.Function.Lookup("Subscribers", "FirstName", "SubscriberKey", _subscriberKey));
var displayName = (firstName === "" || firstName === "null") ? "Subscriber" : firstName;
Variable.SetValue("@displayName", displayName);
</script>
%%=v(@displayName)=%%
Show test script
<script runat="server">
/*
 * Chapter: Email
 * Proves:
 *   1. NON-ASSERTABLE on CloudPage: email precompile context.
 *   Recorded as CloudPage-only probe.
 * EXPECTED OUTPUT: every line starts with PASS.
 */
function assert(id, actual, expected) {
    Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function typeOfThunk(fn) {
    try { return "" + fn(); } catch (ex) { return "THREW:" + ("" + ex.message); }
}
assert("cloudpage-context-only", "documented", "documented");
</script>

Automation Studio (Script Activities)

Script Activities let you run SSJS as a step in an Automation. This is how SSJS is used for scheduled batch processing.

Capabilities:

  • Full SOAP API access via WSProxy
  • Data Extension operations
  • No request/response (not a web context)
  • Hard 30-minute timeout per execution

Practical patterns:

  • Batch-process rows in chunks to stay under the timeout
  • Log progress to a Data Extension
  • Use Platform.Function.Now() and date math to track elapsed time
Platform.Load("core", "1.1.5");

var startTime = new Date();
var maxMinutes = 25; // Leave 5-minute buffer

var proxy = new Script.Util.WSProxy();
var results = proxy.retrieve("DataExtension", ["CustomerKey", "Name"]);

var processed = 0;
for (var i = 0; i < results.Results.length; i++) {
    // Check elapsed time
    var elapsed = (new Date() - startTime) / 60000;
    if (elapsed > maxMinutes) { break; }

    // Process each item...
    processed++;
}

Write("Processed: " + processed + " items");
Show test script
<script runat="server">
/*
 * Chapter: Automation Studio
 * Proves:
 *   1. NON-ASSERTABLE on CloudPage: automation context.
 * EXPECTED OUTPUT: every line starts with PASS.
 */
function assert(id, actual, expected) {
    Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function typeOfThunk(fn) {
    try { return "" + fn(); } catch (ex) { return "THREW:" + ("" + ex.message); }
}
assert("cloudpage-context-only", "documented", "documented");
</script>

Triggered Send (Email)

Similar to email precompile. SSJS runs when a triggered send fires for a subscriber.

Note: Platform.Request.* is not available in triggered send context.

Show test script
<script runat="server">
/*
 * Chapter: Triggered Send
 * Proves:
 *   1. NON-ASSERTABLE on CloudPage.
 * EXPECTED OUTPUT: every line starts with PASS.
 */
function assert(id, actual, expected) {
    Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function typeOfThunk(fn) {
    try { return "" + fn(); } catch (ex) { return "THREW:" + ("" + ex.message); }
}
assert("cloudpage-context-only", "documented", "documented");
</script>

MobileConnect (SMS)

SSJS can run in MobileConnect context for SMS personalization, with significant limitations. Most data operations work, but HTTP and some response functions do not.

Show test script
<script runat="server">
/*
 * Chapter: MobileConnect
 * Proves:
 *   1. NON-ASSERTABLE on CloudPage.
 * EXPECTED OUTPUT: every line starts with PASS.
 */
function assert(id, actual, expected) {
    Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function typeOfThunk(fn) {
    try { return "" + fn(); } catch (ex) { return "THREW:" + ("" + ex.message); }
}
assert("cloudpage-context-only", "documented", "documented");
</script>

Summary Table

Context Request/Response HTTP Calls Platform.Load WSProxy Rows.Retrieve
CloudPage ✅ Full
JSON Code Resource
Email (precompile) ✅ (slow)
Automation Studio
Triggered Send
MobileConnect Partial

→ Next: Embedding SSJS

Show test script
<script runat="server">
/*
 * Chapter: Summary Table
 * Proves:
 *   1. Platform.Request available here (CloudPage row of the table).
 * EXPECTED OUTPUT: every line starts with PASS.
 */
function assert(id, actual, expected) {
    Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function typeOfThunk(fn) {
    try { return "" + fn(); } catch (ex) { return "THREW:" + ("" + ex.message); }
}
assert("Request typeof", typeof Platform.Request, "clr");
</script>