Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
SFMC Custom Preference Center Boilerplate
<script runat="server" language="JavaScript">
// src:
// demo:
Platform.Load("core", "1");
var debug = true;
var request = {};
SetVar("method", Request.Method)
SetVar("urlThis", Platform.Request.RequestURL);
SetVar("MasterDEKey", "ExampleMaster");
SetVar("debug", debug);
if (request.method == "GET") {
if (debug) {
// retrieve the subscriberkey via system personalization string from the send context
SetVar("SubscriberKey", Attribute.GetValue("_SubscriberKey"));
if (request.SubscriberKey != "") {
// retrieve the row from the Master DE
var masterRows = Platform.Function.LookupRows(request.MasterDEKey,['SubscriberKey'], [request.SubscriberKey]);
if (debug) {
Write("<br>masterRows.length: " + masterRows.length);
Write("<br>masterRows: " + Stringify(masterRows));
// set variables for the Master column values (for defaulting below)
if (typeof masterRows !== 'undefined' && masterRows.length > 0) {
// DE field names are case-sensitive
SetVar("SubscriberKey", masterRows[0]["SubscriberKey"]);
SetVar("EmailAddress", masterRows[0]["EmailAddress"]);
SetVar("FirstName", masterRows[0]["FirstName"]);
SetVar("LastName", masterRows[0]["LastName"]);
SetVar("ZipCode", masterRows[0]["ZipCode"]);
} else if (request.method == "POST") {
if (debug) {
// get form field values
SetVar("SubscriberKey", Request.GetFormField("SubscriberKey"));
// if the SubscriberKey is blank then fall back and use the email address
if (request.SubscriberKey == "") {
SetVar("SubscriberKey", Request.GetFormField("EmailAddress"));
// retrieve values from the form submission
// form field names are case-sensitive
SetVar("EmailAddress", Request.GetFormField("EmailAddress"));
SetVar("FirstName", Request.GetFormField("FirstName"));
SetVar("LastName", Request.GetFormField("LastName"));
SetVar("ZipCode", Request.GetFormField("ZipCode"));
if (request.SubscriberKey != "") {
try {
// set values for Subscriber update
var sub = {
"SubscriberKey": request.SubscriberKey
, "EmailAddress": request.EmailAddress
, "Status" : "Active"
// initialize the Subscriber object
var subObj = Subscriber.Init(request.SubscriberKey);
// add/update the Subscriber
SetVar("subscriberUpsertResults", subObj.Upsert(sub));
// upsert a row in the Master Data Extension
var de = DataExtension.Init(request.MasterDEKey);
var row = {};
row.EmailAddress = request.EmailAddress;
row.SubscriberKey = request.SubscriberKey;
row.FirstName = request.FirstName;
row.LastName = request.LastName;
row.ZipCode = request.ZipCode;
if (debug) {
Write("<br><br>DE row: " + Stringify(row));
try {
// attempt to add a row
SetVar("rowAddResults", de.Rows.Add(row));
} catch (e1) {
if (debug) {
Write("<br><br>Exception (1): " + e1);
try {
SetVar("rowUpdateResults", de.Rows.Update(row, ['SubscriberKey'], [request.SubscriberKey]));
} catch (e2) {
if (debug) {
Write("<br><br>Exception (2): " + e2 + " " + Stringify(request));
SetVar("overallResult", "success");
} catch(e3) {
SetVar("overallResult", "error");
} // EmailAddress check
} // POST
// sets JS and AMPScript variables
function SetVar(varName, varValue){
request[varName] = varValue;
Variable.SetValue(varName, varValue);
if (debug) {
Write("<br><br>" + Stringify(request) + "<br><br>");
</script><!DOCTYPE HTML>
body {
font-family: sans-serif;
label {
input[type="text"] {
fieldset {
border: 0;
%%[ if @method == "GET" then ]%%
<form id="form1" action="%%=v(@urlThis)=%%" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="SubscriberKey" value="%%=v(@SubscriberKey)=%%">
<label for="Email Address">Email Address</label>
<input type="text" name="EmailAddress" value="%%=v(@EmailAddress)=%%">
<label for="First Name">First Name</label>
<input type="text" name="FirstName" value="%%=v(@FirstName)=%%">
<label for="Last Name">Last Name</label>
<input type="text" name="LastName" value="%%=v(@LastName)=%%">
<label for="ZipCode">Zip Code</label>
<input type="text" name="ZipCode" value="%%=v(@ZipCode)=%%">
<p><button type="submit">Submit</button></p>
%%[ elseif @method == "POST" then ]%%
%%[ if @overallResult == "success" then ]%%
We got your updates.
%%[ elseif @overallResult == "error" then ]%%
We had some trouble.
%%[ endif ]%%
%%[ endif ]%%
Copy link

would you share some more information about this boilerplate? Where does the subscriber key come from? Is it a URL parameter?

Copy link

wvpv commented Apr 16, 2020

Subscriber Key is included (as are the other send context values and system personalization strings) when you link to the page using the CloudPagesURL AMPscript function

Copy link

ran-michael commented Apr 24, 2020

This is great, Adam!
Two quick questions:

  1. What's the best way to create and populate the Master DE?
    I don't believe we have one out of the box.

  2. Also, when replacing the default profile center link with the custom link - is there a way to override the default %%profile_center_url%% variable? Or do we simply hide it with CSS?
    Email validation requires this link.
    OR maybe we the best way is to circle back with support so they remove this constraint?

Found the answer to the second question here (hopefully it helps someone)

Copy link

Hi Adam,

thank you for this great code. I have one question, in this Profile center you are not managing lists. Subscriber Status = Active / Unsubscribe depending on what they select. Do you have any code where this is achieved?
I managed to unsubscribe the user from a list only if he comes from the Email. But I'd like to give the possibility to subscribe or unsubscribe from any of the existing list without any JOBID.
Can you help me? Thanks in advance

Copy link

wvpv commented May 4, 2020

List membership is maintained as part of the Subscriber object, so if you have a set of ListIDs then you can add/update them there, along with the status of each. Here's an example retrieve. You can also do this with the SOAP structure with WSProxy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment