If you're a marketer focused on lead generation, you're adding parameters to links in campaigns to track campaign performance. If a user clicks one of your links and then completes a form on your site, those campaign parameters need to be passed through to your CRM.

Because my audience is marketers I've written this as simply as possible. Even if you have a primitive understanding of JavaScript, I think you'll be able to follow along.

URL Parameter Examples

Below is an example of a URL that might be created to track a specific campaign. This URL contains the standard UTM parameters but you can also use custom parameters.

http://demandstack.io/?utm_source=reddit&utm_medium=cpc&
utm_campaign=awareness&utm_id=615690&utm_content=open-source	

Below is an example of a URL with custom parameters.

http://demandstack.io/?ds_id=849375894&source=reddit&campaign_id=61560980&ad_id=1842038674

Capturing Parameters

Using vanilla Javascript, we're going to make use of the URLSearchParams utility. This is a JavaScript constructor that provides a lot of helpful methods for manipulating data.

// get query string from url
const paramsString = window.location.search;

// create a new URLSearchParams object 
const params = new URLSearchParams(paramsString);

The code above gets the URL query string (the stuff after the '?'). Then we create an object called 'params' using URLSearchParams. This object stores the URL parameters in key/value pairs. 

Using Cookies to Store Campaign Parameters

This is the important part. We strongly recommend storing campaign parameter data in cookies. This is because when a user clicks your campaign link and visits your landing page, the parameters are there in the URL. However, as soon as that user navigates to another page, all those URL parameters disappear, and that data is gone.

This is why we store data as cookies. Below is a function for setting a cookie in a user's browser.  

function setCookie(cookie_name, cookie_value, expiration_in_days) {
  const d = new Date();
  d.setTime(d.getTime() + (expiration_in_days*24*60*60*1000));
  let expires = "expires="+ d.toUTCString();
  document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}

In this function, we have the cookie name, the cookie value, and the number of days until the cookie expires. Now, we take our key/value pairs and set them as cookies. But, we don't always want all of the parameters. To add some control, I create a variable called targetParams to designate the data I want to collect.

// The keys of the parameters we want to capture
targetParams = ['source', 'campaign_id']

// Iterate through key/value pairs of parameters
for (const [key, value] of params.entries()) {

  // Only include targeted parameters
  if (targetParams.includes(`${key}`)) {
        
    // Set cookie for key value pair (cookie_name, cookie_value, expiration_in_days)
    setCookie(`${key}`, `${value}`, 90)
  }
}

Once you've tried setting a cookie you can verify it's working by opening Chrome developer tools and going to the Application tab (see screenshot below). On the left sidebar, you'll see a section called Cookies. If there are multiple sites listed, pick your site.  In the main window, you'll see the list of cookies on your browser. 

cookies-tab-developer-tools-1fgu8.jpg

For my example, I'm looking for cookies with the name 'source' and 'campaign_id' to ensure everything is working.

Reading Cookies and Setting Form Values

Below is the function for getting the data from a user's stored cookies. If they clicked your campaign link and navigated around the website before going to your form, that's OK. We can still grab the cookie data.

// Get Cookie
function getCookie(cname) {
  let name = cname + "=";
  let decodedCookie = decodeURIComponent(document.cookie);
  let ca = decodedCookie.split(';');
  for(let i = 0; i <ca.length; i++) {
    let c = ca[i];
    while (c.charAt(0) == ' ') {
      c = c.substring(1);
    }
    if (c.indexOf(name) == 0) {
      return c.substring(name.length, c.length);
    }
  }
  return "";
}

Our form might look something like this.

<form action="#">
  <label for="fname">First name:</label><br>
  <input type="text" id="fname" name="fname" value="John"><br>
  <label for="lname">Last name:</label><br>
  <input type="text" id="lname" name="lname" value="Doe"><br><br>

  <input type="hidden" id="source" name="source" value="">
  <input type="hidden" id="campaign_id" name="campaign_id" value="">

  <input type="submit" value="Submit">
</form> 

We have two hidden input fields that we need to set values for, but you might have five or ten. Something that will save a lot of time and code is giving your hidden input fields ids that match your campaign parameters. This makes the code below really simple. We can just iterate through our targeted parameters (from the variable 'targetParams') and set values. 

targetParams.map((param, index) => {

  // Run the getCookie function for a parameter 
  let paramValue = getCookie(param)
  
  // Set the input value for the associated parameter

  document.getElementById(param).value = paramValue
  
})

When the user hits submit, the data in these hidden fields will be sent with the rest of the form data payload.

Handling Form Data

The least technical way to handle this webform data is to use an automation platform like Zapier or Make. Using these tools, you'll need to create a webhook (catch hook) and use that webhook URL as your form action. Then map the data using the connector for your CRM.

Some CRMs have form capture tools that provide an endpoint URL and provide field ids that need to be included in your form inputs.

Cases that involve complex data transformation or sending data to multiple applications might require something more elaborate. One example is to create a form handler service on AWS that can receive payloads and perform ETL.