Add a ContactFire form to any site
Two ways to integrate. The JS snippet takes 30 seconds. The plain HTML form gives you full control over markup and styling.
Two integration approaches
Paste one <script> tag. ContactFire renders the full form for you, styled and ready. Best for most sites.
- No custom HTML needed
- Form updates without re-deploying your site
- Auto-handles spam protection
Write a standard <form> tag and point the action at ContactFire. Full control over markup and CSS.
- Use your own CSS
- Works with any backend or static site
- Needs a redirect URL for success handling
Get your embed token
Both approaches need an embed token. This is a public-safe credential: it is fine to ship it in client-side code.
- Log in to my.contactfire.com
- Go to Embed Tokens in the left sidebar
- Click Create token
- Give it a name (e.g., "My website") and optionally restrict it to your domain
- Copy the token: it starts with
cf_embed_
cf_embed_...) are safe in frontend code. API keys (cf_api_...) are for server-side use only. Learn the difference.Option 1: JS embed snippet
Add two lines of HTML anywhere on your page. ContactFire loads the form asynchronously and renders it inside the #cf-form div.
<!-- Place this where you want the form to appear -->
<div id="cf-form"></div>
<!-- Load the ContactFire embed script -->
<script
src="https://my.contactfire.com/api/embed-script"
data-token="cf_embed_your_token_here"
data-form-id="your_form_public_id"
async
></script>| Attribute | Required | Description |
|---|---|---|
| data-token | Yes | Your embed token (starts with cf_embed_) |
| data-form-id | Yes | 12-character public form ID from Form Studio |
| async | Recommended | Load without blocking page render |
abc123xyz789.Option 2: Plain HTML form
Point a standard HTML form at the ContactFire submission endpoint. Use your own markup and CSS. Works on any static site, WordPress, Webflow, or server-rendered app.
<!-- Load the ContactFire embed script (once per page) -->
<script src="https://my.contactfire.com/api/embed-script" async></script>
<!-- Add data-contactfire-token to your form: the script handles submission -->
<form data-contactfire-token="cf_embed_your_token_here">
<label for="name">Name</label>
<input type="text" id="name" name="name" required />
<label for="email">Email</label>
<input type="email" id="email" name="email" required />
<label for="message">Message</label>
<textarea id="message" name="message" rows="4" required></textarea>
<button type="submit">Send message</button>
</form>When the embed script is loaded, it automatically intercepts the submit event of any form with a data-contactfire-token attribute, converts the field values to JSON, and posts them to ContactFire: no page reload required.
cf_embed_.Domain restrictions
Lock your embed token to specific domains so only your site can use it. This stops anyone else from submitting forms with your token.
- Go to Embed Tokens in your dashboard
- Edit your token
- Add your domain under Allowed domains (e.g.,
yoursite.com) - Save: submissions from other origins are now rejected
yoursite.com and www.yoursite.com if your site is accessible from both.Handle responses with JavaScript
Submit via fetch to show an inline success message instead of a page redirect.
document.querySelector('#contact-form').addEventListener('submit', async (e) => {
e.preventDefault();
const form = e.target;
const raw = new FormData(form);
const formData = Object.fromEntries(raw.entries());
try {
const res = await fetch('https://my.contactfire.com/api/form/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Embed-Token': 'cf_embed_your_token_here',
},
body: JSON.stringify({ formData }),
});
if (res.ok) {
// Show your success message
document.querySelector('#success').hidden = false;
form.reset();
} else {
const err = await res.json();
console.error('Submission failed:', err.error);
}
} catch (err) {
console.error('Network error:', err);
}
});{"message":"Form submission received successfully","submissionId":"abc123xyz","status":"accepted","usage":{"current":42,"limit":1000,"overage":0}}{"error":"No authentication token provided. Include X-API-Key header or X-Embed-Token header."}Redirect after submit (Form Studio)
When using Form Studio (/api/public/forms/{formId}/submit), you can configure a redirect URL in the form's settings. After a successful submission the API returns a redirectUrl field in the response. The embed script follows it automatically.
/api/form/submit, handle redirects in your JavaScript after receiving a successful response. The API does not perform HTTP redirects.Custom fields
Every input name (except reserved names starting with _) becomes a field in the submission. Name your inputs to match how you want them to appear in the inbox.
<!-- These field names appear as-is in the ContactFire inbox -->
<input type="text" name="full_name" />
<input type="email" name="work_email" />
<input type="text" name="company" />
<select name="budget_range" />
<textarea name="project_brief" rows="5"></textarea>Framework examples
React
import { useState } from 'react';
export default function ContactForm() {
const [status, setStatus] = useState('idle');
async function handleSubmit(e) {
e.preventDefault();
setStatus('loading');
const raw = new FormData(e.target);
const formData = Object.fromEntries(raw.entries());
const res = await fetch('https://my.contactfire.com/api/form/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Embed-Token': 'cf_embed_your_token_here',
},
body: JSON.stringify({ formData }),
});
setStatus(res.ok ? 'success' : 'error');
}
if (status === 'success') return <p>Message sent!</p>;
return (
<form onSubmit={handleSubmit}>
<input name="name" type="text" required />
<input name="email" type="email" required />
<textarea name="message" required />
<button type="submit" disabled={status === 'loading'}>
{status === 'loading' ? 'Sending…' : 'Send'}
</button>
</form>
);
}Astro
Download the pre-built Astro component from your dashboard: it includes Live Draft Saving and resume support out of the box.
---
// ContactFireForm.astro: download from Dashboard > Embed Code > Astro tab
import ContactFireForm from './ContactFireForm.astro';
---
<ContactFireForm token="cf_embed_your_token_here" formId="your_form_id" />GET /api/embed-code/{tokenId}?format=astro