ContactLintAPIMCPPricingFree toolsGet a key

Home / Add the Email Typo Checker to React, WordPress and Site Builders

Add the Email Typo Checker to React, WordPress and Site Builders

Published 2026-10-17

The ContactLint widget shows Did you mean jane@gmail.com? under an email field when the domain looks like a typo, and a short note when the domain cannot receive mail or is disposable. This page shows how to add it where you cannot hand-edit plain HTML: React apps, WordPress form plugins and site builders. For the basics, start with the widget setup guide.

Before you start: a publishable key for every domain you use

Create a publishable key with your secret key (free at /signup) and list every origin the form runs on: your live domain, a staging domain if you have one, and http://localhost:PORT for local development. A key accepts up to 5 origins.

curl -X POST https://contactlint.com/v1/widget/keys \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -H "content-type: application/json" \
  -d '{"origins":["https://yoursite.com","http://localhost:5173"],"daily_cap":200}'

How the script finds email fields

React

Load the script once, in index.html or your root layout:

<script src="https://contactlint.com/widget.js" data-key="cl_pub_..." defer></script>

Mark the input and give the hint its own element, so the widget never adds nodes inside markup React manages:

function EmailField({ value, onChange }) {
  return (
    <>
      <input type="email" value={value} onChange={e => onChange(e.target.value)}
             data-contactlint data-contactlint-hint="email-hint" />
      <p id="email-hint"></p>
    </>
  );
}

Controlled inputs work: when someone clicks the suggestion, the widget sets the value the way React expects and fires an input event, so your onChange runs and your state gets the corrected address. To act on the result, for example to disable the submit button for disposable addresses, listen for the contactlint:result event:

const ref = useRef(null);
const [blocked, setBlocked] = useState(false);
useEffect(() => {
  const el = ref.current;
  const onResult = e => setBlocked(e.detail.verdict === 'invalid' || e.detail.disposable);
  el.addEventListener('contactlint:result', onResult);
  return () => el.removeEventListener('contactlint:result', onResult);
}, []);
// <input ref={ref} ... />

WordPress

Form plugins usually do not let you add a custom attribute to the email field, so use data-selector. Add this to your theme's functions.php or a code snippets plugin:

add_action('wp_footer', function () {
  echo '<script src="https://contactlint.com/widget.js" data-key="cl_pub_..." data-selector="input[type=email]" defer></script>';
});

This checks every email field on the site, including comment and checkout forms. To limit it to one form, use a narrower selector such as #signup-form input[type=email].

Webflow and other site builders

Paste the same script tag, with data-selector="input[type=email]", into your site's footer custom code setting. If the builder gives your site a staging domain, add that domain to the publishable key's origins too, or the widget stays silent there.

Limits and costs

Each check uses one check from your account: 100 free checks per month, then credit packs from $9 for 5,000 (see pricing). A field is only checked when it loses focus with a new value. Publishable keys are limited to 10 checks per minute per visitor network, 30 per minute per key, and a daily cap you choose. The widget never blocks a form by itself, and it does not confirm that a mailbox exists. For a check that cannot be skipped, also validate on the server.

Get a free API key. 100 checks per month, no card required.