Template marketplaces
Make a ThemeForest template's contact form work
Short answer
Set the template's form action to your WebForms endpoint. If the template submits with jQuery, add dataType: "json" to its $.ajax call and show response.message on success. No PHP, hosting or mail server is needed, and it works on static hosts like GitHub Pages and Netlify.
ThemeForest HTML templates usually ship a contact form wired to a PHP script that only works on a server that runs PHP and can send email. WebForms replaces that script: the form posts to your endpoint, and each submission is spam checked, stored and emailed to you. Most templates need one changed attribute and one changed line of JavaScript.
Setup
Create a form and copy its endpoint
Sign up, create a form, and copy the endpoint URL. Submissions are emailed to your verified address by default.
Find the contact form
Open the template's contact page, usually
contact.html, and find the<form>tag. Note itsactionand any id or class a script uses, such as#contact-form,.ajax-formor.form-widget.Point the action at WebForms
Replace the
actionvalue (for examplephp/contact.phpormail.php) with your endpoint, and keepmethod="POST". Keep the fieldnameattributes as they are: WebForms stores whatever fields the form sends.Fix the template's AJAX script
If the template submits without reloading the page, open its form script (often
js/ajax-mail.js,js/contact.jsorjs/main.js). AdddataType: "json"to the$.ajaxcall, and showresponse.messageinstead of the raw response. Scripts that hardcode the PHP URL, likecontact_me.js, need that URL replaced with your endpoint too.Delete the PHP files and send a test
Remove the template's mail scripts, such as
contact.php,mail.phpor thephp/folder, so nothing posts to them. Send a test from the live site; it appears in your inbox and the dashboard within seconds.
ThemeForest examples
Swap in your own endpoint and these run as-is.
<!-- contact.html: only the action changes -->
<form id="contact-form" action="https://send.webforms.to/wft_your_key" method="POST">
<input type="text" name="name" placeholder="Your name" required>
<input type="email" name="email" placeholder="Your email" required>
<input type="text" name="subject" placeholder="Subject">
<textarea name="message" placeholder="Message" required></textarea>
<!-- Optional: WebForms reads these -->
<input type="hidden" name="_subject" value="New enquiry from the website">
<input type="text" name="_gotcha" tabindex="-1" autocomplete="off"
style="position:absolute;left:-9999px" aria-hidden="true">
<button type="submit">Send message</button>
</form>The common jQuery handler, with the two changes marked:
// js/ajax-mail.js (or contact.js): the usual jQuery handler
$(form).submit(function (e) {
e.preventDefault();
$.ajax({
type: "POST",
url: $(form).attr("action"), // now your WebForms endpoint
data: $(form).serialize(),
dataType: "json" // add this: asks WebForms for JSON
})
.done(function (response) {
$(formMessages).removeClass("error").addClass("success");
$(formMessages).text(response.message); // was: .text(response)
$(form)[0].reset();
})
.fail(function () {
$(formMessages).removeClass("success").addClass("error");
$(formMessages).text("Sorry, your message could not be sent. Please try again.");
});
});If the template's script is hard to change, remove it and use this instead:
<!-- Replaces the template's form script entirely -->
<script>
document.querySelector("#contact-form").addEventListener("submit", async (e) => {
e.preventDefault();
const form = e.target;
const out = form.querySelector(".form-message") ?? form.appendChild(document.createElement("p"));
const body = new FormData(form);
// So "Reply" on the notification email goes to the visitor.
if (body.get("email")) body.set("_replyto", body.get("email"));
const res = await fetch(form.action, {
method: "POST",
body,
headers: { Accept: "application/json" },
});
const data = await res.json().catch(() => ({ ok: false }));
out.textContent = data.ok ? data.message : "Sorry, something went wrong. Please try again.";
if (data.ok) form.reset();
});
</script>Why the template's contact form does not send
Most marketplace HTML templates post the form to a PHP file that ships with the template, such as contact.php, mail.php, php/contact-form.php or bat/rd-mailform.php. That script calls PHP's mail function or PHPMailer to send you an email. It only works on a server that runs PHP and is allowed to send mail.
Static hosting runs no PHP at all, so on hosts like GitHub Pages and Netlify the POST fails, often with 405 Not Allowed. Some cloud providers, DigitalOcean among them, block outgoing mail ports by default. Shared hosting that does run PHP can still send these emails to spam, because they come from the web server rather than a real mail domain.
Pointing the form at a WebForms endpoint removes the PHP step. The submission goes to WebForms, which checks it for spam, stores it, and emails it to you, or sends it to Slack, Discord, Telegram or a webhook on Pro.
Which form script does your template use?
ThemeForest has no single standard: each author ships their own handler. These are the patterns that come up most, and what each needs.
- Plain form with no script: the page reloads on submit. Changing the
actionis all it needs. Add a hidden_nextfield with your own thank-you page URL, or WebForms shows its own. - jQuery
$.ajaxwithajax-mail.jsandmail.php: success shows the response text. AdddataType: "json"and displayresponse.message, as in the example above. - Start Bootstrap style
contact_me.jswithjqBootstrapValidation: the PHP URL is written into the script. Replace it with your endpoint and adddataType: "json". - Canvas by SemiColonWeb (
.form-widgetwithmodule.ajaxform.js): it already asks for JSON and shows themessageit gets back, so changing the formactionis enough. - jQuery Form plugin (
ajaxForm) or a custom success code, such as RD Mailform'sMF000: see the TemplateMonster guide, or replace the script with the plain fetch version above.
What you get instead of contact.php
Every submission is stored in a searchable inbox, so a missed email never means a missed enquiry. Spam is filtered without a CAPTCHA: a honeypot, a time trap and an AI classifier, on every plan including Free.
Free covers 300 submissions a month to one email address. Pro adds Slack, Discord, Telegram, webhooks, file uploads and an autoresponder, so the person who filled in the form gets a reply straight away.
Worth knowing
- Keep your field names. If the template's PHP read
$_POST['name']and$_POST['email'], the form already sendsnameandemail, and WebForms stores whatever fields arrive. To make Reply on the notification email go to the visitor, send their address as_replytotoo; the fetch script above does that for you. - Cross-domain jQuery requests never send
X-Requested-With, so withoutdataType: "json"the endpoint answers with a thank-you page instead of JSON. That is why the template shows an error, or a page of HTML, even though the message arrived. - If the template has a reCAPTCHA check that posts to its own PHP file, remove that check: it fails without PHP. WebForms filters spam without a CAPTCHA, or can verify your own CAPTCHA keys if you want one.
ThemeForest form FAQ
It posts to a PHP script, such as contact.php or mail.php, that needs a server running PHP with outgoing mail allowed. Static hosts like GitHub Pages, Netlify and Cloudflare Pages run no PHP, so the form fails or returns 405. Point the form at a WebForms endpoint and it works on any host.
No PHP at all. You change one attribute in the HTML, and if the template sends the form without reloading the page, one or two lines in its JavaScript file. The guide above shows exactly which.
Yes. Many Envato Elements HTML templates are the same code as on ThemeForest, so the same steps apply. See the Envato Elements guide for Elementor template kits.
Yes. The Free plan emails up to 300 submissions a month to your address, with spam filtering included. Slack, Discord, Telegram and webhooks are on Pro.
The template's script expected a different reply than the one it got. Add dataType: "json" to its $.ajax call and show response.message; WebForms then answers with JSON that includes alert: "success" and a message.
Yes. Canvas's form widget already asks for JSON and reads the alert and message fields WebForms returns, so you only change the form's action.
Related guides
Where ThemeForest submissions can go
The guide above gets the submission to your endpoint. From there it can land anywhere: one destination on Free, several on Pro.
Need the form markup too? The template gallery has complete forms for contact, waitlist, job application and more, and the form generator builds one field by field.
Ready to wire up your ThemeForest form?
Free for 300 submissions a month. Endpoint in under a minute, no card required.
Start free