Marketo Free Email Domain Blocker: Copy, Paste, Done

February 5, 20267 min read

If you run Marketo forms on your landing pages, you already know the problem. Half the submissions come from gmail.com, yahoo.com, and throwaway addresses that will never turn into pipeline. Here is a free, copy and paste script that blocks free and disposable email domains and requires a business email address. No Marketo admin access needed. No third party tools. Just paste it and go.

Why Free Email Blocking Matters

Every B2B marketer has seen the data. You run a campaign, drive traffic to a gated asset, and watch the leads pour in. Then you look closer. Half of them are personal Gmail addresses. A quarter are Yahoo. A few are from Mailinator and Guerrilla Mail. Your SDRs spend their morning qualifying leads that were never going to buy.

The cost is not just wasted sales time. It pollutes your lead scoring models. It skews your campaign reporting. It inflates your database with contacts that will never engage. And if you are paying per lead or syncing to Salesforce, every junk submission has a real dollar cost attached to it.

Most marketing automation platforms charge by database size. Every fake lead sitting in your Marketo instance is costing you money just by existing.

How This Script Works

This is a lightweight JavaScript snippet that hooks into Marketo's native form validation. It runs entirely in the browser. No server side code, no API calls to your Marketo instance, no third party dependencies you need to worry about.

When the page loads, the script fetches a comprehensive list of roughly 2,800 known free and disposable email domains from a publicly maintained GitHub repository. That list includes the obvious ones like gmail.com and yahoo.com, but also hundreds of temporary email services like mailinator.com, guerrillamail.com, and throwaway.email that most basic blockers miss entirely.

The list gets cached in the visitor's browser using localStorage for 24 hours. So if someone visits multiple landing pages on your site, it does not re-fetch the list every time. One download, cached locally, reused across page views.

If the fetch fails for any reason (network issue, GitHub is down, corporate firewall blocks it), the script falls back to a hardcoded list of the 15 most common free email providers. Your forms stay protected either way.

When a visitor submits the form, the script extracts the domain from their email address and checks it against the list. If the domain matches, Marketo's native form.showErrorMessage() displays a clean inline error asking for a business email. The form does not submit. No page reload, no jarring experience. It looks and feels like native Marketo validation.

The Nerdy Details

A few things make this script particularly well built for production use.

It waits for the MktoForms2 library to load before doing anything. Marketo forms load asynchronously, and if your script runs before the library is ready, nothing works. This script polls for MktoForms2 every 50 milliseconds with a 10 second timeout. No race conditions, no load order dependencies.

The domain matching is not just a simple string comparison. It checks for exact matches and subdomain matches. So if someone tries mail.gmail.com or something.mailinator.com, it still gets caught. The domainMatches() function uses endsWith() to handle these cases cleanly.

There is also a guard for the gap between page load and when the domain list finishes downloading. If someone fills out the form faster than the list can load (unlikely, but possible), the script blocks submission with a "Please wait a moment and try again" message. No false positives, no free email addresses slipping through during the loading window.

The whole thing is wrapped in an IIFE (Immediately Invoked Function Expression) with "use strict", so it does not leak variables into the global scope or conflict with other scripts on your page. It plays nicely with tag managers, other Marketo customizations, and whatever else you have running on your landing pages.

The Script

Copy this entire block and paste it into your Marketo landing page. That is it.

<script>
/* Marketo Free Email Domain Blocker | Coded with care by SRWorks (srworks.co) */
(function(){
"use strict";
function onMktoReady(callback,timeout){
  var maxWait=timeout||10000,elapsed=0,interval=50;
  var check=setInterval(function(){
    elapsed+=interval;
    if(typeof MktoForms2!=="undefined"){clearInterval(check);callback();}
    else if(elapsed>=maxWait){clearInterval(check);console.warn("MktoForms2 not found");}
  },interval);
}
onMktoReady(function(){
  var CACHE_KEY="mkto_free_domains";
  var CACHE_TTL_MS=86400000;
  var FREE_DOMAINS_URL="https://raw.githubusercontent.com/srworksllc/free-email-domains/main/domains.json";
  var FALLBACK_FREE_DOMAINS=[
    "gmail.com","googlemail.com",
    "yahoo.com","yahoo.co.uk","yahoo.ca","yahoo.com.au","yahoo.co.in",
    "yahoo.fr","yahoo.de","yahoo.es","yahoo.it","yahoo.co.jp",
    "yahoo.com.br","yahoo.com.mx","ymail.com","rocketmail.com",
    "hotmail.com","hotmail.co.uk","hotmail.fr","hotmail.de","hotmail.es",
    "hotmail.it","hotmail.ca","outlook.com","outlook.co.uk","outlook.fr",
    "outlook.de","live.com","live.co.uk","live.fr","live.de","msn.com",
    "icloud.com","me.com","mac.com",
    "aol.com","aol.co.uk","protonmail.com","proton.me","pm.me",
    "zoho.com","mail.com","gmx.com","gmx.net","gmx.de","gmx.at","gmx.ch",
    "qq.com","163.com","126.com","sina.com","naver.com","daum.net",
    "rediffmail.com","mail.ru","yandex.com","yandex.ru","web.de",
    "t-online.de","orange.fr","free.fr","laposte.net","libero.it"
  ];
  function getEmailDomain(email){return email.split("@").pop().toLowerCase();}
  function domainMatches(domain,list){
    return list.some(function(d){return domain===d||domain.endsWith("."+d);});
  }
  function findEmailField(form){
    var formEl=form.getFormElem();
    return formEl.find("input[name='Email']").length?formEl.find("input[name='Email']"):formEl.find("input[name='email']");
  }
  function loadDomainList(){
    return new Promise(function(resolve){
      try{
        var cached=JSON.parse(localStorage.getItem(CACHE_KEY));
        if(cached&&cached.data&&cached.fetchedAt&&Date.now()-cached.fetchedAt<CACHE_TTL_MS){return resolve(cached.data);}
      }catch(e){}
      fetch(FREE_DOMAINS_URL)
        .then(function(r){if(!r.ok)throw new Error();return r.json();})
        .then(function(data){
          if(!Array.isArray(data))throw new Error();
          try{localStorage.setItem(CACHE_KEY,JSON.stringify({data:data,fetchedAt:Date.now()}));}catch(e){}
          resolve(data);
        })
        .catch(function(){resolve(FALLBACK_FREE_DOMAINS);});
    });
  }
  MktoForms2.whenReady(function(form){
    var domainList=FALLBACK_FREE_DOMAINS.slice();
    var listReady=false;
    loadDomainList().then(function(list){domainList=list;listReady=true;});
    form.onValidate(function(){
      var vals=form.vals();
      var email=vals.Email||vals.email;
      if(!email)return;
      var domain=getEmailDomain(email);
      var field=findEmailField(form);
      if(!listReady){form.submittable(false);form.showErrorMessage("Please wait a moment and try again.",field);return;}
      if(domainMatches(domain,domainList)){form.submittable(false);form.showErrorMessage("Please use a business email address.",field);return;}
      form.submittable(true);
    });
  });
});
})();
</script>

Installation

Getting this onto your Marketo landing pages takes about 30 seconds.

  1. Open your landing page in Marketo (or edit the landing page template if you want it on every page)
  2. Go to Settings or edit the template HTML
  3. Paste the script into the Head HTML or Footer HTML section
  4. Approve and publish

If you add it to a landing page template, every page using that template picks it up automatically. One paste, all your forms are protected. No need to touch individual pages.

The script works with any Marketo form that has an Email field. It does not care about your form ID, your Munchkin code, or your instance configuration. If MktoForms2 is on the page and there is an email field, the blocker kicks in.

What About Legitimate Personal Emails

This is worth thinking about. Not every Gmail submission is junk. Freelancers, consultants, and small business owners sometimes use personal email for work. Blocking them means you might miss a few real prospects.

In my experience running B2B campaigns, the tradeoff is overwhelmingly worth it. For every one legitimate prospect using a personal email, there are dozens of tire kickers, students downloading assets for class, and competitors poking around. The math is clear.

If you are running campaigns targeting SMBs or freelancers specifically, you might want to trim the blocked list or skip this script entirely for those campaigns. But for enterprise and mid market B2B, requiring a business email is table stakes in 2026.

Why Not Use a Marketo Smart Campaign Instead

You could build domain blocking with Marketo Smart Campaigns and Smart Lists. Filter on email domain, route to a rejection flow, send an automated response asking for a business email. Some teams do this.

The problem is that the lead already entered your database. You already paid for that record. Your form fill metrics are already inflated. And the visitor experience is terrible. They fill out a form, think they got the asset, and then get a rejection email later.

Client side validation catches it before the form ever submits. The visitor sees an immediate, inline error message. No database record created. No wasted API calls. No confused prospects. It is faster, cleaner, and cheaper.

Customization

The script is intentionally simple to modify.

Want to change the error message? Find the form.showErrorMessage() line and update the string. Want to allow a specific free domain? Remove it from the fallback list. Want to change the cache duration? Adjust the CACHE_TTL_MS value. The code is well commented and easy to read.

You can also swap out the domain list URL if you maintain your own blocklist or want to use a different source. The script expects a JSON array of domain strings. Point it at any URL that returns that format and it works.

Free and Open

This script is completely free. No attribution required. No license to worry about. Copy it, paste it, modify it, share it with your team. We built it because we needed it, and figured other Marketo teams could use it too.

That is how we think about building tools at SRWorks. Solve a real problem, keep it simple, and share it. If you are spending time cleaning junk leads out of your Marketo database, this script means you never have to do that again.