Empty
Tests whether a value is missing or blank. Runtime-proven on a live Marketing Cloud Engagement CloudPage — including which inputs count as empty, and the exact literals True and False that the function renders.
Syntax
Empty(value) → boolean
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
value |
string | number | boolean | date | Yes | Value to test — a variable, literal, attribute or nested function call |
Example
%%[
VAR @firstName
SET @firstName = AttributeValue("FirstName")
]%%
Hello %%=IIf(Empty(@firstName), "there", @firstName)=%%,
For a subscriber without a first name this renders Hello there,. That pairing with IIf is the everyday use — Empty produces the boolean, IIf picks the wording.
Rendered on its own, the function shows its two literals directly:
%%=Empty("")=%% renders True
%%=Empty("x")=%% renders False
Return value
boolean — True when the value is missing or blank, False otherwise.
Both literals are capitalised. The returned value compares equal to the boolean true and to the string "True", so either form works in a comparison — but if the result is written straight into the page, the visible text is True or False, never true, 1 or an empty string.
Behaviour
Three inputs count as empty: the empty string, a variable declared but never assigned, and a name that was never declared at all. Everything else is a value.
Whitespace is a value. A variable holding three spaces returned False. A form field the user filled with spaces will pass an Empty check, so trim before testing when the input comes from a person.
Neither 0 nor "0" nor "false" is empty. All three returned False, as a variable and as an inline literal. There is no falsiness here — only presence.
A non-string argument is accepted. Both Empty(0) and Empty(Now()) rendered False at HTTP 200 rather than aborting, even though every source types the parameter as a string.
Missing context reads as empty. An attribute that does not exist, a query-string parameter that was not supplied, _subscriberkey and firstname on an anonymous page request all returned True. That makes this the right test for “did this personalisation resolve”.
How the four Utility tests compare
The same inputs put through all four functions, on one page, in one run:
| Input | Empty |
IsNull |
IsNullDefault(x, "DEF") |
IIf(x, "T", "F") |
|---|---|---|---|---|
| undeclared variable | True | False | (empty) | F |
| declared, never set | True | False | (empty) | F |
"" |
True | False | (empty) | F |
" " |
False | False | ` ` | F |
0 |
False | False | 0 |
F |
"0" |
False | False | 0 |
F |
"false" |
False | False | false |
F |
"hello" |
False | False | hello |
F |
Only Empty distinguishes a missing value from a present one. That is the whole reason to reach for it rather than its neighbours.
Show test script
%%[
VAR @b, @unset, @es, @sp, @z, @z0, @sf, @val
SET @b = RequestParameter("b")
SET @es = ""
SET @sp = " "
SET @z = 0
SET @z0 = "0"
SET @sf = "false"
SET @val = "hello"
/* known-good control: renders on every request, so a run of HTTP 422s
can be told apart from a broken deploy */
OutputLine(Concat("CTRL=[", Uppercase("ok"), "]"))
/* the two literals the function renders, side by side in one render,
plus what the returned value compares equal to */
IF @b == "a_tokens" THEN
OutputLine(Concat("--- a_tokens start ---"))
OutputLine(Concat("TRUE_TOK=[", Empty(""), "]"))
OutputLine(Concat("FALSE_TOK=[", Empty("x"), "]"))
OutputLine(Concat("EQ_TRUE=[", IIf(Empty("") == true, "matches-true", "no-match"), "]"))
OutputLine(Concat("EQ_STR=[", IIf(Empty("") == "True", "matches-True-string", "no-match"), "]"))
OutputLine(Concat("--- a_tokens done ---"))
ENDIF
/* a name that was never declared */
IF @b == "e_und" THEN
OutputLine(Concat("--- e_und start ---"))
OutputLine(Concat("E_UND=[", Empty(@zzz_never_declared), "]"))
OutputLine(Concat("--- e_und done ---"))
ENDIF
/* declared with VAR, never assigned */
IF @b == "e_unset" THEN
OutputLine(Concat("--- e_unset start ---"))
OutputLine(Concat("E_UNSET=[", Empty(@unset), "]"))
OutputLine(Concat("--- e_unset done ---"))
ENDIF
/* the explicitly empty string */
IF @b == "e_es" THEN
OutputLine(Concat("--- e_es start ---"))
OutputLine(Concat("E_ES=[", Empty(@es), "]"))
OutputLine(Concat("--- e_es done ---"))
ENDIF
/* three spaces - the input most likely to surprise a caller */
IF @b == "e_sp" THEN
OutputLine(Concat("--- e_sp start ---"))
OutputLine(Concat("E_SP=[", Empty(@sp), "]"))
OutputLine(Concat("--- e_sp done ---"))
ENDIF
/* the number zero, as a variable and inline */
IF @b == "e_z" THEN
OutputLine(Concat("--- e_z start ---"))
OutputLine(Concat("E_Z=[", Empty(@z), "]"))
OutputLine(Concat("E_ZLIT=[", Empty(0), "]"))
OutputLine(Concat("--- e_z done ---"))
ENDIF
/* the string "0" */
IF @b == "e_z0" THEN
OutputLine(Concat("--- e_z0 start ---"))
OutputLine(Concat("E_Z0=[", Empty(@z0), "]"))
OutputLine(Concat("--- e_z0 done ---"))
ENDIF
/* the string "false" */
IF @b == "e_sf" THEN
OutputLine(Concat("--- e_sf start ---"))
OutputLine(Concat("E_SF=[", Empty(@sf), "]"))
OutputLine(Concat("--- e_sf done ---"))
ENDIF
/* a genuine value, as a variable and inline */
IF @b == "e_val" THEN
OutputLine(Concat("--- e_val start ---"))
OutputLine(Concat("E_VAL=[", Empty(@val), "]"))
OutputLine(Concat("E_VLIT=[", Empty("hello"), "]"))
OutputLine(Concat("--- e_val done ---"))
ENDIF
/* a date value, to show a non-string argument is accepted */
IF @b == "e_date" THEN
OutputLine(Concat("--- e_date start ---"))
OutputLine(Concat("E_DATE=[", Empty(Now()), "]"))
OutputLine(Concat("--- e_date done ---"))
ENDIF
/* an attribute that does not exist */
IF @b == "a_attr" THEN
OutputLine(Concat("--- a_attr start ---"))
OutputLine(Concat("E_ATTR=[", Empty(AttributeValue("zzNoSuchAttribute")), "]"))
OutputLine(Concat("--- a_attr done ---"))
ENDIF
/* a query-string parameter that was not supplied */
IF @b == "a_rp" THEN
OutputLine(Concat("--- a_rp start ---"))
OutputLine(Concat("E_RP=[", Empty(RequestParameter("zzNoSuchParam")), "]"))
OutputLine(Concat("--- a_rp done ---"))
ENDIF
/* the subscriber key on an anonymous page request */
IF @b == "s_sub" THEN
OutputLine(Concat("--- s_sub start ---"))
OutputLine(Concat("E_SUB=[", Empty(_subscriberkey), "]"))
OutputLine(Concat("--- s_sub done ---"))
ENDIF
/* a profile attribute outside a send */
IF @b == "s_prof" THEN
OutputLine(Concat("--- s_prof start ---"))
OutputLine(Concat("E_PROF=[", Empty(firstname), "]"))
OutputLine(Concat("--- s_prof done ---"))
ENDIF
]%%
A bare string literal passed to OutputLine renders an empty line while the page still returns HTTP 200, so a marker silently vanishes and the block looks like a function that produced no output. Always wrap it — OutputLine(Concat("--- safe start ---")) — even for a single argument.
Availability
| Platform | Available |
|---|---|
| Marketing Cloud Engagement | Yes |
| Marketing Cloud Next | Yes (since 67) |
See also
- IsNull — the narrower test; it returned
Falsefor every input above, so it is not a substitute - IsNullDefault — looks like a fallback, but outside a Smart Capture form it never returns the default
- IIf — what usually consumes the boolean this function produces
- Official reference · ampscript.guide