Skip to Content
Embed Script

Embed Script

The SingleForm embed script adds a QR code widget and autofill capabilities to your existing HTML forms. No framework required — it works with plain HTML, React, Vue, or anything that renders a <form> element.

Installation

Add the script tag before the closing </body> tag on any page with a SingleForm-enabled form:

<script src="https://api.singleform.ai/api/embed.min.js"></script>

The script automatically discovers forms on the page by looking for elements with the data-sf-form-id attribute.

Domain Verification

Before the embed script can load on your website, you need to verify your domain in Settings → Domain Verification in the SingleForm dashboard.

  1. Enter your root domain (e.g. acme.com)
  2. Add the provided DNS TXT record to your domain
  3. Click Check Verification — once verified, the embed script will work on that domain and all its subdomains (e.g. shop.acme.com, staging.acme.com)

Development: localhost is always allowed without verification, so you can develop and test locally without adding a domain.

No domains verified yet? The embed script works on any origin until you verify your first domain. Once you verify a domain, only verified domains (and their subdomains) are allowed.

You can verify multiple domains if your forms are embedded across different sites. Each domain goes through the same DNS TXT verification process.

Basic Example

Here’s a minimal webhook form with SingleForm enabled:

<form data-sf-form-id="your-form-id" data-sf-form-type="webhook" data-sf-button="after:submit" > <label for="firstName">First Name</label> <input type="text" name="firstName" data-sf-field="firstName" /> <label for="email">Email</label> <input type="email" name="email" data-sf-field="email" /> <button type="submit">Submit</button> </form> <script src="https://api.singleform.ai/api/embed.min.js"></script>

That’s it. The script will:

  1. Append a “Fill with SingleForm” button next to your submit button
  2. Show a QR code widget when the button is clicked (desktop) or open the mobile app (phone)
  3. Handle the data flow between the mobile app and your form

Form Attributes

These attributes go on the <form> element.

data-sf-form-id (required)

Your form’s unique ID from the SingleForm dashboard.

<form data-sf-form-id="d4e5f6a7-b8c9-4d2e-a1f3-1234567890ab">

data-sf-form-type

Controls how submissions are delivered. Defaults to autofill.

ValueBehavior
autofillFields on your page fill in real-time as the user types on their phone. You control the submit.
webhookData is sent directly from the phone to your webhook endpoint. No page interaction needed.
<!-- Fields fill live on the page --> <form data-sf-form-id="..." data-sf-form-type="autofill"> <!-- Data goes straight to your webhook --> <form data-sf-form-id="..." data-sf-form-type="webhook">

data-sf-button

Controls where the “Fill with SingleForm” button appears. When omitted, no button is created (you’d need to call the JavaScript API manually).

ValueBehavior
after:submitInsert the button after your submit button
before:submitInsert the button before your submit button
replace:submitReplace your submit button entirely
CSS selector (e.g. #my-slot)Insert the button into a specific container element
<!-- Button appears after the submit button --> <form data-sf-form-id="..." data-sf-button="after:submit"> ... <button type="submit">Submit</button> <!-- SingleForm button will appear here --> </form> <!-- Button placed in a custom container --> <form data-sf-form-id="..." data-sf-button="#sf-button-slot"> <div id="sf-button-slot"></div> ... <button type="submit">Submit</button> </form>

data-sf-style

Sets the widget and button theme. Defaults to light.

ValueBehavior
lightLight button and widget (for light backgrounds)
darkDark button and widget (for dark backgrounds)
<form data-sf-form-id="..." data-sf-style="dark">

data-sf-short-code

Optional. The form’s 8-character short code, used to generate compact QR codes. If omitted, the script fetches it from the API automatically.

<form data-sf-form-id="..." data-sf-short-code="aB3kM9xQ">

Field Attributes

These attributes go on <input>, <select>, and <textarea> elements inside the form.

data-sf-field

Maps a form field to a SingleForm field key. When the user submits from the mobile app, data is matched to your fields by this key.

<input type="text" name="firstName" data-sf-field="firstName" /> <input type="email" name="email" data-sf-field="email" /> <input type="tel" name="phone" data-sf-field="phone" /> <select name="role" data-sf-field="role"> <option value="developer">Developer</option> <option value="designer">Designer</option> </select> <textarea name="message" data-sf-field="message"></textarea>

Works with all standard input types including checkboxes, radio buttons, selects, and textareas.

data-sf-meta

Attaches custom metadata to the submission. Use this for hidden values like tracking IDs, campaign sources, or session tokens.

<input type="hidden" data-sf-meta="campaignId" value="spring-2026" /> <input type="hidden" data-sf-meta="referrer" value="homepage" />

Metadata values are included in the deep link to the mobile app and passed along with the submission.

Autofill Behavior

When data-sf-form-type="autofill" is set:

  • The embed script opens a real-time session between the phone and the browser
  • As the user types on their phone, form fields on the page update live
  • Filled fields get a brief green pulse animation for visual feedback
  • The script triggers input and change events on filled fields, so framework-managed forms (React, Vue, etc.) pick up the changes
  • Your submit button stays in control — the user or staff clicks it when ready

Webhook Behavior

When data-sf-form-type="webhook" is set:

  • The user scans the QR code and submits directly from the mobile app
  • Data is delivered to your webhook endpoint as a signed POST request
  • No fields on the page are filled — the form acts as a QR code trigger
  • See Webhook Security for how to verify the signature

Multiple Forms

You can have multiple SingleForm-enabled forms on the same page. Each form gets its own widget and session:

<form data-sf-form-id="form-1" data-sf-form-type="webhook" data-sf-button="after:submit"> ... </form> <form data-sf-form-id="form-2" data-sf-form-type="autofill" data-sf-button="after:submit"> ... </form> <script src="https://api.singleform.ai/api/embed.min.js"></script>

Only include the script tag once — it discovers all forms on the page automatically.

Dynamic Forms

The embed script watches the DOM for changes using a MutationObserver. If your framework renders forms dynamically (e.g. React, Vue, or a SPA), the script will detect new data-sf-form-id elements and initialize them automatically.

If you need to manually trigger initialization after adding a form to the DOM:

window.SingleForm?.init();

Local Development

The embed script automatically allows localhost — no domain verification needed for local testing. Just include the script from the production API:

<script src="https://api.singleform.ai/api/embed.min.js"></script>

The widget, QR codes, and real-time autofill all work on localhost out of the box. The only requirement is that your webhook URL must be reachable from the internet for the mobile app to deliver submissions. If your server is running locally, use a tunneling service like ngrok  or Cloudflare Tunnel  to expose it:

ngrok http 3000 # Use the generated URL as your webhook URL in the SingleForm dashboard # e.g. https://abc123.ngrok.io/webhooks/singleform

When you’re ready to deploy, verify your production domain in Settings → Domain Verification and update your webhook URL to your production server.

Full Example

A complete page with a webhook contact form and an autofill registration form:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>My Site</title> </head> <body> <h2>Contact Us</h2> <form data-sf-form-id="your-webhook-form-id" data-sf-form-type="webhook" data-sf-button="after:submit" > <input type="text" name="firstName" data-sf-field="firstName" placeholder="First Name" /> <input type="text" name="lastName" data-sf-field="lastName" placeholder="Last Name" /> <input type="email" name="email" data-sf-field="email" placeholder="Email" /> <input type="hidden" data-sf-meta="source" value="contact-page" /> <button type="submit">Send</button> </form> <h2>Register</h2> <form data-sf-form-id="your-autofill-form-id" data-sf-form-type="autofill" data-sf-button="after:submit" > <input type="text" name="firstName" data-sf-field="firstName" placeholder="First Name" /> <input type="email" name="email" data-sf-field="email" placeholder="Email" /> <input type="text" name="company" data-sf-field="company" placeholder="Company" /> <button type="submit">Register</button> </form> <script src="https://api.singleform.ai/api/embed.min.js"></script> </body> </html>