← All articles

How to Create a CloudPage in Salesforce Marketing Cloud

Strategy & Career June 15, 2026 · By Matthew Smith

How to Create a CloudPage in Salesforce Marketing Cloud

A CloudPage in Salesforce Marketing Cloud is a web landing page you can build, publish, and host directly within the platform — no external web server required. CloudPages serve as the foundation for subscription center forms, preference pages, event registration, and data capture throughout your SFMC ecosystem. In this guide, you'll learn the complete workflow for creating, building, testing, and publishing a CloudPage, including how to add dynamic AMPscript and Server-Side JavaScript (SSJS) logic.

What is a CloudPage?

A CloudPage is a Marketing Cloud-hosted web page accessible via a unique URL in the format https://<tenant>.cloudpages.com/<page-id>. Unlike legacy Microsites, CloudPages are created and managed through Content Builder, giving you a unified interface for assets, images, and page layouts. CloudPages can function as public-facing landing pages or as authenticated pages that read subscriber context from URL parameters or cookies.

Prerequisites

Before creating a CloudPage, ensure you have:

Step-by-Step: Creating Your First CloudPage

Accessing Content Builder

  1. Log in to Marketing Cloud and navigate to Cloudpages (found under the Web Studio tab in the top navigation).
  2. Click the Folder you want to store your cloudpage in on the left sidebar.
  3. Select Landing Pgae from the dropdown menu in the top right called Add Content.
  4. Fill out the popup form and click next. For this tutorial, select Blank Layout.

Content Builder opens the page editor with a drag-and-drop interface. You can add text blocks, images, forms, and code elements from the component palette on the left.

Naming and Configuring the Page

Before adding content, configure the page properties:

  1. Click the Settings gear icon (⚙️) on the right sidebar.
  2. Set a descriptive Page Name (e.g., "Newsletter Subscription Center").
  3. Set the Page ID slug — this becomes part of your public URL.
  4. Choose Public or Secure access. Secure pages require authentication context from Email Studio.
  5. Click Save.

Building the CloudPage Content

Adding Static HTML Content

Drag an HTML component from the palette onto the page canvas. Double-click to edit the HTML source. A basic subscription form looks like this:

<div class="subscription-form">
  <h2>Subscribe to Our Newsletter</h2>
  <form action="https://pages.example.com/submit" method="POST">
    <label for="email">Email Address:</label>
    <input type="email" id="email" name="email" required>
    <input type="submit" value="Subscribe">
  </form>
</div>

Adding AMPscript for Dynamic Content

AMPscript executes server-side when the page loads, before the HTML renders. Use AMPscript to personalize content, retrieve subscriber data, or handle form submissions.

Personalizing with AMPscript

Insert an AMPscript block at the top of your page (above the HTML):

%%[
VAR @subscriberKey, @email, @firstName, @status

/* Retrieve query string parameters */
SET @subscriberKey = RequestParameter("subkey")
SET @email = RequestParameter("email")

/* If no subscriber key provided, default to guest view */
IF EMPTY(@subscriberKey) THEN
  SET @firstName = "Guest"
  SET @status = "unknown"
ELSE
  /* Look up subscriber attributes from Data Extension */
  SET @firstName = Lookup("SubscriberAttributes", "FirstName", "SubscriberKey", @subscriberKey)
  SET @status = Lookup("SubscriberAttributes", "Status", "SubscriberKey", @subscriberKey)

  /* Handle missing data gracefully */
  IF EMPTY(@firstName) THEN
    SET @firstName = "Subscriber"
  ENDIF
ENDIF
]%%

Then reference these variables in your HTML:

<h1>Welcome, %%=v(@firstName)=%%!</h1>
<p>Your current status: %%=v(@status)=%%</p>

Handling Form Submissions

Use AMPscript to process form data and write to a Data Extension:

%%[
/* Only process on POST */
IF RequestParameter("submit") != "" THEN

  VAR @email, @firstName, @source, @insertResult

  SET @email = RequestParameter("email")
  SET @firstName = RequestParameter("firstname")
  SET @source = "CloudPage Signup"

  /* Validate email format */
  IF EMPTY(@email) OR NOT EMPTY(IndexOf(@email, "@")) == false THEN
    SET @errorMessage = "Please provide a valid email address."
  ELSE
    /* Upsert into Data Extension */
    SET @insertResult = UpsertData(
      "NewsletterSubscribers",
      1,
      "EmailAddress", @email,
      "FirstName", @firstName,
      "Source", @source,
      "SignupDate", NOW()
    )

    IF @insertResult == 1 THEN
      SET @successMessage = "Thank you for subscribing!"
    ELSE
      SET @errorMessage = "There was an error processing your request."
    ENDIF
  ENDIF
ENDIF
]%%

Adding Server-Side JavaScript (SSJS)

SSJS provides more complex logic and access to the SFMC API. Use it when you need loops, try-catch error handling, or external API calls.

Basic SSJS Structure

<script runat="server">
  Platform.Load("core", "1");

  var subscriberKey = Request.GetQueryStringParameter("subkey");
  var email = Request.GetQueryStringParameter("email");

  // Initialize Data Extension
  var DE = DataExtension.Init("NewsletterSubscribers");

  // Perform lookup
  var results = DE.Rows.Retrieve({
    Property: "EmailAddress",
    SimpleOperator: "equals",
    Value: email
  });

  if (results && results.length > 0) {
    // Store data for use in AMPscript via Platform.SetValue
    Platform.SetValue("sub_firstName", results[0].FirstName);
    Platform.SetValue("sub_status", results[0].Status);
  }
</script>

Error Handling in SSJS

<script runat="server">
  Platform.Load("core", "1");

  try {
    var apiClient = new Script.Util.WSProxy();

    var props = { Name: "TestDE" };
    var data = apiClient.Retrieve(props);

    // Process results
    if (data && data.Results) {
      for (var i = 0; i < data.Results.length; i++) {
        Platform.Debug.Write(data.Results[i].Name);
      }
    }
  } catch (e) {
    // Log error without exposing details to user
    Platform.Variable.SetValue("errorMessage", "An error occurred. Please try again.");
    Platform.Debug.Log("SSJS Error: " + String(e));
  }
</script>

Testing Your CloudPage

Preview Mode

Content Builder provides a Preview tab that renders the page with sample data. You can inject test values for query parameters:

Preview URL: ?subkey=test123&email=test@example.com

Testing Form Submissions

  1. Click Preview in the top-right corner.
  2. Select Open in new tab to interact with the live preview.
  3. Fill out the form and submit.
  4. Verify the data was written to your target Data Extension by querying it directly in Automation Studio or via SQL Query Activity.

Common Data Extension Query for Verification

SELECT TOP 100
    EmailAddress,
    FirstName,
    Source,
    SignupDate
FROM NewsletterSubscribers
WHERE Source = 'CloudPage Signup'
ORDER BY SignupDate DESC

Publishing Your CloudPage

Once testing is complete:

  1. Click Publish in the top-right corner of Content Builder.
  2. Marketing Cloud validates the page and assigns a public URL.
  3. The URL follows the format: https://<tenant>.cloudpages.com/<page-id>
  4. Copy this URL for use in emails, SMS messages, or external campaigns.

Important: Publishing updates are immediate. If you modify a published page, click Publish again to push changes live.

Common Pitfalls

1. Missing RequestParameter Validation

Always validate query string parameters before using them in lookups. Unsanitized input can cause errors or expose unintended data:

/* WRONG - Direct lookup without validation */
SET @email = RequestParameter("email")
SET @subscriberKey = RequestParameter("subkey")
SET @name = Lookup("Subscribers", "Name", "SubscriberKey", @subscriberKey)

/* CORRECT - Validate first */
SET @subscriberKey = RequestParameter("subkey")
IF NOT EMPTY(@subscriberKey) AND Length(@subscriberKey) <= 50 THEN
  SET @name = Lookup("Subscribers", "Name", "SubscriberKey", @subscriberKey)
ELSE
  SET @name = "Unknown"
ENDIF

2. SELECT * in Automation Studio Queries

CloudPages often write to Data Extensions that feed Automation Studio reports. Never use SELECT * in your Query Activities — it violates the 30-minute execution timeout and can cause unexpected failures:

/* WRONG */
SELECT * FROM NewsletterSubscribers

/* CORRECT - Specify columns explicitly */
SELECT 
    EmailAddress,
    FirstName,
    Source,
    SignupDate
FROM NewsletterSubscribers
WHERE SignupDate >= DATEADD(day, -1, GETDATE())

3. Hardcoding Business Unit MID

When writing AMPscript that references Data Extensions, avoid hardcoding the Business Unit MID. Use MemberID() to retrieve the current context dynamically:

%%[
SET @currentMID = MemberID()
SET @subscriberData = LookupOrderedRows(
    "SubscriberAttributes",
    1,
    "SignupDate DESC",
    "SubscriberKey", @subscriberKey,
    "MID", @currentMID
)
]%%

4. Forgetting to Publish After Edits

Unlike code repositories, CloudPage edits do not auto-deploy. Forgetting to click Publish after changes is a common cause of support tickets where stakeholders see stale content.

5. Blocking CloudPages in Sender Profiles

If your CloudPage form submits to an email address via a mailto: link or external form handler, ensure your Sender Profile doesn't block the domain. Test the full submission flow end-to-end before campaign launch.

FAQ

How do I pass subscriber data from an email to a CloudPage?

Use AMPscript's CloudPagesURL() function when constructing links in your emails. This function automatically appends the subscriber key and other tracking parameters:

<a href="%%=CloudPagesURL(1234)=%%">Update Preferences</a>

On the CloudPage, retrieve these values with RequestParameter("SubscriberKey") or RequestParameter("jobid").

Can CloudPages access data from data views like _Sent, _Open, or _Click?

Yes, but only from the parent Business Unit, and only if your account has the appropriate data view permissions. Standard data views are read-only and include _Sent, _Open, _Click, _Bounce, and _Unsubscribe. You cannot write to these views:

SELECT 
    s.SubscriberKey,
    s.JobID,
    o.IsUnique,
    o.EventDate
FROM _Sent s
INNER JOIN _Open o ON s.JobID = o.JobID AND s.SubscriberKey = o.SubscriberKey
WHERE s.JobID = @jobID

How do I add CAPTCHA or bot protection to a CloudPage?

Marketing Cloud does not include built-in CAPTCHA functionality. For bot protection, integrate a third-party solution like Google reCAPTCHA v2. Load the reCAPTCHA script in an HTML block and validate the token server-side using AMPscript or SSJS before processing form submissions.

What is the difference between a CloudPage and a Microsite?

CloudPages are the modern replacement for legacy Microsites. CloudPages are created in Content Builder, support responsive design, and integrate with the SFMC publishing workflow. Microsites (deprecated) used a separate interface and are no longer recommended for new implementations.


Free SFMC cheat sheet

Copy-paste AMPscript lookups, SSJS patterns, and Automation Studio SQL — curated from real Marketing Cloud projects.

Instant access. No spam — one useful SFMC pattern per week, unsubscribe anytime.

Let SFMC Agent build your CloudPage forms automatically

SFMC Agent writes validated AMPscript and SSJS for your CloudPages, handling form submissions, subscriber lookups, and Data Extension writes against your real schema — no syntax errors, no trial-and-error.

Create your free account

Matthew Smith

Salesforce Marketing Cloud Developer

SFMC developer and builder of SFMCDeveloper.dev Agent.