BeginImpressionRegion
→ voidMarks the start of a named impression region in rendered content. Unusable from SSJS — every call throws; impression regions are an AMPscript-only feature.
Syntax
Platform.Function.BeginImpressionRegion(name)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Identifier for the impression region |
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: Parameters — Platform.Function.BeginImpressionRegion(name)
*
* Proves:
* 1. The member resolves on Platform.Function (typeof "clrmethodinfo",
* the engine's marker for a host CLR method).
* 2. DEV the 1-argument form — the documented, correct call shape — does
* NOT succeed: it throws. The official docs describe it as a working
* call taking one string region name.
* 3. The rejection is independent of the argument's type: a string
* literal, a number literal, a boolean literal and null all throw.
* The printed message is the same resolved-value error in every case.
* 4. Arities outside the documented 1-argument signature (0 and 2) also
* throw.
*
* SCOPE: run as a CloudPage GET only. Nothing below asserts how the call
* behaves inside an actual email send.
*
* NOT ASSERTED: the exact text of the thrown message. Any string operation
* on this CLR exception message (.length / .indexOf / .substring) aborts
* the CloudPage with HTTP 422, so the message is printed verbatim next to
* each assertion for the reader instead of being matched programmatically.
*
* EXPECTED OUTPUT: every line starts with PASS. A FAIL means the runtime no
* longer matches the documented claim and the page must be revised.
*/
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");
}
/* 1. The member resolves as a host CLR method. */
assert("typeof Platform.Function.BeginImpressionRegion is clrmethodinfo", String(typeof Platform.Function.BeginImpressionRegion), "clrmethodinfo");
/* 2 + 3. DEV every 1-argument call throws, whatever the argument type. */
assertThrows("DEV 1-arg string literal throws (docs: a valid call)", function () {
return Platform.Function.BeginImpressionRegion("hero");
});
assertThrows("DEV 1-arg number literal throws (docs: a valid call)", function () {
return Platform.Function.BeginImpressionRegion(1);
});
assertThrows("DEV 1-arg boolean literal throws (docs: a valid call)", function () {
return Platform.Function.BeginImpressionRegion(true);
});
assertThrows("DEV 1-arg null throws (docs: a valid call)", function () {
return Platform.Function.BeginImpressionRegion(null);
});
/* 4. Off-signature arities throw too. */
assertThrows("arity 0 throws", function () {
return Platform.Function.BeginImpressionRegion();
});
assertThrows("arity 2 throws", function () {
return Platform.Function.BeginImpressionRegion("a", "b");
});
</script>
Description
Platform.Function.BeginImpressionRegion() is documented as the opening half of an impression-tracking region, paired with EndImpressionRegion().
Runtime note: it is unusable from SSJS. Every invocation throws a resolved-value error — a string literal, a number literal, a concatenation, the empty string and a variable all fail identically, so no SSJS call shape works.
The cause is a literal-only rule in the AMPscript parser, not a missing tracking context. The region name must be a literal token in the AMPscript source; an SSJS argument always arrives as a computed value (Parameter Type: ResolvedValueParameter) and is rejected before its content matters — which is why even a compile-time literal fails from SSJS. The same rule applies inside AMPscript itself: an AMPscript variable is rejected as a ResolvedVariableParameter and a nested function call is rejected too, while an AMPscript string literal is accepted. The bare-name Core form BeginImpressionRegion() behaves identically, so it is no escape hatch.
⚠ Scope of the evidence — CloudPage only. Every observation on this page comes from plain
GETrequests against a CloudPage. Nothing here was measured inside a real email send. Since impression regions exist primarily to track what a recipient sees in a delivered message, treat the send-time behaviour as untested: it may well differ from what is described here.
The official docs describe the function as callable with a region name, but every SSJS invocation — including one with a compile-time string literal — throws “the parameter value for this call must be a literal (constant) values”, while the equivalent AMPscript literal call succeeds in the same content. Scope: measured on CloudPage GET requests only — the behaviour inside a real email send was never exercised and may differ.
Show test script — every SSJS call shape throws
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Differs-from-docs claim: the official Salesforce documentation presents
* BeginImpressionRegion(regionName) as a normal callable function taking a
* string region name. At runtime NO SSJS call shape works — every
* invocation throws, while the equivalent AMPscript call succeeds in the
* very same content.
*
* Official docs: BeginImpressionRegion("Header") begins a tracking region
* SFMC runtime: the SSJS call throws
* "A BeginImpressionRegion function call includes an invalid
* parameter value. The values making up the parameter value
* for this call must be a literal (constant) values."
* (printed verbatim by each assertion below)
*
* Proves both halves of the claim:
* 1. DEV a compile-time string literal — the form the docs show — throws.
* A concatenation, a variable and the empty string throw identically,
* so from SSJS there is no working shape: an SSJS argument always
* reaches the function as a ResolvedValueParameter, never as the
* literal token the function requires.
* 2. DEV the bare-name Core alias throws too, so the deviation is not
* specific to the Platform.Function namespace.
* 3. The AMPscript route via TreatAsContent() succeeds in the same
* request, proving the feature itself works and only the SSJS binding
* is blocked. This also disproves the older "no impression-tracking
* context on a CloudPage" explanation: the AMPscript literal form runs
* fine on a plain CloudPage GET.
* 4. The literal-only rule IS real — but it lives in the AMPscript parser.
* Inside the emitted AMPscript the region name must be a literal: an
* AMPscript variable is rejected as a ResolvedVariableParameter, while
* a name spliced into the source string (a literal to the AMPscript
* parser, even though JS built it) is accepted.
*
* SCOPE: all of the above was observed on a plain CloudPage GET. No
* assertion here speaks to what happens during a real email send, which
* was never exercised and may behave differently.
*
* 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 assertNoThrow(id, fn) {
var threw = false, msg = "";
try { fn(); } catch (ex) { threw = true; msg = ex.message; }
Platform.Response.Write((threw ? "FAIL " : "PASS ") + id + " -> " + (threw ? "threw: " + msg : "did not throw") + "\n");
}
/* 1. DEV every argument shape throws — compile-time literal included. */
assertThrows("DEV compile-time string literal throws (docs: valid)", function () {
return Platform.Function.BeginImpressionRegion("hero");
});
assertThrows("DEV string concatenation throws as well", function () {
return Platform.Function.BeginImpressionRegion("he" + "ro");
});
var dyn = "dynamic-name";
assertThrows("DEV a variable throws as well", function () {
return Platform.Function.BeginImpressionRegion(dyn);
});
assertThrows("DEV the empty string literal throws too", function () {
return Platform.Function.BeginImpressionRegion("");
});
/* 2. DEV the bare-name Core alias throws too. */
assertThrows("DEV bare-name literal call throws as well", function () {
return BeginImpressionRegion("hero");
});
/* 3. The AMPscript route succeeds in the same request. */
assertNoThrow("AMPscript form via TreatAsContent succeeds where SSJS throws", function () {
return Platform.Function.TreatAsContent('%%[BeginImpressionRegion("amp-proof")]%%');
});
var out = Platform.Function.TreatAsContent('%%[BeginImpressionRegion("amp-proof-2")]%%');
assert("the AMPscript form produces no output", out, "");
var end = Platform.Function.TreatAsContent('%%[EndImpressionRegion()]%%');
assert("the AMPscript end form produces no output", end, "");
/* 4. The literal-only rule is an AMPscript-parser rule, not a runtime-context
rule: an AMPscript VARIABLE argument is rejected, a literal is accepted. */
assertThrows("an AMPscript variable argument is rejected (ResolvedVariableParameter)", function () {
return Platform.Function.TreatAsContent('%%[ var @r set @r = "amp-var" BeginImpressionRegion(@r) ]%%');
});
assertThrows("an AMPscript function-call argument is rejected too", function () {
return Platform.Function.TreatAsContent('%%[ BeginImpressionRegion(Concat("a", "b")) ]%%');
});
/* A JS-built name spliced INTO the source string is a literal to the AMPscript
parser, so it is accepted — this is the only way to get a dynamic region
name from SSJS. */
var dyn = "built-at-runtime";
assertNoThrow("a JS-built name spliced into the AMPscript source is accepted", function () {
return Platform.Function.TreatAsContent('%%[ BeginImpressionRegion("' + dyn + '") ]%%');
});
/* Control: an AMPscript var block itself works fine through TreatAsContent,
so the rejection above is about the argument, not about var support. */
var ctl = Platform.Function.TreatAsContent('%%[ var @r set @r = "zz" ]%%out=%%=v(@r)=%%');
assert("control: AMPscript variables work through TreatAsContent", ctl, "out=zz");
</script>
To open an impression region from an SSJS context, emit the AMPscript form with Platform.Function.TreatAsContent():
Platform.Function.TreatAsContent('%%[BeginImpressionRegion("hero")]%%');
Write(heroHtml);
Platform.Function.EndImpressionRegion();
A dynamic region name is still possible — build the name in JavaScript and splice it into the AMPscript source string, so that the AMPscript parser sees a literal:
var region = "promo-" + slotIndex;
Platform.Function.TreatAsContent('%%[BeginImpressionRegion("' + region + '")]%%');
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: Description — unusable from SSJS; the TreatAsContent workaround.
*
* Proves:
* 1. DEV the qualified Platform.Function form throws for a string literal.
* 2. DEV the bare-name Core form BeginImpressionRegion() throws too, so
* the two forms do not differ — neither is an escape hatch for the
* other.
* 3. The recommended workaround works: emitting the AMPscript form via
* Platform.Function.TreatAsContent() does NOT throw and produces the
* empty string (the function has no output).
* 4. The paired EndImpressionRegion() half IS callable from SSJS without
* throwing and returns a genuine null — so only the Begin half is
* blocked.
* 5. The AMPscript End form also runs through TreatAsContent().
*
* SCOPE: run as a CloudPage GET only — the email/send context is not
* covered by any assertion here.
*
* 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 assertNoThrow(id, fn) {
var threw = false, msg = "";
try { fn(); } catch (ex) { threw = true; msg = ex.message; }
Platform.Response.Write((threw ? "FAIL " : "PASS ") + id + " -> " + (threw ? "threw: " + msg : "did not throw") + "\n");
}
/* 1. DEV the qualified form throws. */
assertThrows("DEV Platform.Function form throws for a string literal", function () {
return Platform.Function.BeginImpressionRegion("hero");
});
/* 2. DEV the bare-name Core form throws as well. */
assertThrows("DEV bare-name BeginImpressionRegion throws too", function () {
return BeginImpressionRegion("hero");
});
/* 3. Workaround — the AMPscript form via TreatAsContent does not throw. */
assertNoThrow("workaround TreatAsContent begin does not throw", function () {
return Platform.Function.TreatAsContent('%%[BeginImpressionRegion("tac-region")]%%');
});
var tac = Platform.Function.TreatAsContent('%%[BeginImpressionRegion("tac-region-2")]%%');
assert("workaround TreatAsContent begin has no output", tac, "");
assert("typeof the TreatAsContent result is string", String(typeof tac), "string");
/* 4. The End half IS callable from SSJS and returns a genuine null. */
var e = Platform.Function.EndImpressionRegion();
assert("EndImpressionRegion() returns typeof object", String(typeof e), "object");
assert("EndImpressionRegion() returns a genuine null", e === null ? "true" : "false", "true");
/* 5. The AMPscript End form runs through TreatAsContent too. */
var tacEnd = Platform.Function.TreatAsContent('%%[EndImpressionRegion()]%%');
assert("workaround TreatAsContent end has no output", tacEnd, "");
</script>
Examples
The AMPscript form, which is the only form that works:
%%[ BeginImpressionRegion("hero") ]%%
The SSJS workaround via TreatAsContent():
Platform.Function.TreatAsContent('%%[BeginImpressionRegion("promo-slot-1")]%%');
Write(promoContent);
Platform.Function.EndImpressionRegion(true);
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: Examples — the AMPscript form and the TreatAsContent workaround.
*
* Proves the shape of both documented examples:
* 1. The TreatAsContent workaround for a named region does not throw and
* emits nothing (BeginImpressionRegion has no output).
* 2. The paired EndImpressionRegion() call — both the no-argument form of
* the first example and the EndImpressionRegion(true) close-all form of
* the second — is callable from SSJS and returns a genuine null.
* 3. Write() of the surrounding content between the two calls behaves
* normally — the region calls do not interfere with output.
* 4. DEV the direct SSJS call shown by the official docs would throw
* here, which is why the examples use the AMPscript form.
*
* SCOPE: CloudPage GET only — no email/send-context behaviour is asserted.
*
* NOT ASSERTED: whether an impression is actually recorded in tracking.
* Impression counts surface in Marketing Cloud tracking reports after a
* send is processed, which is not deterministically observable from within
* the rendering request, so only the call-level behaviour is asserted.
*
* 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 assertNoThrow(id, fn) {
var threw = false, msg = "";
try { fn(); } catch (ex) { threw = true; msg = ex.message; }
Platform.Response.Write((threw ? "FAIL " : "PASS ") + id + " -> " + (threw ? "threw: " + msg : "did not throw") + "\n");
}
/* Example 1 — open "hero", write content, close it. */
var open1 = Platform.Function.TreatAsContent('%%[BeginImpressionRegion("hero")]%%');
assert("example 1: opening the hero region emits nothing", open1, "");
var heroHtml = "<p>hero</p>";
assert("example 1: the surrounding content is untouched", heroHtml, "<p>hero</p>");
var close1 = Platform.Function.EndImpressionRegion();
assert("example 1: EndImpressionRegion() returns null", close1 === null ? "true" : "false", "true");
/* Example 2 — open "promo-slot-1", write content, close all. */
var open2 = Platform.Function.TreatAsContent('%%[BeginImpressionRegion("promo-slot-1")]%%');
assert("example 2: opening the promo region emits nothing", open2, "");
var close2 = Platform.Function.EndImpressionRegion(true);
assert("example 2: EndImpressionRegion(true) returns null", close2 === null ? "true" : "false", "true");
assert("example 2: typeof the close-all result is object", String(typeof close2), "object");
/* 2. Both End forms stay callable. */
assertNoThrow("EndImpressionRegion() is callable from SSJS", function () {
return Platform.Function.EndImpressionRegion();
});
assertNoThrow("EndImpressionRegion(true) is callable from SSJS", function () {
return Platform.Function.EndImpressionRegion(true);
});
/* 4. DEV the direct SSJS call from the docs throws. */
assertThrows("DEV the direct SSJS call from the docs throws, hence the workaround", function () {
return Platform.Function.BeginImpressionRegion("hero");
});
</script>