Skip to navigation

Vanilla Embed Library

Embed typeforms in your website using vanilla JavaScript

The Vanilla Embed Library lets you embed typeforms directly into your website using pure JavaScript, without any framework dependencies. It works with any website or framework.

Installation

Via CDN (quickest method)

Add the script tag to your HTML:

<script src="https://embed.typeform.com/next/embed.js"></script>

Via NPM

For build-tool projects:

npm install @typeform/embed

Then import in your JavaScript:

import {
createWidget,
createPopup,
createSlider,
createSidetab,
} from '@typeform/embed';

Embed types

Typeform offers four main embed types:

  1. Widget (Inline): Embedded directly in your page
  2. Popup: Opens in a modal overlay
  3. Slider: Slides in from the side
  4. Sidetab: Persistent tab on the side of the page

Widget (Inline) embed

Embed the form directly into your page content.

Basic implementation

<div id="my-typeform"></div>
<script>
const { createWidget } = window.tf.createWidget('YOUR_FORM_ID', {
container: document.getElementById('my-typeform'),
height: 500,
});
</script>

With options

<div id="my-typeform" style="height: 500px;"></div>
<script>
const { createWidget } = window.tf.createWidget('YOUR_FORM_ID', {
container: document.getElementById('my-typeform'),
height: 500,
hidden: {
user_id: '12345',
source: 'website',
},
onReady: () => {
console.log('Form is ready');
},
onSubmit: () => {
console.log('Form submitted');
},
});
</script>

Display the form in a modal overlay.

Trigger on button click

<button id="open-typeform">Take Survey</button>
<script>
const { open, close, toggle } = window.tf.createPopup('YOUR_FORM_ID', {
autoClose: 3000, // Close 3 seconds after submission
hidden: {
user_id: '12345',
},
onSubmit: () => {
console.log('Form submitted');
},
});
document.getElementById('open-typeform').addEventListener('click', () => {
open();
});
</script>

Auto-open on page load

<script>
window.tf.createPopup('YOUR_FORM_ID', {
autoOpen: true,
autoClose: 3000,
});
</script>

Auto-open with delay

<script>
window.tf.createPopup('YOUR_FORM_ID', {
autoOpen: 5000, // Open after 5 seconds
});
</script>

Slider embed

Slide in from the right, left, top, or bottom of the screen.

<button id="open-slider">Get Started</button>
<script>
const { open, close, toggle } = window.tf.createSlider('YOUR_FORM_ID', {
position: 'right', // 'right', 'left', 'top', 'bottom'
width: 500,
height: 600,
hidden: {
source: 'slider',
},
});
document.getElementById('open-slider').addEventListener('click', () => {
open();
});
</script>

Sidetab embed

Display a persistent tab that opens the form when clicked.

<script>
window.tf.createSidetab('YOUR_FORM_ID', {
buttonText: 'Feedback',
position: 'right', // 'right' or 'left'
hidden: {
page: window.location.pathname,
},
});
</script>

Configuration options

Common options (all embed types)

OptionTypeDefaultDescription
hiddenobject{}Hidden fields to pass to the form
trackingobject{}Tracking parameters (UTM, etc.)
domainstring'form.typeform.com'Custom domain for white-label forms
onReadyfunctionnullCallback when form is ready
onSubmitfunctionnullCallback when form is submitted
onClosefunctionnullCallback when form is closed
onQuestionChangedfunctionnullCallback when question changes
onHeightChangedfunctionnullCallback when height changes
autoFocusbooleanfalseAuto-focus the form on load
lazybooleanfalseLazy load the form
keepSessionbooleanfalseKeep session for partial submissions
hideHeadersbooleanfalseHide Typeform branding (PRO feature)
hideFooterbooleanfalseHide footer (PRO feature)
opacitynumber100Background opacity (0-100)
disableScrollbooleanfalseDisable page scrolling when form is open

Widget-specific options

OptionTypeDefaultDescription
containerHTMLElementnullContainer element (required)
heightnumber500Height in pixels
widthnumber/string'100%'Width (px or %)
inlineOnMobilebooleanfalseForce inline on mobile
OptionTypeDefaultDescription
autoOpenboolean/numberfalseAuto-open on load (or delay in ms)
autoClosenumbernullAuto-close after submission (ms)
sizenumber100Size as percentage (50-100)
widthnumbernullFixed width in pixels
heightnumbernullFixed height in pixels

Slider-specific options

OptionTypeDefaultDescription
positionstring'right'Position: ‘left’, ‘right’, ‘top’, ‘bottom’
widthnumber800Width in pixels
heightnumber600Height in pixels

Sidetab-specific options

OptionTypeDefaultDescription
buttonTextstring'Launch me'Text on the tab
positionstring'right'Position: ‘left’ or ‘right’
buttonColorstringnullCustom button color
buttonTextColorstringnullCustom text color
customIconstringnullCustom icon URL

Methods

All embed types return methods for programmatic control:

const { open, close, toggle, refresh, focus, unmount } =
window.tf.createPopup('YOUR_FORM_ID');
// Open the form
open();
// Close the form
close();
// Toggle (open if closed, close if open)
toggle();
// Refresh/reload the form
refresh();
// Focus on the form
focus();
// Remove the form from DOM
unmount();

Callbacks

onReady

Triggered when the form is fully loaded:

window.tf.createWidget('YOUR_FORM_ID', {
container: document.getElementById('form'),
onReady: ({ formId }) => {
console.log(`Form ${formId} is ready`);
},
});

onSubmit

Triggered when the form is submitted:

window.tf.createPopup('YOUR_FORM_ID', {
onSubmit: ({ formId, responseId }) => {
console.log(`Form ${formId} submitted`);
console.log(`Response ID: ${responseId}`);
// Send to analytics
gtag('event', 'form_submit', {
form_id: formId,
});
},
});

onClose

Triggered when a popup/slider/sidetab is closed:

window.tf.createPopup('YOUR_FORM_ID', {
onClose: () => {
console.log('Form closed');
},
});

onQuestionChanged

Triggered when the respondent moves to a new question:

window.tf.createWidget('YOUR_FORM_ID', {
container: document.getElementById('form'),
onQuestionChanged: ({ formId, ref }) => {
console.log(`Question changed to: ${ref}`);
},
});

onHeightChanged

Triggered when the form height changes (useful for responsive iframes):

window.tf.createWidget('YOUR_FORM_ID', {
container: document.getElementById('form'),
onHeightChanged: ({ height }) => {
console.log(`Form height changed to: ${height}px`);
},
});

Complete example

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Typeform Embed Example</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
}
#typeform-container {
max-width: 800px;
margin: 0 auto;
height: 600px;
}
.button-group {
text-align: center;
margin: 20px 0;
}
button {
background: #6c5ce7;
color: white;
border: none;
padding: 12px 24px;
font-size: 16px;
cursor: pointer;
margin: 0 10px;
border-radius: 4px;
}
button:hover {
background: #5b4bc4;
}
</style>
</head>
<body>
<h1>Typeform Embed Demo</h1>
<div class="button-group">
<button id="open-popup">Open Popup</button>
<button id="open-slider">Open Slider</button>
</div>
<div id="typeform-container"></div>
<script src="https://embed.typeform.com/next/embed.js"></script>
<script>
// Widget embed
window.tf.createWidget('YOUR_FORM_ID', {
container: document.getElementById('typeform-container'),
height: 600,
hidden: {
user_id: 'demo_user',
source: 'website',
},
onReady: () => {
console.log('Widget ready');
},
onSubmit: ({ responseId }) => {
console.log('Form submitted:', responseId);
alert('Thank you for your submission!');
},
});
// Popup embed
const { open: openPopup } = window.tf.createPopup('YOUR_FORM_ID', {
autoClose: 3000,
size: 80,
hidden: {
source: 'popup',
},
});
document
.getElementById('open-popup')
.addEventListener('click', openPopup);
// Slider embed
const { open: openSlider } = window.tf.createSlider('YOUR_FORM_ID', {
position: 'right',
width: 600,
hidden: {
source: 'slider',
},
});
document
.getElementById('open-slider')
.addEventListener('click', openSlider);
// Sidetab embed
window.tf.createSidetab('YOUR_FORM_ID', {
buttonText: 'Feedback?',
position: 'right',
hidden: {
source: 'sidetab',
page: window.location.pathname,
},
});
</script>
</body>
</html>

Next steps