splitforms.com
HOME SERVICES · CONTACT FORM TEMPLATE

HVAC Service & Quote Request Form

HVAC tickets are seasonal and shaped like a hockey stick — first 90F day, every AC in town breaks. The form needs to triage by system age and current symptom or your dispatch board melts down.

1,000/mo free·no card·works on any host
form.htmlhtml53 lines
01<form action="https://splitforms.com/api/submit" method="POST">
02 <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY">
03 <input type="hidden" name="subject" value="New HVAC service request">
04
05 <label for="name">Full name *</label>
06 <input id="name" type="text" name="name" placeholder="Hans Becker" required>
07 <label for="email">Email *</label>
08 <input id="email" type="email" name="email" placeholder="hans@example.com" required>
09 <label for="phone">Phone *</label>
10 <input id="phone" type="tel" name="phone" placeholder="+1 555 0142" required>
11 <label for="address">Service address *</label>
12 <input id="address" type="text" name="address" placeholder="1247 Valencia St" required>
13 <label for="service">What do you need? *</label>
14 <select id="service" name="service" required>
15 <option value="">Choose…</option>
16 <option>AC not cooling</option>
17 <option>Heat not working</option>
18 <option>New install / replacement</option>
19 <option>Maintenance / tune-up</option>
20 <option>Duct cleaning</option>
21 <option>Quote for new system</option>
22 </select>
23 <label for="system">System type</label>
24 <select id="system" name="system">
25 <option value="">Choose…</option>
26 <option>Central AC</option>
27 <option>Heat pump</option>
28 <option>Furnace</option>
29 <option>Mini-split</option>
30 <option>Boiler</option>
31 <option>Not sure</option>
32 </select>
33 <label for="age">How old is the system?</label>
34 <select id="age" name="age">
35 <option value="">Choose…</option>
36 <option>Under 5 years</option>
37 <option>5–10 years</option>
38 <option>10–15 years</option>
39 <option>15+ years</option>
40 <option>Not sure</option>
41 </select>
42 <label for="details">Describe the issue *</label>
43 <textarea id="details" name="details" placeholder="When it started, error codes, recent changes…" required></textarea>
44
45 <!-- honeypot — bots fill every field -->
46 <input type="checkbox" name="botcheck" style="display:none" tabindex="-1" autocomplete="off">
47
48 <button type="submit">Send</button>
49</form>
50
51<p style="margin-top:12px;font-size:11px;color:#888;text-align:right">
52 Powered by <a href="https://splitforms.com" style="color:#888;text-decoration:none" target="_blank" rel="noopener">splitforms</a>
53</p>
1,000
submissions / mo, free
8
fields, ready to ship
5
code outputs
60s
from copy to inbox
HVAC Service & Quote Request Form — example splitforms template with submissions inbox
§ 01Why it mattersthe qualifying-fields argument

HVAC has the most predictable lead-volume swings of any trade — first heat wave or first cold snap and your phones don't stop. The form needs system-age and symptom fields up front because they determine whether you're selling a $200 capacitor swap or a $12,000 system replacement. A 14-year-old AC blowing warm air is a replacement conversation; a 3-year-old unit is a repair. Knowing which before the truck rolls is the difference between a profitable day and a lost one.

Built for shops on ServiceTitan / Housecall Pro / Jobber — webhook in 10 minutes.
✦ at a glance
  • HVAC / AC repair request · 8 fields
  • HTML, JS, React, PHP, cURL outputs
  • One POST endpoint, no SDK
  • Honeypot + classifier, no CAPTCHA
§ 02Live previewinteractive · sandboxed · no key required

See exactly what your visitors see — and you’ll receive.

Left: the rendered form, fully interactive in a sandboxed iframe. Right: the email and dashboard view that lands the moment a visitor submits.

preview · hvac-contact-formlocalhost:3000
✦ what you’ll see in your inbox

Every submission becomes an email plus a dashboard row. The fields below are the exact payload your form will send. Reply-to is wired to the visitor’s email so hitting reply goes back to them.

dashboard · new submission14ms · 200 OK
SUBJECT · New HVAC service request
Full name
Maya Iyer
Email
maya@studio71.co
Phone
+1 415 555 0142
Service address
What do you need?
AC not cooling
System type
Central AC
How old is the system?
Under 5 years
Describe the issue
Loved your last open house in Hayes — looking for similar with parking. Pre-approved through Wells Fargo.

Iframe is sandboxed — submit doesn’t actually fire. Get your access key to wire it up live.

§ 03Three steps3 steps · ~60 seconds

Generate, embed, receive.

Three actions stand between you and your first lead. None of them require a backend, a database, or a CAPTCHA library.

STEP 01GENERATE

Capture system age and symptom

Required: system type (central AC / heat pump / furnace / mini-split), age in years, current symptom. Optional: brand and model. Replacement-shoppers vs repair-shoppers split on age alone.

Create your form
key=sk_live_••••••••
STEP 02EMBED

Tier urgency by season

In summer, 'no cooling' is a same-day callout. In winter, 'no heat' is the same. Tune-ups and quotes can wait a week. The dropdown shapes dispatch's morning queue.

snippethtml
<form action="https://splitforms.com/api/submit" method="POST">
  …
</form>
STEP 03RECEIVE

Webhook to ServiceTitan / Jobber

splitforms posts the structured submission to your field-service platform with the system age, symptom, and address. Tech arrives with the right replacement options pre-loaded on the iPad.

inbox · 1 newjust now
FROM contact@yoursite.com
New HVAC service request
Maya Iyer maya@studio71.co
Loved your last open house in Hayes — looking for similar with parking. Pre-approved through Wells Fargo.
§ 04Copy & ship5 languages · same endpoint

Five outputs. One backend.

HTML by default. Click open the language you ship in — every variant POSTs to the same /api/submit endpoint.

01HTMLform.html53 lines
<form action="https://splitforms.com/api/submit" method="POST">
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY">
  <input type="hidden" name="subject" value="New HVAC service request">

  <label for="name">Full name *</label>
  <input id="name" type="text" name="name" placeholder="Hans Becker" required>
  <label for="email">Email *</label>
  <input id="email" type="email" name="email" placeholder="hans@example.com" required>
  <label for="phone">Phone *</label>
  <input id="phone" type="tel" name="phone" placeholder="+1 555 0142" required>
  <label for="address">Service address *</label>
  <input id="address" type="text" name="address" placeholder="1247 Valencia St" required>
  <label for="service">What do you need? *</label>
  <select id="service" name="service" required>
    <option value="">Choose…</option>
    <option>AC not cooling</option>
    <option>Heat not working</option>
    <option>New install / replacement</option>
    <option>Maintenance / tune-up</option>
    <option>Duct cleaning</option>
    <option>Quote for new system</option>
  </select>
  <label for="system">System type</label>
  <select id="system" name="system">
    <option value="">Choose…</option>
    <option>Central AC</option>
    <option>Heat pump</option>
    <option>Furnace</option>
    <option>Mini-split</option>
    <option>Boiler</option>
    <option>Not sure</option>
  </select>
  <label for="age">How old is the system?</label>
  <select id="age" name="age">
    <option value="">Choose…</option>
    <option>Under 5 years</option>
    <option>5–10 years</option>
    <option>10–15 years</option>
    <option>15+ years</option>
    <option>Not sure</option>
  </select>
  <label for="details">Describe the issue *</label>
  <textarea id="details" name="details" placeholder="When it started, error codes, recent changes…" required></textarea>

  <!-- honeypot — bots fill every field -->
  <input type="checkbox" name="botcheck" style="display:none" tabindex="-1" autocomplete="off">

  <button type="submit">Send</button>
</form>

<p style="margin-top:12px;font-size:11px;color:#888;text-align:right">
  Powered by <a href="https://splitforms.com" style="color:#888;text-decoration:none" target="_blank" rel="noopener">splitforms</a>
</p>
02JavaScriptform.js69 lines
<form id="lf-form">
  <label for="name">Full name *</label>
  <input id="name" type="text" name="name" placeholder="Hans Becker" required>
  <label for="email">Email *</label>
  <input id="email" type="email" name="email" placeholder="hans@example.com" required>
  <label for="phone">Phone *</label>
  <input id="phone" type="tel" name="phone" placeholder="+1 555 0142" required>
  <label for="address">Service address *</label>
  <input id="address" type="text" name="address" placeholder="1247 Valencia St" required>
  <label for="service">What do you need? *</label>
  <select id="service" name="service" required>
    <option value="">Choose…</option>
    <option>AC not cooling</option>
    <option>Heat not working</option>
    <option>New install / replacement</option>
    <option>Maintenance / tune-up</option>
    <option>Duct cleaning</option>
    <option>Quote for new system</option>
  </select>
  <label for="system">System type</label>
  <select id="system" name="system">
    <option value="">Choose…</option>
    <option>Central AC</option>
    <option>Heat pump</option>
    <option>Furnace</option>
    <option>Mini-split</option>
    <option>Boiler</option>
    <option>Not sure</option>
  </select>
  <label for="age">How old is the system?</label>
  <select id="age" name="age">
    <option value="">Choose…</option>
    <option>Under 5 years</option>
    <option>5–10 years</option>
    <option>10–15 years</option>
    <option>15+ years</option>
    <option>Not sure</option>
  </select>
  <label for="details">Describe the issue *</label>
  <textarea id="details" name="details" placeholder="When it started, error codes, recent changes…" required></textarea>
  <button type="submit">Send</button>
</form>

<p style="margin-top:12px;font-size:11px;color:#888;text-align:right">
  Powered by <a href="https://splitforms.com" style="color:#888;text-decoration:none" target="_blank" rel="noopener">splitforms</a>
</p>

<script>
  document.getElementById('lf-form').addEventListener('submit', async (e) => {
    e.preventDefault();
    const data = new FormData(e.target);
    data.set('access_key', 'YOUR_ACCESS_KEY');
    data.set('subject', 'New HVAC service request');

    const res = await fetch('https://splitforms.com/api/submit', {
      method: 'POST',
      body: data,
      headers: { Accept: 'application/json' },
    });

    const json = await res.json();
    if (json.success) {
      e.target.reset();
      alert('Sent!');
    } else {
      alert('Error: ' + (json.message || 'Try again'));
    }
  });
</script>
03React / Next.jsForm.tsx84 lines
'use client';

import { useState, type FormEvent } from 'react';

export default function HvacServiceForm() {
  const [status, setStatus] = useState<'idle' | 'sending' | 'sent' | 'error'>('idle');

  async function onSubmit(e: FormEvent<HTMLFormElement>) {
    e.preventDefault();
    setStatus('sending');

    const data = new FormData(e.currentTarget);
    data.set('access_key', 'YOUR_ACCESS_KEY');
    data.set('subject', 'New HVAC service request');

    const res = await fetch('https://splitforms.com/api/submit', {
      method: 'POST',
      body: data,
      headers: { Accept: 'application/json' },
    });

    const json = await res.json();
    setStatus(json.success ? 'sent' : 'error');
    if (json.success) e.currentTarget.reset();
  }

  if (status === 'sent') return <p>Thanks — we&rsquo;ll be in touch.</p>;

  return (
    <>
    <form onSubmit={onSubmit}>
      <label htmlFor="name">Full name *</label>
      <input id="name" type="text" name="name" placeholder="Hans Becker" required />
      <label htmlFor="email">Email *</label>
      <input id="email" type="email" name="email" placeholder="hans@example.com" required />
      <label htmlFor="phone">Phone *</label>
      <input id="phone" type="tel" name="phone" placeholder="+1 555 0142" required />
      <label htmlFor="address">Service address *</label>
      <input id="address" type="text" name="address" placeholder="1247 Valencia St" required />
      <label htmlFor="service">What do you need? *</label>
      <select id="service" name="service" required>
        <option value="">Choose…</option>
        <option>AC not cooling</option>
        <option>Heat not working</option>
        <option>New install / replacement</option>
        <option>Maintenance / tune-up</option>
        <option>Duct cleaning</option>
        <option>Quote for new system</option>
      </select>
      <label htmlFor="system">System type</label>
      <select id="system" name="system">
        <option value="">Choose…</option>
        <option>Central AC</option>
        <option>Heat pump</option>
        <option>Furnace</option>
        <option>Mini-split</option>
        <option>Boiler</option>
        <option>Not sure</option>
      </select>
      <label htmlFor="age">How old is the system?</label>
      <select id="age" name="age">
        <option value="">Choose…</option>
        <option>Under 5 years</option>
        <option>5–10 years</option>
        <option>10–15 years</option>
        <option>15+ years</option>
        <option>Not sure</option>
      </select>
      <label htmlFor="details">Describe the issue *</label>
      <textarea id="details" name="details" placeholder="When it started, error codes, recent changes…" required />

      <button type="submit" disabled={status === 'sending'}>
        {status === 'sending' ? 'Sending…' : 'Send'}
      </button>

      {status === 'error' && <p>Something went wrong. Try again.</p>}
    </form>

      <p style={{ marginTop: 12, fontSize: 11, color: '#888', textAlign: 'right' }}>
        Powered by <a href="https://splitforms.com" target="_blank" rel="noopener" style={{ color: '#888', textDecoration: 'none' }}>splitforms</a>
      </p>
    </>
  );
}
04PHPsubmit.php28 lines
<?php
// Drop into a PHP page. Receives a form POST and proxies it to splitforms.com.
// Useful when you want to add server-side validation or rate limiting.

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $allowed = ['name', 'email', 'phone', 'address', 'service', 'system', 'age', 'details'];
    $payload = ['access_key' => 'YOUR_ACCESS_KEY'];
    $payload['subject'] = 'New HVAC service request';

    foreach ($allowed as $f) {
        if (isset($_POST[$f])) $payload[$f] = $_POST[$f];
    }

    $ch = curl_init('https://splitforms.com/api/submit');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Accept: application/json']);
    $response = curl_exec($ch);
    $status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    header('Content-Type: application/json');
    http_response_code($status);
    echo $response;
    exit;
}
?>
05cURLtest.sh12 lines
curl -X POST https://splitforms.com/api/submit \
  -H "Accept: application/json" \
  -d "access_key=YOUR_ACCESS_KEY" \
  -d "subject=New HVAC service request" \
  -d "name=Jane Builder" \
  -d "email=jane@example.com" \
  -d "phone=+15555555555" \
  -d "address=Jane Builder" \
  -d "service=AC not cooling" \
  -d "system=Central AC" \
  -d "age=Under 5 years" \
  -d "details=Hello from cURL" 

Replace YOUR_ACCESS_KEY with the key from your dashboard. That’s the only edit.

§ 06FAQ4 answered

Things people ask before they ship.

Direct answers, no marketing fluff. Missing one? Email hello@splitforms.com.

01How do I handle the seasonal volume swings?
Use the urgency field plus a 'preferred week' selector. In peak season, no-cool / no-heat goes to the top; tune-ups slide to the next available week. The form sorts itself when dispatch sorts the inbox by those columns.
02Can I quote replacement systems from the form alone?
Not accurately — full system swap quotes need a load calculation and ductwork inspection on-site. But the form's age + symptom + square footage fields tell you whether to roll a salesperson alongside the tech, which is the actual decision.
03What about maintenance plan signups?
Add a 'I'd like to hear about your maintenance plan' checkbox. Half your repeat revenue comes from those plans. Webhook to a separate inbox or CRM tag if checked.
04Should I integrate Google LSA leads here too?
LSAs come in via Google's own pipeline — usually a phone call. Your splitforms-driven form captures organic search and your own paid landing pages. Most shops run both; the form costs you $0 per lead.
✻ ✻ ✻

Ship your hvac service & quote request form in 60 seconds.

1,000 free submissions per month. No credit card. Copy the snippet, paste your access key, watch leads land in your inbox.

Get free access key →Browse all 60 templates →
v0.1 · founders pricing locked in · early access open