List
Core library object for publication lists — create and query lists, remove a list instance, and work with list subscribers.
- SSJS
List- SOAP
List- mcdev
list- GUI
- List
The List Core library object provides an object-oriented interface for SFMC publication lists: static methods create or look up lists, an initialized instance can delete itself, and the Subscribers namespace manages membership on that instance.
Requires Platform.Load("core", "1.1.5") before use.
Methods
| Method | Returns | Description |
|---|---|---|
List.Init(key) |
ListInstance | Bind to a list by external key |
List.Add(properties) |
ListInstance | Create a new list from properties |
List.Retrieve(filter) |
object[] | Query lists with a filter |
<ListInstance>.Remove() |
string | Delete the list represented by the instance |
<ListInstance>.Subscribers.* |
— | Add, retrieve, unsubscribe, update, upsert subscribers (see dedicated page) |
List.Init
Initializes a list instance using the list external key. Required before calling instance methods such as Remove() or Subscribers.*.
Syntax
List.Init(key)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
key |
string | Yes | External key of the publication list |
Return value
ListInstance — object bound to that list.
Examples
Platform.Load("core", "1");
var myList = List.Init("myList");
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: List.Init(key)
*
* CloudPage GET context. Proves:
* 1. List requires the Core load and is then an object exposing the
* documented statics Init, Add and Retrieve.
* 2. There is no static Update / Remove — those are instance methods.
* 3. Init(key) returns a ListInstance: an object whose documented members
* are Remove (function) and Subscribers (object with Add / Retrieve /
* Update / Upsert / Unsubscribe / Tracking.Retrieve).
* 4. The instance carries NO readable list fields (CustomerKey / Name /
* ListName / ID read back undefined) — Init binds a key, it does not
* fetch the record.
* 5. A nonsense key yields an indistinguishable stub.
* 6. The page example shape Init("myList") returns without throwing.
*
* NON-ASSERTABLE here: Subscribers method behaviour (dedicated page).
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function typeOf(fn) {
try { return "" + fn(); } catch (ex) { return "THREW"; }
}
function invocationResult(fn) {
try { fn(); return "returned"; } catch (ex) { return "threw"; }
}
assert("typeof List is object", typeOf(function () { return typeof List; }), "object");
assert("typeof List.Init is function", typeOf(function () { return typeof List.Init; }), "function");
assert("typeof List.Add is function", typeOf(function () { return typeof List.Add; }), "function");
assert("typeof List.Retrieve is function", typeOf(function () { return typeof List.Retrieve; }), "function");
assert("List.Update is not a static", typeOf(function () { return typeof List.Update; }), "undefined");
assert("List.Remove is not a static", typeOf(function () { return typeof List.Remove; }), "undefined");
var myList = List.Init("ssjs-guide-ts-list-init");
assert("typeof List.Init(key) is object", typeof myList, "object");
assert("typeof instance.Remove is function", typeof myList.Remove, "function");
assert("typeof instance.Subscribers is object", typeof myList.Subscribers, "object");
assert("typeof Subscribers.Add is function", typeof myList.Subscribers.Add, "function");
assert("typeof Subscribers.Retrieve is function", typeof myList.Subscribers.Retrieve, "function");
assert("typeof Subscribers.Update is function", typeof myList.Subscribers.Update, "function");
assert("typeof Subscribers.Upsert is function", typeof myList.Subscribers.Upsert, "function");
assert("typeof Subscribers.Unsubscribe is function", typeof myList.Subscribers.Unsubscribe, "function");
assert("typeof Subscribers.Tracking.Retrieve is function", typeof myList.Subscribers.Tracking.Retrieve, "function");
assert("instance has no Add (Add is static)", typeof myList.Add, "undefined");
assert("instance has no Retrieve (Retrieve is static)", typeof myList.Retrieve, "undefined");
assert("instance.CustomerKey is undefined (Init does not fetch)", typeof myList.CustomerKey, "undefined");
assert("instance.Name is undefined (Init does not fetch)", typeof myList.Name, "undefined");
assert("instance.ListName is undefined (Init does not fetch)", typeof myList.ListName, "undefined");
assert("instance.ID is undefined (Init does not fetch)", typeof myList.ID, "undefined");
var bogus = List.Init("ssjs-guide-no-such-list-zzz");
assert("Init(nonsense key) still returns an object", typeof bogus, "object");
assert("Init(nonsense key) exposes Remove", typeof bogus.Remove, "function");
assert("Init(nonsense key) exposes Subscribers", typeof bogus.Subscribers, "object");
assert("Init(nonsense key) stub is indistinguishable", ("" + Stringify(bogus)) === ("" + Stringify(myList)) ? "true" : "false", "true");
assert("page example: Init('myList') returns", invocationResult(function () { return List.Init("myList"); }), "returned");
</script>
List.Add
Creates a new list from the supplied JSON properties (CustomerKey, Name, Description, …). Unlike many Core Add methods, this returns an initialized ListInstance, not "OK".
Syntax
List.Add(properties)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
properties |
object | Yes | Object describing the new list |
Return value
ListInstance — handle for the newly created list.
Examples
Platform.Load("core", "1.1.5");
var myNewList = List.Add({
CustomerKey: "libList",
Name: "testLib",
Description: "desc"
});
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: List.Add(properties)
*
* CloudPage GET context. Proves:
* 1. List.Add is a function taking one properties object.
* 2. Add(properties) with the page example fields (CustomerKey, Name,
* Description) creates a retrievable publication list.
* 3. Unlike most Core Add methods, the return value is a ListInstance
* (object exposing Remove + Subscribers), NOT the string "OK" —
* matching the page Return value section.
* 4. The returned instance is usable immediately: Remove on it returns
* "OK" after a control Retrieve proves the row exists (cleanup path
* recreates then removes again for the final re-count).
* 5. Negative cases: Add() with no argument, Add({}), and re-using an
* existing CustomerKey all throw.
*
* FIXTURE: creates ssjs-guide-ts-list-add and removes it again at the end.
* Cleanup is verified by re-counting Retrieve rows (ghost-record rule).
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function invocationResult(fn) {
try { fn(); return "returned"; } catch (ex) { return "threw"; }
}
function countByKey(key) {
var rows = List.Retrieve({ Property: "CustomerKey", SimpleOperator: "equals", Value: key });
return rows && rows.length ? rows.length : 0;
}
var KEY = "ssjs-guide-ts-list-add";
List.Init(KEY).Remove();
assert("precondition: no list under the probe key", "" + countByKey(KEY), "0");
assert("typeof List.Add is function", typeof List.Add, "function");
assert("Init instance has no Add (Add is static)", typeof List.Init(KEY).Add, "undefined");
var props = {
CustomerKey: KEY,
Name: "SSJS Guide TS List Add",
Description: "desc"
};
var myList = null;
assert("Add(properties) does not throw", invocationResult(function () { myList = List.Add(props); }), "returned");
assert("typeof Add() result is object (page: ListInstance, not \"OK\")", typeof myList, "object");
assert("Add() result is not the string OK", myList === "OK" ? "true" : "false", "false");
assert("returned instance exposes Remove", typeof myList.Remove, "function");
assert("returned instance exposes Subscribers", typeof myList.Subscribers, "object");
assert("the list exists after Add", "" + countByKey(KEY), "1");
assert("Add() with no argument throws", invocationResult(function () { return List.Add(); }), "threw");
assert("Add({}) with an empty object throws", invocationResult(function () { return List.Add({}); }), "threw");
assert("Add() re-using an existing CustomerKey throws", invocationResult(function () { return List.Add(props); }), "threw");
assert("fixture cleanup removed the created list", "" + List.Init(KEY).Remove(), "OK");
assert("cleanup re-count is 0", "" + countByKey(KEY), "0");
</script>
List.Retrieve
Returns array of list objects matching the WSProxy-style filter.
Syntax
List.Retrieve(filter)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
filter |
object | Yes | { Property, SimpleOperator, Value } (or compatible compound filter) |
Return value
object[] — matching lists.
Examples
Platform.Load("core", "1.1.5");
var lists = List.Retrieve({
Property: "ListName",
SimpleOperator: "equals",
Value: "BirthdayList"
});
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: List.Retrieve(filter)
*
* CloudPage GET context. Proves:
* 1. Retrieve is a function taking one PascalCase WSProxy-style filter.
* 2. On a match the result reports as [object Array], exposes .length,
* and is not a JS Array (instanceof Array is false).
* 3. A matched row exposes readable CustomerKey, ListName, ID, Description.
* 4. On no match the same array-like shape is returned with length 0
* and Stringify "[]".
* 5. The page example filter Property "ListName" resolves the owned
* fixture; CustomerKey filter also resolves it.
*
* FIXTURE: creates ssjs-guide-ts-list-retrieve and removes it at the end.
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function countByKey(key) {
var rows = List.Retrieve({ Property: "CustomerKey", SimpleOperator: "equals", Value: key });
return rows && rows.length ? rows.length : 0;
}
var KEY = "ssjs-guide-ts-list-retrieve";
var NAME = "SSJS Guide TS List Retrieve";
List.Init(KEY).Remove();
List.Add({ CustomerKey: KEY, Name: NAME, Description: "retrieve probe" });
assert("typeof List.Retrieve is function", typeof List.Retrieve, "function");
var rows = List.Retrieve({ Property: "CustomerKey", SimpleOperator: "equals", Value: KEY });
assert("typeof the matched result is object", typeof rows, "object");
assert("the matched result reports as [object Array]", Object.prototype.toString.call(rows), "[object Array]");
assert("the matched result exposes a numeric .length", typeof rows.length, "number");
assert("the matched result has exactly one row", "" + rows.length, "1");
assert("instanceof Array is false (engine-wide host-array quirk)", rows instanceof Array ? "true" : "false", "false");
assert("matched row CustomerKey equals the filter value", "" + rows[0].CustomerKey, KEY);
assert("matched row ListName is a string", typeof rows[0].ListName, "string");
assert("matched row ListName equals Name used at Add", "" + rows[0].ListName, NAME);
assert("matched row ID is a number", typeof rows[0].ID, "number");
assert("matched row Description is a string", typeof rows[0].Description, "string");
var byName = List.Retrieve({ Property: "ListName", SimpleOperator: "equals", Value: NAME });
assert("page example: ListName filter finds the fixture", "" + (byName && byName.length ? byName.length : 0), "1");
assert("page example: ListName row CustomerKey matches", "" + byName[0].CustomerKey, KEY);
var empty = List.Retrieve({ Property: "CustomerKey", SimpleOperator: "equals", Value: "ssjs-guide-no-such-list-zzz" });
assert("empty result reports as [object Array]", Object.prototype.toString.call(empty), "[object Array]");
assert("empty result length is 0", "" + empty.length, "0");
assert("empty result Stringify is []", "" + Stringify(empty), "[]");
assert("workaround: guard with rows && rows.length before indexing", (rows && rows.length) ? "true" : "false", "true");
assert("fixture cleanup removed the created list", "" + List.Init(KEY).Remove(), "OK");
assert("cleanup re-count is 0", "" + countByKey(KEY), "0");
</script>
<ListInstance>.Remove
Deletes the list bound to this instance (the publication list itself).
Syntax
<ListInstance>.Remove()
Return value
"OK" on success. A nonexistent key returns the plain string "Error" (does not throw).
Runtime-verified on a CloudPage: a missing list key returns the plain string "Error" rather than throwing. Official docs claim Remove returns "OK" or throws on failure — callers must check the return value; try/catch alone is not enough.
Examples
Platform.Load("core", "1.1.5");
var myList = List.Init("myList");
var status = myList.Remove();
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: <ListInstance>.Remove()
*
* CloudPage GET context. Proves:
* 1. Remove is an instance method (typeof "function") and takes no args.
* 2. Remove() returns the string "OK" on success.
* 3. The deletion really happened: after Remove, Retrieve count is 0.
* 4. DEV: Remove() on a nonexistent key returns the plain string "Error"
* rather than throwing (official docs / earlier guide prose: throws).
* Callers MUST test the return value; try/catch alone is not enough.
* This is also why other scripts can call Remove as an unconditional
* orphan-cleanup preamble.
*
* FIXTURE: creates ssjs-guide-ts-list-remove and deletes it as the assert.
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function invocationResult(fn) {
try { fn(); return "returned"; } catch (ex) { return "threw"; }
}
function countByKey(key) {
var rows = List.Retrieve({ Property: "CustomerKey", SimpleOperator: "equals", Value: key });
return rows && rows.length ? rows.length : 0;
}
var KEY = "ssjs-guide-ts-list-remove";
List.Init(KEY).Remove();
List.Add({
CustomerKey: KEY,
Name: "SSJS Guide TS List Remove",
Description: "remove probe"
});
var myList = List.Init(KEY);
assert("typeof instance.Remove is function", typeof myList.Remove, "function");
assert("control: fixture count is 1 before Remove", "" + countByKey(KEY), "1");
var status = myList.Remove();
assert("page example: Remove() returns \"OK\"", "" + status, "OK");
assert("Remove returns a string", typeof status, "string");
assert("after Remove the Retrieve count is 0", "" + countByKey(KEY), "0");
assert("after Remove a second Remove returns \"Error\"", "" + List.Init(KEY).Remove(), "Error");
assert("DEV Remove on a nonexistent key returns \"Error\" (docs: throws)", "" + List.Init("ssjs-guide-no-such-list-zzz").Remove(), "Error");
assert("DEV Remove on a nonexistent key does NOT throw (docs: throws)", invocationResult(function () { return List.Init("ssjs-guide-no-such-list-zzz").Remove(); }), "returned");
</script>
Subscribers
Subscriber membership operations are invoked on list.Subscribers after List.Init. See List.Subscribers for Add, Retrieve, Unsubscribe, Update, Upsert, and Subscribers.Tracking.Retrieve.
Subscribe / unsubscribe pattern
Platform.Load("core", "1.1.5");
var action = Platform.Request.GetFormField("action"); // "subscribe" or "unsubscribe"
var email = Platform.Request.GetFormField("email");
var listKey = "Newsletter_PublicList";
if (!Platform.Function.IsEmailAddress(email)) {
Write(Stringify({ status: 400, statusMessage: "Bad Request", error: "Invalid email" }));
} else {
var list = List.Init(listKey);
try {
if (action === "subscribe") {
list.Subscribers.Upsert(email, {
SubscribedAt: Platform.Function.Now()
});
Write(Stringify({ status: "subscribed" }));
} else if (action === "unsubscribe") {
list.Subscribers.Unsubscribe(email);
Write(Stringify({ status: "unsubscribed" }));
}
} catch (e) {
Write(Stringify({ status: 500, statusMessage: "Internal Server Error", error: e.message }));
}
}