SAVEFORM

Surveys · Last updated May 16, 2026

Embedding surveys

A survey doesn't have to live on a saveform.io link — one script tag renders it inline on your own page, styled and sandboxed, sized to its content. This page is the full embed reference: the tag, its attributes, the framework patterns, and what to check when something looks off.

The script tag

Copy the snippet from your survey's Share screen, or write it yourself — the only survey-specific part is the id:

HTMLanywhere in your HTML
<script
  src="https://saveform.io/embed.js"
  data-survey="YOUR_SURVEY_ID"
  async
></script>

The survey renders right where the tag sits. No wrapper element, no stylesheet, no initialisation call — the script derives its origin from its own src and everything else from the attributes.

Embed attributes

AttributeEffect
data-surveyRequired. The survey's id (from the Share screen or the dashboard URL).
data-targetA CSS selector (e.g. "#survey") to mount the iframe inside, when the script tag can't sit where the survey should render — common in site builders that pin scripts to the footer. Defaults to right after the script tag.
data-min-heightInitial height in pixels before the first auto-resize (default 320). Match it roughly to your survey's first screen to minimise layout shift.

How the embed works

Under the hood the script does three things:

StepWhat happens
InjectIt creates an <iframe> pointing at the hosted survey in embed mode (standalone page chrome stripped) and mounts it after the tag or inside data-target.
AttributeIt forwards your page's hostname so responses are attributed to your site in the dashboard — inside an iframe the browser's own Origin header would say saveform.io.
ResizeThe survey reports its content height via postMessage on every step change, and the script sets the iframe height to match — no fixed heights, no inner scrollbars, welcome screen through thank-you screen.

React, Vue & Angular

SPA frameworks strip raw <script> tags from templates, so create the element in code after mount:

ReactSurveyEmbed.tsx
import { useEffect, useRef } from 'react';

export function SurveyEmbed() {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const s = document.createElement('script');
    s.src = 'https://saveform.io/embed.js';
    s.async = true;
    s.dataset.survey = 'YOUR_SURVEY_ID';
    s.dataset.target = '#saveform-survey';
    el.appendChild(s);
    return () => { el.innerHTML = ''; }; // clean up on unmount
  }, []);

  return <div id="saveform-survey" ref={ref} />;
}

The identical pattern works in Vue's onMounted and Angular's ngAfterViewInit — create the script element, set src, async and the data-* attributes, append it once. If your framework serves a static index.html you control, dropping the plain one-liner into the body works too. The framework guides cover the surrounding integration patterns.

WordPress & site builders

Anywhere you can paste HTML, the one-liner works as-is:

PlatformWhere to paste
WordPressA "Custom HTML" block in the block editor, or a raw HTML widget in classic themes.
WebflowAn "Embed" element wherever the survey should sit.
Squarespace / WixA code/embed block. If the builder pins scripts to the footer, add an element with an id and point data-target at it.
Notion, Framer, …Any embed surface that accepts raw HTML works the same way.

Several embeds per page

Multiple script tags on one page are fine, including several different surveys. Each tag manages its own iframe, and resize messages carry the survey id, so two embeds never fight over each other's height.

Troubleshooting

SymptomLikely cause & fix
Nothing rendersThe tag is missing data-survey (check the browser console for a SaveForm error), or your framework stripped the script tag — use the mount-in-code pattern above.
Iframe stays at initial heightSomething on the page is filtering message events, or the embed was copied without the script (a bare iframe won't auto-resize). Always embed via embed.js.
Blocked by CSPSites with a strict Content-Security-Policy need frame-src https://saveform.io (and script-src allowing the embed script).
Responses not attributed to my siteAttribution uses the hostname the script reads at load time. Previewing from a local file (file://) has no hostname — deploy to a real origin (localhost is fine) and it appears.
Embedding surveys | SaveForm.io