Custom form validation for Instapage landing pages

Created by Todd Belcher, Modified on Sat, 13 Jul at 9:53 PM by Todd Belcher

When the standard email, phone, required/not required validations are not sufficient, Instapage allows us to tap into their validation API to customize the experience.


In the form field settings, each field has a "Text field label" which ends up in the HTML form element as the name attribute.

The example custom JavaScript below can be added by a technical marketer or ZappyPeople, customized to suit your needs.


The script below, unedited, would automatically find fields that contain "email" or "phone" as well as "first name" and "last name". If those are required fields, they will be checked with some custom validation to try and reduce spam entries.


This can be done by heading to the "Scripts & Privacy" area from the landing page settings:



Here's where we would paste the modified script into the footer of a test landing page to make sure it works the way you want it-- if something else is there, be careful not to disturb it:



And here's the code example, feel free to use it! Be sure to copy/paste as text :) 


document.addEventListener('DOMContentLoaded', function() {
    // List of patterns for detecting junk email addresses
    var junkEmailPatterns = [
      /\d{2,}/, /temp/, /dispos/, /trash/, /fake/, /spam/, /mailinator/,
      /maildrop/, /throwaway/, /guerrillamail/, /10minutemail/, /yopmail/, 
      /mailnesia/, /mailinator\.com|rhyta\.com|gsko\.com|dayrep\.com|elahan\.com|cesjoplin\.com|jourrapide\.com|busd\.com|teleworm\.us|armyspy\.com$/i,
      /\.ru$/, /\.tk$/, /\.ml$/, /\.ga$/, /\.gq$/, /\.cf$/, /\.top$/, /\.xyz$/, /\.site$/, /\.win$/, /\.club$/
    ];

    // List of fake strings commonly used in spam
    var fakeStrings = ['dgf', 'sdf', 'jhk', 'hjk', 'asd', 'asdf'];

    // HTML for the validation modal
    var modalHtml = `
      <div id="validationModal" class="modal">
        <div class="modal-content">
          <span class="close">&times;</span>
          <p id="modalMessage"></p>
        </div>
      </div>
    `;
    document.body.insertAdjacentHTML('beforeend', modalHtml);

    // CSS for the validation modal
    var modalCss = `
      .modal {
        display: none; 
        position: absolute; 
        background-color: rgba(0,0,0,0.4); 
        z-index: 9999; /* Adjust this value as needed */
      }
      .modal-content {
        background-color: #fff;
        padding: 20px;
        border: 1px solid #ccc;
        width: 100%;
        box-sizing: border-box;
        position: relative; 
      }
      .close {
        position: absolute;
        top: 1px;
        right: 10px;
        color: #aaa;
        font-size: 28px;
        font-weight: bold;
        cursor: pointer;
      }
      .close:hover,
      .close:focus {
        color: black;
        text-decoration: none;
      }
    `;
    var style = document.createElement('style');
    style.type = 'text/css';
    style.appendChild(document.createTextNode(modalCss));
    document.head.appendChild(style);

    // Convert email inputs to lowercase
    document.querySelectorAll("input").forEach(function(input) {
      if (input.name.toLowerCase().includes('email')) {
        input.addEventListener("input", function(e) {
          e.target.value = e.target.value.toLowerCase();
        });
      }
    });

    // Email validation function
    function isValidEmail(email) {
      const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
      const isValidFormat = emailPattern.test(email);
      const domain = email.split('@')[1];
      const domainParts = domain.split('.');
      const isSingleCharacterDomain = domainParts.some(part => part.length === 1);
      const matchesJunkPattern = junkEmailPatterns.some(pattern => pattern.test(email));
      const hasFakeStringsTwice = fakeStrings.filter(str => email.includes(str)).length > 1;
      const hasEnoughUniqueChars = new Set(email).size >= 6;
      const hasFiveVowelsInRow = /[aeiou]{5}/i.test(email);

      const front = email.split('@')[0];
      const hasNoVowelsInFront = front.length >= 6 && !/[aeiou]/i.test(front);

      return isValidFormat && 
             !isSingleCharacterDomain && 
             !matchesJunkPattern && 
             !hasFakeStringsTwice && 
             hasEnoughUniqueChars && 
             !hasFiveVowelsInRow && 
             !hasNoVowelsInFront;
    }

    // Phone number validation function
    function isValidPhoneNumber(phoneNumber) {
      const pattern = /^(?:(?:\+?1\s*(?:[.\-\s]*)?)?(?!(?:.*555[\-\s]*555[\-\s]*5555|.*123[\-\s]*456[\-\s]*7890|.*012[\-\s]*345[\-\s]*6789))\(?([2-9][0-9]{2})\)?[\s.\-]*([2-9][0-9]{2})[\s.\-]*([0-9]{4}))$/;
      const cleanedPhoneNumber = phoneNumber.replace(/[^\d+]/g, '');
      return pattern.test(cleanedPhoneNumber);
    }

    // Zip code validation function
    function isValidZipCode(zip) {
      const usZipPattern = /^\d{5}(-\d{4})?$/;
      const caZipPattern = /^[A-Za-z]\d[A-Za-z] ?\d[A-Za-z]\d$/;
      return usZipPattern.test(zip) || (caZipPattern.test(zip) && /[A-Za-z]/.test(zip));
    }

    // Name validation function
    function isValidName(firstName, lastName) {
      const fullName = firstName + lastName;
      const hasThreeUniqueChars = new Set(fullName).size >= 3;
      const fiveConsonantsPattern = /[^aeiou]{5}/i;
      const threeSameLetterPattern = /(.)\1\1/;
      const hasConsecutiveConsonants = fiveConsonantsPattern.test(firstName) || fiveConsonantsPattern.test(lastName);
      const hasSameLetterInRow = threeSameLetterPattern.test(firstName) || threeSameLetterPattern.test(lastName);
      const hasFakeStrings = fakeStrings.some(str => firstName.includes(str) || lastName.includes(str));
      return hasThreeUniqueChars && !hasConsecutiveConsonants && !hasSameLetterInRow && !hasFakeStrings;
    }

    // Validation functions for different field types
    var validationFunctions = {
      email: function(input) {
        var email = input.value;
        var isValidEmailAddress = email.length >= 8 && isValidEmail(email);
        return {
          isValid: isValidEmailAddress,
          message: 'Please enter a valid email address.',
        };
      },
      phone: function(input) {
        var phone = input.value;
        var isValidPhone = isValidPhoneNumber(phone);
        return {
          isValid: isValidPhone,
          message: 'Please enter a valid phone number.',
        };
      },
      zip: function(input) {
        var zip = input.value;
        var isValidZip = isValidZipCode(zip);
        return {
          isValid: isValidZip,
          message: 'Please enter a valid US or CA zip code.',
        };
      },
      name: function(input) {
        var firstName = document.querySelector('[name*="First Name"]').value;
        var lastName = document.querySelector('[name*="Last Name"]').value;
        var isValid = isValidName(firstName, lastName);
        return {
          isValid: isValid,
          message: 'Please enter a valid name.',
        };
      }
    };

    // Validate fields when form button is clicked
    document.querySelectorAll('.form-btn').forEach(function(button) {
      button.addEventListener('click', function(event) {
        var form = button.closest('form');
        var allValid = true;
        var messages = new Set();
        var lastInvalidField = null;

        Object.keys(validationFunctions).forEach(function(validationType) {
          var input = Array.from(form.querySelectorAll('[name]')).find(input => input.name.toLowerCase().includes(validationType));
          if (input) {
            if (input.type === 'select-multiple' || (validationType === 'phone' && input.type !== 'tel' && !input.name.toLowerCase().includes('phone number'))) {
              return;
            }
            var result = validationFunctions[validationType](input);
            if (!result.isValid) {
              allValid = false;
              messages.add(result.message);
              lastInvalidField = input;
            }
          }
        });

        if (!allValid && lastInvalidField) {
          event.preventDefault();
          var formRect = form.getBoundingClientRect();
          var buttonRect = button.getBoundingClientRect();
          showModal(Array.from(messages).join('\n'), formRect.width, buttonRect.top - formRect.top - 10);
        }
      });
    });

    var modal = document.getElementById("validationModal");
    var span = document.getElementsByClassName("close")[0];

    // Show validation modal with error messages
    function showModal(message, formWidth, buttonTop) {
      document.getElementById("modalMessage").innerText = message;
      var modalContent = modal.querySelector('.modal-content');
      modalContent.style.width = formWidth + 'px';
      modal.style.top = buttonTop + 'px';
      modal.style.left = '50%';
      modal.style.transform = 'translateX(-50%)';
      modal.style.display = 'block';
    }

    // Close the modal when the close button is clicked
    span.onclick = function() {
      modal.style.display = "none";
    }

    // Close the modal when clicking outside of it
    window.onclick = function(event) {
      if (event.target == modal) {
        modal.style.display = "none";
      }
    }
  });

Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article