Add subscribers to a Journey from a CloudPage using Fire Entry Event

Firing an Entry Event is great for injecting contacts into a Salesforce Marketing Cloud journey, especially if you need to be able to inject them from an external system or a website.

It’s also useful when you’re creating a custom form on a CloudPage and would like to replicate the behavior of SmartCapture forms, which allow injecting contacts to a journey upon form submission (real-time).

In order to use the Fire Entry Event on a CloudPage, we will build a simple form to capture the end user’s email address and we will use REST API to post the collected information to /interaction/v1/events route using Server-Side JavaScript. But first, let’s start with creating a new journey in Salesforce Marketing Cloud’s Journey Builder.

API Event Entry Source

When you create the journey for use with a custom form on a CloudPage, the only difference in the setup is the entry source, which in this case will be the API Event.

The API event in Journey Builder connects the journey canvas to an API used to admit contacts into a journey. When the API fires an event, the contacts entering the journey are stored in a Marketing Cloud data extension you choose. You can set a filter using Marketing Cloud data attributes to ensure that only intended customers enter the journey.

When you drag and drop the API Event into your journey’s canvas, click on it and choose to create an event. You will be prompted to choose a Data Extension for use with the journey and you will also see that an Event Definition Key has been created for your journey – copy it, as we will need it later for our script. Activate the journey.

Custom form on a CloudPage

We can now create our form on a CloudPage. For the purpose of this tutorial, it will be a very simple form collecting just the end user’s email address. We will also add some AMPscript to process the data from the form. If you haven’t created a form on a CloudPage yet, you might want to check out this article first: Create a Sales Cloud-integrated lead capture form using AMPscript. Here’s a basic form for our use case:

%%[
SET @Submit = RequestParameter("Submit")
IF @Submit != "Success" THEN
]%%
<h2>Email:</h2>
<form action="%%=RequestParameter('PAGEURL')=%%" method="GET">
<label for="email">Email address:</label>
<input type="email" id="email" name="email" required="yes">
<button type="submit" name="Submit" id="Submit" value="Success">Submit</button>
</form>
%%[
ENDIF
]%%
%%[
SET @email = RequestParameter("email")
IF @email != "" THEN
]%%
<! –– fire entry event script placeholder ––>
%%[
ENDIF
]%%

Fire an Entry Event using API

In order to inject a contact from our form into a journey, we will use Salesforce Marketing Cloud’s REST API, specifically the /interaction/v1/events route. Here’s an example request:

Host: https://YOUR_SUBDOMAIN.rest.marketingcloudapis.com
POST /interaction/v1/events
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
{
"ContactKey": "ID601",
"EventDefinitionKey":"AcmeBank-AccountAccessed",
"Data": {
"accountNumber":"123456",
"patronName":"John Smith" }
}

And an example response, which would indicate that the request has been processed correctly:

HTTP/1.1 201
{
"eventInstanceId": "########-####-####-####-############"
}

Like with any other API call, we will need to start with authentication. If you are not familiar with the concept, check out my other article, Salesforce Marketing Cloud API Authentication using Server-Side JavaScript.

As a security measure, it’s best to store your Client Id and Secret as encoded values in a Data Extension to avoid exposing them in your script. My preferred way is to use the EncryptSymmetric and DecryptSymmetric AMPscript functions for encryption, and a simple lookup to get their values from a Data Extension.

Here’s how the authentication part could look like:

//authenticate to get access token
var authEndpoint = 'https://mcxxx.auth.marketingcloudapis.com/&#39; //provide API endpoint
var payload = {
client_id: "xxxxxx", //pass Client ID
client_secret: "xxxxxx", //pass Client Secret
grant_type: "client_credentials"
};
var url = authEndpoint + '/v2/token'
var contentType = 'application/json'
var accessTokenRequest = HTTP.Post(url, contentType, Stringify(payload));
if (accessTokenRequest.StatusCode == 200) {
var tokenResponse = Platform.Function.ParseJSON(accessTokenRequest.Response[0]);
var accessToken = tokenResponse.access_token
var rest_instance_url = tokenResponse.rest_instance_url
};

Once we obtain the access_token and the rest_instance_url, we can move on to our actual call. We will pass the access_token in the authentication header, and in the payload, we will pass the data collected through the form and our journey’s event definition key. To get the form data, we will use an undocumented Server-Side JavaScript function, Request.GetQueryStringParameter(). Remember to include all the values passed in the payload in your target Data Extension, which you chose earlier upon creating the journey. Here we have just one such field, called email_field:

//make api call to inject contact to a journey
if (email != null && accessToken != null) {
var email = Request.GetQueryStringParameter("email");
var headerNames = ["Authorization"];
var headerValues = ["Bearer " + accessToken];
var jsonBody = {
"ContactKey": email,
"EventDefinitionKey": "APIEvent-xxxxxx", //provide journey EVENT DEFINITION KEY
"Data": {
"email_field": email
}
};
var requestUrl = rest_instance_url + "/interaction/v1/events";
var fireEntryEvent = HTTP.Post(requestUrl, contentType, Stringify(jsonBody), headerNames, headerValues);

The full script

If you put all the above together, you should end up with something like this:

%%[
SET @Submit = RequestParameter("Submit")
IF @Submit != "Success" THEN
]%%
<h2>Email:</h2>
<form action="%%=RequestParameter('PAGEURL')=%%" method="GET">
<label for="email">Email address:</label>
<input type="email" id="email" name="email" required="yes">
<button type="submit" name="Submit" id="Submit" value="Success">Submit</button>
</form>
%%[
ENDIF
]%%
%%[
SET @email = RequestParameter("email")
IF @email != "" THEN
]%%
<script runat="server">
Platform.Load("Core", "1");
try {
//authenticate to get access token
var authEndpoint = 'https://xxxx.auth.marketingcloudapis.com/&#39; //provide API endpoint
var payload = {
client_id: "xxxxxx", //pass Client ID
client_secret: "xxxxxx", //pass Client Secret
grant_type: "client_credentials"
};
var url = authEndpoint + '/v2/token'
var contentType = 'application/json'
var accessTokenRequest = HTTP.Post(url, contentType, Stringify(payload));
if (accessTokenRequest.StatusCode == 200) {
var tokenResponse = Platform.Function.ParseJSON(accessTokenRequest.Response[0]);
var accessToken = tokenResponse.access_token
var rest_instance_url = tokenResponse.rest_instance_url
};
//make api call to inject contact to a journey
if (email != null && accessToken != null) {
var email = Request.GetQueryStringParameter("email");
var headerNames = ["Authorization"];
var headerValues = ["Bearer " + accessToken];
var jsonBody = {
"ContactKey": email,
"EventDefinitionKey": "APIEvent-xxxxxxx", //provide journey EVENT DEFINITION KEY
"Data": {
"email_field": email
}
};
var requestUrl = rest_instance_url + "/interaction/v1/events";
var fireEntryEvent = HTTP.Post(requestUrl, contentType, Stringify(jsonBody), headerNames, headerValues);
if (fireEntryEvent.StatusCode == 201) {
Write("Success");
}
};
} catch (error) {
Write("Error");
}
</script>
%%[
ENDIF
]%%


Questions? Comments?

Leave a comment below or email me at zuzanna@sfmarketing.cloud.


6 thoughts on “Add subscribers to a Journey from a CloudPage using Fire Entry Event

  1. I left a comment already but it seems it didn’t go through, sorry if it did.

    Does the data extension used for the Data Entry source need to be the same populated by the form in Cloudpages?

    Like

  2. Arthur

    Great article, thank you! Given that the code runs server side, why do you feel you need to encrypt or hide the credentials? Do you mean from any marketers who might be working on the Cloudpage?

    Like

  3. rajesh

    Hi, If the data is coming into the marketing cloud from an external lead generation form through Mulesoft and multiple contacts enter their information parallelly from anywhere in the world but JSON is handling the single request. If we want to handle multiple requests at the same time, Then do we need to change anything?

    Like

Leave a comment