Embed on your website
Add a Clipform to any website with a two-line code snippet.
Add an interactive Clipform to any website. Visitors can watch videos and respond directly on your page - no redirects, no popups.
Quick start
Paste this wherever you want the form to appear:
<div data-embed-id="YOUR_FORM_ID"></div>
<script src="https://www.clipform.io/embed.js"></script>Replace YOUR_FORM_ID with your form's Form ID - the code at the end of your share link (e.g. the abc123 part of clipform.io/abc123).
That's it. The form renders as a 9:16 vertical video player, centered, up to 460px wide. On phones, tapping the form opens it fullscreen so respondents can answer comfortably - the back button returns them to your page.
Customize with data attributes
Everything is optional - the defaults just work. To tweak them, add attributes to the same <div>:
<div
data-embed-id="YOUR_FORM_ID"
data-embed-max-width="400px"
></div>| Attribute | Default | Description |
|---|---|---|
data-embed-id | required | Your form's Form ID (your share ID or slot ID) |
data-embed-max-width | 460px | Width cap. The embed centers itself and never grows wider |
data-embed-min-width | 375px | Width floor. The embed never shrinks below a usable size |
data-embed-height | 9:16 auto | Explicit height. Bypasses the 9:16 ratio - use inside fixed-height containers |
data-embed-poster | auto | Your own poster image URL, or "false" to disable the poster and play button |
data-embed-inline-on-mobile | false | Set "true" to keep the form inline on phones instead of opening fullscreen |
data-embed-auto-resize | false | Set "true" to let the embed grow past 9:16 to fit the form's content |
data-embed-source | - | A label for where this embed lives (e.g. your domain), shown in analytics |
Sizing
By default the embed fills its container's width up to a 460px cap (centered), holds a 9:16 aspect ratio, and never shrinks below a 375px floor - the smallest width where buttons and progress stay comfortably tappable.
| Value | |
|---|---|
| Aspect ratio | 9:16 (portrait) |
| Default max width | 460px, centered (override with data-embed-max-width or your own CSS) |
| Min width floor | 375px (override with data-embed-min-width) |
The cap is a default, not a constraint - your own CSS on the container always wins:
<div style="max-width: 400px; margin: 0 auto;">
<div data-embed-id="YOUR_FORM_ID"></div>
</div>When you pass an explicit height via the JavaScript API, the aspect ratio is bypassed and the embed uses your value exactly. This is useful when embedding inside a fixed-size container:
cfEmbed.embed({
formId: 'YOUR_FORM_ID',
container: '#my-form',
height: '780px',
});Responsive layout
On mobile, the form looks best when it fills the full screen width with no side padding or decorative borders. On desktop, you can wrap it in a frame or add padding. A common pattern:
<style>
.form-wrapper {
width: 100%;
aspect-ratio: 9 / 16;
}
@media (min-width: 640px) {
.form-wrapper {
max-width: 420px;
margin: 0 auto;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
}
}
</style>
<div class="form-wrapper">
<div data-embed-id="YOUR_FORM_ID"></div>
</div>Below 640px the form goes edge-to-edge. Above 640px it gets a centered frame with rounded corners.
Mobile behavior
On phones, tapping the poster opens the form in a fullscreen overlay. Respondents stay on your page - the browser back button (or back gesture) closes the overlay and returns them exactly where they were. Progress is kept, so tapping again resumes the form.
Prefer everything inline? Set data-embed-inline-on-mobile="true" (or inlineOnMobile: true in the JavaScript API).
Preventing layout shift
The embed automatically holds its space on your page (a 9:16 box) while the form loads, so surrounding content doesn't jump around. It shows a subtle loading shimmer immediately, so visitors always see that something is on its way.
By default, the embed fetches a thumbnail of the first question and displays it as a poster with a play button while the interactive form loads behind it. Visitors see content immediately and know the embed is interactive. When they click play, the form crossfades in - if it has already loaded, playback starts instantly; if it's still loading, the Clipform loading screen appears briefly before the form starts.
To provide your own poster image (skipping the auto-fetch), use the data-embed-poster attribute:
<div
data-embed-id="YOUR_FORM_ID"
data-embed-poster="https://example.com/my-thumbnail.jpg"
></div>To disable the poster entirely, set data-embed-poster="false". The embed shows the loading shimmer (or your backgroundColor, if you set one) until the form loads.
JavaScript API
For more control, use the JavaScript API instead of data attributes:
<div id="my-form"></div>
<script src="https://www.clipform.io/embed.js"></script>
<script>
cfEmbed.embed({
formId: 'YOUR_FORM_ID',
container: '#my-form',
onComplete: function(data) {
console.log('Form completed:', data.formId);
}
});
</script>Options
| Option | Type | Default | Description |
|---|---|---|---|
formId | string | required | Your form's Form ID (your share ID or slot ID) |
container | string | required | CSS selector for the container element |
maxWidth | string | '460px' | Width cap, centered. Your own CSS on the container also overrides it |
minWidth | string | '375px' | Width floor. The embed holds this even in narrower columns |
height | string | 9:16 auto | Explicit CSS height. When set, bypasses the 9:16 aspect ratio |
width | string | '100%' | CSS width for the iframe |
poster | string | false | auto-fetched | Thumbnail URL shown while the form loads. Set to false to disable |
backgroundColor | string | 'transparent' | Loading background. Replaces the default shimmer |
borderRadius | string | '8px' | Corner rounding |
autoResize | boolean | false | Opt in to grow the embed to the form's content height instead of holding 9:16 |
inlineOnMobile | boolean | false | Keep the form inline on phones instead of opening fullscreen on tap |
source | string | - | A label for where this embed lives, shown in analytics |
title | string | 'Embedded form' | Accessible label for the iframe (screen readers) |
Lifecycle callbacks (onReady, onStarted, onComplete, and more) are listed under Events.
Events
Lifecycle callbacks let your page react to the form - fire your own analytics, show a thank-you message, or redirect after completion. Pass them to cfEmbed.embed():
cfEmbed.embed({
formId: 'YOUR_FORM_ID',
container: '#my-form',
onStarted: function (data) { console.log('started', data.formId); },
onComplete: function (data) { console.log('completed', data.formId); },
});| Callback | Fires when | Receives |
|---|---|---|
onReady(iframe) | The form has loaded and is ready | the iframe element |
onStarted(data) | The respondent answers the first node | { formId } |
onNodeComplete(data) | The respondent finishes a node | { formId, nodeId, index } - index counts nodes completed so far |
onComplete(data) | The respondent completes the form | { formId } |
onEndScreenButtonClick(data) | The respondent clicks an end-screen button | { formId, nodeId } |
onLoad(iframe) | The form is first revealed (legacy - prefer onReady) | the iframe element |
Privacy: callbacks carry IDs and counts only, never the respondent's answers. Answer content stays between the form and Clipform, so forwarding these events to your own analytics is safe.
Troubleshooting
Form not loading
- Check that the Form ID is correct (the 8-12 character code from your share link)
- Make sure the form is set to Live in the dashboard
- Check browser console for errors
Form appears but video won't play
- Embedded forms use click-to-play. The respondent must click the play button to start.
Content is clipped
The embed sizes itself to a 9:16 box from its container's width, so make sure the container has a defined width and isn't constrained to a shorter height. If you're embedding inside a fixed-height container, pass an explicit height option so the embed fills your container instead.
Embed overflows a narrow column
The embed holds a 375px minimum width so buttons and progress stay usable - in a narrower column it overflows rather than shrinking into an unusable form. Give the column more room, or lower the floor with data-embed-min-width if you accept smaller tap targets.
Camera/microphone not working
The embed iframe includes allow="camera; microphone" permissions. If your site has a strict Content Security Policy, you may need to add camera and microphone to your permissions-policy header.