Handle form events
Makeform embed events let you track form readiness, submissions, and popup or slider opening and closing for free on every plan. Get your form embed from Share > Embed Form, then enable events in your website code.
Makeform is a free AI form builder: describe what you want to collect and it builds the form for you, with unlimited forms and submissions on the free plan.
Event layers
Makeform uses two event layers:
| Layer | Who uses it | How to listen |
|---|---|---|
| SDK CustomEvents | Most website analytics and app code | window.addEventListener('MakeForm:submit', handler) |
| iframe postMessage | Advanced integrations and debugging | window.addEventListener('message', handler) |
For most websites, use SDK CustomEvents. The SDK validates the iframe source and converts Makeform iframe messages into simpler MakeForm:* events when you opt in.
Enable events
Standard embed
Add data-makeform-events to the iframe:
<iframe
data-makeform-src="https://www.makeform.ai/e/YOUR_FORM_ID"
data-makeform-auto-resize
data-makeform-events
loading="lazy"
style="width: 100%; height: 200px; border: 0;"
title="Makeform form"
></iframe>
<script async src="https://www.makeform.ai/widgets/embed.js"></script>Standard embeds dispatch MakeForm:ready and MakeForm:submit.
Popup and slider
For data-attribute triggers, add data-makeform-events to the trigger:
<button
data-makeform-popup="https://www.makeform.ai/e/YOUR_FORM_ID"
data-makeform-events
>
Open Form
</button>
<script async src="https://www.makeform.ai/widgets/embed.js"></script>For the JavaScript API, set dispatchEvents: true:
MakeForm.openPopup("YOUR_FORM_ID", {
dispatchEvents: true
});Popup and slider embeds can dispatch MakeForm:open, MakeForm:ready, MakeForm:submit, and MakeForm:close.
Full page embed
Full page embeds use /f/{FORM_ID}. To emit submission events, append __mf_emitEvents=1, use data-makeform-src, and add data-makeform-events:
<iframe
data-makeform-src="https://www.makeform.ai/f/YOUR_FORM_ID?__mf_emitEvents=1"
data-makeform-events
style="position: absolute; inset: 0; border: 0; width: 100%; height: 100%;"
title="Makeform form"
></iframe>
<script async src="https://www.makeform.ai/widgets/embed.js"></script>SDK CustomEvents
MakeForm:ready
Fires when the form iframe reports that it has loaded.
window.addEventListener("MakeForm:ready", (event) => {
console.log("Ready:", event.detail.formId);
});MakeForm:submit
Fires when the form is successfully submitted.
window.addEventListener("MakeForm:submit", (event) => {
console.log("Submitted form:", event.detail.formId);
console.log("Submission data:", event.detail.data);
});MakeForm:open
Fires when a popup or slider opens.
window.addEventListener("MakeForm:open", (event) => {
console.log("Opened:", event.detail.formId);
});MakeForm:close
Fires when a popup or slider closes.
window.addEventListener("MakeForm:close", (event) => {
console.log("Closed:", event.detail.formId);
});PostMessage events
The form iframe sends postMessage payloads to its parent window. These are useful if you are building a custom wrapper around the embed SDK.
MakeForm.Loaded
{
"type": "MakeForm.Loaded",
"payload": {}
}MakeForm.SubmitSuccess
{
"type": "MakeForm.SubmitSuccess",
"payload": {
"Name": "Jane Doe",
"Email": "jane@example.com"
}
}Internal layout messages
The SDK also listens for these iframe messages:
| Event | Purpose |
|---|---|
MakeForm.SetHeight |
Auto-resizes standard embeds and popup height. Payload shape: { "height": 640 }. |
MakeForm.LayoutReady |
Reveals popups only after the first stable layout height is available. |
MakeForm.SetBackgroundColor |
Syncs modal background color with the form background. |
MakeForm.Submitted |
Payload-free submit signal used for safe auto-close on /f popup embeds. |
Complete examples
window.addEventListener("MakeForm:ready", (event) => {
console.log("Form ready:", event.detail.formId);
});
window.addEventListener("MakeForm:submit", (event) => {
console.log("Submitted:", event.detail.formId, event.detail.data);
});
window.addEventListener("MakeForm:open", (event) => {
console.log("Modal opened:", event.detail.formId);
});
window.addEventListener("MakeForm:close", (event) => {
console.log("Modal closed:", event.detail.formId);
});type MakeFormEventDetail = {
formId: string;
data?: Record<string, unknown>;
};
const onSubmit = (event: Event) => {
const detail = (event as CustomEvent<MakeFormEventDetail>).detail;
console.log("Submitted:", detail.formId, detail.data);
};
window.addEventListener("MakeForm:submit", onSubmit);'use client';
import Script from 'next/script';
import { useEffect } from 'react';
export function EmbeddedForm({ formId }: { formId: string }) {
useEffect(() => {
const handleSubmit = (event: Event) => {
const detail = (event as CustomEvent).detail;
console.log('Submitted:', detail.formId, detail.data);
};
window.addEventListener('MakeForm:submit', handleSubmit);
return () => window.removeEventListener('MakeForm:submit', handleSubmit);
}, []);
return (
<>
<iframe
data-makeform-src={`https://www.makeform.ai/e/${formId}`}
data-makeform-auto-resize
data-makeform-events
loading="lazy"
style={{ width: '100%', height: 200, border: 0 }}
title="Makeform form"
/>
<Script
async
src="https://www.makeform.ai/widgets/embed.js"
onLoad={() => window.MakeForm?.loadEmbeds?.()}
/>
</>
);
}Advanced postMessage listener
If you listen to raw iframe messages, validate the origin before using the payload:
window.addEventListener("message", (event) => {
if (
event.origin !== "https://www.makeform.ai" &&
event.origin !== "https://makeform.ai"
) {
return;
}
if (typeof event.data !== "string") return;
try {
const data = JSON.parse(event.data);
if (data.type === "MakeForm.SubmitSuccess") {
console.log("Submission:", data.payload);
}
} catch {
// Ignore unrelated postMessage traffic.
}
});Event reference
SDK CustomEvents
| Event | Fires when | Detail |
|---|---|---|
MakeForm:ready |
Form iframe reports loaded | { formId } |
MakeForm:submit |
Form submission succeeds | { formId, data } |
MakeForm:open |
Popup or slider opens | { formId } |
MakeForm:close |
Popup or slider closes | { formId } |
iframe postMessage events
| Event | Public use |
|---|---|
MakeForm.Loaded |
Advanced wrapper can detect iframe readiness |
MakeForm.SubmitSuccess |
Advanced wrapper can read submission data |
MakeForm.SetHeight |
Internal resizing |
MakeForm.LayoutReady |
Internal popup reveal timing |
MakeForm.SetBackgroundColor |
Internal modal background sync |
MakeForm.Submitted |
Internal payload-free auto-close signal |
Best practices
-
Use SDK CustomEvents first They are easier to consume and work across standard, popup, and slider embeds when event tracking is enabled.
-
Clean up listeners in SPAs Remove event listeners when components unmount.
-
Validate postMessage origin Raw
messagelisteners receive traffic from many sources. Checkevent.originbefore reading the payload. -
Do not build product logic on layout messages
SetHeight,LayoutReady,SetBackgroundColor, andSubmittedexist for SDK behavior and can change as the embed runtime evolves.
Related
- Embed Your Form — Overview of all embed types
- Developer Resources — Full JavaScript API reference