Variable
→ objectThe global Variable object provides access to AMPscript variables from SSJS, enabling bidirectional data exchange between the two scripting languages.
Syntax
Variable.GetValue(name)
Variable.SetValue(name, value)
Methods
| Method | Returns | Description |
|---|---|---|
Variable.GetValue(name) |
string, number, boolean, or null | Gets the value of an AMPscript variable |
Variable.SetValue(name, value) |
undefined | Sets the value of an AMPscript variable |
Official docs describe a string GetValue return. Runtime preserves number and boolean scalars and returns JavaScript null for a never-set variable. SetValue returns undefined (void-like), while Platform.Variable.SetValue returns null — both share the same request-local variable state.
Show test script — return types vs official docs
<script runat="server">
/*
* Chapter: Methods — Variable.GetValue / Variable.SetValue
*
* Proves:
* 1. After Platform.Load("core", "1.1.5") Variable.GetValue and
* Variable.SetValue are callable.
* 2. GetValue returns the stored scalar (string / number / boolean)
* or strict null when never set.
* 3. SetValue returns undefined (void-like; Methods table: undefined).
* 4. DEV: GetValue preserves number/boolean and returns null when never
* set (official docs: string).
* 5. DEV vs Platform.Variable: Platform.Variable.SetValue returns null
* while bare Variable.SetValue returns undefined.
* 6. SetValue accepts string, number, boolean, empty string, null,
* and undefined; null/undefined read back as null.
*
* NON-ASSERTABLE: personalization strings (_subscriberKey, emailaddr)
* require send/subscriber context — not present on a plain CloudPage GET.
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function assertThrows(id, fn) {
var threw = false, msg = "";
try { fn(); } catch (ex) { threw = true; msg = "" + ex.message; }
Platform.Response.Write((threw ? "PASS " : "FAIL ") + id + " -> " + (threw ? "threw: " + msg : "did NOT throw") + "\n");
}
function typeOfThunk(fn) {
try { return "" + fn(); } catch (ex) { return "THREW:" + ("" + ex.message); }
}
function capture(fn) {
try { return { threw: false, value: fn() }; } catch (ex) { return { threw: true, message: "" + ex.message }; }
}
Platform.Load("core", "1.1.5");
assert("typeof Variable is object after Core load", typeOfThunk(function () { return typeof Variable; }), "object");
assert("typeof Variable.GetValue is function", typeOfThunk(function () { return typeof Variable.GetValue; }), "function");
assert("typeof Variable.SetValue is function", typeOfThunk(function () { return typeof Variable.SetValue; }), "function");
var setRet = Variable.SetValue("@coreVarMethodsStr", "hello");
assert("SetValue returns undefined", setRet === undefined ? "undefined" : "other", "undefined");
assert("SetValue return typeof is undefined", "" + (typeof setRet), "undefined");
var platRet = Platform.Variable.SetValue("@coreVarMethodsStrPlat", "hello-plat");
assert("DEV Platform.Variable.SetValue returns null (bare returns undefined)", platRet === null ? "null" : "other", "null");
assert("GetValue returns the string that was set", Variable.GetValue("@coreVarMethodsStr"), "hello");
assert("GetValue string typeof is string", "" + (typeof Variable.GetValue("@coreVarMethodsStr")), "string");
Variable.SetValue("@coreVarMethodsNum", 42);
var numVal = Variable.GetValue("@coreVarMethodsNum");
assert("DEV GetValue preserves number (official docs: string)", numVal, 42);
assert("DEV GetValue number typeof is number (official docs: string)", "" + (typeof numVal), "number");
Variable.SetValue("@coreVarMethodsTrue", true);
assert("DEV GetValue preserves boolean true (official docs: string)", Variable.GetValue("@coreVarMethodsTrue"), true);
var missing = Variable.GetValue("@coreVarMethodsMissing20260803");
assert("DEV never-set GetValue is strict null (official docs: string)", missing === null ? "null" : "other", "null");
assert("DEV never-set GetValue typeof is object", "" + (typeof missing), "object");
Variable.SetValue("@coreVarMethodsEmpty", "");
assert("explicit empty string remains empty", Variable.GetValue("@coreVarMethodsEmpty"), "");
var setNull = capture(function () { return Variable.SetValue("@coreVarMethodsNull", null); });
var unset;
var setUndef = capture(function () { return Variable.SetValue("@coreVarMethodsUndef", unset); });
assert("SetValue null does not throw", setNull.threw ? "threw:" + setNull.message : "returned", "returned");
assert("null input reads back strict null", Variable.GetValue("@coreVarMethodsNull") === null ? "null" : "other", "null");
assert("SetValue undefined does not throw", setUndef.threw ? "threw:" + setUndef.message : "returned", "returned");
assert("undefined input reads back strict null", Variable.GetValue("@coreVarMethodsUndef") === null ? "null" : "other", "null");
</script>
Description
The global Variable object provides the bridge between AMPscript and SSJS. AMPscript variables are prefixed with @ and live in a shared scope accessible by both languages on the same page.
After Platform.Load("core", "1.1.5"), bare Variable.GetValue / Variable.SetValue share request-local state with Platform.Variable. GetValue behaviour matches the Platform form; SetValue returns undefined here, while Platform.Variable.SetValue returns null.
Show test script
<script runat="server">
/*
* Chapter: Description — Variable is the Core alias of Platform.Variable
*
* Proves:
* 1. Before Platform.Load the bare Variable is undefined; invoking
* GetValue throws. typeof is resolved inside a thunk.
* 2. Platform.Variable is available without Platform.Load.
* 3. After Platform.Load("core", "1.1.5") Variable is an object and
* shares request-local state with Platform.Variable.
* 4. DEV: bare SetValue returns undefined; Platform.Variable.SetValue
* returns null — state is shared, return values are not identical.
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function assertThrows(id, fn) {
var threw = false, msg = "";
try { fn(); } catch (ex) { threw = true; msg = "" + ex.message; }
Platform.Response.Write((threw ? "PASS " : "FAIL ") + id + " -> " + (threw ? "threw: " + msg : "did NOT throw") + "\n");
}
function typeOfThunk(fn) {
try { return "" + fn(); } catch (ex) { return "THREW:" + ("" + ex.message); }
}
assert("before load typeof Variable is undefined", typeOfThunk(function () { return typeof Variable; }), "undefined");
assertThrows("before load Variable.GetValue throws", function () { return Variable.GetValue("@x"); });
assert("Platform.Variable exists without load", typeOfThunk(function () { return typeof Platform.Variable; }), "clr");
Platform.Load("core", "1.1.5");
assert("after load typeof Variable is object", typeOfThunk(function () { return typeof Variable; }), "object");
Variable.SetValue("@coreVarDescAlias", "alias-roundtrip");
assert("bare Variable shares Platform.Variable state", Platform.Variable.GetValue("@coreVarDescAlias"), "alias-roundtrip");
Platform.Variable.SetValue("@coreVarDescFromPlatform", "from-platform");
assert("Platform.Variable writes are visible via bare Variable", Variable.GetValue("@coreVarDescFromPlatform"), "from-platform");
var bareSetRet = Variable.SetValue("@coreVarDescRet", "r");
var platSetRet = Platform.Variable.SetValue("@coreVarDescRetPlat", "r");
assert("DEV bare SetValue returns undefined (Platform returns null)", bareSetRet === undefined ? "undefined" : "other", "undefined");
assert("DEV Platform.Variable.SetValue returns null (bare returns undefined)", platSetRet === null ? "null" : "other", "null");
</script>
Examples
Read an AMPscript variable
%%[
SET @subscriberKey = _subscriberKey
SET @emailAddress = emailaddr
]%%
<script runat="server">
// Read variables set by AMPscript
var sk = Variable.GetValue("@subscriberKey");
var email = Variable.GetValue("@emailAddress");
Write("<p>Processing: " + email + "</p>");
</script>
Write an AMPscript variable
<script runat="server">
var data = String(Platform.Function.Lookup("Preferences", "Theme", "SubscriberKey", sk));
// Never use `data || "light"` on a raw Lookup result — a NULL field throws
var theme = (data === "" || data === "null") ? "light" : data;
Variable.SetValue("@theme", theme);
</script>
<!-- Use the variable in AMPscript -->
<body class="theme-%%=v(@theme)=%%">
Bridge pattern for AMPscript functions
The most important use: safely pass values into AMPscript functions via Platform.Function.TreatAsContent:
// Safe: set value via Variable.SetValue, reference by name in AMPscript
Variable.SetValue("@inputStr", userValue);
Platform.Function.TreatAsContent("%%[Set @encoded = URLEncode(@inputStr, 1, 1)]%%");
var encoded = Variable.GetValue("@encoded");
This pattern avoids AMPscript injection vulnerabilities.
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: Examples — read / write / TreatAsContent bridge
*
* Prerequisite: a preceding AMPscript block sets @coreVarExAmpSk and
* @coreVarExAmpEmail (stand-ins for the page's @subscriberKey / @emailAddress).
*
* Proves:
* 1. Variable.GetValue reads AMPscript-set values in the same request.
* 2. Variable.SetValue writes a value readable by later SSJS (and by
* later AMPscript in a combined harness).
* 3. The TreatAsContent bridge: SetValue -> TreatAsContent(URLEncode) ->
* GetValue returns the encoded result (injection-safe pattern).
* 4. SetValue with the String()-first fallback stores the fallback when
* the lookup produced no usable value. The example deliberately does
* NOT use `data || "light"`: truthiness on a raw Lookup result throws
* when the matched row's field is NULL (see platform-functions/lookup).
* Asserted here on the same underlying facts, using the two values a
* Lookup can produce for "no usable value" — a genuine JavaScript null
* (no matching row) and an empty string (a blank field) — plus a real
* value to prove the guard does not fire on it.
*
* NOT ASSERTED: that the CLR null a never-populated DE field returns also
* stringifies to "" and is caught by the same guard. That needs a data
* extension fixture, which this chapter does not create; it is proven in the
* empty-returns chapter of platform-functions--lookup.yml.
*
* NON-ASSERTABLE: Lookup("Preferences", ...) DE row; personalization
* strings _subscriberKey / emailaddr on a plain CloudPage GET.
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
assert("read AMPscript @coreVarExAmpSk", Variable.GetValue("@coreVarExAmpSk"), "sk-example");
assert("read AMPscript @coreVarExAmpEmail", Variable.GetValue("@coreVarExAmpEmail"), "user@example.com");
/* The example's guard, on a no-match Lookup result (a genuine JS null). */
var noMatch = null;
var dataNoMatch = String(noMatch);
assert("String() of a no-match Lookup result is the string \"null\"", dataNoMatch, "null");
Variable.SetValue("@theme", (dataNoMatch === "" || dataNoMatch === "null") ? "light" : dataNoMatch);
assert("write fallback theme when the lookup found no row", Variable.GetValue("@theme"), "light");
/* The same guard, on a blank field (an ordinary empty string). */
var dataBlank = String("");
assert("String() of a blank field is the empty string", dataBlank, "");
Variable.SetValue("@themeBlank", (dataBlank === "" || dataBlank === "null") ? "light" : dataBlank);
assert("write fallback theme when the field is blank", Variable.GetValue("@themeBlank"), "light");
/* The guard must NOT fire on a real value. */
var dataReal = String("dark");
Variable.SetValue("@themeReal", (dataReal === "" || dataReal === "null") ? "light" : dataReal);
assert("a real lookup value is stored unchanged, the fallback does not fire", Variable.GetValue("@themeReal"), "dark");
Variable.SetValue("@inputStr", "hello world");
var pct = "%" + "%";
Platform.Function.TreatAsContent(pct + "[Set @encoded = URLEncode(@inputStr, 1, 1)]" + pct);
var encoded = Variable.GetValue("@encoded");
assert("bridge GetValue returns a string", "" + (typeof encoded), "string");
assert("bridge encoded differs from raw input", encoded === "hello world" ? "same" : "encoded", "encoded");
assert("bridge encoded is non-empty", encoded && ("" + encoded).length > 0 ? "true" : "false", "true");
assert("bridge encoded contains encoded space or plus", (("" + encoded).indexOf("%20") >= 0 || ("" + encoded).indexOf("+") >= 0) ? "true" : "false", "true");
</script>
Notes
Variable names must include the @ prefix:
Variable.SetValue("@name", "Jane"); // ✅ correct
Variable.SetValue("name", "Jane"); // ⚠️ may work but non-standard
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: Notes — @ prefix is correct; bare name may work
*
* Proves:
* 1. Variable.SetValue("@name", ...) is the correct form and round-trips.
* 2. Variable.SetValue("name", ...) without @ also addresses the same
* variable (page: may work but non-standard).
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
Variable.SetValue("@name", "Jane");
assert("SetValue with @ prefix round-trips", Variable.GetValue("@name"), "Jane");
assert("GetValue without @ finds the same @name", Variable.GetValue("name"), "Jane");
Variable.SetValue("name", "Jane-bare");
assert("DEV SetValue without @ may work (non-standard)", Variable.GetValue("@name"), "Jane-bare");
assert("bare SetValue is visible via @ GetValue", Variable.GetValue("name"), "Jane-bare");
</script>