AMPscript Bridge
Patterns for passing data between AMPscript and SSJS — reading AMPscript variables, sharing computation results, and mixing AMPscript rendering with SSJS logic.
Reading AMPscript Variables in SSJS
%%[
SET @subscriberKey = _subscriberkey
SET @emailAddr = emailaddr
SET @firstName = FirstName
]%%
<script runat="server">
var subKey = Platform.Variable.GetValue("@subscriberKey");
var email = Platform.Variable.GetValue("@emailAddr");
var firstName = Platform.Variable.GetValue("@firstName");
// Now use these in SSJS logic
var score = Platform.Function.Lookup("LeadScores", "score", "email", email);
Platform.Variable.SetValue("@leadScore", score);
</script>
%%[ /* Render the SSJS-computed value in AMPscript */ ]%%
Lead score: %%=v(@leadScore)=%%
Show test script
<script runat="server">
/*
* Chapter: Reading AMPscript Variables in SSJS
* Proves:
* 1. SetValue/GetValue round-trip (SSJS-side stand-in for AMPscript SET).
* 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); }
}
Platform.Variable.SetValue("@subscriberKey", "sk-1");
Platform.Variable.SetValue("@leadScore", 42);
assert("GetValue sk", Platform.Variable.GetValue("@subscriberKey"), "sk-1");
assert("GetValue score number", Platform.Variable.GetValue("@leadScore"), 42);
</script>
Passing SSJS Results to AMPscript Rendering
// SSJS computes complex logic
var tier = "standard";
if (parseInt(score, 10) > 80) tier = "premium";
if (parseInt(score, 10) > 95) tier = "vip";
Platform.Variable.SetValue("@tier", tier);
Platform.Variable.SetValue("@discountCode", discountCodes[tier]);
%%[ IF @tier == "vip" THEN ]%%
<div class="vip-banner">Welcome, VIP!</div>
<p>Your exclusive code: %%=v(@discountCode)=%%</p>
%%[ ELSEIF @tier == "premium" THEN ]%%
<p>Premium member discount: %%=v(@discountCode)=%%</p>
%%[ ELSE ]%%
<p>Standard member</p>
%%[ ENDIF ]%%
Show test script
<script runat="server">
/*
* Chapter: Passing SSJS Results to AMPscript Rendering
* Proves:
* 1. Tier computation + SetValue.
* 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); }
}
var score = "90";
var tier = "standard";
if (parseInt(score, 10) > 80) tier = "premium";
if (parseInt(score, 10) > 95) tier = "vip";
Platform.Variable.SetValue("@tier", tier);
assert("tier premium", Platform.Variable.GetValue("@tier"), "premium");
</script>
Safe URL Encoding via AMPscript
AMPscript’s URLEncode has more encoding options than SSJS:
Variable.SetValue("@rawValue", userInput);
Platform.Function.TreatAsContent("%%[SET @encoded = URLEncode(@rawValue, 1, 1)]%%");
var encoded = Variable.GetValue("@encoded");
Show test script
<script runat="server">
/*
* Chapter: Safe URL Encoding via AMPscript
* Proves:
* 1. Variable + TreatAsContent URLEncode path.
* 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); }
}
Platform.Load("core", "1.1.5");
Variable.SetValue("@rawValue", "a b");
Platform.Function.TreatAsContent("%%[SET @encoded = URLEncode(@rawValue, 1, 1)]%%");
var encoded = Variable.GetValue("@encoded");
assert("encoded has percent-or-plus", ("" + encoded).indexOf("%") >= 0 || ("" + encoded).indexOf("+") >= 0 ? "true" : "false", "true");
</script>
Using Platform.Function.TreatAsContent Safely
Never pass user input directly to Platform.Function.TreatAsContent(). Use Variable.SetValue() first so the value arrives as data and is never parsed as AMPscript source. This stops AMPscript injection — but it is not output encoding: v() encodes nothing and TreatAsContent() sanitises nothing, so <script>alert(1)</script> comes back byte-for-byte. HTML-encode the result yourself before writing it into a page — see Security → Output Encoding.
// Output encoder — canonical copy lives in Security → Output Encoding
function htmlEncode(str) {
return (str + "")
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
// SAFE against AMPscript injection
Variable.SetValue("@name", userName);
Variable.SetValue("@code", promoCode);
var rendered = Platform.Function.TreatAsContent("Hello, %%=v(@name)=%%. Your code is %%=v(@code)=%%.");
// Still unsafe to write raw — the rendered string is not HTML-encoded.
Write(htmlEncode(rendered));
// DANGEROUS — never do this:
// Platform.Function.TreatAsContent(userInput); // AMPscript injection!
Show test script
<script runat="server">
/*
* Chapter: Using TreatAsContent Safely
* Proves:
* 1. htmlEncode; TreatAsContent via Variable.
* 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); }
}
Platform.Load("core", "1.1.5");
function htmlEncode(str) {
return (str + "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
}
assert("htmlEncode", htmlEncode("<x>"), "<x>");
Variable.SetValue("@tac", "hi");
assert("TreatAsContent v()", Platform.Function.TreatAsContent("%%=v(@tac)=%%"), "hi");
</script>
Reading Subscriber Attributes in SSJS
%%[
SET @city = AttributeValue("City")
SET @language = AttributeValue("PreferredLanguage")
]%%
<script runat="server">
var city = Platform.Variable.GetValue("@city");
var language = Platform.Variable.GetValue("@language") || "en";
// Or use the global Attribute object directly
var city2 = Attribute.GetValue("City");
</script>
Show test script
<script runat="server">
/*
* Chapter: Reading Subscriber Attributes in SSJS
* Proves:
* 1. Attribute.GetValue typeof after Core (CloudPage may return empty).
* NON-ASSERTABLE: real send-time personalization strings.
* 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); }
}
Platform.Load("core", "1.1.5");
assert("Attribute typeof", typeOfThunk(function () { return typeof Attribute; }), "object");
assert("GetValue typeof", typeOfThunk(function () { return typeof Attribute.GetValue; }), "function");
</script>
JSON Data Bridge
Pass complex data from AMPscript to SSJS via JSON strings:
%%[
SET @productJson = LookupRows("Products", "Category", "featured")
]%%
<script runat="server">
// Better: use SSJS to retrieve directly
var products = Platform.Function.LookupRows("Products", "Category", "featured");
// products is already an array in SSJS
</script>
For data computed in SSJS and consumed in AMPscript, use simple string variables since AMPscript doesn’t parse JSON natively:
// SSJS
Platform.Variable.SetValue("@productCount", products.length);
Platform.Variable.SetValue("@topProduct", products[0] ? products[0].Name : "");
%%[ /* AMPscript */ ]%%
We have %%=v(@productCount)=%% featured products.
Top pick: %%=v(@topProduct)=%%
Show test script
<script runat="server">
/*
* Chapter: JSON Data Bridge
* Proves:
* 1. Stringify then SetValue then ParseJSON round-trip.
* 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); }
}
var payload = { a: 1, b: "x" };
var json = Platform.Function.Stringify(payload);
Platform.Variable.SetValue("@jsonBridge", json);
var back = Platform.Function.ParseJSON(Platform.Variable.GetValue("@jsonBridge") + "");
assert("round-trip a", back.a, 1);
assert("round-trip b", back.b, "x");
</script>