How to enhance your forms with asynchronous calls using AMPscript and plain JavaScript

How to enhance your forms with asynchronous calls using AMPscript and plain JavaScript

This article explains how to use Javascript and AMPscript to extend the functionality of your forms by creating asynchronous calls towards Marketing Cloud pages.

Not a fan of reading? Jump to the code snippet.

Ever heard of AJAX?

In a nutshell, AJAX is technique that allows us to retrieve the data from the server at any point in time after the page has been loaded.

It can be used in a multitude of cases, such as creating an autocomplete on an input field or checking if the specified email address is already in use.

But how does AJAX work within the limits of Marketing Cloud?

Return structured data with JSON

For starters, we need to create a page that would return Marketing Cloud data upon request.

The perfect candidate for this task is a JSON Code Resource page that can be created from the Web Studio.

Like any other page, a Code Resource page can run AMPscript and server-side Javascript, meaning that the content of the JSON object written on our page can be defined by whatever we want to retrieve from the Data Extensions.

Consider a JSON page with the URL https://somedomain.com/subscriptions and the following content:

%%[
	SET @NumberOfSubscriptions = DataExtensionRowCount('Subscriptions')
]%%
{
    "Subscriptions": %%=v(@NumberOfSubscriptions)=%%
}

In this particular example, the JSON object has a key named Subscriptions which is equal to number of records that can be found in a Data Extension with the same name.

Retrieving the data from a JSON page

So far so good, but how do we actually make an AJAX call to retrieve the data from the JSON page?

Let’s create a Cloud Page with a single button.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Cloud page</title>
</head>
<body>
	<button>Get Subscriptions</button>
</body>
</html>

Now, we need a proper Javascript to make the call and display it as an alert in our browser.

var xhr = new XMLHttpRequest();
xhr.onload = function () {
	if (xhr.status >= 200 && xhr.status < 300) {
		var response = JSON.parse(xhr.response);
		alert("Number of subscriptions: " + response['Subscriptions']);
	} else {
		alert('The request failed!');
	}
};
xhr.open('GET', 'https://somedomain.com/subscriptions');
xhr.send();

Seems about right. The only thing left to do is to attach an Event Listener to the button to trigger our script.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Cloud page</title>
</head>
<body>
	<button>Get Subscriptions</button>
	<script>
		function getSubscriptions() {
			var xhr = new XMLHttpRequest();
			xhr.onload = function () {
				if (xhr.status >= 200 && xhr.status < 300) {
					var response = JSON.parse(xhr.response);
					alert("Number of subscriptions: " + response['Subscriptions']);
				} else {
					alert('The request failed!');
				}
			};
			xhr.open('GET', 'https://somedomain.com/subscriptions');
			xhr.send();
		}
		var button = document.querySelector('button');
		button.addEventListener("click", getSubscriptions, false);
	</script>
</body>
</html>

Sending data to a JSON page

Retrieving a predefined piece of data from a JSON page is pretty sweet. But what if we wanted to retrieve something according to our parameters.

Consider it as a dialog, where you ask a question and receive a reply.

To accomplish this, let’s modify the JSON page to look for an email parameter, coming from the form or the URL.

%%[
	SET @AlreadyInUse = false
	SET @EmailAddress = RequestParameter('email')
	IF NOT EMPTY(@EmailAddress) THEN
		SET @Id = Lookup('Subscriptions','Id','EmailAddress',@EmailAddress)
		IF NOT EMPTY(@Id) THEN
			SET @AlreadyInUse = true
		ENDIF
	ENDIF
]%%
{
	"AlreadyInUse" : %%=v(Lowercase(@AlreadyInUse))=%%
}

From this point on, if we put a value in a URL parameter called email, the page will look for a matching email address in the Data Extension.

If the email parameter matches a value from any record in the Data Extension, the JSON key “AlreadyInUse” will be equal to “true“.

Note that, in order for this to work, we need to consider the following:

  • The Data Extension must have these 2 fields: Id and EmailAddress.
  • AMPscript boolean values are in capital case, which means that in order for the JSON to be valid, we’ll need to convert it to lower case.

Now that the JSON page is dealt with, let’s modify the Cloud page that sends the request.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Cloud page</title>
</head>
<body>
	<form action="" method="post">
		<input id="email" name="EmailAddress" type="email" placeholder="Your email" required>
		<button>Does it exist?</button>
	</form>
</body>
</html>	

As you can see, the page now accommodates a form where we can fill out the email address.

The next step is to write some Javascript that will send an AJAX request to the JSON page when a user submits the form.

var form = document.querySelector('form');
var button = document.querySelector('button');
var email = document.querySelector('input');
form.addEventListener("submit", onFormSubmit, false);
function onFormSubmit(e) {
	e.preventDefault();
	button.disabled = true;
	var xhr = new XMLHttpRequest();
	xhr.onload = function () {
		if (xhr.status >= 200 && xhr.status < 300) {
			var response = JSON.parse(xhr.response);
			if(response['AlreadyInUse'] == true) {
				button.disabled = false;
				alert('This email is already in use');
			} else {
				form.submit(); 
			}
		} else {
			alert('The request failed!');
		}
	};
	xhr.open('POST', 'https://somedomain.com/subscriptions?email=' + email.value);    
	xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
	xhr.send();
}

As you can see, the script will first wait for the response from the JSON page and then according to the response it got, it will either submit the form or display an error message.

Disabling the submit button while the request is being sent is just a simulation of a loading screen, but also prevents the user from submitting the form several times during the request.

Congratulations! We have now created a form that verifies that the email address is unique before submitting the form. Isn’t that something.

Full code

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Cloud page</title>
</head>
<body>
	<form action="" method="post">
		<input id="email" name="EmailAddress" type="email" placeholder="Your email" required>
		<button>Does it exist?</button>
	</form>
	<script>
		var form = document.querySelector('form');
		var button = document.querySelector('button');
		var email = document.querySelector('input');
		form.addEventListener("submit", onFormSubmit, false);
		function onFormSubmit(e) {
			e.preventDefault();
			button.disabled = true;
			var xhr = new XMLHttpRequest();
			xhr.onload = function () {
				if (xhr.status >= 200 && xhr.status < 300) {
					var response = JSON.parse(xhr.response);
					if(response['AlreadyInUse'] == true) {
						button.disabled = false;
						alert('This email is already in use');
					} else {
						form.submit(); 
					}
				} else {
					alert('The request failed!');
				}
			};
			xhr.open('POST', 'https://somedomain.com/subscriptions?email=' + email.value);    
			xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			xhr.send();
		}
	</script>
</body>
</html>	

Consider the possibilities

In this example, we have only considered 2 Javascript events: click and submit. But there are many others that you can use.

For instance, we can run the same script every time there is a blur event on the email input field. The blur event is fired every time we click on an input field and then click away.

What about the keyup event which is fired every time a keyboard key is released? This would work as follows: if the value of the email field is equal to something @ someding dot and the keyboard key is released, send a query to figure out if the email address already exists.

There are so many things we can do, but of course, it depends on what your requirements are.

Have I missed anything?

Please poke me with a sharp comment below or use the contact form.

  1. Hi, Ivan, really useful this content, congratulations!!
    I got a question, Can I use a script in SSJS (that create a data extension) into a button in onclick event?It’s possible? I found that AJAX could help me, but how can I do that? thanks in advance

  2. Hi Ivar, it’s me again, when you write, “xhr.open(‘POST’, ‘https://somedomain.com/subscriptions?email=’ + email.value);”

    What should I put in “https//:….” my marketing cloud link? my Landing page link? or what? Thanks again, i’m new with this things!!

  3. Hey Ivan, I wanted to create a One time Password Verification for our customer using Cloud Pages. Kindly let me know if this is feasible using AJAX

  4. Hey, I have no experience with this One time Password Verification, check if they have a documentation on how to implement it.

  5. Hello Ivan,
    I am looking forward to solve a use case:
    Do we have a solution via API/Ampscript where I want to see in how many Emails (Landing pages) my org specific Unsubscription URL is being used? There are few emails which are using the static unsubscription url but not the Unsub cloudpageID, so I want to know how many emails are using that static URL?

  6. Hi! I believe what you’re looking for is an SQL query looking into the Data Views where you can query on Clicks.

Comments are closed.

ampscript
Up Next:

How to use delimited strings to store more data in a single Data Extension record with AMPscript

How to use delimited strings to store more data in a single Data Extension record with AMPscript