How to Build a Salesforce Multi-Cloud Preference Center
To be honest, I could not come up with a title that fully captures the multi-cloud concept. I considered something like “Multiverse,” although “Connected Cloud” might be more accurate. For now, the current title seems to work.
In most Salesforce Marketing Cloud Engagement implementations, the out-of-the-box preference center is not sufficient for the client’s requirements. More often than not, we are asked to build a custom preference center instead. In this article, we assume that the preference center is intended for known subscribers, most likely users who have accessed it through an email communication.Â
When we send email in salesforce marketing cloud, it automatically attaches personalization strings to every link in a safe way, so the link will not expose any private data. If you generate such link in email preview it will work only on subscribers we already sent some communication.
<a alias="click here" conversion="false" href="%%=redirectto(CloudPagesURL(253)=%%">Unsubscribe</a>
Updating Subscriber Preferences Using a CloudPage only
Link is leading to the cloud page under key 253. Here we can see that no additional information is needed to pass on as marketing cloud is adding all necessary information we need to identify subscribers on the cloud pages. In case anything has to be added you can in form of additional arguments all query parameters will be encrypted by marketing cloud when email is sent.
CloudPagesURL(253, "param1", @param1Value, "param2", @param2value)
Subscriber lands on the cloud page from the email click. We can directly access his _subscriberkey.
Define redirect page, error page on the top along with the request parameter that we will explain later.
<script runat="server">
Platform.Load("core","1.1.1");
Variable.SetValue('@request', Platform.Request.Method);
</script>
%%[
SET @errorPage = 222
SET @redirectPage = 223
]%%
If we do not have _subscriberkey we simply can tell somebody accessed the page accidentally and  navigate them to the error page.
%%[ IF EMPY(_subscriberkey) THEN Redirect(CloudPagesURL(@errorPage)) ENDIF ]%%
Next we add section to collect data from form submissions
SET @submit = RequestParameter("submit")
SET @field1 = RequestParameter("field1")
SET @field2 = RequestParameter("field2")
SET @field3 = RequestParameter("field3")
SET @field4 = RequestParameter("field4")
We also want to display data on the form that are perhaps loaded directly from sales cloud. To do that we would need to get account from contact id from either the salesforce tables or you can create one data extension that holds all the data from account and contact in one row. We will use one data extension that contain row where we can see account id and contact id. We will populate form data after we process the when someone submits the form.
SET @accountId = Lookup("MASTER_TABLE", "AccountId", "ContactId", _subscriberkey)
Check in service cloud the account by the account id we got from the mapping data extension above.
SET @accounts = RetrieveSalesforceObjects("Account", "Salutation, FirstName, LastName, PersonBirthdate, PersonEmail, NLBranch__pc", "Id", "=", @accountId)
Now we want to process data only when the form has been submitted via the POST request. Now it is time to reuse above mentioned variable @request
%%[
IF NOT EMPTY(@submit) AND @request == "POST" THEN
/*Check if _subscriberkey has match in the sales cloud*/
IF RowCount(@accounts) THEN
SET @account = Row(@accounts, 1)
/* bring any fields from SC that you may need */
SET @field1 = Field(@account, "field1")
ELSE
/*redirect to error error page */
Redirect(CloudPagesURL(@errorPage)
ENDIF
]%%
In case of error we can also do not want to show customer 500 page but instead we want to handle any error that may happen during the update object in sales cloud. For example we can redirect customer to the same  to the same page showing a banner at the top of the page or redirect them to our own custom error page that displays contact for support.
/*try catch block so sales cloud will not suprise customer with 500 */
<script runat="server">
try{
</script>
%%[
/*now the main program of todays event is to update sales cloud :) */
UpdateSingleSalesforceObject("Account", @accountId, "Field1", @field1, "Field2", @field2, "Field3", @field3, "Field4", @field4)
]%%
<script runat="server">
catch(e){
/*Load core library as the functions are no vosible in this ode block*/
Platform.Load("core","1.1.1");
Variable.SetValue("@error","True") /*maybe try with boolean but for me it did not work at the first time*/
}
</script>
%%[
IF @error == "True" THEN Redirect(CloudPagesURL(@errorPage) ENDIF
*/
ENDIF ]%%
Sometimes may happen that customer will remove data from form this may cause issues when saving the field as you cannot save null values to sales cloud. Instead we need to append additional arguments to the UpdateSingleSalesforceObject()
UpdateSingleSalesforceObject("Account", @accountId, "Field1", @field1, "Field2", @field2, "Field3", @field3, "Field4", @field4,"fieldsToNull", "field3")
Problem here is you can only null one field at a time. You will need to send as many update calls with all the empty fields that were set to the form. Maybe if you have to set null 10 fields is better to select another approach. As to do 10 calls to null fields and then 1 call to update object might be sometimes very resource consuming and customer could wait couple seconds for page to process. You can share in comments your thoughts.
Also for future enhancements we might think of adding field values validation.
Also you might ask yourself why we do not update marketing cloud data extension. It is because updates in sales cloud will be synchronized back to marketing cloud from where automation is set to update our MASTER_TABLE data extension and set to run every hour
In case we want to redirect customers to the same page we can add some additional information to the URL so we tell the cloud page to display specific message to the customer
/* we can also redirect to the same page and show banner at the top of the page */
Redirect(CloudPagesURL(@self,"m", "e"))
Define the alert message based on the query parameter we used in redirect. Do not worry it is all encrypted in the URL bar, nobody will fiddle with that. (hope).Â
SET @m = RequestParameter("m")
IF NOT EMPTY(@m) THEN
IF @m == "s" THEN
SET @alertMessage = "Data saved successfully!"
SET @alertType = "success"
ELSEIF @m == "e" THEN
SET @alertMessage = "Oops something happened. Please try again later."
SET @alertType = "danger"
ENDIF
ENDIF
Display the alert banner on page. I do use bootstrap as CSS library.
%%[ IF NOT EMPTY(@alertType) THEN ]%%
<div class="alert alert-%%=v(@alertType)=%% my-4" role="alert">
%%=v(@alertMessage)=%%
</div>
%%[ENDIF]%%
Last but not least we need to add form and possibly prepopulate it with the data coming from sales cloud. It is good to add as many field validations already in html (and JavaScript) so we can stop customer submit invalid fields already on client side and also on the back end side to have second layer of validation as more is better. Because when eg. you will submit field that is out of the limits in sales cloud or another type we will get infamous 500 back
<form action="%%=RequestParameter("PAGEURL")=%%" method="POST">
<input type="text" name="field1" maxlength="40" value="%%=v(@field1)=%%" />
<input type="date" name="field2" format="...." value="%%=v(@field2)=%%" />
<input type="submit" name="submit"/>
</form>
The main issue with this setup is that the CloudPage directly updates a Salesforce object through a synchronous request. This can take several seconds, which may frustrate users and create the impression that a million-dollar company cannot process a form instantly. Users may wonder why the submission is taking so long, and honestly, it would irritate me as well. The delay occurs because updating the object triggers additional Salesforce Flows. The request is not completed, and the CloudPage cannot return a success response, until all downstream automation has finished. As a result, users must wait for the entire Salesforce process instead of receiving immediate confirmation that their form was submitted successfully.
Updating Subscriber Preferences Using a CloudPage and Automation
A better and more controlled approach is to save the changes submitted by the user on…
đź”’Â Premium Subscriber Content
What you can learn with Premium
Unlock the full article to explore these topics in detail.
Already a Premium subscriber? Log in to continue reading, or register to create your account.
You must log in and have a Premium Subscriber account to read the full article.
When upgrading, please use the same email address as your WordPress account so we can correctly link your Premium membership.
Please allow us a little time to process and upgrade your account after the purchase. If you need faster access or encounter any issues, feel free to contact us at info@martechnotes.com or through any other available channel.
To join the Discord community, please also provide your Discord username after subscribing, or reach out to us directly for access.
You can subscribe even before creating a WordPress account — your subscription will be linked to the email address used during checkout.
Premium Subscriber
29,99 € / Year
- Free e-book with all revisions - 101 Adobe Campaign Classic (SFMC 101 in progress)
- All Premium Subscriber Benefits - Exclusive blog content, weekly insights, and Discord community access
- Lock in Your Price for a Full Year - Avoid future price increases
- Limited Seats at This Price - Lock in early before it goes up
- Monthly 15-Minute Call - Discuss any topic directly








