Building embeddable page templates
How to build page templates that work when embedded on external websites via iframe
Movement pages can be embedded on external websites using an iframe. When embedded, only the form content is shown — the surrounding chrome is automatically hidden.
This guide covers how to build templates that adapt to an embedded context.
Getting started
To enable embedding for your account, contact us with the domain(s) you'd like to embed pages on (e.g. yourwebsite.org). These need to be whitelisted before embeds will work.
Once enabled, you can get the embed snippet from the Embed button in the page builder, or from the Manage dropdown on the page overview.
The embed URL
Every page has an embed variant at {publicUrl}/embed. This URL:
- Hides the header and language switcher
- Sets
flow.is_embeddedtotruein the Liquid context
The embed snippet generated in the UI produces an iframe like:
<iframe src="https://your-domain.com/p/my-page/embed" style="width:100%;border:0;min-height:600px;" loading="lazy"></iframe>Detecting embed mode in Liquid
Use flow.is_embedded in your Body HTML to conditionally show or hide content:
{% if flow.is_embedded == true %}
<div class="embedded-header">
<h2>{{ template.heading }}</h2>
</div>
{% else %}
<div class="full-header">
<img src="{{ template.logo }}" />
<h1>{{ template.heading }}</h1>
<nav>...</nav>
</div>
{% endif %}This is useful for:
- Hiding navigation and branding that doesn't make sense inside an iframe
- Simplifying the layout for a more compact embedded form
- Adjusting spacing and padding for a tighter fit
- Hiding footers or disclaimers that are already on the host page
Template design tips for embeds
Keep it compact
Embedded forms typically sit within a section of a larger page. Avoid large hero images, excessive padding, or full-page layouts when in embed mode.
{% if flow.is_embedded != true %}
<div class="hero">
{{ template.heroImage }}
</div>
{% endif %}
<div class="form-content">
<surveyform></surveyform>
</div>Use responsive widths
The iframe is set to width: 100%, so the form takes the width of its container on the host page. Use percentage-based or max-width layouts rather than fixed pixel widths:
.form-content {
max-width: 600px;
margin: 0 auto;
padding: 16px;
}Handle the iframe height
The iframe has min-height: 600px by default. If your form is taller, you may need to adjust this on your website. Consider keeping embedded forms concise — fewer questions per page, minimal vertical spacing.
JavaScript events in embeds
All page template events (movement:page:loaded, movement:action:changed, etc.) fire inside the iframe as normal. The host page cannot listen to these directly due to cross-origin restrictions, but you can use postMessage in your template's Head HTML to relay events to the parent:
<script>
document.addEventListener('movement:action:changed', function(event) {
window.parent.postMessage({
type: 'movement:action:changed',
detail: event.detail
}, '*');
});
</script>